additive only — every existing name preserved, swallow contract unchanged. brings mongo in line with the redis/psql/mysql datastore trio's naming/lifecycle. bump v0.1.3 -> v0.1.4 Signed-off-by: disqualifier <dev@disqualifier.me>
3.6 KiB
mongo
Async MongoDB wrapper over motor. Thin, opinionated helpers for the common paths, with a raw escape hatch for everything else.
Install
requirements.txt:
mongo @ git+ssh://git@git.rethinkstudios.io/rethink-public/mongo.git@v0.1.4
Direct:
pip install "mongo @ git+ssh://git@git.rethinkstudios.io/rethink-public/mongo.git@v0.1.4"
Requires motor and pymongo (pulled transitively).
Drop the @v0.1.4 suffix from the line above to install the latest unpinned.
Usage
Object (preferred) — one client per process:
from mongo import MongoDB
db = MongoDB(conn_string, database) # attach as bot.db / app.db
await db.connect() # optional: ping to fail-early on a bad URI
users = await db.get_documents("users", {"active": True})
db.close() # on shutdown (sync)
# or with guaranteed cleanup:
async with MongoDB(conn_string, database) as db:
await db.get_documents("users", {"active": True})
The class is MongoDB; Mongo remains a back-compat alias (Mongo = MongoDB), so
existing Mongo(...) call sites keep working unchanged.
Module proxy (back-compat) — arm once, then call bare:
import mongo # NOT `from mongo import ...`
mongo.init(conn_string, database)
users = await mongo.get_documents("users", {"active": True})
Both styles share one client. The proxy exists so legacy call sites keep working
after a one-line init(); new code should use the object.
Naming consistency with the datastore trio
mongo predates the redis/psql/mysql trio; this version makes it surface-consistent
without breaking anything (all additive, every old name preserved):
- class is
MongoDB(withMongokept as an alias) connect()+async withlike the trio (motor connects lazily, soconnect()just pings to validate early)exists()aliasescheck_document_exists();delete()aliasesdelete_document()— old names still work, the trio-consistent names are now available
The one deliberate difference that remains: mongo swallows (see below) where the trio is fail-loud. That's intentional — flipping it would break existing consumers' branch- on-result control flow.
Error contract
- Wrapped methods log-and-swallow exceptions and return a safe default
(
False/[]/{}/0/None). Branch on the result. (connect()is the exception — it raises on a bad connection so you can fail-early.) db.collection(name)(ordb[name]) returns the raw motor collection: full driver surface, no swallowing, raises. Use it for anything not wrapped (find_one_and_*beyond what's exposed, change streams, complex bulk ops).
API
See the module docstring and method docstrings in mongo.py — that's the source
of truth. Grouped as: collection/index management, create, read, update, delete,
bulk, checks. Atomic ops (find_one_and_update/replace/delete) and bulk_write
are included.
Gotchas
from mongo import funcwon't see the proxy (resolved at import, beforeinit). Useimport mongothenmongo.func(...).find_one_and_updatereturns the after image by default (return_after=True).bulk_writetakes pymongo ops the caller builds:from pymongo import UpdateOne ops = [UpdateOne({"_id": i}, {"$set": {...}}, upsert=True) for i in ids] await db.bulk_write("col", ops)
Versioning
Releases are tagged vX.Y.Z. The install line above pins a release; drop the @vX.Y.Z suffix to install the latest unpinned. Pin deliberately for reproducible installs.