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.3.tar.gz (50.3 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.3-cp313-cp313-musllinux_1_2_x86_64.whl (4.5 MB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ x86-64

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

Uploaded CPython 3.13musllinux: musl 1.2+ ARM64

pyanylist-0.0.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.2 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

pyanylist-0.0.3-cp313-cp313-macosx_11_0_arm64.whl (3.8 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

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

Uploaded CPython 3.13macOS 10.12+ x86-64

pyanylist-0.0.3-cp312-cp312-musllinux_1_2_x86_64.whl (4.5 MB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ x86-64

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

Uploaded CPython 3.12musllinux: musl 1.2+ ARM64

pyanylist-0.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.2 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

pyanylist-0.0.3-cp312-cp312-macosx_11_0_arm64.whl (3.8 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

pyanylist-0.0.3-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.3.tar.gz.

File metadata

  • Download URL: pyanylist-0.0.3.tar.gz
  • Upload date:
  • Size: 50.3 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.3.tar.gz
Algorithm Hash digest
SHA256 b074cde251e90c9c4b0a7a41bdc6a0fd13f0042042e206ab37b9cbc4e5d8c4ef
MD5 a42d033a132a6969dcb836e47999bd6c
BLAKE2b-256 11ca2537fa322466fe3b4ccd91d2d3f4ebffb11af19ba9d88289e261330bfb6c

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.3.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.3-cp313-cp313-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.3-cp313-cp313-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 d5ba6c6ee7b802c264e7984b07da3a2c42bbf7d8ac1e7cff05c7fb9de79b43ef
MD5 73ca08d85318ab6a1ec24b249a49c5d9
BLAKE2b-256 ff3e003bf398b7c1b2d0cded0ca429b3facaf94e3ee85414930f2f1317cfd49f

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.3-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.3-cp313-cp313-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.3-cp313-cp313-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 33925e38a18d7f111c386837edfc74e42577c929b44c0ac81f0a5c7f61444383
MD5 82b9ccb31f856ec89814319d2bfbac92
BLAKE2b-256 03c8cc85ab304618037586afc86c0200107f683c9461b8c4c42c405b966736be

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.3-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.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 733497e298881ffd068031dbad41820f23561a9cbd76979364644008680e6c67
MD5 3212d4d241cecf1d86895abb2871dbc8
BLAKE2b-256 c44815516837778bd9b33f738549f45d811ed80b29e2f5a7b4dc2d720a51e3f7

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.3-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.3-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.3-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2b07722e38cb822f7f6a8db359e601837383bc36bda4f911dccf09d94a37f729
MD5 d9c5f5fbc88b1834557203cef35fa0ec
BLAKE2b-256 5669102e4365cb60ccb26007b46ea82d53b5169e58ce3539429edac1b07afbb2

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.3-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.3-cp313-cp313-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.3-cp313-cp313-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 4fe6cfb92eb541b54eacf17771b5fd56bba367c523b02c8d8c840b4cf250d243
MD5 aa4e92ea7a38cc0f31a44513ab4be23a
BLAKE2b-256 2594fa2ff2ba995339046f05c00ef7b1b29dcc427f21ed2cadcf4be8800d8e86

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.3-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.3-cp312-cp312-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.3-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 a98c7e2670f95152d9c2cf9b1a579818327128317eb6a1f60d7ccadfa043ec2d
MD5 f1f0753c1020a19f961f3579d5f865f2
BLAKE2b-256 b210bb8e4306dd3d863dee5747bd9e50fde81fbd181a1fdd8fe6391f05eb3be5

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.3-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.3-cp312-cp312-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.3-cp312-cp312-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 c679f78985df83f12f99d53c984d8e54c8f7a76dad3f771b1eb5fced502d9035
MD5 e388f3a7bb00058c8ca4f9f4d6739e9c
BLAKE2b-256 8044fe952d87096aa21e66607f5cec9f21171ab47ed32823743457bb288ddcd7

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.3-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.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d6694841b4691e95d2b15d096d4ab37b669063f93d664b93cab091c2ec1c0bc2
MD5 bb3772d6d7d771ef45402697776891b0
BLAKE2b-256 96655ad9b957d51c66392d6c600136f363f797b7df894d8ec391ade4d61ee0e5

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.3-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.3-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.3-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 fe64358298024daced08d979471b913783584e9846d1205a888f96b702ab7a2f
MD5 aee373b7c0224dd0e71b4dc8a406de7d
BLAKE2b-256 1261c2bb009a706e0e8fb3daa641e551c4ad4f200441895e763d1ebce9628269

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.3-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.3-cp312-cp312-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for pyanylist-0.0.3-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 5324af0e1cb4580c870f45c03d69fa3845934dcfa44268e9b7890453a6366066
MD5 239e47ed62dbd0acd89ccef19165113e
BLAKE2b-256 c2cfb95c812212cbead28ba2eb347e4f64cf2acce45bac3a752ff3e8517ef8a6

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyanylist-0.0.3-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