Skip to main content

Python bindings for AnyList API via anylist_rs

Project description

pyanylist

CI PyPI Python Versions

Unofficial Python bindings for the AnyList API, built with Rust and PyO3 for performance.

Features

  • Shopping Lists: Create, read, update, and delete shopping lists and items
  • Favourites: Manage favourite/starter items
  • Recipes: Full recipe CRUD with ingredient scaling
  • Meal Planning: iCalendar integration for meal plan calendars
  • Real-time Sync: WebSocket-based live updates
  • Token Persistence: Save and restore authentication sessions

Installation

uv add pyanylist

Or with pip:

pip install pyanylist

Quick Start

from pyanylist import AnyListClient

# Login with email and password
client = AnyListClient.login("your-email@example.com", "your-password")

# Get all shopping lists
lists = client.get_lists()
for lst in lists:
    print(f"{lst.name}: {len(lst.items)} items")

# Add an item to a list
item = client.add_item(lists[0].id, "Milk")
print(f"Added: {item.name}")

# Add item with details
item = client.add_item_with_details(
    lists[0].id,
    "Apples",
    quantity="6",
    details="Honeycrisp preferred",
    category="Produce"
)

Authentication

Login with credentials

client = AnyListClient.login("email@example.com", "password")

Save and restore session

# Export tokens for persistence
tokens = client.export_tokens()

# Save to file, database, etc.
save_tokens(tokens.access_token, tokens.refresh_token, tokens.user_id)

# Later, restore from saved tokens
from pyanylist import SavedTokens

tokens = SavedTokens(
    access_token="...",
    refresh_token="...",
    user_id="...",
    is_premium_user=False
)
client = AnyListClient.from_tokens(tokens)

Shopping Lists

# Get all lists
lists = client.get_lists()

# Get a specific list
grocery_list = client.get_list_by_name("Groceries")
# or by ID
grocery_list = client.get_list_by_id("list-id-here")

# Create a new list
new_list = client.create_list("Weekly Shopping")

# Rename a list
client.rename_list(new_list.id, "Monthly Shopping")

# Delete a list
client.delete_list(new_list.id)

List Items

# Add a simple item
item = client.add_item(list_id, "Bread")

# Add item with details
item = client.add_item_with_details(
    list_id,
    "Chicken Breast",
    quantity="2 lbs",
    details="Boneless, skinless",
    category="Meat"
)

# Check/uncheck items
client.cross_off_item(list_id, item.id)
client.uncheck_item(list_id, item.id)

# Delete an item
client.delete_item(list_id, item.id)

# Clear all checked items
client.delete_all_crossed_off_items(list_id)

Favourites

# Get all favourite items
favourites = client.get_favourites()

# Get favourites organized by list
fav_lists = client.get_favourites_lists()
for fav_list in fav_lists:
    print(f"{fav_list.name}: {len(fav_list.items)} items")

# Add a favourite
fav = client.add_favourite("Coffee", category="Beverages")

# Remove a favourite
client.remove_favourite(fav_list.id, fav.id)

Recipes

from pyanylist import Ingredient

# Get all recipes
recipes = client.get_recipes()
for recipe in recipes:
    print(f"{recipe.name}: {len(recipe.ingredients)} ingredients")

# Get a specific recipe
recipe = client.get_recipe_by_name("Pasta Carbonara")

# Create a recipe
ingredients = [
    Ingredient("Spaghetti", quantity="400g"),
    Ingredient("Eggs", quantity="4"),
    Ingredient("Parmesan", quantity="100g", note="freshly grated"),
    Ingredient("Pancetta", quantity="200g"),
]
steps = [
    "Boil pasta according to package directions",
    "Fry pancetta until crispy",
    "Mix eggs and parmesan",
    "Combine everything off heat",
]
recipe = client.create_recipe("Carbonara", ingredients, steps)

# Add recipe ingredients to a shopping list
client.add_recipe_to_list(recipe.id, list_id)

# Scale recipe (e.g., double it)
client.add_recipe_to_list(recipe.id, list_id, scale_factor=2.0)

# Delete a recipe
client.delete_recipe(recipe.id)

Meal Plan Calendar (iCalendar)

# Enable iCalendar export
info = client.enable_icalendar()
print(f"Calendar URL: {info.url}")
# Use this URL in any calendar app (Google Calendar, Apple Calendar, etc.)

# Get existing calendar URL
url = client.get_icalendar_url()

# Disable iCalendar
client.disable_icalendar()

Real-time Sync

import time
from pyanylist import SyncEvent

# Start real-time sync
sync = client.start_realtime_sync()

# Poll for events
while sync.is_connected():
    events = sync.poll_events()
    for event in events:
        if event == SyncEvent.ShoppingListsChanged:
            print("Lists changed! Refreshing...")
            lists = client.get_lists()
        elif event == SyncEvent.RecipeDataChanged:
            print("Recipes changed!")
    time.sleep(1)

# Disconnect when done
sync.disconnect()

Available Sync Events

  • ShoppingListsChanged - Shopping lists modified
  • StarterListsChanged - Favourites modified
  • RecipeDataChanged - Recipes modified
  • MealPlanCalendarChanged - Meal plan modified
  • AccountDeleted - Account was deleted

Error Handling

All methods raise RuntimeError on failure:

try:
    client = AnyListClient.login("bad@email.com", "wrongpassword")
except RuntimeError as e:
    print(f"Login failed: {e}")

try:
    client.get_list_by_id("nonexistent-id")
except RuntimeError as e:
    print(f"List not found: {e}")

Development

Prerequisites

  • Python 3.12+
  • Rust 1.70+
  • uv
  • protoc (Protocol Buffers compiler)
    • Ubuntu/Debian: sudo apt-get install protobuf-compiler
    • macOS: brew install protobuf

Setup

# Clone the repository
git clone https://github.com/ozonejunkieau/pyanylist.git
cd pyanylist

# Install dependencies (includes dev dependencies)
uv sync

# Build and install in development mode
uv run maturin develop

Running Tests

# Run unit tests (no credentials needed)
uv run pytest -v -m "not integration"

# Run all tests including integration (requires credentials)
export ANYLIST_EMAIL="your-email@example.com"
export ANYLIST_PASSWORD="your-password"
uv run pytest -v

# Run with coverage
uv run pytest --cov=tests --cov-report=term-missing

Linting & Type Checking

# Check code style
uv run ruff check tests/

# Format code
uv run ruff format tests/

# Type check
uv run pyright tests/

Acknowledgements

This library is built on top of anylist_rs by Phil Denhoff, which provides the core Rust implementation for interacting with the AnyList API.

License

MIT License - see LICENSE for details.

Disclaimer

This is an unofficial library and is not affiliated with or endorsed by AnyList. Use at your own risk and in accordance with AnyList's terms of service.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyanylist-0.0.5.tar.gz (53.1 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pyanylist-0.0.5-cp313-cp313-musllinux_1_2_x86_64.whl (4.6 MB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ x86-64

