Python runtime
The Python runtime lives under py/ and is published as the wheel tabletheory_py-X.Y.Z-py3-none-any.whl. The importable module inside that wheel is theorydb_py — the wheel asset name and the importable package name differ. It targets Python 3.14 and the AWS SDK for Python (boto3).
The Python runtime is a peer implementation of the TableTheory contract — not a port. It passes the same P0 contract scenarios as Go and TypeScript independently.
Install
This repo does not publish to PyPI. GitHub Releases are the source of truth. Install the release wheel directly:
# Stable release (replace X.Y.Z)
pip install \
https://github.com/theory-cloud/tabletheory/releases/download/vX.Y.Z/tabletheory_py-X.Y.Z-py3-none-any.whl
# Prerelease (replace X.Y.Z-rc.N — PEP 440 form: vX.Y.Z-rc.N tag → X.Y.ZrcN wheel)
pip install \
https://github.com/theory-cloud/tabletheory/releases/download/vX.Y.Z-rc.N/tabletheory_py-X.Y.ZrcN-py3-none-any.whl
The release wheel asset is tabletheory_py-X.Y.Z-py3-none-any.whl; the importable module inside that wheel is theorydb_py. Use from theorydb_py import … in your application code.
ModelDefinition + Table
The Python public surface declares models as plain dataclasses with theorydb_field() defaults, then registers them via ModelDefinition.from_dataclass(). CRUD runs through a Table instance.
from dataclasses import dataclass
import boto3
from theorydb_py import ModelDefinition, Table, theorydb_field
@dataclass(frozen=True)
class Note:
pk: str = theorydb_field(roles=["pk"])
sk: str = theorydb_field(roles=["sk"])
body: str = theorydb_field()
client = boto3.client("dynamodb", region_name="us-east-1")
model = ModelDefinition.from_dataclass(Note, table_name="notes_contract")
table = Table(model, client=client)
table.put(Note(pk="USER#42", sk="NOTE#welcome", body="Hello, Theory Cloud."))
note = table.get("USER#42", "NOTE#welcome")
table.delete("USER#42", "NOTE#welcome")
For a complete working program, see py/docs/getting-started.md.
Role vocabulary
theorydb_field(roles=[…], encrypted=…, omitempty=…) maps one-to-one onto the canonical TableTheory contract:
| Go tag | Python field arg |
|---|---|
theorydb:"pk" |
theorydb_field(roles=["pk"]) |
theorydb:"sk" |
theorydb_field(roles=["sk"]) |
theorydb:"gsi1pk" |
theorydb_field(roles=["gsi1pk"]) |
theorydb:"encrypted" |
theorydb_field(encrypted=True) |
theorydb:"version" |
theorydb_field(roles=["version"]) |
theorydb:"created_at" |
theorydb_field(roles=["created_at"]) |
theorydb:"updated_at" |
theorydb_field(roles=["updated_at"]) |
theorydb:"ttl" |
theorydb_field(roles=["ttl"]) |
theorydb:"omitempty" |
theorydb_field(omitempty=True) |
CRUD methods
Table exposes the canonical CRUD surface:
table.put(note)
note = table.get(pk, sk) # raises NotFoundError on miss
table.update(pk, sk, {"body": "updated"}) # third arg is a Mapping[str, Any]
table.update(pk, sk, {"body": "guarded"}, expected_version=note.version) # versioned write
table.delete(pk, sk)
# Composite updates use update_builder for set/remove/add chains.
table.update_builder(pk, sk).set("body", "updated").execute()
Workflows
uv --directory py run ruff format --check .— format verificationuv --directory py run ruff check .— lint using thepy/pyproject.tomlline length of 110uv --directory py run mypy src— typecheckuv --directory py run pytest -q tests/unit— unit pytest suiteuv --directory py run pytest -q tests/integration— integration tests with DynamoDB Local- Exercised against shared contract scenarios via
contract-tests/runners/on every commit
Where to go next
- Getting Started — full walkthrough
py/docs/getting-started.md— Python-specific runtime documentationpy/docs/api-reference.md— full Python API reference- Features → CRUD & Marshaling, Optimistic Locking, Encryption
Stability and support
The Python runtime is GA. Versions are aligned with Go and TypeScript per the multi-language version-sync invariant (see scripts/verify-branch-version-sync.sh).