Skip to main content

varco-beanie

PyPI version Python License: Apache 2.0 GitHub

Beanie (Motor / MongoDB) async backend for varco.

Generates Beanie Document classes at runtime from your DomainModel subclasses — no hand-written Document models needed. Requires varco-core.


Install

pip install varco-beanie

Requirements

  • Python ≥ 3.12
  • MongoDB ≥ 4.0
  • For multi-document transactions: a MongoDB replica set or sharded cluster

Features

  • Zero-boilerplate ODMBeanieModelFactory generates Document subclasses at runtime from your DomainModel classes; no duplication
  • Full repositoryAsyncBeanieRepository implements AsyncRepository (CRUD, exists(), stream_by_query())
  • Unit of WorkBeanieUnitOfWork wraps Motor session lifecycle with optional transactions
  • One-liner bootstrapBeanieRepositoryProvider + BeanieFastrestApp wire everything including init_beanie()
  • Query integration — accepts varco-core QueryParams / QueryBuilder AST natively
  • Multitenancyvarco_beanie.tenancy: database-per-tenant isolation via per-tenant Document class clones (BeanieTenantPool/BeanieTenantBinding), the per-tenant dropDatabase GDPR-erasure primitive (BeanieDatabaseProvisioner), and the durable tenant catalog (BeanieTenantCatalog) — see technical_docs/features/multitenancy.md for the RD-7 clone-cost formula and worked example

What's in the package

Module Purpose
factory.py BeanieModelFactory — generates Document subclasses; BeanieDocRegistry — escape hatch to access the generated Document
repository.py AsyncBeanieRepository — Motor-backed CRUD + exists() + stream_by_query()
uow.py BeanieUnitOfWork — Motor session lifecycle (optional transactions)
provider.py BeanieRepositoryProvider — wires factory + repos + UoW + init_beanie()
bootstrap.py BeanieFastrestApp — one-liner app setup (takes a BeanieSettings; BeanieConfig is a deprecated alias, removed in 4.0.0)

Quick start

Bootstrap (one-liner)

from motor.motor_asyncio import AsyncIOMotorClient
from varco_beanie import BeanieFastrestApp, BeanieSettings

client = AsyncIOMotorClient("mongodb://localhost:27017")

app = BeanieFastrestApp(
    BeanieSettings(
        motor_client=client,
        db_name="myapp",
        entity_classes=(User, Post),
    )
)

await app.init()  # calls beanie.init_beanie() internally
uow_provider = app.uow_provider  # ready to inject as IUoWProvider

Manual setup

from varco_beanie import BeanieRepositoryProvider

provider = BeanieRepositoryProvider(motor_client=client, db_name="myapp")
provider.register(User, Post)
await provider.init()

async with provider.make_uow() as uow:
    user = await uow.users.save(User(name="Edo", email="edo@example.com"))
    print(user.pk)

Transactions (replica set required)

provider = BeanieRepositoryProvider(
    motor_client=client,
    db_name="myapp",
    transactional=True,  # wraps each UoW in a Motor session transaction
)

Query integration

from varco_core import QueryBuilder, QueryParams

async with provider.make_uow() as uow:
    # exists() — uses .count(), no document load
    if await uow.posts.exists(post_id):
        ...

    # stream_by_query() — Motor batches internally, bounded memory
    params = QueryParams(node=QueryBuilder().eq("published", True).build())
    async for post in uow.posts.stream_by_query(params):
        await process(post)

Access the generated Beanie Document (escape hatch)

from varco_beanie import BeanieDocRegistry

PostDoc = BeanieDocRegistry.get(Post)
# use PostDoc for Beanie-specific operations not exposed by the repository

Migrations

MongoDB is schemaless, so there is no autogenerate and no document-shape differ — that would compare varco's generated Document shape against sampled documents and produce guesses. What ships instead is hand-written, ordered migrations plus index reconciliation, behind the same varco_core.migration.AbstractMigrator contract varco_sa implements.

from varco_beanie import Migration, MigrationRegistry, BeanieMigrator


class BackfillOrderStatus(Migration):
    version = "20260812_001"  # sortable; uniqueness validated at register() time
    name = "backfill order status"

    async def up(self, db) -> None:
        await db.orders.update_many({"status": None}, {"$set": {"status": "pending"}})

    async def down(self, db) -> None:  # optional — omit and downgrade raises
        await db.orders.update_many({"status": "pending"}, {"$set": {"status": None}})