pyanylist-0.0.5-cp313-cp313-musllinux_1_2_aarch64.whl (4.5 MB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ ARM64

pyanylist-0.0.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.3 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

pyanylist-0.0.5-cp313-cp313-macosx_11_0_arm64.whl (3.9 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

pyanylist-0.0.5-cp313-cp313-macosx_10_12_x86_64.whl (4.0 MB view details)

Uploaded CPython 3.13macOS 10.12+ x86-64

pyanylist-0.0.5-cp312-cp312-musllinux_1_2_x86_64.whl (4.6 MB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ x86-64

pyanylist-0.0.5-cp312-cp312-musllinux_1_2_aarch64.whl (4.5 MB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ ARM64

pyanylist-0.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.3 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

pyanylist-0.0.5-cp312-cp312-macosx_11_0_arm64.whl (3.9 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

pyanylist-0.0.5-cp312-cp312-macosx_10_12_x86_64.whl (4.0 MB view details)

Uploaded CPython 3.12macOS 10.12+ x86-64

File details

Details for the file pyanylist-0.0.5.tar.gz.

File metadata

  • Download URL: pyanylist-0.0.5.tar.gz
  • Upload date:
  • Size: 53.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pyanylist-0.0.5.tar.gz
Algorithm Hash digest
SHA256 3779a15e63bb3ebbe67b854ef64fdfc7d97d1e1753ec4a11606c1cdc201a8d03
MD5 6163dc7c96a26bf1c432b0fe5d7a67de
BLAKE2b-256 6dce29b6fd6c59c807b4bbd091ed433dbd43e16d4bec2a4739aed2302ba29d2b

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.5.tar.gz:

Publisher: release.yml on ozonejunkieau/pyanylist

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyanylist-0.0.5-cp313-cp313-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.5-cp313-cp313-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 3503e7760f9cb54fae4a1ae515437fc96f7f35b6f93b3a9cfdbbb04920849a06
MD5 8560ad001c75b6117511e29dbfda19f3
BLAKE2b-256 0c90a048e875bcfa11e532599baa76cad3dd29fe6679e53b24c05c9d0e530251

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.5-cp313-cp313-musllinux_1_2_x86_64.whl:

Publisher: release.yml on ozonejunkieau/pyanylist

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyanylist-0.0.5-cp313-cp313-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.5-cp313-cp313-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 a7d304c40349f71340a5ad219beb895b8cfd7fc8102151d7a295f3454b96a349
MD5 ffa6c23788dbcea5e41687b7f66fe62e
BLAKE2b-256 1dda1ecdb28aff2453ff2a93d60ca2485102557d7bc6ad1c76cadc6a814faadb

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.5-cp313-cp313-musllinux_1_2_aarch64.whl:

Publisher: release.yml on ozonejunkieau/pyanylist

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyanylist-0.0.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 5be22a3908c5cc4884bd9b801c2ab8567a2e7b227536cd9a6f2c1b48b47f8bdd
MD5 1cbf681e74f0cd7328467e1ef30b45b7
BLAKE2b-256 8085004e7b344fac1644f5fa7e57eef760c79706df54035e88b701773609089b

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on ozonejunkieau/pyanylist

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyanylist-0.0.5-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.5-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6a6e70a574c1b8e865f4f251fad0ef296308ce7a87e13a2cf87fdf3a8281a62c
MD5 9685dce0ef80c2d453d423ff72928bf0
BLAKE2b-256 7ee24430a08639e3471db14a059c1acbea090d711ef8cd10f04eb966f356e3a7

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.5-cp313-cp313-macosx_11_0_arm64.whl:

Publisher: release.yml on ozonejunkieau/pyanylist

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyanylist-0.0.5-cp313-cp313-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.5-cp313-cp313-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 8ba73b831c293536e10619f5bd8270cc5c4603d88fe0f7519617f4f4192e8a60
MD5 914e1fe7406b1a555b3b3aa37094c96b
BLAKE2b-256 265018ed6c69d51dacb8b7cdfed433495fa481ffe31e712eded8d4aaa2871acd

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.5-cp313-cp313-macosx_10_12_x86_64.whl:

Publisher: release.yml on ozonejunkieau/pyanylist

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyanylist-0.0.5-cp312-cp312-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.5-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 0acf29824e1a813f333d10d22199149a898267527312171b8643669da80b0d82
MD5 0a18720c5a99fa0e845579a0a93689bc
BLAKE2b-256 c1a1f70c8e50b88ce6d4a1613f3053814c1e0db70da25368d23d8744b74c6511

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.5-cp312-cp312-musllinux_1_2_x86_64.whl:

Publisher: release.yml on ozonejunkieau/pyanylist

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyanylist-0.0.5-cp312-cp312-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.5-cp312-cp312-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 5b70e38cafbaa0c50d87bd0f1ccba9b3c82024679a2e80e924746d66e70d12ea
MD5 d04a19ab6b32d51376108c28dabb905a
BLAKE2b-256 4fb2995538d283437a2795c952272a82a601a9c7edf7ef28c660a6c2b90cbb48

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.5-cp312-cp312-musllinux_1_2_aarch64.whl:

Publisher: release.yml on ozonejunkieau/pyanylist

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyanylist-0.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 7b6caaf3d1f0c566e92408b4b5efdea0723af6648611abd26637f2e1ed8b49e1
MD5 c6644dd1cbc5cb339a4c5fc5cc1913b8
BLAKE2b-256 d481b89b20b8a16c7838f907b3abaf06cd8b90c43786e7c3436f9f0e204f041f

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on ozonejunkieau/pyanylist

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyanylist-0.0.5-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.5-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e4f3b3a0dcfe4d06b0d38b7622344cc8c62bf251a27fca535c8a4adf62f25ae1
MD5 23aeffd739d2bcd919d218b2d786eef8
BLAKE2b-256 8917ca641cd35e8e0cb13df15e056edf1256aba625bc2cc5e3f55935d8207563

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.5-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: release.yml on ozonejunkieau/pyanylist

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyanylist-0.0.5-cp312-cp312-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.5-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 80554101faa13da01fe814cc13d5c5bcb254c09b2b026d64cd0b5005b8dbeb28
MD5 76fdc1e17d01bc6a83a78757f5be1a79
BLAKE2b-256 f90789c4c7c41c2a004966a93f2fb988c1e9b8bcbdcca6846084be1f787f2d38

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.5-cp312-cp312-macosx_10_12_x86_64.whl:

Publisher: release.yml on ozonejunkieau/pyanylist

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page