Skip to main content

PocketBase Python SDK - A unofficial Python client library for PocketBase backend

Project description

PocketBase Python SDK

A unofficial Python client library for PocketBase, the open-source backend as a service.

Features

  • ๐Ÿš€ Async/Await Support - Built on asyncio for high-performance asynchronous operations
  • ๐Ÿ” Authentication - Complete auth support including OAuth2, OTP, and password reset
  • ๐Ÿ“ก Realtime - WebSocket connections for real-time subscriptions
  • ๐Ÿ—„๏ธ CRUD Operations - Full Create, Read, Update, Delete operations
  • ๐Ÿ“Š Batch Operations - Transactional batch requests
  • ๐Ÿฅ Health Checks - Monitor server health and status
  • ๐Ÿ“ Logging - Access and manage server logs
  • ๐Ÿช Token Storage - Multiple auth store implementations (memory, local file, async)
  • ๐Ÿ“ Type Hints - Full TypeScript-style type annotations
  • ๐Ÿงช Test Coverage - Comprehensive test suite

Installation

pip install pocketbase_sdk

Quick Start

import asyncio
from pocketbase_sdk import Client, LocalAuthStore

async def main():
    # Initialize client
    client = Client("http://127.0.0.1:8090")
    
    try:
        # Check server health
        health = await client.health.check()
        print(f"Server status: {health}")
        
        # Authenticate with email/password
        auth_data = await client.collection("users").auth_with_password(
            "user@example.com", 
            "password123"
        )
        print(f"Authenticated as: {auth_data.record.email}")
        
        # Create a record
        record = await client.collection("posts").create({
            "title": "Hello PocketBase",
            "content": "My first post"
        })
        print(f"Created record: {record.id}")
        
        # Subscribe to real-time updates
        def on_update(data):
            print(f"Real-time update: {data.action} - {data.record.id}")
        
        await client.collection("posts").subscribe("*", on_update)
        
        # Keep running to receive updates
        await asyncio.sleep(10)
        
    except Exception as e:
        print(f"Error: {e}")

if __name__ == "__main__":
    asyncio.run(main())

API Overview

Client

The main Client class provides access to all services:

from pocketbase_sdk import Client

client = Client("http://127.0.0.1:8090")

Authentication

# Email/password authentication
auth_data = await client.collection("users").auth_with_password(
    "user@example.com", 
    "password"
)

# OAuth2 authentication
auth_data = await client.collection("users").auth_with_oauth2_code(
    "google",
    "authorization_code",
    "code_verifier",
    "http://localhost/callback"
)

# Refresh token
auth_data = await client.collection("users").auth_refresh()

# Password reset
await client.collection("users").request_password_reset("user@example.com")
await client.collection("users").confirm_password_reset(
    "reset_token", 
    "new_password", 
    "new_password"
)

CRUD Operations

# Create
record = await client.collection("posts").create({
    "title": "New Post",
    "content": "Post content"
})

# Read
record = await client.collection("posts").get_one(record.id)

# List
list_result = await client.collection("posts").get_list(
    page=1, 
    per_page=30,
    filter="created > '2023-01-01'"
)

# Full list
all_posts = await client.collection("posts").get_full_list(
    batch=200
)

# Update
updated = await client.collection("posts").update(record.id, {
    "title": "Updated Title"
})

# Delete
await client.collection("posts").delete(record.id)

Real-time Subscriptions

async def on_record_change(data):
    if data.action == "create":
        print(f"New record: {data.record}")
    elif data.action == "update":
        print(f"Updated record: {data.record}")
    elif data.action == "delete":
        print(f"Deleted record: {data.record}")

# Subscribe to all changes in a collection
unsubscribe = await client.collection("posts").subscribe("*", on_record_change)

# Subscribe to specific record changes
await client.collection("posts").subscribe(record.id, on_record_change)

# Unsubscribe
await unsubscribe()  # or await client.collection("posts").unsubscribe()

Batch Operations

batch = client.create_batch()

# Add multiple operations
batch.collection("posts").create({"title": "Post 1"})
batch.collection("posts").update("post-id", {"title": "Updated Post"})
batch.collection("users").delete("user-id")

# Execute all operations in a single request
results = await batch.send()

Health Checks

# Basic health check
health = await client.health.check()

# Wait for server to be healthy
is_healthy = await client.health.wait_until_healthy(timeout=30)

# Get database stats
db_stats = await client.health.get_database_stats()

# Get cache stats
cache_stats = await client.health.get_cache_stats()

Logging

# Get recent logs
logs = await client.logs.get_list(page=1, per_page=50)

# Get error logs only
error_logs = await client.logs.get_error_logs()

# Get logs statistics
stats = await client.logs.get_stats()

# Delete old logs
await client.logs.delete_logs_older_than(days=30)

Filter Expressions

# Build filters with parameters
filter_expr = client.filter(
    "title ~ {:title} && created >= {:date}",
    {"title": "example", "date": "2023-01-01"}
)

# Use in queries
posts = await client.collection("posts").get_list(filter=filter_expr)

Advanced Usage

Custom Auth Store

from pocketbase_sdk import Client, BaseAuthStore

