Repository navigation
Description
Tracks upstream friction in TinyDB. The explanation lives in the docs; this issue is the unit of work.
Explanation: Query conditions never see the document id — the limitation, why it matters to an ODM, the workaround tinydantic carries, and the change that would remove it. That section is written to be read standalone by an upstream maintainer, so it doubles as the ready-to-send proposal if we ever file this.
Reproduction
Upstream only — no tinydantic import, so this is what a report would carry.
from tinydb import TinyDB
from tinydb.storages import MemoryStorage
db = TinyDB(storage=MemoryStorage)
db.insert({"name": "a"})
def probe(doc):
print("search() passes:", type(doc).__name__, doc, "doc_id:", getattr(doc, "doc_id", None))
return False
db.search(probe)
print("__iter__ yields: ", [type(d).__name__ for d in db])Run with python repro.py.
Actual output:
search() passes: dict {'name': 'a'} doc_id: None
__iter__ yields: ['Document']
The condition is handed the raw body mapping. The id sits right there as the dict key in the evaluation loop, but nothing the condition receives carries it — so no query object, however constructed, can express "document id equals 1". Table.__iter__ is the only API that yields Documents.
Expected: with the needs_doc_id/DocId opt-in described in the docs section, a condition that asks for the id is handed Document(body, doc_id) and every other condition keeps the current fast path untouched.
Environment: TinyDB 4.9.0, Python 3.10.20, macOS. Run 2026-08-13.
What tinydantic carries today
A whole id-translation layer: id-bearing conditions are detected in every model method and executed via doc_id=/doc_ids= operations or by iterating the table. See src/tinydantic/_query.py and the id-condition branches in src/tinydantic/_model.py.
Private API: QueryInstance._hash (read-only) in has_id_condition() — composition (&/|/~) produces plain QueryInstance objects, so the hashval tree is the only place a marker survives. Approved 2026-08-02; degrades loudly, never silently.
Upstream status
Not filed. No draft prepared.
What would close this
The needs_doc_id/DocId opt-in protocol described in the docs section, which would let tinydantic delete the translation layer entirely — or a maintainer decision to carry the workaround indefinitely.
Assisted-by: Claude:claude-opus-5
Activity