Skip to main content

Steerage

Pluggable async storage backends for Python projects.

This project implements the Repository Pattern for data access, using Pydantic 2.0 models for entity composition and decomposition.

Features

  • One model, many possible storage backends: Start simple and add complexity as you need it.
  • Use a fast, ephemeral in-memory database for tests, and a slow, reliable SQL database for production.
  • One unified query interface: write most queries once, apply them to any backend.
  • Simple environment-based configuration with Convoke
  • 100% test coverage

Installation

With Pip:

pip install steerage

Example

Let's create a simple blog engine. First, we'll want a Pydantic entity model:

from uuid import UUID
from datetime import datetime
from pydantic import BaseModel, Field
from pydantic.types import AwareDatetime

class Entry(BaseModel):
    id: UUID
    path: str
    title: str
    body: str

    created_at: AwareDatetime = Field(
        default_factory=lambda: datetime.utcnow().replace(tzinfo=timezone.utc)
    )
    published_at: AwareDatetime | None = Field(default=None)

Models are all fine and good, but we need to be able to store it somewhere. Let's start simple, with an in-memory repository and a repository factory:

from steerage.repositories.memdb import AbstractInMemoryRepository


class InMemoryEntryRepository(AbstractInMemoryRepository):
    table_name: str = "entries"
    entity_class = Entry


def get_entry_repository():
    return InMemoryEntityRepository()

Now, in the async request handler, we can easily create an entry:

async def create_entry(request: Request):
    form = await EntryForm.from_request(request)
    if form.is_valid():
        repo = get_entry_repository()
        entry = Entry.model_validate(form)
        await repo.insert(entry)
        return redirect('entry-admin')

... and retrieve an entry:

async def get_entry(request: Request, id: UUID):
    repo = get_entry_repository()
    entry = await repo.get(id)
    return render('entry.html', {'entry': entry})

This is great, but whenever we restart the server, we lose all our data!

Let's go a step up and add a more durable disk-based repository:

from convoke.configs import BaseConfig
from steerage.repositories.shelvedb import ShelveInMemoryRepository


class ShelveEntryRepository(AbstractShelveRepository):
    table_name: str = "entries"
    entity_class = Entry


def get_entry_repository():
    config = BaseConfig()
    if config.TESTING:
        return InMemoryEntityRepository()
    else:
        return ShelveEntityRepository()

Now we have a durable repository for development use, and an in-memory repository for our tests.

Contribute

License

The project is licensed under the BSD 3-clause license.

Metadata

Release files for steerage 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for steerage 2.0.0
File Size Uploaded Provenance
steerage-2.0.0.tar.gz 17.8 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for steerage 2.0.0
File Interpreter ABI Platform
steerage-2.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 41.7 kB

Release files / steerage-2.0.0.tar.gz

Download URL steerage-2.0.0.tar.gz
Size 17.8 kB
Tags Source
SHA-256 checksum
How to use checksums
c1fc1061bc8ec6078280b6080ca289b86818ef51ebcd52e2183f0303db74bdca
BLAKE2b-256 checksum
How to use checksums
744c5f06056799aa0e33eb4aac8ec7d3329bedd818eee5b8523212cefb2a8777
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.7.1 CPython/3.11.8 Linux/6.2.0-1019-azure

Release files / steerage-2.0.0-py3-none-any.whl

Download URL steerage-2.0.0-py3-none-any.whl
Size 23.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3e79cc7e1628a7cdae960ec3d00e3b3df89ce715e1a37710851f003cb7b522d2
BLAKE2b-256 checksum
How to use checksums
44842642071c1b91bc1fe63ad89a6153c739a383f7a5861e033eaecb78b65106
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.7.1 CPython/3.11.8 Linux/6.2.0-1019-azure

Security for steerage 2.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page