registry = MigrationRegistry()
registry.register(BackfillOrderStatus)
# or: registry.discover("myapp.migrations")

migrator = BeanieMigrator(db, registry)
await migrator.upgrade()

Applied migrations are recorded one document per migration in the varco_migrations collection (created lazily on first use), alongside a {_id: "__lock__"} document that provides multi-pod exclusion — acquired with a conditional find_one_and_update upsert, renewed by a background heartbeat, and released with owner fencing so a reclaimed holder cannot delete the new holder's lock. A recorded migration whose source no longer matches its stored checksum raises (tamper detection); opt out with verify_checksums=False. A migration with no down() raises IrreversibleMigrationError on downgrade.

⚠️ Index reconciliation is check by default — even in upgrade mode

index_mode: "off" | "check" | "create" defaults to "check" and is independent of VARCO_MIGRATE_MODE. Running mode="upgrade" does not silently start building indexes.

This is a rule, not a caveat. An index build on a large collection is minutes-to-hours of work; on a replica set it replicates and can stall secondaries; and it would happen exactly when a rolling deploy is starting N new pods. check reports drift through the existing BeanieIndexGuard and lets on_failure decide; missing indexes appear in the plan as Revision(id="index:<collection>:<label>", branch="index"). create applies missing indexes only — it never drops unexpected ones, because dropping an index someone added deliberately is destructive.

Create indexes from the CLI, as a pre-deploy job:

varco migrate index -t myapp.db:migrator --create
varco migrate new --name "backfill status" --out myapp/migrations   # scaffold a Migration

Hand-written up(db) scripts run under mode="upgrade" normally — the restriction applies only to reconciled indexes, the ones varco derives implicitly.

The Mongo lock does have the TTL-sizing problem that the Postgres advisory-lock design avoids (a crashed holder is reclaimed only after expiry), which is one more reason index builds belong in the CLI path. See technical_docs/features/schema-migrations.md.


Notes

  • CheckConstraint entries in varco-core metadata are silently ignored — MongoDB has no SQL CHECK constraints. Use Pydantic validators instead.
  • Foreign key hints are metadata only — MongoDB has no FK enforcement.
  • Composite PKs are emulated via compound unique indexes; find_by_id(pk_tuple) issues a find_one with a composite filter.

Related packages

Package Description
varco-core Domain model, service layer, query AST, JWT — required dependency
varco-sa SQLAlchemy async backend (alternative to this package)

Links

Download files

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

Source Distribution

varco_beanie-3.2.0.tar.gz (205.0 kB view details)

Uploaded Source

Built Distribution

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

varco_beanie-3.2.0-py3-none-any.whl (155.8 kB view details)

Uploaded Python 3

File details

Details for the file varco_beanie-3.2.0.tar.gz.

File metadata

  • Download URL: varco_beanie-3.2.0.tar.gz
  • Upload date:
  • Size: 205.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for varco_beanie-3.2.0.tar.gz
Algorithm Hash digest
SHA256 aa443383c85967afc9e6cf84d2a23813ca3769eee37b7fff04ffba03da568a2e
MD5 b5f6735c5879103dc2cdf7bc3922f1f0
BLAKE2b-256 7b6614606ea76420cdf0188258d9d8f4cf08e2f2be60986706a6a365b2a85673

See more details on using hashes here.

Provenance

The following attestation bundles were made for varco_beanie-3.2.0.tar.gz:

Publisher: release.yml on edoardoscarpaci/varco

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file varco_beanie-3.2.0-py3-none-any.whl.

File metadata

  • Download URL: varco_beanie-3.2.0-py3-none-any.whl
  • Upload date:
  • Size: 155.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for varco_beanie-3.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7b4155a6ef4b12d83c753c39ebd263ee7f58d32442af62b09416983398bee9c4
MD5 7d994a866bf0d857541d07683faa8ef7
BLAKE2b-256 c352052108382d82d0eaac21d10ef422465a16d2b3bee92d52eb16ac649ef66a

See more details on using hashes here.

Provenance

The following attestation bundles were made for varco_beanie-3.2.0-py3-none-any.whl:

Publisher: release.yml on edoardoscarpaci/varco

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

3.2.0 This release

2 files

3.1.0

2 files

3.0.0

2 files

1.1.1

2 files

1.1.0

2 files

1.0.6

2 files

0.1.0

2 files

0.0.3

2 files

0.0.2

2 files

0.0.1

2 files

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