class CustomAuthStore(BaseAuthStore):
    def __init__(self):
        super().__init__()
        # Custom initialization
    
    def save(self, token, record=None):
        # Custom save logic
        super().save(token, record)
    
    def clear(self):
        # Custom clear logic
        super().clear()

client = Client("http://127.0.0.1:8090", auth_store=CustomAuthStore())

Request Hooks

async def before_send(url, options):
    print(f"Making request to: {url}")
    # Modify request if needed
    return {"url": url, "options": options}

async def after_send(response, data, options):
    print(f"Response status: {response.status}")
    # Modify response if needed
    return data

client.before_send = before_send
client.after_send = after_send

File Uploads

from aiohttp import FormData

# Upload file with form data
form = FormData()
form.add_field('file', open('image.jpg', 'rb'), filename='image.jpg')
form.add_field('title', 'My Image')

record = await client.collection("images").create(form)

Error Handling

from pocketbase_sdk import Client, ClientResponseError

try:
    await client.collection("users").auth_with_password("invalid", "credentials")
except ClientResponseError as e:
    print(f"Authentication failed: {e.message}")
    print(f"Status: {e.status}")
    print(f"URL: {e.url}")

Configuration Options

Client Options

client = Client(
    base_url="http://127.0.0.1:8090",
    auth_store=LocalAuthStore(),  # Default
    lang="en-US"  # Default
)

Request Options

All API methods accept optional request options:

from pocketbase_sdk import RecordOptions

await client.collection("posts").get_one(
    "record-id",
    RecordOptions(
        fields="id,title,created",
        expand="author,comments"
    )
)

Development

Setup Development Environment

# Clone repository
git clone https://github.com/pocketbase/pocketbase-python-sdk
cd pocketbase-python-sdk

# Install development dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run tests with coverage
pytest --cov=pocketbase

# Format code
black src tests

# Type checking
mypy src

Architecture Notes

The SDK uses lazy initialization to avoid circular dependencies between Client and Services. Services are created only when first accessed through properties:

client = Client("http://127.0.0.1:8090")

# Services are created on-demand
collections = client.collections  # CollectionService created here
health = client.health      # HealthService created here
logs = client.logs          # LogService created here
realtime = client.realtime  # RealtimeService created here

This approach:

  • โœ… Eliminates circular dependency during initialization
  • โœ… Improves memory usage (only used services are created)
  • โœ… Maintains API compatibility
  • โœ… Thread-safe for concurrent access

For details, see CIRCULAR_DEPENDENCY_FIX.md.

Project Structure

pocketbase-python-sdk/
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ pocketbase_sdk/
โ”‚   โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ”‚   โ”œโ”€โ”€ client.py           # Main client class
โ”‚   โ”‚   โ”œโ”€โ”€ exceptions.py       # Error handling
โ”‚   โ”‚   โ”œโ”€โ”€ services/          # API services
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ base_service.py
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ collection_service.py
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ crud_service.py
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ health_service.py
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ log_service.py
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ record_service.py
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ realtime_service.py
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ batch_service.py
โ”‚   โ”‚   โ”œโ”€โ”€ stores/            # Auth stores
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ base_auth_store.py
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ local_auth_store.py
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ async_auth_store.py
โ”‚   โ”‚   โ””โ”€โ”€ utils/             # Utilities
โ”‚   โ”‚       โ”œโ”€โ”€ __init__.py
โ”‚   โ”‚       โ”œโ”€โ”€ dtos.py
โ”‚   โ”‚       โ”œโ”€โ”€ options.py
โ”‚   โ”‚       โ”œโ”€โ”€ jwt.py
โ”‚   โ”‚       โ””โ”€โ”€ cookie.py
โ”œโ”€โ”€ tests/                    # Test suite
โ”œโ”€โ”€ README.md
โ””โ”€โ”€ pyproject.toml

Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature-name
  3. Make your changes and add tests
  4. Run the test suite: pytest
  5. Submit a pull request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Related Projects

Support

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

pocketbase_sdk-0.1.1.tar.gz (46.0 kB view details)

Uploaded Source

Built Distribution

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

pocketbase_sdk-0.1.1-py3-none-any.whl (41.3 kB view details)

Uploaded Python 3

File details

Details for the file pocketbase_sdk-0.1.1.tar.gz.

File metadata

  • Download URL: pocketbase_sdk-0.1.1.tar.gz
  • Upload date:
  • Size: 46.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for pocketbase_sdk-0.1.1.tar.gz
Algorithm Hash digest
SHA256 cd8c0644386c821416bd4b349a2e3d13721bdf0cccd2584ffd17b91026596daf
MD5 5f235e91ef6ba4fb79f89a0e52bbf94c
BLAKE2b-256 17bb6b68dca9616861cd7639fe140464b7d03642b82576b0ad212b463914a3de

See more details on using hashes here.

File details

Details for the file pocketbase_sdk-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: pocketbase_sdk-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 41.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for pocketbase_sdk-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 7a1c70f863a41011d248fa37d80f828908ce84d96a318b1d5331dcfcd4c3feda
MD5 00d3595c93983f64edbadfb92d91724c
BLAKE2b-256 ba13d0ec2db590d9d56cba36d9b05319d625b7edd12afc658eefb8d5aa7bb805

See more details on using hashes here.

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