commit b79f965d07d5bf919801e837486e543d1c6d8b40 Author: disqualifier Date: Mon Jun 22 21:26:40 2026 -0400 mongodb wrapper in py Signed-off-by: disqualifier diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ae590bc --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +# claude +CLAUDE.md + +# python +__pycache__/ +*.py[cod] +*.egg-info/ +build/ +dist/ +.eggs/ + +# env +.venv/ +venv/ +.env diff --git a/README.md b/README.md new file mode 100644 index 0000000..f62dab0 --- /dev/null +++ b/README.md @@ -0,0 +1,67 @@ +# mongo + +Async MongoDB wrapper over [motor](https://motor.readthedocs.io/). Thin, opinionated +helpers for the common paths, with a raw escape hatch for everything else. + +## Install + +```bash +# requirements.txt +mongo @ git+ssh://git@github.com//mongo.git@v0.1.0 +``` + +Requires `motor` and `pymongo` (pulled transitively). + +## Usage + +**Object (preferred)** — one client per process: + +```python +from mongo import Mongo + +db = Mongo(conn_string, database) # attach as bot.db / app.db +users = await db.get_documents("users", {"active": True}) +await db.close() # on shutdown +``` + +**Module proxy (back-compat)** — arm once, then call bare: + +```python +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. + +## Error contract + +- **Wrapped methods** log-and-swallow exceptions and return a safe default + (`False` / `[]` / `{}` / `0` / `None`). Branch on the result. +- **`db.collection(name)`** (or `db[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 func` won't see the proxy (resolved at import, before `init`). + Use `import mongo` then `mongo.func(...)`. +- `find_one_and_update` returns the **after** image by default (`return_after=True`). +- `bulk_write` takes pymongo ops the caller builds: + ```python + from pymongo import UpdateOne + ops = [UpdateOne({"_id": i}, {"$set": {...}}, upsert=True) for i in ids] + await db.bulk_write("col", ops) + ``` + +## Versioning + +Tagged `vX.Y.Z`. Pin the tag in `requirements.txt`; bump deliberately. \ No newline at end of file