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.2.tar.gz (50.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.2-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.2-cp313-cp313-musllinux_1_2_aarch64.whl (4.4 MB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ ARM64

pyanylist-0.0.2-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.2-cp313-cp313-macosx_11_0_arm64.whl (3.8 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

pyanylist-0.0.2-cp313-cp313-macosx_10_12_x86_64.whl (3.9 MB view details)

Uploaded CPython 3.13macOS 10.12+ x86-64

pyanylist-0.0.2-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.2-cp312-cp312-musllinux_1_2_aarch64.whl (4.4 MB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ ARM64

pyanylist-0.0.2-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.2-cp312-cp312-macosx_11_0_arm64.whl (3.8 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

pyanylist-0.0.2-cp312-cp312-macosx_10_12_x86_64.whl (3.9 MB view details)

Uploaded CPython 3.12macOS 10.12+ x86-64

File details

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

File metadata

  • Download URL: pyanylist-0.0.2.tar.gz
  • Upload date:
  • Size: 50.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.2.tar.gz
Algorithm Hash digest
SHA256 b9000180eaabd2389a9310ca9238bfe0745e1ba3417e7a7c0d5a6c4b0e317349
MD5 d67eece5cd5bec257ca68742ce50283a
BLAKE2b-256 2b1a62b88a6393f1c0bd46529ec33b768d152925b04f3fd9e5c7de1f74a96e94

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pyanylist-0.0.2-cp313-cp313-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 c1c233cc0a816df5de04b9ac9bf4615578176ffc89947d3dfb7d8396163b66fb
MD5 c9e69a88a1551eeab0769f045092c1dc
BLAKE2b-256 dab9a54081c215d62bdfdf489ee2ba4dac4ed3653e6317fb35a6a06140968eb5

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pyanylist-0.0.2-cp313-cp313-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 1239d4bbadaa6c90f06a5bbb6ce1af06af23926163c83c2a7b34cf8a62ee362a
MD5 d8a3162a7fe6ef49aae2a7ab0083125c
BLAKE2b-256 75e61c0dfc7732b25b263c37283bcb2e9dffa86c90a48254e24ee210b0eba95b

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pyanylist-0.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 935315ffc030391d3d24fcef90fa2d0e4981141294e64fc07e49283cc138506e
MD5 e4f22a6dc4c47443fce43e3e9e8316c5
BLAKE2b-256 9d40bb42e4cf2c8a4fcef4e2cf4a98a7f942928f60244cd5b5dd5b12bbac89e7

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pyanylist-0.0.2-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 29896c28f3e5a5455b2b18d7c44ae98d7b93499fa7a6ce0d9096b4b9a3bab164
MD5 a11bf870895e5adb006a3b4a76e9188d
BLAKE2b-256 07dc4615d7fcb852f67e5daa983a537977a0e7a1cd9db52fe4721e8fb23259d5

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pyanylist-0.0.2-cp313-cp313-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 fca84e503e81c26e91dce7a73e3036a2756fab4aa4f756352dcd527417376de4
MD5 9562b44f4ba86e4a6a10d11d05055e01
BLAKE2b-256 d833228a27027316fa44f39dd7d3ca48be4b901d210003eba8eb3e2e36d55798

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pyanylist-0.0.2-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 d3a58e6a754eaccfdccb80be118c179838d894162cccf0a53fe3118c6147729c
MD5 b5444afa4177792df499703c32d865ef
BLAKE2b-256 f0c4775570671a8592605eae4a5e69552f5b26310ed8685af161baacb0771af9

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pyanylist-0.0.2-cp312-cp312-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 fcaa045b4159e6ee0f7c0aea288bbe176a1de45ffe27ba445f924ce1ff6c5acd
MD5 7abbf6fbdee76ba26e061af76be7ef55
BLAKE2b-256 ae7d57e18def9b9eeaa231d39f6a4c3170860ef4d75135eddc0ddc06ccb72586

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pyanylist-0.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e592f5a50db03be633b58604837a02e36f239382ca2c7d52a33cd76a9ea6a182
MD5 cd0072848f695481b84ceeb48a60e387
BLAKE2b-256 7711a52d6ff1d464a408a63e92f582cec243fc640306217a46545c17cf26d1cc

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pyanylist-0.0.2-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 aadeff4a76e52715697fa417ce2d422c449387939d9eab163698018073a88f38
MD5 b309335876623cd7b9d318dca61d9e51
BLAKE2b-256 cfb46a9bb32cb6d1d9c5ae1adf70aa7d1f50b6b8355b70337a54bec015918ef6

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pyanylist-0.0.2-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 2dde9bb29e63f0ae27cfa5a9c8145f36ae4ad67695a1ddea65e5929705abdc54
MD5 2fc77e2092b3f63929610bce71485d45
BLAKE2b-256 aa2ea904391fd66ffe1c088ebb9a6e8b5690be7caa43d24b68de5868f201f4c7

See more details on using hashes here.

Provenance

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