Metadata-Version: 2.4
Name: obj-db
Version: 1.0.0
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Rust
Classifier: Topic :: Database :: Database Engines/Servers
Summary: Python binding for the obj embedded document database.
Author: obj contributors
License: MIT OR Apache-2.0
Requires-Python: >=3.9
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Homepage, https://github.com/uname-n/obj
Project-URL: Repository, https://github.com/uname-n/obj

# obj — Python binding

Python bindings for [`obj`](https://github.com/uname-n/obj), the
embedded document database.

The wheel exposes a single extension module named `obj`. The Rust
crate name is `obj-py`; the import name is `obj`.

```python
import obj

with obj.Db("app.obj") as db:
    with db.transaction() as tx:
        doc_id = tx.insert("orders", b"<your payload bytes>")

    with db.read_transaction() as tx:
        payload = tx.get("orders", doc_id)
        for (id_, bytes_) in tx.iter_all("orders"):
            ...
```

## Raw-bytes contract

`obj-py` is the **raw-bytes** Python surface. Payloads cross the
boundary as `bytes` / `bytearray` in and `bytes` out. The library
does NOT serialise dicts, dataclasses, or JSON on your behalf —
encode your payloads however you like (`json`, `msgpack`,
`postcard`, `pickle`, ...) and pass the resulting bytes through.

This mirrors the obj C ABI's contract: encoding decisions are the
caller's. A typed `dataclass`-based ergonomic layer is post-v1.0.

## Local development loop

```bash
# One-time setup: a fresh venv + maturin + pytest.
python3 -m venv .venv
source .venv/bin/activate
pip install maturin pytest

# From the workspace root:
cd crates/obj-py
maturin develop          # builds the cdylib + installs it editable
                         # into the active venv.
pytest tests/ -v         # run the Python test suite.
```

`maturin develop` rebuilds the extension module on every invocation;
the typical dev loop is "edit Rust → `maturin develop` → `pytest`".

For a release-style wheel:

```bash
maturin build --release          # writes target/wheels/obj-*.whl
pip install target/wheels/obj-*.whl
```

## Exception hierarchy

All `obj` operations raise instances of `obj.ObjError`. The
sub-exceptions narrow the diagnosis:

| Exception                  | When raised                                                   |
|----------------------------|----------------------------------------------------------------|
| `obj.NotFoundError`        | document / collection / index / namespace absent              |
| `obj.BusyError`            | lock contention (pager mutex, writer lock, cross-process)     |
| `obj.CorruptionError`      | on-disk format / checksum / B-tree invariant violation        |
| `obj.IntegrityError`       | `Db.integrity_check()` found at least one failure             |
| `obj.InvalidArgumentError` | caller-side argument problem (encoding, range, type)          |

`ObjError` itself is the catch-all base — subclasses `Exception`.
Use `except obj.ObjError` if you don't care which sub-arm fired;
use the narrow ones to recover.

