varco-beanie
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 ODM —
BeanieModelFactorygeneratesDocumentsubclasses at runtime from yourDomainModelclasses; no duplication - Full repository —
AsyncBeanieRepositoryimplementsAsyncRepository(CRUD,exists(),stream_by_query()) - Unit of Work —
BeanieUnitOfWorkwraps Motor session lifecycle with optional transactions - One-liner bootstrap —
BeanieRepositoryProvider+BeanieFastrestAppwire everything includinginit_beanie() - Query integration — accepts
varco-coreQueryParams/QueryBuilderAST natively - Multitenancy —
varco_beanie.tenancy: database-per-tenant isolation via per-tenant Document class clones (BeanieTenantPool/BeanieTenantBinding), the per-tenantdropDatabaseGDPR-erasure primitive (BeanieDatabaseProvisioner), and the durable tenant catalog (BeanieTenantCatalog) — seetechnical_docs/features/multitenancy.mdfor 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
CheckConstraintentries invarco-coremetadata 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 afind_onewith 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
- Repository: https://github.com/edoardoscarpaci/varco
- Full docs: https://github.com/edoardoscarpaci/varco#beanie-backend
- Issue tracker: https://github.com/edoardoscarpaci/varco/issues
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aa443383c85967afc9e6cf84d2a23813ca3769eee37b7fff04ffba03da568a2e
|
|
| MD5 |
b5f6735c5879103dc2cdf7bc3922f1f0
|
|
| BLAKE2b-256 |
7b6614606ea76420cdf0188258d9d8f4cf08e2f2be60986706a6a365b2a85673
|
Provenance
The following attestation bundles were made for varco_beanie-3.2.0.tar.gz:
Publisher:
release.yml on edoardoscarpaci/varco
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
varco_beanie-3.2.0.tar.gz -
Subject digest:
aa443383c85967afc9e6cf84d2a23813ca3769eee37b7fff04ffba03da568a2e - Sigstore transparency entry: 2808894749
- Sigstore integration time:
-
Permalink:
edoardoscarpaci/varco@6093e05ade8aff23196c37c1a4a0685f939fb2a3 -
Branch / Tag:
refs/tags/v3.2.0 - Owner: https://github.com/edoardoscarpaci
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6093e05ade8aff23196c37c1a4a0685f939fb2a3 -
Trigger Event:
push
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7b4155a6ef4b12d83c753c39ebd263ee7f58d32442af62b09416983398bee9c4
|
|
| MD5 |
7d994a866bf0d857541d07683faa8ef7
|
|
| BLAKE2b-256 |
c352052108382d82d0eaac21d10ef422465a16d2b3bee92d52eb16ac649ef66a
|
Provenance
The following attestation bundles were made for varco_beanie-3.2.0-py3-none-any.whl:
Publisher:
release.yml on edoardoscarpaci/varco
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
varco_beanie-3.2.0-py3-none-any.whl -
Subject digest:
7b4155a6ef4b12d83c753c39ebd263ee7f58d32442af62b09416983398bee9c4 - Sigstore transparency entry: 2808894787
- Sigstore integration time:
-
Permalink:
edoardoscarpaci/varco@6093e05ade8aff23196c37c1a4a0685f939fb2a3 -
Branch / Tag:
refs/tags/v3.2.0 - Owner: https://github.com/edoardoscarpaci
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6093e05ade8aff23196c37c1a4a0685f939fb2a3 -
Trigger Event:
push
-
Statement type: