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/

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.1.tar.gz (49.5 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.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.5 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

pyanylist-0.0.1-cp313-cp313-macosx_11_0_arm64.whl (2.9 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

pyanylist-0.0.1-cp313-cp313-macosx_10_12_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.13macOS 10.12+ x86-64

pyanylist-0.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.5 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

pyanylist-0.0.1-cp312-cp312-macosx_11_0_arm64.whl (2.9 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

pyanylist-0.0.1-cp312-cp312-macosx_10_12_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.12macOS 10.12+ x86-64

File details

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

File metadata

  • Download URL: pyanylist-0.0.1.tar.gz
  • Upload date:
  • Size: 49.5 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.1.tar.gz
Algorithm Hash digest
SHA256 9de02930a5315da37cfbfce1661227e5ce9c4cce9d3281ef6add3def79114be4
MD5 9d22a43c91ac1a745898fce0f6743595
BLAKE2b-256 67524e79ea5b6b497416448d02a70fcb5913c81f1bfb34db54ff671a7c505529

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pyanylist-0.0.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 436edf8c6cbcc8bf81b1dc1916bcf632ff9bb551edff9074db3766039889d241
MD5 d081a2461090ae8c8044a3bf693b131e
BLAKE2b-256 a6d488afb8ede45fe8b721ffd0077cb287e1132d8ab831d64452a3e4b7ebf7e1

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pyanylist-0.0.1-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6a6b89d60a5145211fd2bed37244634f0ee3af7b967344da9c12b110c963dc2c
MD5 794d4eb7da3a25e543b2a91b384f2f61
BLAKE2b-256 225020b90e93405ac093418495dbd08011ac05156a0e5ceb8062eca8de245e35

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pyanylist-0.0.1-cp313-cp313-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 120f75a43d5bec8fb69f422a834ddb593677b19fbdbd6cc3bbeb4fd41750d85d
MD5 fbe1f6ea3f44d7244e3fcbb81e09aac0
BLAKE2b-256 6790198f65d4f64ccffcb0259d2ceb3b9af8496ed19b8977e7bcb8f25c99bf21

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pyanylist-0.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 756a392010a504b3b89ea6f825088568a41b9fe506b2eb6f389a4ebe1462dc3b
MD5 9b029ce3805bd40ccaacd1d865c52ba9
BLAKE2b-256 29840c33b913f8684570009b50c3f1bbede48035ddc1772f500959468419fa0f

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pyanylist-0.0.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3459a3b624b56d7fb65a8f0cf0c2d3d367aa48de83a45c463ebb605a99173230
MD5 897eb20695ba49c84ff043f475898ae4
BLAKE2b-256 7ffc97e95d70d839ad7606897114c063bbacd8eca484190fe537fb0e3c73eff0

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pyanylist-0.0.1-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 24f9fb5a4f00fbeb0bee0f3fd3f5ec6568f4e6290f840f765915f0484821a9b8
MD5 a299952895c14c97039055457bb45948
BLAKE2b-256 a094a0806c3351393260c6642508280b1b3c0edac8d428d2d232749b3f6517ed

See more details on using hashes here.

Provenance

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