Skip to main content

python-sanity

Python client for Sanity.io CMS HTTP API. Sanity is a hosted CMS solution for content management. This project is not affiliated with Sanity.io and is a third-party package.

ℹ️ Note: This package is an active fork of the original project at OmniPro-Group/sanity-python.

Install

Available on pypi as package python-sanity

Install with uv:

uv add python-sanity

Install with pip:

pip install python-sanity

Environment Variables

You can pass parameters to the client constructor directly, but it is recommended to use environment variables.

Variable Description Required Default Value
SANITY_PROJECT_ID The project ID Yes
SANITY_DATASET The dataset to use No production
SANITY_API_TOKEN The API token No (required for mutations)
SANITY_LOG_LEVEL Level of logging No INFO

What's New in v0.2.0

  • AsyncClient: Full async/await support for all operations
  • Optional Logger: Logger parameter is now optional, uses built-in logger with SANITY_LOG_LEVEL support
  • httpx: Migrated from requests to httpx for better async support and HTTP/2
  • Automatic Retries: Configurable retry logic with exponential backoff
  • Better Error Handling: Specific exception types (SanityAuthError, SanityRateLimitError, etc.)
  • New API Parameters:
    • Query: perspective, result_source_map, tag, return_query
    • Mutation: auto_generate_array_keys, skip_cross_dataset_references_validation, transaction_id
  • Context Managers: Both Client and AsyncClient support context managers
  • Updated API Version: Default API version updated to 2025-02-19

Quick Start

Synchronous Client

from sanity import Client

# Simple initialization (logger is now optional!)
client = Client()  # Uses environment variables

# Or with explicit parameters
client = Client(
    project_id="your-project-id",
    dataset="production",
    token="your-api-token",  # Optional for read-only queries
    use_cdn=True
)

# Query with GROQ
result = client.query(
    groq="*[_type == 'post'] | order(publishedAt desc)[0...10]",
    variables={"limit": 10}
)

# Mutations
transactions = [{
    "createOrReplace": {
        "_id": "post.123",
        "_type": "post",
        "title": "Hello World",
        "publishedAt": "2025-01-15T00:00:00Z"
    }
}]

result = client.mutate(
    transactions=transactions,
    return_documents=True
)

# Upload assets
result = client.assets(
    file_path="https://example.com/image.png"
)

Async Client

from sanity import AsyncClient
import asyncio

async def main():
    # Use async context manager
    async with AsyncClient() as client:
        # Async query
        result = await client.query(
            groq="*[_type == 'post']",
            perspective="published"
        )

        # Async mutation
        result = await client.mutate(
            transactions=[{
                "create": {
                    "_type": "post",
                    "title": "Async Post"
                }
            }]
        )

        # Async asset upload
        result = await client.assets(
            file_path="/path/to/image.png"
        )

asyncio.run(main())

Advanced Configuration

from sanity import Client, TimeoutConfig, RetryConfig

# Custom timeouts and retries
client = Client(
    timeout=TimeoutConfig(
        connect=5.0,
        read=30.0,
        write=30.0,
        pool=5.0
    ),
    retry_config=RetryConfig(
        max_retries=5,
        backoff_factor=1.0
    ),
    http2=True
)

Error Handling

from sanity import (
    Client,
    SanityAuthError,
    SanityRateLimitError,
    SanityValidationError
)

client = Client()

try:
    result = client.query(groq="*[_type == 'post']")
except SanityAuthError as e:
    print(f"Authentication failed: {e.message}")
except SanityRateLimitError as e:
    print(f"Rate limited, retry after {e.retry_after}s")
except SanityValidationError as e:
    print(f"Validation error: {e.response_body}")

Migration Guide from v0.1.x

Breaking Changes

None! v0.2.0 is fully backward compatible.

Optional Improvements

  1. Logger is now optional:

    # Old way (still works)
    import logging
    client = Client(logger=logging.getLogger(__name__))
    
    # New way (simpler)
    client = Client()  # Uses built-in logger with SANITY_LOG_LEVEL
    
  2. Use context managers for cleanup:

    # Recommended
    with Client() as client:
        result = client.query(groq="*[_type == 'post']")
    
  3. Try async for better performance:

    from sanity import AsyncClient
    
    async with AsyncClient() as client:
        result = await client.query(groq="*[_type == 'post']")
    
  4. Use new parameters:

    # Query with perspective
    result = client.query(
        groq="*[_type == 'post']",
        perspective="published",  # drafts, published, raw
        tag="my-app"
    )
    
    # Mutations with new options
    result = client.mutate(
        transactions=[...],
        auto_generate_array_keys=True,
        transaction_id="my-custom-id"
    )
    

Download files

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

Source Distribution

python_sanity-0.2.0.post1.tar.gz (20.9 kB view details)

Uploaded Source

Built Distribution

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

python_sanity-0.2.0.post1-py3-none-any.whl (25.2 kB view details)

Uploaded Python 3

File details

Details for the file python_sanity-0.2.0.post1.tar.gz.

File metadata

  • Download URL: python_sanity-0.2.0.post1.tar.gz
  • Upload date:
  • Size: 20.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.2

File hashes

Hashes for python_sanity-0.2.0.post1.tar.gz
Algorithm Hash digest
SHA256 3a24614b74a6eb24ea42a42bfafdb9e7ac9d37d0685d5a3b13cdaa8ac312e7d4
MD5 1e943eaadea5f10f6baf1990b47fada5
BLAKE2b-256 8eeed6c0c2ee9c7a0013ca423a9e89d43400a3c70eb42dd49046e47f2801c164

See more details on using hashes here.

File details

Details for the file python_sanity-0.2.0.post1-py3-none-any.whl.

File metadata

File hashes

Hashes for python_sanity-0.2.0.post1-py3-none-any.whl
Algorithm Hash digest
SHA256 c8a09b49fac1d12c2de49db7845b5f0ae7679cecf159153f429de89716b41e24
MD5 8a1a57da3326d8767d5d199aaedf695c
BLAKE2b-256 905a94d9b85b5f0ac247ad2881659f789887bd9ab42e23940be75cf872adc11e

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.2.0.post1 This release

2 files

0.2.0

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

Supported by

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