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

Quick Start

import asyncio
from pocketbase 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 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 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 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 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/
โ”‚   โ”‚   โ”œโ”€โ”€ __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.0.tar.gz (21.6 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.0-py3-none-any.whl (11.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: pocketbase_sdk-0.1.0.tar.gz
  • Upload date:
  • Size: 21.6 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.0.tar.gz
Algorithm Hash digest
SHA256 f6c1f37bc5af8d6c01fca4d50b30467db648eaabb4fe888b8ddbbba121a4be9c
MD5 ddcc4de06d2916bbf96f259c51ae855a
BLAKE2b-256 6430f58320cac71325f63bc5d6816f2d09f0668432dcb26ada2e968d92ff60b1

See more details on using hashes here.

File details

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

File metadata

  • Download URL: pocketbase_sdk-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.7 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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 68ab4cf0338fbb001ce9979e7c86cb64e2e5eb9da0a849dff833b400a2eda9c6
MD5 18e1a33e5b168eaac6285d3dfb61cdad
BLAKE2b-256 11c47da7596aa995403cf38e98220c81d59af4988dc1bbcba5ee45fd778ab0e0

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