Changelog¶
All notable changes to TypeBridge will be documented in this file.
[Unreleased]¶
[1.5.10] - 2026-07-16¶
Bug Fixes¶
- Sub-type migration planning and apply (#190) - Planning a migration
that adds an entity or relation with a parent no longer panics with
no entry found for key. Authored add operations now emit parents before children and carry only declared capabilities, so the child's define step keeps itssubclause without redeclaring inherited attributes or roles, which TypeDB rejects at apply time. Verified against live TypeDB servers from 3.8.3 through 3.12.1.
[1.5.9] - 2026-07-15¶
New Features¶
- Public migration and TOML-transpiler crates -
type-bridge-migrationandtype-bridge-toml-transpilernow participate in the validated crates.io publication graph. The transpiler publishes as an independent crate; migration publishes only after itstype-bridge-ormdependency is visible in the registry index.
Bug Fixes¶
- Fail-closed Python relation players (#170) - Python typed queries reject
nested relation-player materialization during planning, before provider I/O,
while preserving legacy
Role[Relation]declarations and CRUD. Defensive result hydration also rejects unsupported evidence; Node retains its released shallow V1 result contract.
Testing & Tooling¶
- Exact F8 release-artifact gate (#170) - registry publication now waits for the exact Python wheels and packed Node tarball to prove the Python rejection and Node shallow-result contracts live on TypeDB 3.8.3, 3.11.5, and 3.12.1.
[1.5.8] - 2026-07-15¶
New Features¶
-
@doc/@metaschema annotations (#169) - TypeDB 3.12's schema documentation and metadata annotations are declarable from all three model surfaces:TypeFlags(doc=..., meta=...)/AttributeFlags(doc=..., meta=...)and theFlag(Doc(...), Meta(...))ownership markers in Python, with matching TypeScript typed-layer and Rust static-model options, plus role-leveldoc=/meta=onRole(...). Annotations are emitted in schema define lowering, round-trip through the generator with three-target surface parity, and are carried by schema export/introspection. -
Annotation-aware migrations (#169) -
makemigrationsdetects@doc/@metaadditions, value changes, and removals on types, ownerships, and roles, authoring newModifyTypeAnnotations/ModifyRoleAnnotationsoperations with reverse steps. Annotation transitions lower to per-annotation schema steps (groupeddefine/undefineblocks, oneredefineper value change; removals first) โ this also fixesModifyOwnershiptransitions involving parameterless annotations (@key/@unique), which the old blanket-redefinelowering rejected live (REX28). Annotation-only changes classify as metadata-safe. -
Version gate for schema annotations (#169) - the server version detected by the connect-time gate is retained and exposed as
Database.detected_server_version(). Schema-apply seams (SchemaManager.sync_schema, the migration executor) check annotated DDL against it before sending: annotated schemas bound for a pre-3.12 server fail client-side with an actionable versioned error instead of a server syntax error.Database.check_schema_annotation_support()exposes the check directly. -
Band-9 embedded driver (#169) - the TypeDB 3.12 Rust driver ships vendored as
type-bridge-typedb-driver-b9alongside the band-7 fork and the crates.io band-8 driver, so 3.12 connections negotiate the native band-9 protocol automatically. Live measurement surfaced a hazard: a band-9 connection attempt crashes a 3.11 server, so the gRPC fallback discovers unknown servers through band 8 and upgrades to band 9 only after the reported version proves it safe. -
given-stage parameterized queries (#169) - one compiled TypeQL pipeline runs over many input rows, with the rows passed through the driver API instead of interpolated into the query string.Database.execute_with_rows()/TransactionContext.execute_with_rows()expose the raw surface (requiring both TypeDB 3.12+ and the negotiated band-9 provider;Database.supports_given_stage()reports that effective capability), and entityinsert_many()automatically rides one given pipeline for homogeneous batches when available โ measured ~4x faster than the per-row path at 1000 rows โ while degrading transparently to per-row inserts on older servers, band-8 fallbacks, and heterogeneous batches. -
Unified immutable typed queries (#170โ#177) - added additive
type_bridge.typedand@type-bridge/node/typedfacades with owner-aware variables, fields, and roles; exact or subtype matching; exact 1โ16-slot positional and named output typing; collected pages; and distinct-root page/count/exists operations. Rust owns canonical validation, TypeQL lowering, bounded execution, result identity, and transaction lifecycle. On negotiated band-9 connections, supported predicate values travel separately from TypeQL in one compiler-ownedgivenrow; older bands retain the validated inline path, and both routes preserve bounded streaming; existing package-root query and manager APIs remain available unchanged. -
TypeDB 3.12 server support - the compatibility window now extends to 3.12.x. Compatibility was measured live: server 3.12 accepts band-8 (3.11) drivers, while a 3.12 driver is refused by a 3.11 server, so the version gate now models servers as accepting a set of protocol bands and negotiates the connect band from that set. The embedded band-9 driver is selected only after a server is confirmed as 3.12; unknown-server fallback starts with band 8 to avoid probing a 3.11 server with the incompatible band-9 client. Installed Python driver 3.12 (band 9) is dispatched with the band-8 option form and gated correctly against both 3.11 (reject) and 3.12 (accept) servers; the
typedb-driverextra now allows<3.13.
Bug Fixes¶
- Reliable band-7 fallback on remapped TypeDB endpoints - when the HTTP version probe is unavailable, a lazy band-8 connection failure now advances to band 7 instead of terminating negotiation early. Rust integration helpers and Node parity consumers also honor the configured HTTP port.
- CPython 3.14 direct-driver compatibility - optional and development dependencies now select TypeDB driver 3.12.0 on CPython 3.14, with native constructor coverage. The CPython 3.12โ3.13 development environments retain driver 3.11.5 for the default 3.11 server, while the public extra continues to permit driver lines 3.8โ3.12. The embedded ORM runtime remains compatible with TypeDB 3.8โ3.12 on every supported interpreter.
- CPython 3.12 typed-facade compatibility - package metadata, defaulted
owner generics, static-tool targets, CI, and exact-artifact acceptance again
cover the declared
>=3.12,<3.15release range.
Testing & Tooling¶
- Typed-query artifact and live parity gates (#170โ#177) - added isolated Python-wheel and packed-npm consumers, positive/negative static contracts, native resource/lifecycle/snapshot regressions, and shared Python/Node live query coverage on the TypeDB 3.8, 3.10, 3.11, and 3.12 server lines.
- Release-candidate acceptance (#170โ#177) - each package registry consumes only its accepted immutable candidate; crates.io publication additionally waits for both complete Python archive/metadata/payload validation and exact npm-package acceptance. Exact-wheel runtime and typing consumers run on CPython 3.12, 3.13, and 3.14, and exact npm-package runtime consumers run on the declared Node 18 and 20 lines. Registry retries accept an existing artifact only when its published hash matches the candidate.
- TypeDB 3.12.0 CI legs - all ordinary Python integration groups (including
sessioncoverage forgivennegotiation), node-integration, and cross-language-parity matrices gainedtypedb/typedb:3.12.0legs (paired with Python driver 3.12.0), and the version-gate cells gained aNEG-driver-band9regression for the asymmetric 3.12-driver / 3.11-server rejection.
[1.5.6] - 2026-07-10¶
New Features¶
-
Expose migration-state schema boundary for external ledgers (#165) - added a public migration-state schema descriptor and filtering helpers so callers can keep migration execution metadata in an external state store while leaving target application schema management untouched.
-
Pluggable migration state manager (#165) -
MigrationExecutornow accepts an optionalstate_managerso external orchestrators can inject their own state persistence backend while retaining the existing default TypeDB-backed behavior.
Testing & Tooling¶
- Integration coverage for external-state migrations (#165) - added live tests for external ledger execution paths and schema filtering behavior that validate default and injected-state modes across TypeDB live integration.
[1.5.5] - 2026-06-30¶
Bug Fixes¶
- Strict Boolean wrappers -
Booleannow rejects non-boolvalues at construction, Pydantic validation, Pydantic serialization, hydration, and Rust-backend dynamic value boundaries instead of truthiness-coercing strings such as"False"intoTrue.
Testing & Tooling¶
- Boolean strictness regressions - added unit coverage for direct Boolean
construction, Pydantic hooks, CRUD hydration through
wrap_attribute_value, and Rust backend boolean value marshalling.
[1.5.4] - 2026-06-26¶
New Features¶
- Generator name-case overrides (#163) - bindgen now accepts case
annotations case-insensitively, including
@case(PascalCase)and language-scoped forms such as@case(Python, SnakeCase). - PascalCase and TOML bindgen metadata (#163) - Python model generation now
maps PascalCase TypeDB names to
TypeNameCase.CLASS_NAME, and TOML schemas can carrybindgen_caseplusannotationsmetadata for generated bindings.
Bug Fixes¶
- Mixed-case generated names (#163) - class-name generation now preserves
mixed-case sub-segments such as
FirstPersoninstead of lowercasing them during Python and Rust bindgen output. - Explicit generated type names (#163) - generated attribute configs now
emit explicit
name="..."flags when the TypeDB name does not align with the default language-specific name inference.
Testing & Tooling¶
- Cargo CI isolation (#163) - CI now keeps Cargo homes and caches outside the workspace, isolates cache keys by lockfile, and pins the stable Rust toolchain to reduce release-run cache and registry churn.
- Cargo lock checksum repair (#163) - refreshed the affected Rust lockfile checksums so locked metadata validation passes cleanly in release checks.
[1.5.3] - 2026-06-24¶
New Features¶
- ORM-backed Python data migrations (#158) - migrations can now use
ops.RunPython(...)to run normal TypeBridge ORM code during migration execution, includingUser.manager(db).filter(...), bulk inserts, updates, deletes, and JSON/TOML-backed data loading. - Database-backed migration history (#158) - applied migration state and
execution attempts are stored in TypeDB through
type_bridge_migrationandtype_bridge_migration_run, including run IDs, checksums, direction, status, timestamps, errors, and executor metadata when available. - Historical snapshot bindings for generated migrations (#160) - generated
migrations now import stable time-state bindings such as
migrations.snapshots.v0001.Userinstead of the active generated model package, keeping old migrations replayable after later bindgen output removes or reshapes types.
Changes¶
- Snapshot drift protection (#160) - existing snapshot packages are validated by schema hash, generated file hash manifest, and top-level binding exports before reuse, so stale or hand-edited historical bindings fail clearly instead of silently changing migration semantics.
Documentation¶
- Migration guide added (#158/#160) - added a dedicated migration guide that
explains the generated migration workflow, why snapshots matter,
RunPythondata migrations, rollback, sidecar checksum drift, and TypeDB-backed migration/run history.
[1.5.2] - 2026-06-18¶
New Features¶
- Rust bindgen model renderer (#157) - Python, TypeScript, and Rust model
rendering now run through the shared Rust bindgen engine, with Python
generate_modelsand the Node generator facade delegating to nativerender_models_jsonbindings. - Renderer deduplication (#157) - The old Python Jinja renderer and duplicated TypeScript renderer implementation were removed, so future model generation changes land in one core implementation with cross-language parity coverage.
Bug Fixes¶
- Shared TypeDB runtime parity (#155/#154) -
type_bridge_server::typedb::TypeDBClientnow uses the same gRPC-only connect path, HTTP-probe fallback, and exactserver_versionoverride logic as the ORMDatabase.connectsurface. The ORM and server both depend on a shared TypeDB runtime crate for driver construction, database lifecycle, transaction execution, and JSON result conversion. - Node gRPC-only connect option parity (#154) -
@type-bridge/nodeensureDatabaseandRustDatabase.connectnow acceptserverVersion, letting Node callers skip the HTTP version probe for gRPC-only deployments while still validating the exact TypeDB server version.
[1.5.1] - 2026-06-17¶
Bug Fixes¶
- gRPC-only TypeDB connect support (#154) -
Database.connect(..., server_version=...)now accepts an exact server version across Rust, PyO3, and Python connect surfaces, letting deployments without a reachable HTTP version endpoint skip the HTTP probe while still validating the supported window. - HTTP probe fallback to embedded driver negotiation (#154) - when no
server_versionis supplied and the HTTP probe fails, the Rust runtime now falls back through gRPC band negotiation, trying band 8 and then band 7 and reporting every attempted path if neither driver can connect. - Version-gate CI coverage for fallback paths (#154) - CI now includes positive cells that force the HTTP probe onto a bad port and assert the gRPC fallback succeeds, with helper updates for both success and rejection expectations.
New Features¶
- Band-aware server database admin API (#155) -
type_bridge_server::typedb::TypeDBClientnow exposesdatabase_exists,create_database,delete_database, andreset_database, dispatching through the embedded TypeDB driver band selected at connection time. - Node database lifecycle parity (#155) -
@type-bridge/nodeRustDatabasenow exposesdatabaseExists,createDatabase,deleteDatabase, andresetDatabaseon the bound database handle, matching the Python/Rust ORM lifecycle surface.
[1.5.0] - 2026-06-15¶
Changes¶
Rust-SSOT typed migrations from generated schema diffs (#152)¶
- Generated migrations default to typed operations โ
makemigrationsnow renders schema diffs as operations such asops.AddAttribute(...),ops.AddEntity(...),ops.AddRelation(...),ops.AddOwnership(..., optional=True), and role/player changes instead of flattening schema diffs to raw TypeQL. - Rust remains the migration execution source of truth โ generated migration
sidecars preserve structured Rust
OperationSpecvalues, and the Rust planner lowers typed operations to executable TypeQL at planning/execution time. ops.RunTypeQLremains supported as an escape hatch โ handwritten data migrations and custom TypeQL can still useops.RunTypeQL(...); Rust planning infers schema vs write transaction kind so data scripts execute correctly.- Django-style
schema.tomllifecycle documented โ the generator guide andexamples/advanced/toml_migration/now show the user flow: editschema.toml, run bindgen/generator andmakemigrations, receive0001_initial.py, migrate, edit the TOML again, and receive a follow-up typed migration such as0002_add_email.py. - Real smoke coverage added โ integration coverage exercises TOML bindgen,
an initial typed migration, real data insertion, a typed optional-ownership
delta, an explicit
ops.RunTypeQLdata migration, and a failing migration path that remains unapplied while preserving prior data.
Rust runtime as the default Python execution backend¶
Database.connect()now opens the embedded Rust runtime by default โ the Python ORM no longer needs the optional externaltypedb-driverpackage for normal connection, schema, CRUD, query, migration, or database lifecycle operations.- Database lifecycle operations are Rust-backed โ
database_exists(),create_database(),delete_database(), and schema export use the same embedded Rust runtime path as query execution. - Direct Python driver access remains explicit โ
Database.driverstill opens the optional external Pythontypedb-driverand keeps its installed driver/server compatibility gate for callers that need direct driver APIs.
Dual-band TypeDB driver support: servers 3.8โ3.11 served by one artifact (#145)¶
- Both TypeDB Rust driver lines now embedded โ the wheel ships a vendored band-7 fork
(3.8.1) alongside the upstream band-8 driver (3.11.5). The runtime dispatches to the
correct driver at
Database.connect()time based on the server's protocol band; no user-side configuration is required. - TypeDB 3.11 newly supported โ band-8 (3.11.x) servers are now served in addition to the existing band-7 window.
- Existing 3.8/3.10 deployments keep working without change โ the band-7 embedded driver is a drop-in for the previous release line; upgrading type-bridge does not require a server upgrade.
- One release artifact covers TypeDB 3.8.0 through 3.11.x โ the per-band install
guidance is retired. Install
type-bridgeand connect to any server in the supported window. - CI proven on all three server lines โ
test-integration,node-integration, andcross-language-paritynow fan across 3.8.3, 3.10.4, and 3.11.5 (parity ร2). Theversion-gate-cellsjob retains only the true rejection cells (NEG-window, NEG-driver).
Cross-language CI and release coverage (#110)¶
- Node binding built, tested, and released โ the
@type-bridge/nodebinding is now built and gated in CI (native module, TypeScript surface, unit,.d.tsbaseline, and package smoke), runnable locally viascripts/check.sh node, and packaged as a tarball attached to each GitHub release (registry publish staged behind anNPM_TOKEN). - Cross-language parity enforced โ the Python/Node parity suite runs against live
TypeDB in CI under a strict mode that fails (rather than silently skips) when the
binding is unbuilt, so a semantic divergence between the two bindings reds CI; the
migrationintegration group is also covered. - Release hardening โ third-party GitHub Actions are pinned to commit SHAs, and a crates.io publish that fails for any reason other than an already-published version now fails the release instead of being swallowed.
- Node binding integration gated in CI โ a
node-integrationjob runs the binding's own live-TypeDB suites (test:integration, which chainstest:typed-integration) against a TypeDB service, mirroring the Python integration job. Previously only the offline Node gates and the Python-side parity suite ran; the binding's own integration assertions now red CI on a regression. - Consolidated test/check scripts โ
test.shis now the single full-test entrypoint (Rust + Python + Node, unit + integration) with--no-integration,--proxy, and--no-isolatedflags; it manages a TypeDB by default. Thetest-integration.sh,test-integration-dind.sh, andtest-proxy-integration.shscripts (and the Docker-in-Docker image stack) are retired into those flags, andscripts/check.shis the single canonical check (the redundant rootcheck.shis removed).
Generator parsing routed through the Rust core (#125)¶
larkremoved โ the generator no longer depends onlark. TQL schema parsing runs entirely through the Rusttype_bridge_corecore, which is the single source of the parsed schema. Thetypeql.larkgrammar and the lark-vs-Rust differential test have been deleted, andlarkis dropped from the runtime dependencies.- Structured function return types โ
FunctionSpec.return_typeis now a structuredReturnTypeSpec(ais_streamflag plus an ordered list ofReturnTypeItem(name, optional)) instead of a formatted string. Optionality is carried as a boolean, so the intermediate representation is language-neutral and additive for future bindings. Generated output is unchanged โ the renderer reconstructs any?tokens at its own emit site.
New Features¶
Plays-side role cardinality (#130)¶
- Cross-language plays-cardinality authoring โ Rust
SchemaInfo, PythonRole(..., plays_cardinality=Card(...)), TypeScriptrole(..., { playsCardinality: Card(...) }), and TOMLplays = [{ card = "..." }]now emitplays relation:role @card(...)through the shared Rust schema emitter/parser path. - Relates/plays separation โ relates-side
cardinalitystill constrains players per relation instance, while plays-side cardinality constrains how many relation instances a single player may participate in for that role. The two constraints may coexist on the same role. - Generated surface round-trip โ parsed TypeQL with plays-side
@cardrenders back to Python and TypeScript role declarations, preserving authoring/render parity.
TOML schema DSL (#138)¶
- TOML schema authoring โ schemas may now be authored in TOML as an
additive alternative to TypeQL. A new Rust/PyO3
toml_to_typeqltranspiles a TOML document to canonical TypeQL, which feeds the single existing parse path, so the intermediate representation, renderers, and generated packages are unchanged. Equivalent TOML and.tqlschemas produce byte-for-byte identical packages..tqlauthoring remains fully supported. - Full schema surface โ the DSL covers attributes (value types,
sub,abstract,@regex/@values/@range), entities (ownswith@key/@unique/@card,playswith optional per-plays@card,sub,abstract), relations (roleswith per-role@cardandassuper-role overrides,owns, relation-levelplays,sub,abstract), functions (signature plus verbatim body), and structs. - Generator routing โ
generate_modelstranspiles a.tomlsource by file suffix, or for raw text via an explicitformat="toml"argument. - Field-level diagnostics โ a semantic validation pass rejects malformed TOML
with a clear
ValueErrornaming the offending field or type (unknown value type,value/subconflict, danglingsubparent, missing role player, empty struct, malformed function body) before any TypeQL is emitted.
Node.js typed model layer (#124)¶
- Branded attributes โ
class Name extends attr.String("name") {}defines a hard-typed attribute whose class is nominally distinct from other attributes (Nameis not interchangeable withEmailor rawstring). One factory per TypeDB value type; the mandatory name is both the schema attribute name and the compile-time brand. - Typed
Entity/Relationclasses โclass Person extends Entity("person", { name: field(Name, Key), age: field(Age).optional() }) {}yields typed construction and field reads, mirroring the Python class surface. Relations support multi-playerrole(...)declarations. - Descriptor emission โ typed models emit registration descriptors byte-identical to the Python facade (verified against the shared parity fixture), so the same model definition drives the existing dynamic managers.
[1.4.5] - 2026-05-21¶
Bug Fixes¶
Python ORM¶
- Relation role-player hydration โ relation role players fetched as IID-only placeholders now hydrate correctly without requiring their own nested role players (#126).
- Optional relation roles โ
Relation.manager(...).all()/ fetch queries now include relations whose optional roles have no players (#127). - Optional role validation โ omitted optional roles normalize to
Noneinstead of leaking class-levelRoleRefdefaults, while required roles are still rejected when missing. - Role-player deduplication โ relation role players are deduplicated by IID when available, preserving distinct attribute-less relation players.
- TypeDB driver compatibility โ added
create_driver_options()helper and exported it fromtype_bridgeto support driver option construction across supported TypeDB driver APIs.
Rust Core / Server¶
- Raw TypeQL endpoint โ restored
POST /query/rawon the Rust server, parsing TypeQL text into clauses before running the existing query pipeline. - Server configuration โ TypeDB connection settings can now be overridden with
TYPEDB_ADDRESS,TYPEDB_DATABASE,TYPEDB_USERNAME, andTYPEDB_PASSWORD. - Clippy cleanup โ updated ORM role collection code to satisfy current Rust lints.
Compatibility¶
- Pinned TypeDB runtime โ Python dependency now pins
typedb-driver==3.10.0. - Python version bounds โ package metadata now declares
>=3.13,<3.15. - Integration environment โ Docker Compose defaults now use TypeDB 3.10.4 and expose a configurable
TYPEDB_PORT.
Testing & Tooling¶
- Pinned Docker-in-Docker integration runner โ added
Dockerfile.integration,docker-compose.dind.yml, andtest-integration-dind.shfor reproducible Python 3.13.5 + TypeDB 3.10.4 integration tests. - Added regression coverage for relation role-player hydration, optional relation fetches, raw proxy queries, and server environment overrides.
[1.4.4] - 2026-04-09¶
New Features¶
Cross-type attribute lookup (PR #117)¶
Entity.has / Relation.has / <Concrete>.has โ find all instances that own a
given attribute, optionally filtered by value or expression.
Python ORM โ type_bridge.crud.has_lookup¶
- Cross-type form โ
Entity.has(db, Name)returns mixed concrete subtypes across all entities owningName. - Concrete-class narrowing โ
HLPerson.has(db, Name)narrows to that type and its TypeDB subtypes viaisapolymorphism. Abstract base subclasses get subtype matching for free. - Role-player hydration โ relation results always include hydrated role players. Entity lookups remain single-query; relations are re-fetched per result through
concrete_class.manager(connection).get(_iid=iid). Attribute.get_owners()โ static discovery of attribute owners without a database connection, backed by a reverse_attribute_ownersindex inModelRegistry.
[1.4.3] - 2026-04-05¶
Bug Fixes¶
Rust Server โ type-bridge-server¶
- fix:
extract_crud_info()now reports the write-target type for Match + Insert/Put queries (#121)
Rust Core โ type-bridge-core-lib¶
- refactor: use idiomatic match guards in validation.rs
[1.4.2] - 2026-03-04¶
Rust Server โ type-bridge-server¶
CrudInfoonRequestContextโ operation, type_name, type_kind, attribute_names, iidCrudInterceptortrait withon_crud_request/on_crud_responseandshould_interceptCrudInterceptorAdapterbridgesCrudInterceptorinto the existingInterceptorchain
[1.4.1] - 2026-03-03¶
New Features¶
Lifecycle Hook System (PR #118, closes #116)¶
Three-layer hook system for reacting to CRUD lifecycle events (audit logging, validation, cache invalidation, async notifications).
Python ORM โ type_bridge.crud.hooks¶
CrudEventenum โPRE_INSERT,POST_INSERT,PRE_UPDATE,POST_UPDATE,PRE_DELETE,POST_DELETE,PRE_PUT,POST_PUTLifecycleHookprotocol โ implement only the methods you need (pre_insert,post_delete, etc.)HookCancelledexception โ raise in a pre-hook to abort the operation- Per-manager registration โ
manager.add_hook(hook)/manager.remove_hook(hook), chainable should_run(event, sender)filtering by event type or model class- Pre-hooks run in registration order; post-hooks run in reverse order (middleware unwinding)
- Zero overhead when no hooks are registered
Rust ORM โ type-bridge-orm¶
LifecycleHooktrait withHookContext,PreHookResult(Continue/Reject), andHookRunner- Integrated into
EntityManagerandRelationManagerviaadd_hook() - Same semantics as the Python layer (registration-order pre-hooks, reverse-order post-hooks)
Put (Upsert) Clause โ type-bridge-core-lib¶
- Added
Clause::Put(Vec<Statement>)variant for idempotent insert (upsert) operations - Parser:
parse_put_clausewith keyword lookahead in bothparse_patternsandparse_statements - Compiler: Generates
put\n<statements>;TypeQL output - Validation: Reuses Insert validation rules (
Clause::Insert | Clause::Put) - Full roundtrip support (parse โ AST โ compile โ parse)
Refactoring¶
Server API Simplification โ type-bridge-server¶
- Removed standalone CRUD module (
/entities/*,/relations/*endpoints,CrudQueryBuilder, raw query support) โ superseded by the interceptor-based design - Removed
crud_builderbenchmark andcriteriondev-dependency - Server now has 4 endpoints:
POST /query,POST /query/validate,GET /health,GET /schema
[1.4.0] - 2026-02-20¶
Highlights¶
- 5 new Rust crates:
core-lib,orm,orm-derive,server, andpython(PyO3 bindings) - Up to 40x faster validation and 2.5x faster query compilation via the Rust backend
- Async Rust ORM with derive macros, chainable queries, and batch operations
- Query-intercepting proxy server with REST endpoints
- MkDocs Material documentation site
New Features¶
Rust Core โ type-bridge-core-lib (PRs #95, #101-#108)¶
- TypeQL schema parser with inheritance resolution and PyO3 bindings
- TypeQL query parser with bidirectional AST roundtrip
- Schema-aware query validation with statement and pattern validators
- Rust-backed value coercion and
format_value - Custom validation rules with portable JSON DSL
- Wired Rust core into Python compiler and validation pipeline
Async Rust ORM โ type-bridge-orm (PR #114)¶
- Async ORM with entity CRUD and mock-testable session layer
- Derive macros โ
#[derive(TypeBridgeEntity)],#[derive(TypeBridgeRelation)],#[derive(TypeBridgeAttribute)] - Chainable query builders with expression filtering and aggregation
- Schema management โ registration, generation, diff, and sync
- Abstract types with inheritance and code generation
- Batch operations โ
insert_many,delete_many,update_many FieldRef<A>for type-safe query field referencesinclude_schema!proc-macro for compile-time TQL codegen- Schema introspection from live TypeDB database
- Group-by queries with
GroupByResult - Role player field access for relation query filtering
- Expression helpers โ
in_range(),startswith(),endswith() - Connection pooling with
Database::into_shared() - Serde support on all ORM model types
- Structured tracing spans on all public methods
Query Intercept Proxy โ type-bridge-server (PR #109)¶
- REST CRUD endpoints with schema-aware query building
CrudQueryBuilderPyO3 class for TypeQL generation from Python- Extensible library/framework โ pluggable
QueryExecutor,Interceptor,SchemaSource - 207 tests with 100% MC/DC coverage
Performance: Python vs Rust¶
Validation¶
| Operation | Python | Rust | Speedup |
|---|---|---|---|
| Single type name | 1.89 us | 354.75 ns | 5.3x |
| Long name (100+ chars) | 24.90 us | 620.52 ns | 40.1x |
| Batch 1,000 names | 5.32 ms | 266.80 us | 19.9x |
| Batch 5,000 names | 28.02 ms | 1.33 ms | 21.1x |
Query Compilation (via serde bridge)¶
| Operation | Python | Rust | Speedup |
|---|---|---|---|
| Standalone update | 93.28 us | 37.82 us | 2.5x |
| Large batch (200 clauses) | 2.26 ms | 1.07 ms | 2.1x |
| Heavy insert (100x6) | 1.71 ms | 896.19 us | 1.9x |
Documentation & CI¶
- MkDocs + Material documentation site with auto-generated API reference (PR #98)
- Rust crate CI with multi-platform wheel builds โ Linux (x86_64, aarch64), macOS (x86_64, aarch64), Windows (x86_64) (PR #95)
- Comprehensive benchmark suite with TOML storage, comparison reports, and markdown generation (PR #103)
- Codecov integration for Rust coverage tracking (PR #109)
Bug Fixes¶
- Resolve Rust 1.93.0 clippy lint errors
- Pin Python 3.13 for Rust CI jobs and fix coverage script
- Add version specifiers to inter-crate path dependencies for crates.io publishing
- Make release workflow idempotent (skip already-published packages)
[1.3.0] - 2026-02-09¶
New Features¶
API DTO Generator (PRs #96, #97, #99, #100)¶
- Pydantic DTO generation from TypeQL schemas โ Generate typed Create/Out/Patch DTOs directly from parsed schemas
- Composite DTOs โ
CompositeEntityConfigfor flat/merged DTOs across entity types with name clash validation - Per-variant field requiredness overrides โ
FieldOverrideandEntityFieldOverrideto control field requiredness per DTO variant (Create, Out, Patch) skip_variantsโ Skip generating specific variant classes while keeping the type Literal enumextra_fields_outโ Per-variant override for extra fields on Out DTOsstrict_out_modelsโ Flag for required fields in Out DTOs- Reusable Jinja macros โ Refactored templates into
_dto_macros.jinja - CLI support โ
python -m type_bridge.generatornow supports DTO generation
Date Arithmetic and Query-Level Arithmetic Expressions¶
- Date arithmetic โ
__add__,__radd__,__sub__onDatefor Duration arithmetic, matching DateTime/DateTimeTZ - ArithmeticExpr โ New expression class with helpers (
add,sub,mul,div,mod,pow_) for TypeQL infix operators - ArithmeticValue AST node and compiler support
Improvements¶
- TypeDB 3.8.0 stable โ Bumped from 3.8.0-rc0 to 3.8.0 release
- TypeDB driver 3.8.0 โ Upgraded
typedb-driverdependency to 3.8.0 - Expression module cleanup โ Improved handling across boolean, comparison, and string expression modules
- Field module cleanup โ Enhanced field handling in base and role modules
Housekeeping¶
- Applied ruff formatting to all test files
- Added
.coverageto.gitignore(was accidentally tracked)
[1.2.7] - 2026-02-03¶
New Features¶
TypeDB 3.8.0 Support (PR #93)¶
- Full compatibility with TypeDB 3.8.0
- Updated driver integration
Performance Improvements¶
Batch Operations Optimization¶
- Batch delete operations with disjunctive IID matching
- Batch entity inserts/puts into single query
- Optimized IID retrieval with single-query insert+fetch
Bug Fixes¶
- HydrationError handling - Raise HydrationError instead of silently swallowing exceptions
- Variable collision prevention - Use double underscore separator to prevent variable collisions
- TypeDB 3.x relation syntax - Use correct relation insert syntax with
linkskeyword - Multi-variable let fix - Remove incorrect parentheses in multi-variable let assignment
- Polymorphic attributes - Restore polymorphic attribute fetching with nested wildcard
Refactoring¶
- Consolidate duplicated code and fix Python 3.13 warnings
- Unify entity identification logic across managers
- Extract shared attribute-to-AST logic into TypeDBType
- Remove
.caccessor for direct field access
Code Quality¶
- Remove all
type: ignorecomments for full type safety
Testing¶
- Add recursive relation tests
- Add validation performance benchmarks
[1.2.6] - 2026-02-01¶
New Features¶
Polymorphic Role Player Type Resolution (PR #92)¶
- Role players now resolve to their concrete Python types
- When querying relations with abstract role types, role players are resolved to concrete types (e.g.,
Personinstead ofProfile) - Uses TypeQL
label()function to fetch type labels and resolve to correct Python class - Location:
type_bridge/crud/relation/manager.py
Relations as Role Players¶
- Fixed hydration for relations serving as role players
- Relations can now properly participate as role players in other relations
- Comprehensive test suites added for this pattern
- Location:
type_bridge/crud/relation/manager.py
Improvements¶
Modular Helper Methods (PR #92)¶
- Extracted reusable helper methods for DRY refactoring
_resolve_entity_class_from_label()- Resolves concrete types using TypeQLlabel()function_hydrate_entity_from_data()- Helper for role player instantiation- Eliminates duplicate code in
get()andget_by_iid()methods
Generator Enhancements (PR #92)¶
- Improved code generation for relations
- Role cardinality annotations now properly rendered
- Docstrings and type annotations rendering improvements
- Location:
type_bridge/generator/
Bug Fixes¶
Polymorphic Role Validation (PR #92)¶
- Fixed polymorphic role validation and role player IIDs
- Correct handling of abstract types in role player resolution
- Fixed role player IID extraction in polymorphic queries
Test Fixes (PR #92)¶
- Fixed
manager.count()โmanager.filter().count()in tests - Renamed attribute types to avoid naming collisions
Testing¶
- 19 new integration tests (
tests/integration/queries/test_social_network_queries.py) - Deep inheritance (3-level: Entity โ Profile โ Person/Organization)
- Self-referential symmetric relations (Friendship)
- Geographic hierarchy chains (Person โ City โ Country)
- Polymorphic role players with concrete type verification
- Multi-value attributes with
@card(0..*) - Chained relations and complex filter combinations
Key Files Modified¶
type_bridge/crud/relation/manager.py- Polymorphic role player resolutiontype_bridge/generator/render/- Role cardinality and annotations renderingtests/integration/queries/test_social_network_queries.py- New comprehensive tests
[1.2.5] - 2026-01-31¶
New Features¶
IID-preferring Role Player Matching (PR #91)¶
- RelationManager now prefers IID for role player matching
- Uses IID for precise matching when available
- Falls back to key attribute matching when IID not set
- Raises clear
ValueErrorwhen neither IID nor key attributes available - Location:
type_bridge/crud/relation/manager.py
Affected Methods: insert(), put(), update(), delete() and *_many variants
Documentation¶
- Updated role player matching docs in
docs/SKILL.mdanddocs/api/crud.md
[1.2.4] - 2026-01-30¶
New Features¶
TypeDB 3.8.0 Built-in Functions (PR #88)¶
- Added support for TypeDB 3.8.0 built-in functions
- Identity functions:
iid(),label() - Math functions:
abs_(),ceil(),floor(),round_() - Collection functions:
len_(),max_(),min_() - Location:
type_bridge/expressions/builtins.py
Usage Example:
from type_bridge.expressions import iid, label, abs_, ceil, floor
# Get entity IID
query = Person.manager(db).filter(iid() == "0x1a2b3c").execute()
# Use math functions
query = Person.manager(db).filter(abs_(Age.value) > 18).execute()
Unicode XID Identifier Validation (PR #88)¶
- Added Unicode identifier validation for TypeDB 3.8.0 compatibility
- Validates identifiers follow Unicode XID_Start/XID_Continue rules
- Ensures TypeQL identifiers are compatible with TypeDB 3.8.0
- Clear error messages for invalid identifiers
- Location:
type_bridge/validation.py
Bug Fixes¶
Value Extraction Fix (PR #88)¶
- Fixed value extraction for
_Valueconcepts - Changed from
.as_value()to.get()for proper value extraction - Fixes issues with function return values and aggregations
- Location:
type_bridge/session.py
Driver Initialization Warning Fix (PR #88)¶
- Fixed "Failed to initialize logging" warning
- Suppresses fd 2 (stderr) during TypeDB driver initialization
- Eliminates spurious warning messages on startup
- Location:
type_bridge/typedb_driver.py
Documentation¶
- Added AI Assistant Skill Documentation (
docs/SKILL.md) - Guidelines for using TypeBridge with AI code assistants
Testing¶
- 32 new unit tests for builtin expressions
- 7 new integration tests for
iid()andlabel()functions - All existing tests pass with TypeDB 3.8.0-rc0
- Fixed hardcoded port 1729 in tests to use TEST_DB_ADDRESS
CI/CD¶
- Updated CI to TypeDB 3.8.0-rc0
- All tests now run against TypeDB 3.8.0-rc0
Key Files Modified¶
type_bridge/expressions/builtins.py- New built-in function expressionstype_bridge/session.py- Value extraction fixtype_bridge/typedb_driver.py- Driver initialization fixtype_bridge/validation.py- Unicode identifier validationdocs/SKILL.md- New AI assistant documentation
[1.2.3] - 2025-12-28¶
New Features¶
Enhanced FunctionQuery System (PR #84)¶
- Complete TypeQL query generation for function calls
- FunctionQuery generates full
match letqueries with variable binding - Support for scalar returns, stream returns, and composite tuples
- Query methods:
to_call(),to_match_let(),to_fetch(),to_query() - Pagination support with limit/offset/sort
- Location:
type_bridge/expressions/functions.py
Usage Example:
from myschema.functions import count_artifacts, get_neighbor_ids
# Simple count
fn = count_artifacts()
query = fn.to_query()
# โ match let $integer = count-artifacts(); fetch { "integer": $integer };
# Stream with pagination
fn = get_neighbor_ids(target_id="abc-123")
query = fn.to_query(limit=10, offset=5)
Driver Injection Support (PR #86)¶
- Share TypeDB driver instances across Database objects
- Optional
driverparameter inDatabase.__init__() - Ownership tracking with
_owns_driverflag for lifecycle control - Enables connection pooling and framework integration
- Location:
type_bridge/session.py
Benefits: - Resource efficiency (share one TCP connection) - Application-level connection pooling strategies - Centralized driver lifecycle management - Backwards compatible (default behavior unchanged)
Usage Example:
driver = TypeDB.driver("localhost:1729", Credentials("admin", "password"))
db1 = Database(database="project_a", driver=driver) # Shares driver
db2 = Database(database="project_b", driver=driver) # Shares driver
db1.close() # Just clears reference
db2.close() # Just clears reference
driver.close() # Actually closes connection
@independent Annotation Support (PR #83)¶
- Standalone attributes without entity/relation owners
- Add
independent = TrueClassVar to attribute classes - Generates
@independentannotation in TypeQL schema - Enables standalone attribute insertion and queries
- Location:
type_bridge/attribute/base.py
Usage Example:
class Language(String):
"""Can exist without an owner."""
independent = True
# Generated TypeQL: attribute Language @independent, value string;
@range Validation and Schema Generation (PR #82)¶
- Runtime validation with database enforcement
IntegerandDoublevalidaterange_constraintClassVar at initialization- Schema generation includes
@range(min..max)annotations - Also generates
@regexand@valuesannotations from ClassVars - Two-layer validation: Python-side (fail-fast) + TypeDB-side (enforcement)
- Location:
type_bridge/attribute/integer.py,type_bridge/attribute/double.py
Usage Example:
from typing import ClassVar
class Age(Integer):
range_constraint: ClassVar[tuple[str | None, str | None]] = ("0", "150")
Age(200) # Raises: ValueError: Age value 200 is above maximum 150
# Generated schema: attribute Age, value integer @range(0..150);
Batch IID Filtering (PR #81)¶
- Django-style
iid__inlookup for efficient batch queries - Filter entities/relations by multiple IIDs in single query
- Role player filtering:
employee__iid__in=[...] - Uses flat BooleanExpr to avoid stack overflow with many IIDs
- Location:
type_bridge/expressions/iid.py,type_bridge/crud/entity/manager.py
Usage Example:
# Fetch multiple entities by IID
persons = Person.manager(db).filter(iid__in=["0x1a2b3c", "0x4d5e6f"]).execute()
# Filter relations by role player IIDs
employments = Employment.manager(db).filter(employee__iid__in=["0x1a2b3c"]).execute()
Performance: O(1) query vs O(N) get_by_iid() calls.
TypeQL Annotation Validation (PR #86)¶
- Comprehensive validation for schema annotations
@card: Validates min โค max, non-negative values, detects comma syntax@regex: Validates patterns compile as valid regex@values: Validates at least one value, detects duplicates@range: Validates proper..syntax, rejects comma/single-value- Clear, actionable error messages
- Location:
type_bridge/generator/parser.py
Bug Fixes¶
Code Generator Fixes (PR #86)¶
- Fixed relation inheritance to include keys, uniques, and cardinalities
- Child relations now inherit
@key,@unique, and@cardfrom parent - Ensures complete type definitions in generated code
-
Location:
type_bridge/generator/render/relations.py -
Fixed optional relation attributes in generated models
- Correct type hints with
| Nonefor optional fields - Proper default values (e.g.,
timestamp: Timestamp | None = None) - Respects cardinality:
@card(1)= required, no annotation = optional -
Location:
type_bridge/generator/render/relations.py -
Fixed Python literal rendering for @range annotations
- Range values output as numeric literals:
(1, None)not("1", null) - Fixed type hint from
str | Nonetoint | float | None - Location:
type_bridge/generator/render/attributes.py
Query Generation Fixes (PR #84)¶
- Fixed composite variable lists in FunctionQuery
- Removed incorrect parentheses around variable lists
- Correct:
match let $a, $b in func() - Incorrect (previous):
match let ($a, $b) in func() - Location:
type_bridge/expressions/functions.py
Type Checking Fixes¶
- Proper type annotations for ty type checker
- Use
type[Attribute]instead of generic type - Use
type[Entity] | type[Relation]for model params - Core library passes ty with zero warnings
-
Location:
type_bridge/crud/relation/lookup.py,type_bridge/schema/introspection.py -
Added None checks for optional attributes
assert position is not Noneguards before accessing.value- Fixes pyright errors in tests
- Location:
tests/integration/crud/test_iid_feature.py
Development & Tooling¶
Project Restructuring¶
- Moved Python package to repository root
- Transitioned from monorepo (
packages/python/) to root-level package - TypeScript split into separate type-bridge-ts repository
- Simplified CI/CD configuration
Pre-commit Hooks¶
- Comprehensive code quality automation
- ruff linting and formatting
- pyright type checking
- ty type checker for enhanced type safety
- Location:
.pre-commit-config.yaml
Type Checker Configuration¶
- Configured ty rules for metaclass compatibility
- Overrides for tests/examples to handle metaclass-generated code
- Rules: unknown-argument, unresolved-attribute, call-non-callable
- Location:
pyproject.toml[tool.ty.overrides]
Documentation¶
- FunctionQuery documentation and integration tests
- Comprehensive examples of query generation patterns
-
All function patterns tested (scalar, stream, composite)
-
Database driver injection guide
- Connection pooling examples
-
Framework integration patterns
-
Generator relation cardinality documentation
- Clarified
@cardbehavior on relation attributes - Required vs optional attribute patterns
Testing¶
- 1096 unit tests passing (100% pass rate)
- All integration tests passing
- 0 errors with pyright and ty type checkers
Key Files Modified¶
type_bridge/expressions/functions.py- Enhanced FunctionQuerytype_bridge/session.py- Driver injection supporttype_bridge/generator/parser.py- Annotation validationtype_bridge/generator/render/relations.py- Inheritance and optional attributestype_bridge/generator/render/attributes.py- Python literal renderingtype_bridge/crud/relation/lookup.py- Type annotationstype_bridge/schema/introspection.py- Type annotationstype_bridge/attribute/base.py- @independent supporttype_bridge/attribute/integer.py- @range validationtype_bridge/attribute/double.py- @range validation.pre-commit-config.yaml- Pre-commit hooks configurationpyproject.toml- ty type checker configuration
[1.2.2] - 2025-12-25¶
Bug Fixes¶
RelationManager IID Correlation Fix (Issue #78)¶
- Fixed incorrect IID assignment in RelationManager.all()
- Problem: All relations were getting the same IID values for their role players instead of unique IIDs for each relation
- Root cause:
_populate_iidsmethod didn't properly correlate query results to the correct relation instances - Solution: Capture key attribute values as variables in the query and build a lookup map for correlating results back to the correct relations
- Impact: Critical for code relying on role player
_iidvalues for deduplication or correlation - Example: Multiple friendships now correctly show unique IIDs for each person instead of all showing the same IIDs
- Location:
type_bridge/session.py,type_bridge/crud/relation/manager.py
Testing¶
- Added 133 lines of regression tests for Issue #78
- Verifies multiple relations each get their own unique IIDs
Key Files Modified¶
type_bridge/session.py- Added value extraction for attribute concepts in_extract_concept_rowtype_bridge/crud/relation/manager.py- Fixed IID correlation logic (198 additions, 134 deletions)tests/integration/crud/test_iid_feature.py- Added regression tests for Issue #78
[1.2.1] - 2025-12-25¶
Bug Fixes¶
Stack Overflow Fix for __in Lookup (Issue #76)¶
- Fixed TypeDB stack overflow when using
__inlookup with many values (75+) - Root cause: Deeply nested binary OR expressions
((((a or b) or c) or d)...)caused TypeDB query planner to stack overflow - Solution: Use flat BooleanExpr structure for OR operations
- Example:
manager.filter(name__in=["Alice", "Bob", ...150 names])now works reliably - Location:
type_bridge/crud/entity/manager.py,type_bridge/crud/relation/lookup.py,type_bridge/expressions/boolean.py - Added automatic flattening of BooleanExpr operations
BooleanExpr.and_()andBooleanExpr.or_()now automatically flatten operands of the same operation type- Prevents deeply nested expression trees
- Improves query compilation performance
Testing¶
- Added 249 new tests for BooleanExpr flattening and __in lookup edge cases
- All tests passing
Key Files Modified¶
type_bridge/crud/entity/manager.py- Flat OR structure for __in lookupstype_bridge/crud/relation/lookup.py- Flat OR structure for relation lookupstype_bridge/expressions/boolean.py- Automatic flattening in and_() and or_()tests/unit/crud/test_lookup_parser.py- Entity lookup tests (37 tests)tests/unit/crud/test_role_lookup_parser.py- Relation lookup tests (31 tests)tests/unit/expressions/test_boolean_expr.py- BooleanExpr flattening tests (181 tests)
[1.2.0] - 2025-12-22¶
New Features¶
TypeDB 3.0 Structs Support (PR #71)¶
- Parse and generate Python code for TypeDB struct types
- Structs are value types composed of named fields
- Full code generator support for struct definitions
- Location:
type_bridge/generator/
Additional Annotations Support (PR #71)¶
@rangeannotation rendering in code generator- Support for
@range(min..max)constraints on attributes - Renders as validation metadata in generated code
Role Player IIDs (PR #70)¶
- Populate IIDs on role player entities when fetching relations
- Role players now have their
_iidfield populated automatically - Enables direct IID-based lookups on role players
Generator CLI Enhancement (PR #70)¶
- New
--schema-pathCLI option for code generator - Specify custom path for schema file in generated output
Batch Delete Error Handling¶
strictparameter fordelete_many- Optional error handling for batch deletes- When
strict=True, raises error if any entity not found - When
strict=False(default), silently skips missing entities
Performance Improvements¶
Batch Query Optimizations (PR #75)¶
- 50-100x improvement for bulk operations
- Batch
update_withoperations to reduce round-trips - Batch
_populate_iidsfor efficient IID resolution - Significant performance gains for large datasets
N+1 Query Fix (PR #73)¶
- Fix N+1 query problem in entity IID/type resolution
- Previously: 1 query per entity for IID resolution
- Now: Single batched query for all entities
- Major performance improvement for
all()andfilter().execute()
Batched CRUD Operations¶
- Batched
update_manyanddelete_manyoperations - Efficient batch processing instead of per-entity queries
- Reduced database round-trips
Bug Fixes¶
- None check in
delete_many- Add None check for entity in batched delete query to prevent errors when entity list contains None values
Key Files Modified¶
type_bridge/generator/parser.py- Struct parsing supporttype_bridge/generator/render/- Struct code generationtype_bridge/generator/__main__.py---schema-pathCLI optiontype_bridge/crud/entity/manager.py- Batch operations, strict parametertype_bridge/crud/entity/query.py- Batch IID populationtype_bridge/crud/relation/manager.py- Role player IID population
[1.1.0] - 2025-12-19¶
New Features¶
Polymorphic Entity Instantiation¶
- Querying a supertype now returns proper subtype instances (Issue #65)
Artifact.manager(db).all()returns a mix ofUserStory,DesignAspect, etc.- Each entity has the correct Python type with all subtype-specific attributes populated
- IIDs and type information correctly extracted for each subtype
Usage Example:
# Define type hierarchy
class Artifact(Entity):
flags = TypeFlags(abstract=True)
name: Name = Flag(Key)
class UserStory(Artifact):
story_points: StoryPoints
class DesignAspect(Artifact):
priority: Priority
# Query supertype - get proper subtypes back
artifacts = Artifact.manager(db).all()
for artifact in artifacts:
print(type(artifact)) # UserStory, DesignAspect, etc.
print(artifact.name) # All have base attributes
if isinstance(artifact, UserStory):
print(artifact.story_points) # Subtype-specific attributes
Refactoring¶
Jinja2 Templates for Code Generation¶
- Code generator now uses Jinja2 templates instead of string concatenation
- 6 new templates: attributes, entities, relations, functions, package_init, registry
- Significant code reduction in render modules:
registry.py: 578 โ 156 lines (-422)package.py: 116 โ 61 lines (-55)entities.py: 234 โ 198 lines (-36)
Typer CLI¶
- Generator and migration CLIs migrated to Typer
- Improved help messages and command structure
- Better argument parsing and validation
Dependencies¶
- Added
jinja2>=3.1.0- Template engine for code generation - Added
typer>=0.15.0- CLI framework for generator and migration tools
Key Files Modified¶
type_bridge/crud/entity/manager.py- Polymorphic instantiation inget()type_bridge/crud/entity/query.py- Polymorphic instantiation inexecute()type_bridge/crud/utils.py-resolve_entity_class()utilitytype_bridge/generator/__main__.py- Typer CLItype_bridge/generator/render/- Jinja2 template integrationtype_bridge/generator/templates/- 6 new Jinja2 templatestype_bridge/migration/__main__.py- Typer CLI with subcommands
[1.0.1] - 2025-12-19¶
New Features¶
TypeDB IID Support¶
- Expose TypeDB Internal ID (IID) on entity and relation instances
_iidfield automatically populated when entities/relations are fetched from database- New
get_by_iid(iid: str)method on EntityManager and RelationManager - IID populated from
get(),filter().execute(), andall()operations
Usage Example:
# Insert entity
person = Person(name=Name("Alice"), age=Age(30))
Person.manager(db).insert(person)
# Fetch - IID is automatically populated
fetched = Person.manager(db).get(name="Alice")
print(fetched[0]._iid) # '0x1e00000000000000000000'
# Direct IID lookup
person = Person.manager(db).get_by_iid("0x1e00000000000000000000")
Bug Fixes¶
- Fixed relation IID assignment order - Set
_iidafter role player assignments to prevent Pydantic revalidation from resetting the value
Key Files Modified¶
type_bridge/session.py- IID extraction functionstype_bridge/crud/entity/manager.py-get_by_iid()methodtype_bridge/crud/entity/query.py- IID extraction from resultstype_bridge/crud/relation/manager.py-get_by_iid()methodtype_bridge/crud/relation/query.py- IID extraction from results
[1.0.0] - 2025-12-15¶
New Features¶
Django-style Migration System¶
- Complete migration framework for TypeDB schema evolution
- Auto-generate migrations from Python model changes
- Apply and rollback migrations with transaction safety
- Track migration state in TypeDB database
- CLI commands:
type-bridge makemigrations,type-bridge migrate -
Location:
type_bridge/migration/(2872 lines) -
Migration Operations
AddAttribute- Add new attribute typesAddEntity- Add new entity typesAddRelation- Add new relation types with rolesAddOwnership- Add attribute ownership to typesAddRolePlayer- Add role players to relationsRemoveAttribute,RemoveEntity,RemoveRelation- Remove typesRunTypeQL- Execute raw TypeQL for custom migrations- All operations support forward and rollback
-
Location:
type_bridge/migration/operations.py -
Migration Generator
- Auto-detect schema changes by comparing Python models to database
- Generate migration files with operations
- Support for incremental migrations (detect only changes)
-
Location:
type_bridge/migration/generator.py -
Migration Executor
- Apply pending migrations in order
- Rollback migrations in reverse order
- Dry-run mode for previewing changes
sqlmigratefor viewing generated TypeQL-
Location:
type_bridge/migration/executor.py -
Migration State Tracking
- Track applied migrations in TypeDB
-
Location:
type_bridge/migration/state.py -
Model Registry
- Register models for migration tracking
- Auto-discover models from modules
- Location:
type_bridge/migration/registry.py
Schema Introspection¶
- Query existing schema from TypeDB database
- Introspect entities, relations, attributes, and ownerships
- TypeDB 3.x compatible queries
- Model-aware introspection for efficient checking
- Location:
type_bridge/schema/introspection.py(527 lines)
Breaking Change Detection¶
- Analyze schema changes for safety
- Detect breaking vs safe changes
- Categories: BREAKING, SAFE, WARNING
- Check role player narrowing, type removal, etc.
- Location:
type_bridge/schema/breaking.py(411 lines)
Enhanced Schema Diff¶
- Improved schema comparison
- Compare by TypeDB type name instead of Python object identity
- Detect modified entities, relations, and role players
- Track attribute and ownership changes
- Location:
type_bridge/schema/info.py,type_bridge/schema/diff.py
Bug Fixes¶
TypeDB 3.x Compatibility¶
- Fixed schema comparison using Python object identity instead of type name
-
SchemaInfo.compare()now correctly matches entities/relations by type name -
Fixed migration executor to execute operations separately
-
TypeDB 3.x doesn't allow multiple
defineblocks in single query -
Fixed schema introspection to query ownership from schema definition
-
Uses
match {type_name} owns $a;for schema queries -
Fixed migration state tracking for TypeDB 3.x @key semantics
- Uses composite key (
migration_id) instead of dual@keyattributes
Testing¶
- All 391 integration tests passing
- Added comprehensive migration test suite
- Added role player diff tests
- Added schema introspection tests
Key Files Added¶
type_bridge/migration/__init__.py- Migration module exportstype_bridge/migration/__main__.py- CLI commandstype_bridge/migration/base.py- Migration base classtype_bridge/migration/operations.py- Migration operationstype_bridge/migration/generator.py- Auto-generationtype_bridge/migration/executor.py- Apply/rollbacktype_bridge/migration/loader.py- Load migration filestype_bridge/migration/state.py- State trackingtype_bridge/migration/registry.py- Model registrytype_bridge/schema/introspection.py- Schema introspectiontype_bridge/schema/breaking.py- Breaking change detectiontests/integration/migration/- Migration integration teststests/integration/schema/test_role_player_diff.py- Role player tests
Usage Example¶
from type_bridge.migration import MigrationGenerator, MigrationExecutor
from type_bridge import Database
db = Database("localhost:1729", "mydb")
# Generate migration from models
generator = MigrationGenerator(db, "./migrations")
generator.generate(models=[Person, Company], name="initial")
# Apply migrations
executor = MigrationExecutor(db, "./migrations")
results = executor.migrate()
# Rollback
executor.rollback()
CLI Usage¶
# Generate migrations
type-bridge makemigrations ./migrations --models myapp.models
# Apply migrations
type-bridge migrate ./migrations
# Show migration status
type-bridge showmigrations ./migrations
# Preview TypeQL
type-bridge sqlmigrate ./migrations 0001_initial
[0.9.4] - 2025-12-12¶
New Features¶
Debug Logging Support (Issue #43)¶
- Added comprehensive logging throughout TypeBridge using Python's standard
loggingmodule - See generated TQL queries during CRUD operations
- Hierarchical logger structure for fine-grained control
- Documentation:
docs/api/logging.md
Bug Fixes¶
Type Safety Improvements¶
- Fixed pyright errors for
TransactionType.nameaccess in session.py - Added
_tx_type_name()helper function for type-safe transaction type logging
Documentation¶
- Added
docs/api/logging.md- Comprehensive logging configuration guide - Updated
docs/DEVELOPMENT.mdwith logging section
Key Files Modified¶
type_bridge/session.py- Fixed type errors, added loggingtype_bridge/query.py- Added loggingtype_bridge/validation.py- Added loggingtype_bridge/schema/manager.py- Added loggingtype_bridge/schema/migration.py- Added loggingtype_bridge/crud/entity/manager.py- Added loggingtype_bridge/crud/entity/query.py- Added loggingtype_bridge/crud/entity/group_by.py- Added loggingtype_bridge/crud/relation/manager.py- Added loggingtype_bridge/crud/relation/query.py- Added loggingtype_bridge/crud/relation/group_by.py- Added loggingtype_bridge/generator/__main__.py- Added loggingtype_bridge/generator/render/attributes.py- Added loggingtype_bridge/generator/render/entities.py- Added loggingtype_bridge/generator/render/relations.py- Added loggingtype_bridge/models/entity.py- Added loggingtype_bridge/models/relation.py- Added loggingdocs/api/logging.md- New documentationdocs/DEVELOPMENT.md- Added logging section
[0.9.3] - 2025-12-12¶
Documentation¶
@key Attribute Requirement for update() (Issue #45)¶
- Added prominent documentation explaining that
update()requires @key attributes - New section "Important: @key Attributes Required for update()" in CRUD docs
- Clear examples showing proper
@keyattribute definition - Error scenarios documented: no
@keydefined,@keyvalue isNone - Guidance for UUID/ID fields as
@keyattributes - Cross-reference to Exception Handling section
- Location:
docs/api/crud.md(lines 369-413)
Key Files Modified¶
docs/api/crud.md- Added @key requirement documentation in Update Operations section
[0.9.2] - 2025-12-12¶
New Features¶
KeyAttributeError Exception (Issue #44)¶
- Added
KeyAttributeErrorexception for @key validation failures - Raised when @key attribute is None during update/delete
- Raised when no @key attributes are defined on entity
- Structured attributes:
entity_type,operation,field_name,all_fields - Helpful error messages with hints for fixing issues
- Inherits from
ValueErrorfor backward compatibility - Location:
type_bridge/crud/exceptions.py
Testing¶
- Added 7 unit tests for
KeyAttributeError - 813 unit tests passing
Key Files Added/Modified¶
type_bridge/crud/exceptions.py- AddedKeyAttributeErrorclasstype_bridge/crud/__init__.py- ExportKeyAttributeErrortype_bridge/__init__.py- ExportKeyAttributeErrorin public APItype_bridge/crud/entity/manager.py- UseKeyAttributeErrortype_bridge/crud/entity/query.py- UseKeyAttributeErrortests/unit/exceptions/test_exceptions.py- Added KeyAttributeError tests
Usage Example¶
from type_bridge import KeyAttributeError
try:
manager.update(entity_with_none_key)
except KeyAttributeError as e:
print(f"Entity: {e.entity_type}")
print(f"Operation: {e.operation}")
print(f"Field: {e.field_name}")
[0.9.1] - 2025-12-11¶
New Features¶
Enhanced Code Generator (PR #53)¶
- Registry Module - Generates
registry.pywith schema metadata as Python dictionaries - Entity/relation attributes, roles, and inheritance info
- JSON Schema fragments for validation
- Convenience lookup functions
- Schema hash for change detection
-
Location:
type_bridge/generator/render/registry.py -
Enhanced Function Generation - Generic
FunctionCallExpr[T]with precise return type hints - Support for all TypeDB function variations: stream, scalar, tuple, optional returns
- Added
boolto type mapping - Improved docstrings with return type documentation
-
Location:
type_bridge/generator/render/functions.py -
TypeQL Parser Enhancements
@independentattribute flag support@range(min..max)constraint parsing (integers, floats, dates, datetimes, open-ended)@cardonplaysdeclarations with inheritance@cardonrelatesdeclarations//C-style comments alongside#comments- Comment annotations parsing (
@prefix,@tags, etc.) - Location:
type_bridge/generator/parser.py,type_bridge/generator/typeql.lark
Testing¶
- Added comprehensive generator unit tests for annotations, functions, and registry
- 1,268 total tests passing
Key Files Added/Modified¶
type_bridge/generator/render/registry.py- Registry module generation (new)type_bridge/generator/annotations.py- Annotation parsing (new)type_bridge/generator/render/functions.py- Enhanced function generationtype_bridge/generator/parser.py- Parser enhancementstype_bridge/generator/typeql.lark- Grammar updatestype_bridge/generator/models.py- New annotation modelstype_bridge/expressions/functions.py- Generic FunctionCallExprdocs/api/generator.md- Updated documentation
Contributors¶
- @CaliLuke - Generator enhancements
[0.9.0] - 2025-12-11¶
New Features¶
Type-Safe Role Player Expressions (PR #42)¶
- Type-safe role player field expressions
- Access role player attributes with type safety:
Employment.employee.age.gte(Age(30)) RoleRefclass for class-level role accessRolePlayerFieldReffor type-safe attribute accessRolePlayerNumericFieldReffor numeric comparison methodsRolePlayerStringFieldReffor string-specific methods (contains, like, regex)-
Location:
type_bridge/fields/role.py -
Django-style role-player lookup filters
- Filter by role player attributes:
filter(employee__age__gt=30) - Support for comparison operators:
__eq,__gt,__lt,__gte,__lte - Support for string operators:
__contains,__like,__regex -
Location:
type_bridge/crud/relation/lookup.py -
Added
order_by()method to EntityQuery and RelationQuery - Sort results by entity/relation attributes or role player attributes
- Supports ascending (default) and descending (
-field) order - Role-player sorting:
order_by('employee__age', '-salary') -
Location:
type_bridge/crud/entity/query.py,type_bridge/crud/relation/query.py -
Added public
Relation.get_roles()method - Clean API for accessing relation roles without internal
_rolesaccess - Returns:
dict[str, Role]mapping role names to Role instances - Location:
type_bridge/models/relation.py
Bug Fixes¶
- Fixed
RelationQuery.filter()to support Django-style kwargs - Chained
.filter()calls now properly support**filtersparameter - Location:
type_bridge/crud/relation/query.py
Testing¶
- Added
TestCombinedWithPaginationintegration tests - Added
TestRoleMultiAttributeAccessunit tests - All type checks pass without suppressions (uses
isinstancefor type narrowing) - 806 unit tests + 377 integration tests = 1,183 total tests
Key Files Added/Modified¶
type_bridge/fields/role.py- RoleRef and RolePlayerFieldRef classestype_bridge/crud/relation/lookup.py- Django-style lookup parsertype_bridge/crud/relation/query.py- RelationQuery with filter and order_bytype_bridge/crud/entity/query.py- EntityQuery with order_bytype_bridge/models/relation.py- Added get_roles() methodtype_bridge/generator/render/relations.py- Updated generated code patternstests/unit/fields/test_role_ref.py- RoleRef unit teststests/integration/queries/test_role_field_expressions.py- Integration tests
Usage Examples¶
from type_bridge import Relation, Role, Entity, TypeFlags, String, Integer
class Age(Integer):
pass
class Name(String):
pass
class Person(Entity):
flags = TypeFlags(name="person")
name: Name = Flag(Key)
age: Age | None = None
class Employment(Relation):
flags = TypeFlags(name="employment")
employee: Role[Person] = Role("employee", Person)
# Type-safe role player expression
results = Employment.manager(db).filter(
Employment.employee.age.gte(Age(30))
).execute()
# Django-style lookup
results = Employment.manager(db).filter(employee__age__gt=30).execute()
# Combined with sorting and pagination
results = (
Employment.manager(db)
.filter(Employment.employee.age.gte(Age(25)), salary__gte=80000)
.order_by("employee__age", "-salary")
.limit(10)
.execute()
)
[0.8.1] - 2025-12-11¶
New Features¶
TypeDB Function Support in Code Generator¶
- Parse TypeQL
fundeclarations with parameters and return types - Generate Python function wrappers that return
FunctionCallExprobjects - Auto-generate
functions.pymodule when functions are defined in schema - Support for all TypeDB data types (string, integer, date, datetime, double, boolean, decimal, duration)
-
Location:
type_bridge/generator/render/functions.py -
Added
FunctionCallExprclass for building function calls in queries - New expression type for calling TypeDB functions
- Location:
type_bridge/expressions/functions.py
Lark-based Parser¶
- Migrated from regex-based parser to robust Lark grammar
- Added formal grammar file (
typeql.lark) for better maintainability - Improved handling of edge cases (whitespace, optional clauses)
- Better support for TypeDB 3.0 features
- Location:
type_bridge/generator/typeql.lark,type_bridge/generator/parser.py
Bug Fixes¶
Parser Grammar Fixes¶
- Fixed parsing of
suband@abstractin entity/relation bodies - Now correctly handles patterns like
entity page @abstract, sub content, - Supports
subappearing anywhere in the type definition, not just at the start - Fixed parsing of
@cardannotations onplaysandrelatesstatements - Now correctly parses
plays posting:post @card(1)andrelates subject @card(1)
Testing¶
- Added 136 new unit tests for function parsing and rendering
- All 808 tests passing (520 unit + 288 integration)
Key Files Added/Modified¶
type_bridge/generator/typeql.lark- Formal TypeQL grammar (75 lines)type_bridge/generator/parser.py- Rewritten with Lark integrationtype_bridge/generator/models.py- AddedFunctionSpec,ParameterSpectype_bridge/generator/render/functions.py- Function code generationtype_bridge/expressions/functions.py-FunctionCallExprclasstype_bridge/expressions/__init__.py- ExportFunctionCallExprtype_bridge/generator/__init__.py- Expose function parsing APItests/unit/generator/test_functions.py- Function unit tests
[0.8.0] - 2025-12-11¶
New Features¶
Code Generator (TypeQL โ Python)¶
- Added
type_bridge.generatormodule for generating Python models from TypeQL schema files - Eliminates manual synchronization between
.tqlschemas and Python code - Write schema once in TypeQL, generate type-safe Python models automatically
-
Location:
type_bridge/generator/ -
CLI interface for code generation
- Usage:
python -m type_bridge.generator schema.tql -o ./models/ - Options:
--version,--no-copy-schema,--implicit-keys -
Location:
type_bridge/generator/__main__.py -
Programmatic API
generate_models(schema, output_dir)- Main generation functionparse_tql_schema(schema_content)- Parse TypeQL to intermediate representation-
Location:
type_bridge/generator/__init__.py -
Full TypeDB 3.x schema support
- All value types: string, integer, double, decimal, boolean, date, datetime, datetime-tz, duration
- Entity and relation inheritance (
subdeclarations) - Abstract types (
@abstract) - Attribute constraints:
@key,@unique,@card,@regex,@values - Role definitions and
playsdeclarations -
Comment annotations for customization (
# @prefix:,# @internal) -
Generated package structure
Bug Fixes¶
Optional Attribute Update Fix¶
- Fixed silent update failures for optional attributes (Resolves #47)
- Previously: Updating an entity with an optional attribute set to
Nonecould silently fail - Now: Properly handles
Nonevalues in update operations - Location:
type_bridge/crud/entity/manager.py
Testing¶
- Added comprehensive generator test suite
- 62 unit tests covering parser, naming utilities, and renderers
- 18 integration tests verifying generated code imports and executes correctly
- Test fixtures with complex TypeQL schemas
-
Location:
tests/unit/generator/,tests/integration/generator/ -
Expanded lookup filter tests
- Additional test coverage for lookup filter parsing and execution
- Location:
tests/unit/crud/test_lookup_parser.py,tests/integration/queries/test_lookup_filters.py
Documentation¶
- Added generator documentation
- Complete API reference and usage guide
- CLI reference and examples
- Supported TypeQL features and cardinality mapping
- Best practices for generated code management
-
Location:
docs/api/generator.md -
Updated project documentation
- Added generator to project structure in CLAUDE.md
- Updated README.md with code generator feature
Key Files Added/Modified¶
type_bridge/generator/__init__.py- Public API:generate_models(),parse_tql_schema()type_bridge/generator/__main__.py- CLI interfacetype_bridge/generator/models.py-ParsedSchema,AttributeSpec,EntitySpec,RelationSpectype_bridge/generator/parser.py- TypeQL parser with inheritance resolutiontype_bridge/generator/naming.py- kebab-case โ PascalCase/snake_case utilitiestype_bridge/generator/render/- Code generation renderers (attributes, entities, relations, package)type_bridge/crud/entity/manager.py- Optional attribute update fixdocs/api/generator.md- Generator documentation
Usage Examples¶
CLI Usage¶
# Generate models from a schema file
python -m type_bridge.generator schema.tql -o ./myapp/models/
# With options
python -m type_bridge.generator schema.tql \
--output ./myapp/models/ \
--version 2.0.0 \
--implicit-keys id
Programmatic Usage¶
from type_bridge.generator import generate_models
# From a file path
generate_models("schema.tql", "./myapp/models/")
# From schema text
schema = """
define
entity person, owns name @key;
attribute name, value string;
"""
generate_models(schema, "./myapp/models/")
Using Generated Models¶
from myapp.models import attributes, entities, relations
from myapp.models import SCHEMA_VERSION, schema_text
# Access generated classes
person = entities.Person(name=attributes.Name("Alice"))
# Get schema version
print(SCHEMA_VERSION) # "1.0.0"
[0.7.2] - 2025-12-10¶
Breaking Changes¶
New Exceptions for Delete Operations¶
- Added
EntityNotFoundError- Raised when deleting an entity that doesn't exist - Now raised for both keyed and keyless entities when no match is found
- Previously: keyed entities silently succeeded, keyless raised
ValueError -
Subclass of
LookupError -
Added
RelationNotFoundError- Raised when deleting a relation that doesn't exist - Raised when relation with given role players is not found
- Previously: silently succeeded
-
Subclass of
LookupError -
Added
NotUniqueError- Raised when keyless entity matches multiple records - Replaces
ValueErrorfor multiple match scenarios - Subclass of
ValueError - Suggestion to use
filter().delete()for bulk deletion
Migration Guide¶
# Handling non-existent entity deletion (NEW in v0.7.2)
from type_bridge import EntityNotFoundError, RelationNotFoundError, NotUniqueError
# Entity with @key that doesn't exist
try:
manager.delete(nonexistent_entity)
except EntityNotFoundError:
print("Entity was already deleted or never existed")
# Relation that doesn't exist
try:
relation_manager.delete(nonexistent_relation)
except RelationNotFoundError:
print("Relation was already deleted or never existed")
# Entity without @key matching multiple records
try:
manager.delete(keyless_entity)
except NotUniqueError:
print("Multiple entities matched - use filter().delete() for bulk deletion")
# Bulk delete with __in (migrating from v0.7.0)
# OLD: manager.delete_many(name__in=["Alice", "Bob"])
# NEW:
count = manager.filter(name__in=["Alice", "Bob"]).delete()
Key Files Modified¶
type_bridge/crud/exceptions.py- NEW - Exception classestype_bridge/crud/__init__.py- Export exceptionstype_bridge/crud/entity/manager.py- Add existence check before deletetype_bridge/crud/relation/manager.py- Add existence check before deletetype_bridge/__init__.py- Export exceptions
[0.7.1] - 2025-12-09¶
Breaking Changes¶
Delete API Refactored to Instance-Based Pattern¶
- Changed
EntityManager.delete()signature - Old:
delete(**filters) -> int(filter-based, returns count) - New:
delete(entity: E) -> E(instance-based, returns deleted entity) - Uses
@keyattributes to identify entity (same pattern asupdate()) -
Related: Issue #37
-
Changed
EntityManager.delete_many()signature - Old:
delete_many(**filters) -> int(filter-based with__insupport) -
New:
delete_many(entities: list[E]) -> list[E](instance list, returns list) -
Changed
RelationManager.delete()anddelete_many()similarly - Uses role players'
@keyattributes to identify the relation - Each role player is matched by their
@keyattribute
New Features¶
Instance Delete Methods¶
- Added
Entity.delete(connection)instance method - Delete entity directly:
alice.delete(db) - Returns self for chaining
-
Location:
type_bridge/models/entity.py -
Added
Relation.delete(connection)instance method - Delete relation directly:
employment.delete(db) - Returns self for chaining
- Location:
type_bridge/models/relation.py
Fallback for Entities Without @key¶
- Entities without
@keycan still be deleted if they match exactly 1 record - Matches by ALL non-None attributes
- Raises
ValueErrorif 0 or >1 matches found - Provides safer delete behavior than filter-based approach
Migration Guide¶
# OLD (v0.7.0): Filter-based deletion
deleted_count = manager.delete(name="Alice") # Returns int
# NEW (v0.7.1): Instance-based deletion
alice = manager.get(name="Alice")[0]
deleted = manager.delete(alice) # Returns Alice instance
# OR use instance method
alice.delete(db) # Returns alice
# For filter-based deletion, use filter().delete()
count = manager.filter(name__in=["Alice", "Bob"]).delete() # Still returns int
count = manager.filter(Age.gt(Age(65))).delete() # Expression filters
Key Files Modified¶
type_bridge/crud/entity/manager.py- Refactoreddelete(),delete_many()type_bridge/crud/relation/manager.py- Refactoreddelete(),delete_many()type_bridge/models/entity.py- Addeddelete()instance methodtype_bridge/models/relation.py- Addeddelete()instance method
[0.7.0] - 2025-12-08¶
๐ New Features¶
TransactionContext for Shared Operations¶
- Added
TransactionContextclass for sharing transactions across operations - Multiple managers can share a single transaction
- Auto-commit on context exit, rollback on exception
- Location:
type_bridge/session.py
with db.transaction(TransactionType.WRITE) as tx:
person_mgr = Person.manager(tx) # reuses tx
artifact_mgr = Artifact.manager(tx) # same tx
# ... operations commit together
Unified Connection Type¶
- Added
Connectiontype alias for flexible connection handling Connection = Database | Transaction | TransactionContext- All managers accept any Connection type
ConnectionExecutorhandles transaction reuse internally- Location:
type_bridge/session.py
Entity Dict Helpers¶
- Added
Entity.to_dict()for serialization - Unwraps Attribute instances to
.value - Supports
include,exclude,by_alias,exclude_unsetoptions - Added
Entity.from_dict()for deserialization - Optional
field_mappingfor external key names strict=Falsemode to ignore unknown fields- Location:
type_bridge/models/entity.py
person.to_dict() # {'name': 'Alice', 'age': 30}
Person.from_dict(payload, field_mapping={"display-id": "display_id"})
Django-style Lookup Filters¶
- Added lookup suffix operators to
filter() __contains,__startswith,__endswith,__regexfor strings__gt,__gte,__lt,__ltefor comparisons__infor disjunction (multiple values)__isnullfor null checks- Location:
type_bridge/crud/entity/manager.py
person_manager.filter(name__startswith="Al", age__gt=30).execute()
person_manager.filter(status__in=["active", "pending"]).execute()
Bulk Operations¶
- Added
EntityManager.update_many()- Update multiple entities in one transaction - Added
EntityManager.delete_many()- Bulk delete with__infilter support
๐ Documentation¶
- Comprehensive documentation update
- Fixed broken example paths in README.md
- Added Connection types documentation to docs/api/crud.md
- Added TransactionContext usage examples
- Added lookup filter documentation with TypeQL mappings
- Added dict helpers documentation to docs/api/entities.md
๐ง Maintenance¶
- Fixed version mismatch between pyproject.toml and init.py
- Added
typings/stubs forisodateandtypedb.driver
๐ฆ Key Files Modified¶
type_bridge/session.py- Added TransactionContext, Connection, ConnectionExecutortype_bridge/models/entity.py- Added to_dict(), from_dict()type_bridge/crud/entity/manager.py- Added lookup filters, update_many, delete_manytype_bridge/crud/relation/manager.py- Unified connection handlingdocs/api/crud.md- New sections for transactions, lookups, bulk opsdocs/api/entities.md- Dict helpers documentation
[0.6.4] - 2025-12-04¶
๐ New Features¶
CRUD PUT Operations (Idempotent Insert)¶
- Added
EntityManager.put()for idempotent entity insertion - Inserts entity only if it doesn't already exist
- Safe to call multiple times without creating duplicates
- Uses TypeQL's PUT clause for atomic match-or-insert semantics
-
Location:
type_bridge/crud/entity/manager.py -
Added
EntityManager.put_many()for bulk idempotent insertion - All-or-nothing semantics: entire pattern must match or all is inserted
-
Efficient batch operations for data synchronization
-
Added
RelationManager.put()for idempotent relation insertion - Same PUT semantics for relations with role players
- Prevents duplicate relationships
-
Location:
type_bridge/crud/relation/manager.py -
Added
RelationManager.put_many()for bulk relation PUT - Batch idempotent insertion for relations
Use Cases¶
- Data import scripts (safe re-runs)
- Ensuring reference data exists
- Synchronization with external systems
- Idempotent API endpoints
๐ Documentation¶
- Updated
docs/api/crud.mdwith PUT operations section - Comparison table: INSERT vs PUT behavior
- All-or-nothing semantics explanation
-
Usage examples for entities and relations
-
Added
examples/basic/crud_08_put.pytutorial - Demonstrates PUT vs INSERT differences
- Shows idempotent behavior patterns
๐งช Testing¶
- Added entity PUT integration tests (
tests/integration/crud/entities/test_put.py) - Single put, bulk put_many
- Idempotency verification
-
All-or-nothing behavior
-
Added relation PUT integration tests (
tests/integration/crud/relations/test_put.py) - Relation put operations
- Role player handling
๐ฆ Key Files Modified¶
type_bridge/crud/entity/manager.py- Addedput(),put_many()type_bridge/crud/relation/manager.py- Addedput(),put_many()docs/api/crud.md- PUT documentationexamples/basic/crud_08_put.py- New tutorialtests/integration/crud/entities/test_put.py- Entity PUT teststests/integration/crud/relations/test_put.py- Relation PUT testsREADME.md- Updated features
๐ก Usage Examples¶
# Single PUT (idempotent insert)
alice = Person(name=Name("Alice"), age=Age(30))
person_manager.put(alice)
person_manager.put(alice) # No duplicate created
# Bulk PUT
persons = [Person(name=Name("Bob")), Person(name=Name("Carol"))]
person_manager.put_many(persons)
person_manager.put_many(persons) # No duplicates
# Relation PUT
employment = Employment(employee=alice, employer=techcorp)
employment_manager.put(employment)
[0.6.3] - 2025-12-04¶
๐ New Features¶
Multi-Player Roles¶
- Added
Role.multi()for roles playable by multiple entity types - Syntax:
origin: Role[Document | Email] = Role.multi("origin", Document, Email) - Eliminates need for artificial supertype hierarchies
- Generates multiple
playsdeclarations in TypeQL schema - Location:
type_bridge/models/role.py - Full CRUD support for multi-role relations
- Filter by specific player type:
manager.get(origin=doc) - Chainable operations work with multi-roles
- Batch insert with mixed player types supported
- Runtime validation: TypeError if wrong player type assigned
- Pydantic integration: Union types provide IDE/type-checker support
TypeDB 3.7 Compatibility¶
- Verified compatibility with TypeDB 3.7.0-rc0
- Updated documentation to reflect tested TypeDB version
๐ Bug Fixes¶
Inherited Attribute Filter Bug¶
- Fixed filters on inherited attributes being silently ignored
- Root cause:
get_owned_attributes()was used instead ofget_all_attributes()in filter operations - Affected methods:
EntityManager.delete(),EntityQuery.delete(),QueryBuilder.match_entity() - Example:
Dog.manager(db).get(name=LivingName("Buddy"))now works whennameis inherited from parentLivingclass - Location:
type_bridge/crud/entity/query.py:215,type_bridge/crud/entity/manager.py:219,type_bridge/query.py:193 - Impact: Dictionary-based filters (
get(),delete()) now correctly handle inherited attributes in subtype queries
๐งช Testing¶
Multi-Role Tests¶
- Multi-role integration tests (
tests/integration/crud/relations/test_multi_role.py) - 37 tests - Insert relations with different role player types
- Filter by multi-role players
- Delete filtered by multi-role
- Chainable
update_withoperations - Multi-role with 3+ entity types
- Multi-role unit tests (
tests/unit/core/test_multi_role_players.py) - Role.multi() API validation
- Type safety and runtime validation
Inherited Attribute Filter Tests¶
- Created unit tests (
tests/unit/core/test_inherited_attribute_filter.py) with 9 tests: get_owned_attributes()vsget_all_attributes()behavior verificationQueryBuilder.match_entity()with inherited/owned/mixed attribute filters- Deep inheritance chain (grandparent โ parent โ child) attribute access
- Created integration tests (
tests/integration/crud/test_inherited_attribute_filter.py) with 5 tests: get()with inherited key attributedelete()with inherited attribute filter- Combined inherited + owned attribute filters
๐ฆ Key Files Modified¶
type_bridge/models/role.py- AddedRole.multi()and multi-player supporttype_bridge/schema/info.py- Generate multipleplaysdeclarationstype_bridge/crud/relation/manager.py- Multi-role query handlingtype_bridge/crud/relation/query.py- Multi-role filtering supportdocs/api/relations.md- Added "Multi-player Roles" documentationtype_bridge/crud/entity/query.py- Fixeddelete()to useget_all_attributes()type_bridge/crud/entity/manager.py- Fixeddelete()to useget_all_attributes()type_bridge/query.py- Fixedmatch_entity()to useget_all_attributes()tests/integration/crud/relations/test_multi_role.py- New multi-role test suite (37 tests)tests/unit/core/test_multi_role_players.py- New multi-role unit tests
[0.6.0] - 2025-11-24¶
๐ New Features¶
Chainable Delete and Update Operations¶
- Added
EntityQuery.delete()for chainable deletion - Delete entities after complex filtering:
manager.filter(Age.gt(Age(65))).delete() - Builds TypeQL delete query from both dict-based and expression-based filters
- Single atomic transaction with automatic rollback on error
- Returns count of deleted entities (0 if no matches)
-
Location:
type_bridge/crud.py:626-676 -
Added
EntityQuery.update_with(func)for functional bulk updates - Update multiple entities using lambda or named functions
- Example:
manager.filter(Age.gt(Age(30))).update_with(lambda p: setattr(p, 'age', Age(p.age.value + 1))) - Fetches matching entities, applies function, updates all in single transaction
- Returns list of updated entities (empty list if no matches)
- Error handling: Stops immediately and raises error if function fails on any entity
- All updates in single atomic transaction (all-or-nothing)
-
Location:
type_bridge/crud.py:678-730 -
Helper methods added
_build_update_query(entity): Builds TypeQL update query for single entity_is_multi_value_attribute(flags): Checks attribute cardinality- Reuses existing EntityManager logic for consistency
Benefits¶
- Chainable API: Natural method chaining for complex operations
- Type-safe: Full integration with expression-based filtering
- Atomic transactions: All operations are all-or-nothing
- Functional updates: Clean lambda/function-based bulk updates
- Consistent API: Works seamlessly with existing filter() method
AttributeFlags Configuration for Attribute Type Names¶
- Added
AttributeFlags.namefield - Explicitly override attribute type name:
flags = AttributeFlags(name="person_name") - Use case: Interop with existing TypeDB schemas, legacy naming conventions
-
Location:
type_bridge/attribute/flags.py:229 -
Added
AttributeFlags.casefield - Apply case formatting to attribute type names:
flags = AttributeFlags(case=TypeNameCase.SNAKE_CASE) - Supports: CLASS_NAME (default), LOWERCASE, SNAKE_CASE, KEBAB_CASE
- Use case: Consistent naming conventions across large schemas
-
Location:
type_bridge/attribute/flags.py:230 -
Updated
Attribute.__init_subclass__to use AttributeFlags - Priority: flags.name > attr_name > flags.case > class.case > default CLASS_NAME
- Respects both explicit name and case formatting
- Location:
type_bridge/attribute/base.py:108-126
Benefits¶
- Flexible naming: Support for legacy schemas and naming conventions
- Consistent API: Mirrors TypeFlags.name pattern for entities/relations
- Migration friendly: Easier interop with existing TypeDB databases
- Developer choice: Explicit name or automatic case formatting
๐๏ธ Refactoring¶
Modularized CRUD Operations¶
- Refactored monolithic
crud.py(3008 lines) into modular structure - Split into 11 focused modules under
crud/directory - Entity operations:
crud/entity/with manager, query, and group_by modules - Relation operations:
crud/relation/with manager, query, and group_by modules - Shared utilities:
crud/utils.pyforformat_valueandis_multi_value_attribute - Base definitions:
crud/base.pyfor type variables - Benefits:
- Eliminated code duplication (shared utilities now have single implementations)
- Improved maintainability (files are now 200-800 lines each)
- Better code organization and discoverability
- Preserved backward compatibility (all imports still work)
- Impact: No breaking changes, all existing code continues to work
Modularized Models¶
- Previously refactored
models.pyinto modular structure - Split into
models/directory with base, entity, relation, role, and utils modules - Improved separation of concerns and maintainability
๐ Bug Fixes¶
String Attribute Escaping in Multi-Value Attributes¶
- Fixed proper escaping of special characters in multi-value string attributes
- Backslashes are now properly escaped:
\โ\\ - Double quotes are properly escaped:
"โ\" - Escape order matters: backslashes first, then quotes
- Location:
type_bridge/query.py,type_bridge/crud.py,type_bridge/models/base.py - Impact: Multi-value string attributes with quotes or backslashes now work correctly in insert/update operations
- Examples:
- Quotes:
Tag('skill "Python"')โ TypeQL:has Tag "skill \"Python\"" - Backslashes:
Path("C:\\Users\\Alice")โ TypeQL:has Path "C:\\Users\\Alice" - Mixed:
Description(r'Path: "C:\Program Files"')โ TypeQL:has Description "Path: \"C:\\Program Files\""
๐ Documentation¶
API Documentation Updated¶
- Updated
docs/api/crud.mdwith comprehensive new sections: - Chainable Delete section with examples and behavior explanation
- Bulk Update with Function section demonstrating lambda and named function usage
- Updated EntityQuery method signatures
- Added "New in v0.6.0" markers for discoverability
-
Error handling and empty results behavior documented
-
Updated
docs/api/attributes.mdwith new section: - "Configuring Attribute Type Names" section with comprehensive examples
- Documents AttributeFlags.name for explicit type name overrides
- Documents AttributeFlags.case for automatic case formatting
- Shows priority order and all configuration options
-
Use cases and best practices
-
Updated
docs/INTERNALS.md: - Updated AttributeFlags dataclass documentation
- Added name and case fields with usage examples
- Updated cardinality field names (card_min, card_max)
README Updated¶
- Added "Chainable Operations" to features list
- Highlights filter, delete, and bulk update capabilities
- Location:
README.md
New Example Created¶
- Created
examples/advanced/crud_07_chainable_operations.py - Comprehensive demonstration of chainable delete and update
- Shows lambda functions, named functions, and complex multi-attribute updates
- Demonstrates atomic transaction behavior with rollback examples
- Interactive tutorial format with step-by-step explanations
๐งช Testing¶
Integration Tests Added¶
- Created
tests/integration/crud/entities/test_chainable.pywith 9 comprehensive tests: test_chainable_delete_with_expression_filter- Basic delete with expressionstest_chainable_delete_with_multiple_filters- Multiple filter combinationstest_chainable_delete_returns_zero_for_no_matches- Empty results handlingtest_chainable_delete_with_range_filter- Range queries (gte/lt)test_update_with_lambda_increments_age- Lambda function updatestest_update_with_function_modifies_status- Named function updatestest_update_with_returns_empty_list_for_no_matches- Empty results handlingtest_update_with_complex_function_multiple_attributes- Multi-attribute updatestest_update_with_atomic_transaction- Transaction rollback verification
Test Results¶
- All 9 tests passing โ
- Tests verify:
- Correct entity deletion with expression filters
- Accurate counts returned
- Proper transaction boundaries (atomic behavior)
- Error propagation and rollback
- Empty result handling
- Multi-attribute updates
- Lambda and function-based updates
Escaping Test Coverage Added¶
- Created comprehensive string escaping test suite
- 7 unit tests for multi-value string escaping patterns
- 9 integration tests verifying end-to-end escaping behavior
- Location:
tests/unit/attributes/test_multivalue_escaping.py,tests/integration/crud/attributes/test_multivalue_escaping.py - Test coverage includes:
- Quotes in strings:
'skill "Python"' - Backslashes in paths:
C:\Users\Alice - Mixed escaping:
"C:\Program Files\App" - Empty strings and special characters
- Unicode characters (cafรฉ, ๆฅๆฌ่ช, emoji๐)
- Single quotes (not escaped in TypeQL)
- Relations with multi-value escaping
- Batch operations:
insert_many(),update_with()
๐ฆ Key Files Modified¶
type_bridge/crud.py- Added delete() and update_with() to EntityQuery classdocs/api/crud.md- Updated API documentation with new methodsREADME.md- Added chainable operations to features listexamples/advanced/crud_07_chainable_operations.py- New comprehensive exampletests/integration/crud/entities/test_chainable.py- New integration test suitetests/unit/attributes/test_multivalue_escaping.py- New unit test suite (7 tests)tests/integration/crud/attributes/test_multivalue_escaping.py- New integration test suite (9 tests)
๐ก Usage Examples¶
Chainable Delete¶
# Delete all persons over 65
count = Person.manager(db).filter(Age.gt(Age(65))).delete()
# Delete with multiple filters
count = manager.filter(
Age.lt(Age(18)),
Status.eq(Status("inactive"))
).delete()
Chainable Update with Lambda¶
# Increment age for all persons over 30
updated = manager.filter(Age.gt(Age(30))).update_with(
lambda person: setattr(person, 'age', Age(person.age.value + 1))
)
Chainable Update with Function¶
def promote(person):
person.status = Status("senior")
person.salary = Salary(int(person.salary.value * 1.1))
promoted = manager.filter(Age.gte(Age(35))).update_with(promote)
[0.5.1] - 2025-11-20¶
๐ Bug Fixes¶
Integer Key Query Bug¶
- Fixed entities with Integer-type keys failing to query by key value
- Root cause: Attribute instances not being unwrapped before TypeQL value formatting
EntityId(123)was formatted as"123"(string) instead of123(integer)- Generated incorrect TypeQL:
has EntityId "123"causing type mismatch - Fix: Added
.valueextraction in_format_value()before type checking - Location:
type_bridge/query.py:252-256,type_bridge/crud.py:419-423,type_bridge/crud.py:1145-1149 - Impact: All non-string attribute types (Integer, Double, Decimal, Boolean, Date, DateTime, DateTimeTZ, Duration) now work correctly as entity keys and in query filters
- Silent failure fixed: Entities would insert successfully but couldn't be queried, now both work correctly
๐งช Testing¶
Regression Tests Added¶
- Created comprehensive Integer key test suite
- 5 new integration tests specifically for Integer key bug regression
- Tests cover: basic insert/query, comparison with String keys, various integer values, chainable queries, all()/count() methods
- Location:
tests/integration/crud/entities/test_integer_key_bug.py - Test Results: 422/422 tests passing (284 unit + 138 integration) โ
- All existing tests still passing
- All new regression tests passing
- Zero test failures or regressions
Why String Keys Worked¶
- String attributes need quotes in TypeQL anyway
- Bug accidentally produced correct output:
"KEY-123" - Integer, Boolean, Double, etc. require unquoted values in TypeQL
- These would fail with incorrect quoting:
"123","true","3.14"
๐ฆ Key Files Modified¶
type_bridge/query.py- Fixed_format_value()functiontype_bridge/crud.py- FixedEntityManager._format_value()andRelationManager._format_value()tests/integration/crud/entities/test_integer_key_bug.py- New regression test suite (5 tests)
[0.5.0] - 2025-11-20¶
๐ New Features¶
Concise Attribute Type-Based Expression API¶
- New streamlined query API using attribute class methods
- Old:
Person.age.gt(Age(30))โ New:Age.gt(Age(30))โจ - Shorter, more readable syntax with better type checking support
- Type checkers now correctly validate all expression methods
- Location:
type_bridge/attribute/base.py,type_bridge/attribute/string.py
Class Methods Added to Attribute Base Class¶
- Comparison methods:
gt(),lt(),gte(),lte(),eq(),neq() - Example:
Age.gt(Age(30)),Salary.gte(Salary(80000)) - Aggregation methods:
sum(),avg(),max(),min(),median(),std() - Example:
Salary.avg(),Age.sum() - String-specific methods (on
Stringclass):contains(),like(),regex() - Example:
Email.contains(Email("@company.com")),Name.like(Name("^A.*"))
Runtime Validation¶
- Automatic attribute ownership validation in filter() methods
- Validates that entity owns the attribute type being queried
- Raises
ValueErrorwith helpful message if validation fails - Example:
person_manager.filter(Salary.gt(Salary(50000)))validates Person owns Salary - Location:
type_bridge/crud.py,type_bridge/expressions/base.py
๐ API Changes¶
Expression Classes Refactored¶
- Changed from field-based to attribute type-based
ComparisonExpr,StringExpr,AggregateExprnow useattr_typeinstead offield- Simpler internal structure with 1-to-1 mapping (attribute type uniquely identifies field)
- Location:
type_bridge/expressions/comparison.py,type_bridge/expressions/string.py,type_bridge/expressions/aggregate.py
Backwards Compatibility¶
- Old field-based API still works
Person.age.gt(Age(30))continues to work alongside new API- FieldRef classes now delegate to attribute class methods internally
- Gradual migration path for existing code
- Location:
type_bridge/fields.py
๐ง Type Safety Improvements¶
Keyword-Only Arguments Enforced¶
- Changed
@dataclass_transform(kw_only_default=False)โTrue - All Entity/Relation constructors now require keyword arguments for clarity and safety
- Improves code readability and prevents positional argument order errors
- Example:
Person(name=Name("Alice"), age=Age(30))โ - Positional args now rejected by type checkers:
Person(Name("Alice"), Age(30))โ - Location:
type_bridge/models/base.py:20,type_bridge/models/entity.py:81,type_bridge/models/relation.py:30
Optional Field Defaults Required¶
- Added explicit
= Nonedefaults for all optional fields - Pattern:
age: Age | None = None(previouslyage: Age | None) - Makes field optionality explicit in code for better clarity
- Improves IDE autocomplete and type checking accuracy
- Required by
kw_only_default=Trueto distinguish optional from required fields - Applied throughout codebase: examples, tests, integration tests
Pyright Type Checking Configuration¶
- Added
pyrightconfig.jsonfor project-wide type checking - Excludes validation tests from type checking (
tests/unit/type-check-except/) - Tests intentionally checking Pydantic validation failures now properly excluded
- Core library achieves 0 errors, 0 warnings, 0 informations โจ
- Proper separation of type-safe code vs runtime validation tests
- Location:
pyrightconfig.json(new file)
Validation Tests Reorganized¶
- Moved intentional validation tests to
tests/unit/type-check-except/ - Tests using raw values to verify Pydantic validation now excluded from type checking
- Original tests fixed to use properly wrapped attribute types
- Clean separation: type-safe tests vs validation behavior tests
- Moved files:
test_pydantic.py,test_basic.py,test_update_api.py,test_cardinality.py,test_list_default.py
Benefits¶
- Clearer code: Keyword arguments make field names explicit at call sites
- Better IDE support: Explicit
= Noneimproves autocomplete for optional fields - 100% type safety: Pyright validates correctly with zero false positives
- Maintainability: Adding new fields doesn't break existing constructor calls
- Error prevention: Type checker catches argument order mistakes at development time
๐ Documentation¶
Automatic Conversions Documented¶
avg()โmeanin TypeQL- TypeDB 3.x uses
meaninstead ofavg - User calls
Age.avg(), generatesmean($age)in TypeQL - Result key converted back to
avg_agefor consistency - Clearly documented in docstrings and implementation comments
regex()โlikein TypeQL- TypeQL uses
likefor regex pattern matching regex()provided as user-friendly alias- Both methods generate identical TypeQL output
- Documented in method docstrings and code comments
TypeQL Compliance Verification¶
- All expressions verified against TypeDB 3.x specification
- Comparison operators:
>,<,>=,<=,==,!=โ - String operations:
contains,likeโ - Aggregations:
sum,mean,max,min,median,std,countโ - Boolean logic:
;(AND),or,notโ - Created
tmp/typeql_verification.mdandtmp/automatic_conversions.md
Examples Updated¶
- Updated query_expressions.py to use new API
- All field-based expressions converted to attribute type-based
- Added notes about API improvements and type safety
- Location:
examples/advanced/query_expressions.py
๐งช Testing¶
Test Results¶
- 417/417 tests passing (100% pass rate) โ
- Unit tests: 284/284 passing (0.3s)
- Integration tests: 133/133 passing
- Type checking: 0 errors, 0 warnings, 0 informations โ
- All type errors eliminated (250 errors โ 0 errors)
Tests Updated¶
- Updated field reference tests for new API
- Tests now check
attr_typeinstead offieldattributes - All expression creation and TypeQL generation tests passing
- Location:
tests/unit/expressions/test_field_refs.py
Test Organization¶
- Integration tests reorganized into subdirectories
tests/integration/queries/test_expressions.py- Query expression integration teststests/integration/crud/relations/test_abstract_roles.py- Abstract role type tests- Better organization: crud/, queries/, schema/ subdirectories
- Improved test discoverability and maintenance
๐ง Type Safety¶
Type Checking Improvements¶
- Eliminated all expression-related type errors
- Before: 26 errors (
.gt(),.avg()"not a known attribute" errors) - After: 0 errors โ
- Type checkers now fully understand class method API
- Pyright passes with 0 errors, 0 warnings, 0 informations
Benefits¶
- Type-safe: Full type checker support with zero errors
- Concise: Shorter syntax (
Age.gt()vsPerson.age.gt()) - Validated: Runtime checks prevent invalid queries
- Compatible: Old API still works for gradual migration
- Documented: All automatic conversions clearly explained
๐ฆ Key Files Modified¶
type_bridge/attribute/base.py- Added class methods for comparisons and aggregationstype_bridge/attribute/string.py- Added string-specific class methodstype_bridge/expressions/comparison.py- Changed toattr_type-basedtype_bridge/expressions/string.py- Changed toattr_type-basedtype_bridge/expressions/aggregate.py- Changed toattr_type-basedtype_bridge/expressions/base.py- Addedget_attribute_types()methodtype_bridge/expressions/boolean.py- Added recursive attribute type collectiontype_bridge/fields.py- Updated to delegate to attribute class methodstype_bridge/crud.py- Added validation in filter() methodsexamples/advanced/query_expressions.py- Updated to use new API
[0.4.4] - 2025-11-19¶
๐ Bug Fixes¶
- Fixed inherited attributes not included in insert/get operations
- Entity and Relation insert queries now include all inherited attributes
- Fetch operations properly extract inherited attribute values
- Added
get_all_attributes()method to collect attributes from entire class hierarchy - Location:
type_bridge/models/base.py,type_bridge/models/entity.py,type_bridge/crud.py
๐ API Changes¶
- Removed deprecated
EntityFlagsandRelationFlagsaliases - Use
TypeFlagsfor both entities and relations - All example files updated to use
TypeFlags - Documentation updated to reflect unified API
๐ Documentation¶
- Updated CLAUDE.md: Replaced all EntityFlags/RelationFlags references with TypeFlags
- Updated examples: All 17 example files now use the unified TypeFlags API
[0.4.0] - 2025-11-15¶
๐ New Features¶
Docker Integration for Testing¶
- Automated Docker management for integration tests
- Added
docker-compose.ymlwith TypeDB 3.5.5 server configuration - Created
test-integration.shscript for automated Docker lifecycle management - Docker containers start/stop automatically with test fixtures
- Location:
docker-compose.yml,test-integration.sh,tests/integration/conftest.py - Optional Docker usage: Set
USE_DOCKER=falseto use existing TypeDB server - Port configuration: TypeDB server on port 1729
Schema Validation¶
- Duplicate attribute type detection
- Prevents using the same attribute type for multiple fields in an entity/relation
- Validates during schema generation to catch design errors early
- Raises
SchemaValidationErrorwith detailed field information - Location:
type_bridge/schema/info.py,type_bridge/schema/exceptions.py - Why it matters: TypeDB stores ownership by attribute type, not by field name
- Using
created: TimeStampandmodified: TimeStampcreates a single ownership - This causes cardinality constraint violations at runtime
- Solution: Use distinct types like
CreatedStampandModifiedStamp
๐งช Testing¶
Test Infrastructure¶
- Improved test organization: 347 total tests (249 unit + 98 integration)
- Docker-based integration tests: Automatic container lifecycle management
- Added duplicate attribute validation tests: 6 new tests for schema validation
- Location:
tests/unit/validation/test_duplicate_attributes.py
๐ Documentation¶
- Updated CLAUDE.md:
- Added Docker setup instructions for integration tests
- Documented duplicate attribute type validation rules
- Added schema validation best practices
- Included examples of correct vs incorrect attribute usage
- Updated test execution patterns: Docker vs manual TypeDB server options
๐ง CI/CD¶
- Updated GitHub Actions workflow:
- Integrated Docker Compose for automated integration testing
- Added TypeDB 3.5.5 service container configuration
- Location:
.github/workflows/(multiple CI updates)
๐ฆ Dependencies¶
- Added
docker-composesupport for development workflow - No changes to runtime dependencies
๐ Bug Fixes¶
- Fixed test fixture ordering: Improved integration test reliability with Docker
- Enhanced error messages: Schema validation errors now include field names
[0.3.X] - 2025-01-14¶
โ Full TypeDB 3.x Compatibility¶
Major Achievement: 100% Test Pass Rate (341/341 tests)
Fixed¶
Query Pagination¶
- Fixed TypeQL clause ordering: offset must come BEFORE limit in TypeDB 3.x
- Changed
limit X; offset Y;โoffset Y; limit X; - Location:
type_bridge/query.py:151-154 - Added automatic sorting for pagination: TypeDB 3.x requires sorting for reliable offset results
- Automatically finds and sorts by key attributes when using limit/offset
- Falls back to required attributes if no key exists
- Location:
type_bridge/crud.py:447-468
Schema Conflict Detection¶
- Updated to TypeDB 3.x syntax: Changed from
subtoisafor type queries - TypeDB 3.x uses
$e isa personinstead of$e sub entity - Fixed
has_existing_schema()to properly detect existing types - Fixed
_type_exists()to use correct TypeQL syntax - Location:
type_bridge/schema/manager.py:65-284 - Improved conflict detection: Now properly raises SchemaConflictError when types exist
Type Safety¶
- Fixed AttributeFlags attribute access: Changed
cardinality_mintocard_min - Resolved pyright type checking error
- Location:
type_bridge/crud.py:460
Testing¶
Test Results¶
- Unit tests: 243/243 passing (100%) - ~0.3s runtime
- Integration tests: 98/98 passing (100%) - ~18s runtime
- Total: 341/341 passing (100%)
Test Coverage¶
- All 9 TypeDB attribute types fully tested (Boolean, Date, DateTime, DateTimeTZ, Decimal, Double, Duration, Integer, String)
- Full CRUD operations for each type (insert, fetch, update, delete)
- Multi-value attribute operations
- Query pagination with limit/offset/sort
- Schema conflict detection and inheritance
- Reserved word validation
Code Quality¶
- โ Ruff linting: 0 errors, 0 warnings
- โ Ruff formatting: All 112 files properly formatted
- โ Pyright type checking: 0 errors, 0 warnings, 0 informations
Documentation¶
- Updated README.md with current test counts and features
- Updated CLAUDE.md testing strategy section
- Added TypeDB 3.x compatibility notes
- Documented pagination requirements and automatic sorting
Key Files Modified¶
type_bridge/query.py- Fixed clause ordering in build()type_bridge/crud.py- Added automatic sorting for pagination, fixed attribute accesstype_bridge/schema/manager.py- Updated to TypeDB 3.xisasyntax
[0.2.0] - Previous Release¶
See git history for earlier changes.