ferro-orm 0.12.3__tar.gz → 0.14.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/.github/workflows/ci.yml +5 -2
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/AGENTS.md +48 -25
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/CHANGELOG.md +187 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/Cargo.lock +180 -32
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/Cargo.toml +11 -3
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/PKG-INFO +4 -4
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/README.md +3 -3
- ferro_orm-0.14.0/benchmarks/README.md +133 -0
- ferro_orm-0.14.0/benchmarks/__init__.py +11 -0
- ferro_orm-0.14.0/benchmarks/__main__.py +10 -0
- ferro_orm-0.14.0/benchmarks/backends.py +88 -0
- ferro_orm-0.14.0/benchmarks/baselines/postgres.json +49 -0
- ferro_orm-0.14.0/benchmarks/baselines/sqlite.json +49 -0
- ferro_orm-0.14.0/benchmarks/compare.py +98 -0
- ferro_orm-0.14.0/benchmarks/harness.py +99 -0
- ferro_orm-0.14.0/benchmarks/model.py +84 -0
- ferro_orm-0.14.0/benchmarks/run.py +270 -0
- {ferro_orm-0.12.3/crates/ferro-migrate → ferro_orm-0.14.0/crates/ferro-ddl-lowering}/Cargo.toml +3 -1
- ferro_orm-0.14.0/crates/ferro-ddl-lowering/src/lib.rs +1509 -0
- ferro_orm-0.14.0/crates/ferro-migrate/Cargo.toml +10 -0
- ferro_orm-0.14.0/crates/ferro-migrate/src/emit.rs +712 -0
- ferro_orm-0.14.0/crates/ferro-migrate/src/lib.rs +322 -0
- ferro_orm-0.14.0/crates/ferro-migrate/src/tests.rs +1461 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/crates/ferro-schema-ir/src/lib.rs +101 -2
- ferro_orm-0.14.0/docs/brainstorms/2026-06-24-ir-p8-119-wire-automigrate-requirements.md +116 -0
- ferro_orm-0.14.0/docs/brainstorms/2026-06-25-ir-p8-120-parity-gate-requirements.md +119 -0
- ferro_orm-0.14.0/docs/brainstorms/2026-06-26-ir-p8.5-140-shared-lowering-requirements.md +111 -0
- ferro_orm-0.14.0/docs/brainstorms/2026-06-26-ir-p8.5-143-db-type-drop-requirements.md +116 -0
- ferro_orm-0.14.0/docs/brainstorms/2026-06-26-ir-p8.5-144-reconcile-indexes-requirements.md +130 -0
- ferro_orm-0.14.0/docs/brainstorms/2026-06-28-ir-p8.5-141-single-schema-ir-producer-requirements.md +166 -0
- ferro_orm-0.14.0/docs/brainstorms/2026-06-29-ir-p8.6-146-dialect-enum-unification-requirements.md +264 -0
- ferro_orm-0.14.0/docs/brainstorms/2026-06-29-ir-p8.6-153-create-path-ir-requirements.md +331 -0
- ferro_orm-0.14.0/docs/brainstorms/2026-06-30-ir-p8.6-155-deferred-annotations-requirements.md +338 -0
- ferro_orm-0.14.0/docs/brainstorms/2026-06-30-ir-p8.6-158-check-renderer-requirements.md +358 -0
- ferro_orm-0.14.0/docs/brainstorms/2026-07-01-ir-p8.6-154-datetime-tz-coarseness-requirements.md +327 -0
- ferro_orm-0.14.0/docs/brainstorms/2026-07-01-ir-p8.6-162-typed-save-bind-requirements.md +307 -0
- ferro_orm-0.14.0/docs/brainstorms/2026-07-01-ir-p8.6-165-blob-introspection-false-positive-requirements.md +353 -0
- ferro_orm-0.14.0/docs/brainstorms/2026-07-02-ff-c1-codec-plan-design.md +150 -0
- ferro_orm-0.14.0/docs/brainstorms/2026-07-06-upgrade-guide-consolidation-requirements.md +222 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/examples/multiple_databases.py +9 -7
- ferro_orm-0.14.0/docs/examples/mutations.py +112 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/examples/pagination.py +12 -10
- ferro_orm-0.14.0/docs/examples/predicates.py +84 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/examples/predicates_annotated.py +13 -11
- ferro_orm-0.14.0/docs/examples/quickstart.py +112 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/examples/quickstart_annotated.py +8 -7
- ferro_orm-0.14.0/docs/examples/raw_sql.py +45 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/examples/relationships.py +37 -36
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/examples/relationships_annotated.py +19 -18
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/examples/soft_deletes.py +12 -11
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/examples/soft_deletes_annotated.py +10 -9
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/examples/testing_conftest.py +3 -2
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/examples/timestamps.py +10 -9
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/examples/timestamps_annotated.py +8 -7
- ferro_orm-0.14.0/docs/examples/transactions.py +59 -0
- ferro_orm-0.14.0/docs/pages/api/exceptions.md +57 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/api/migrations.md +1 -1
- ferro_orm-0.14.0/docs/pages/api/queries.md +9 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/concepts/architecture.md +17 -6
- ferro_orm-0.14.0/docs/pages/concepts/identity-map.md +227 -0
- ferro_orm-0.14.0/docs/pages/concepts/query-typing.md +56 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/concepts/type-safety.md +2 -2
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/faq.md +3 -1
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/getting-started/quickstart.md +3 -3
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/guide/connections.md +2 -2
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/guide/migrations.md +3 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/guide/models-and-fields.md +64 -1
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/guide/mutations.md +72 -16
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/guide/queries.md +49 -42
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/howto/migrate-from-sqlalchemy.md +4 -4
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/howto/multiple-databases.md +5 -3
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/howto/pagination.md +2 -2
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/howto/soft-deletes.md +1 -1
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/howto/testing.md +7 -5
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/howto/timestamps.md +13 -1
- ferro_orm-0.14.0/docs/pages/howto/upgrade-guide.md +446 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/plans/2026-06-19-001-ir-first-roadmap.md +244 -24
- ferro_orm-0.14.0/docs/plans/2026-06-24-001-feat-ir-p8-119-wire-automigrate-plan.md +301 -0
- ferro_orm-0.14.0/docs/plans/2026-06-25-001-feat-ir-p8-120-parity-gate-plan.md +286 -0
- ferro_orm-0.14.0/docs/plans/2026-06-26-001-feat-ir-p8.5-140-shared-lowering-plan.md +311 -0
- ferro_orm-0.14.0/docs/plans/2026-06-26-002-feat-ir-p8.5-143-db-type-drop-plan.md +229 -0
- ferro_orm-0.14.0/docs/plans/2026-06-26-003-feat-ir-p8.5-144-reconcile-indexes-plan.md +503 -0
- ferro_orm-0.14.0/docs/plans/2026-06-28-001-feat-ir-p8.5-141-single-schema-ir-producer-plan.md +394 -0
- ferro_orm-0.14.0/docs/plans/2026-06-29-001-refactor-ir-p8.6-153-create-path-unification-plan.md +362 -0
- ferro_orm-0.14.0/docs/plans/2026-06-29-002-refactor-ir-p8.6-146-dialect-enum-unification-plan.md +388 -0
- ferro_orm-0.14.0/docs/plans/2026-06-30-001-refactor-ir-p8.6-158-check-renderer-plan.md +670 -0
- ferro_orm-0.14.0/docs/plans/2026-06-30-002-fix-ir-p8.6-155-deferred-annotations-plan.md +341 -0
- ferro_orm-0.14.0/docs/plans/2026-07-01-001-feat-ir-p8.6-162-typed-save-bind-plan.md +917 -0
- ferro_orm-0.14.0/docs/plans/2026-07-01-002-fix-ir-p8.6-154-datetime-tz-coarseness-plan.md +467 -0
- ferro_orm-0.14.0/docs/plans/2026-07-01-003-fix-ir-p8.6-165-blob-introspection-plan.md +307 -0
- ferro_orm-0.14.0/docs/plans/2026-07-02-001-fable-fixes-roadmap.md +449 -0
- ferro_orm-0.14.0/docs/plans/2026-07-02-002-feat-ff-a-172-typed-exceptions-plan.md +37 -0
- ferro_orm-0.14.0/docs/plans/2026-07-02-003-ff-c-native-decode-design.md +105 -0
- ferro_orm-0.14.0/docs/plans/2026-07-02-004-ff-c-c2-catalog-cache-design.md +159 -0
- ferro_orm-0.14.0/docs/plans/2026-07-02-005-ff-d-identity-routing-design.md +207 -0
- ferro_orm-0.14.0/docs/plans/2026-07-02-006-ff-d-identity-routing-plan.md +1474 -0
- ferro_orm-0.14.0/docs/plans/2026-07-03-007-ff-e-registry-identity-design.md +267 -0
- ferro_orm-0.14.0/docs/plans/2026-07-03-008-ff-e-registry-identity-plan.md +1584 -0
- ferro_orm-0.14.0/docs/plans/2026-07-06-009-ff-f-query-builder-1.0-design.md +152 -0
- ferro_orm-0.14.0/docs/plans/2026-07-06-010-ff-f-query-builder-1.0-plan.md +1290 -0
- ferro_orm-0.14.0/docs/plans/2026-07-06-011-ff-g-hardening-design.md +268 -0
- ferro_orm-0.14.0/docs/plans/2026-07-06-012-ff-g-hardening-plan.md +985 -0
- ferro_orm-0.14.0/docs/plans/2026-07-06-013-ff-g2-operations-dedup-design.md +193 -0
- ferro_orm-0.14.0/docs/plans/2026-07-06-014-ff-g2-operations-dedup-plan.md +1203 -0
- ferro_orm-0.14.0/docs/plans/2026-07-06-015-docs-upgrade-guide-consolidation-plan.md +518 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/plans/ir-first-migration-guide.md +21 -4
- ferro_orm-0.14.0/docs/solutions/architecture-patterns/ir-first-lowering-consolidation-audit.md +246 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/solutions/architecture-patterns/ir-first-merge-readiness-review.md +1 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/solutions/issues/sa-pk-column-nullable-divergence.md +10 -1
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/solutions/issues/sa-vs-rust-unique-constraint-shape.md +13 -1
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/solutions/patterns/cross-emitter-ddl-parity.md +37 -9
- ferro_orm-0.14.0/docs/solutions/patterns/derived-type-and-naming-decision-table.md +161 -0
- ferro_orm-0.14.0/docs/solutions/patterns/persistence-state.md +76 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/justfile +6 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/pyproject.toml +2 -4
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/backend.rs +280 -44
- ferro_orm-0.14.0/src/codec.rs +523 -0
- ferro_orm-0.14.0/src/codec_plan.rs +591 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/connection.rs +56 -28
- ferro_orm-0.14.0/src/errors.rs +181 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/__init__.py +113 -9
- ferro_orm-0.14.0/src/ferro/_bind_payload.py +51 -0
- ferro_orm-0.14.0/src/ferro/_core.pyi +236 -0
- ferro_orm-0.14.0/src/ferro/exceptions.py +134 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/ir/compiler.py +56 -46
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/metaclass.py +118 -25
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/migrations/alembic.py +99 -76
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/models.py +224 -144
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/query/__init__.py +1 -2
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/query/builder.py +183 -206
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/query/nodes.py +61 -129
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/raw.py +17 -24
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/relations/__init__.py +36 -17
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/relations/descriptors.py +3 -11
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/schema_metadata.py +20 -1
- ferro_orm-0.14.0/src/ferro/state.py +217 -0
- ferro_orm-0.14.0/src/hydration.rs +286 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/introspect.rs +109 -8
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/lib.rs +36 -5
- ferro_orm-0.14.0/src/migrate.rs +2438 -0
- ferro_orm-0.14.0/src/naming_ffi.rs +92 -0
- ferro_orm-0.14.0/src/operations.rs +3856 -0
- ferro_orm-0.14.0/src/query.rs +558 -0
- ferro_orm-0.14.0/src/schema.rs +622 -0
- ferro_orm-0.14.0/src/schema_bind.rs +23 -0
- ferro_orm-0.14.0/src/state.rs +641 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/conftest.py +25 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/fixtures/ir_vectors/schema_invoice_baseline_v1.json +11 -8
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/fixtures/ir_vectors/schema_phase1_fixture_models_v1.json +118 -16
- ferro_orm-0.14.0/tests/fixtures/shadow_reports/postgres.json +32 -0
- ferro_orm-0.14.0/tests/fixtures/shadow_reports/sqlite.json +32 -0
- ferro_orm-0.14.0/tests/static_fixtures/bad_predicates.py +19 -0
- ferro_orm-0.14.0/tests/static_fixtures/good_predicates.py +20 -0
- ferro_orm-0.14.0/tests/test_aggregation.py +74 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_alembic_autogenerate.py +13 -10
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_alembic_bridge.py +45 -17
- ferro_orm-0.14.0/tests/test_auto_migrate.py +1313 -0
- ferro_orm-0.14.0/tests/test_bulk_update.py +66 -0
- ferro_orm-0.14.0/tests/test_catalog_cache.py +244 -0
- ferro_orm-0.14.0/tests/test_codec_plan.py +81 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_composite_index.py +21 -17
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_composite_unique.py +19 -17
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_connection.py +92 -31
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_connection_redaction.py +2 -2
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_constraints.py +6 -7
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_cross_emitter_parity.py +63 -74
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_crud.py +86 -59
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_db_type_cross_emitter_parity.py +173 -15
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_db_type_integration.py +56 -52
- ferro_orm-0.14.0/tests/test_deletion.py +90 -0
- ferro_orm-0.14.0/tests/test_documentation_features.py +874 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_enum_cold_hydration.py +11 -8
- ferro_orm-0.14.0/tests/test_exception_mapping.py +160 -0
- ferro_orm-0.14.0/tests/test_exceptions.py +126 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_field_wrapper.py +17 -11
- ferro_orm-0.14.0/tests/test_fk_target_pk.py +69 -0
- ferro_orm-0.14.0/tests/test_helpers.py +136 -0
- ferro_orm-0.14.0/tests/test_hydration.py +204 -0
- ferro_orm-0.14.0/tests/test_hydration_equivalence.py +275 -0
- ferro_orm-0.14.0/tests/test_identity_memory.py +80 -0
- ferro_orm-0.14.0/tests/test_identity_refresh.py +79 -0
- ferro_orm-0.14.0/tests/test_identity_scoped_invalidation.py +86 -0
- ferro_orm-0.14.0/tests/test_identity_weakref.py +37 -0
- ferro_orm-0.14.0/tests/test_import_budget.py +38 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_ir_vectors_contract.py +92 -1
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_metaclass_internals.py +44 -5
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_metadata.py +25 -22
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_migrate_plan.py +99 -14
- ferro_orm-0.14.0/tests/test_model_identity.py +234 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_models.py +4 -1
- ferro_orm-0.14.0/tests/test_mutation_pagination_guard.py +99 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_named_connections_integration.py +52 -32
- ferro_orm-0.14.0/tests/test_naming_single_source.py +315 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_one_to_one.py +22 -20
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_query_builder.py +90 -112
- ferro_orm-0.14.0/tests/test_query_column_validation.py +151 -0
- ferro_orm-0.14.0/tests/test_query_immutability.py +101 -0
- ferro_orm-0.14.0/tests/test_query_typing.py +173 -0
- ferro_orm-0.14.0/tests/test_raw_sql.py +528 -0
- ferro_orm-0.14.0/tests/test_refresh.py +55 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_relationship_engine.py +10 -2
- ferro_orm-0.14.0/tests/test_relationship_resolution_errors.py +47 -0
- ferro_orm-0.14.0/tests/test_route_single_site.py +33 -0
- ferro_orm-0.14.0/tests/test_routing_errors.py +64 -0
- ferro_orm-0.14.0/tests/test_save_pk_edges.py +53 -0
- ferro_orm-0.14.0/tests/test_save_semantics.py +358 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_schema.py +6 -6
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_session.py +14 -18
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_shadow_fk_types.py +58 -54
- ferro_orm-0.14.0/tests/test_shadow_reports.py +107 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_sqlite_alembic_reconnect_hydration.py +21 -11
- ferro_orm-0.14.0/tests/test_static_contracts.py +191 -0
- ferro_orm-0.14.0/tests/test_string_search.py +54 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_structural_types.py +152 -140
- ferro_orm-0.14.0/tests/test_temporal_types.py +75 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_transactions.py +134 -117
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_typed_null_binds.py +130 -115
- ferro_orm-0.14.0/tests/test_typed_save_bind.py +196 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/uv.lock +28 -1
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/zensical.toml +2 -2
- ferro_orm-0.12.3/crates/ferro-migrate/src/lib.rs +0 -271
- ferro_orm-0.12.3/docs/examples/mutations.py +0 -49
- ferro_orm-0.12.3/docs/examples/predicates.py +0 -92
- ferro_orm-0.12.3/docs/examples/quickstart.py +0 -111
- ferro_orm-0.12.3/docs/examples/raw_sql.py +0 -43
- ferro_orm-0.12.3/docs/examples/transactions.py +0 -58
- ferro_orm-0.12.3/docs/pages/api/exceptions.md +0 -5
- ferro_orm-0.12.3/docs/pages/api/queries.md +0 -11
- ferro_orm-0.12.3/docs/pages/concepts/identity-map.md +0 -151
- ferro_orm-0.12.3/docs/pages/concepts/query-typing.md +0 -106
- ferro_orm-0.12.3/docs/pages/howto/migrating-to-v0-12-0.md +0 -151
- ferro_orm-0.12.3/src/codec.rs +0 -517
- ferro_orm-0.12.3/src/ferro/_core.pyi +0 -199
- ferro_orm-0.12.3/src/ferro/exceptions.py +0 -17
- ferro_orm-0.12.3/src/ferro/state.py +0 -166
- ferro_orm-0.12.3/src/hydration.rs +0 -57
- ferro_orm-0.12.3/src/migrate.rs +0 -1481
- ferro_orm-0.12.3/src/operations.rs +0 -3228
- ferro_orm-0.12.3/src/query.rs +0 -853
- ferro_orm-0.12.3/src/schema.rs +0 -1166
- ferro_orm-0.12.3/src/schema_bind.rs +0 -49
- ferro_orm-0.12.3/src/state.rs +0 -328
- ferro_orm-0.12.3/tests/fixtures/shadow_reports/postgres.json +0 -47
- ferro_orm-0.12.3/tests/fixtures/shadow_reports/sqlite.json +0 -47
- ferro_orm-0.12.3/tests/test_aggregation.py +0 -70
- ferro_orm-0.12.3/tests/test_auto_migrate.py +0 -582
- ferro_orm-0.12.3/tests/test_bulk_update.py +0 -62
- ferro_orm-0.12.3/tests/test_deletion.py +0 -87
- ferro_orm-0.12.3/tests/test_deprecated_operator_inventory.py +0 -51
- ferro_orm-0.12.3/tests/test_documentation_features.py +0 -833
- ferro_orm-0.12.3/tests/test_framework_predicates.py +0 -72
- ferro_orm-0.12.3/tests/test_helpers.py +0 -129
- ferro_orm-0.12.3/tests/test_hydration.py +0 -167
- ferro_orm-0.12.3/tests/test_query_typing.py +0 -295
- ferro_orm-0.12.3/tests/test_raw_sql.py +0 -493
- ferro_orm-0.12.3/tests/test_refresh.py +0 -53
- ferro_orm-0.12.3/tests/test_shadow_reports.py +0 -112
- ferro_orm-0.12.3/tests/test_static_contracts.py +0 -8
- ferro_orm-0.12.3/tests/test_string_search.py +0 -52
- ferro_orm-0.12.3/tests/test_temporal_types.py +0 -71
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/.github/PERMISSIONS.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/.github/PYPI_CHECKLIST.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/.github/PYPI_SETUP.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/.github/generated/wheels.generated.yml +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/.github/pull_request_template.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/.github/workflows/packaging-smoke.yml +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/.github/workflows/publish-docs.yml +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/.github/workflows/publish.yml +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/.github/workflows/release.yml +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/.gitignore +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/.pre-commit-config.yaml +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/.python-version +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/CONTRIBUTING.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/LICENSE +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/crates/ferro-schema-ir/Cargo.toml +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/brainstorms/2026-04-29-named-connections-role-routing-requirements.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/brainstorms/2026-05-08-typed-query-predicates-requirements.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/brainstorms/2026-05-13-configurable-column-storage-types-requirements.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/brainstorms/2026-05-14-autogenerate-support-for-db-type-requirements.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/brainstorms/2026-05-25-annotated-strenum-cold-hydration-requirements.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/api/connection.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/api/fields.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/api/model.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/api/raw-sql.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/api/relationships.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/api/transactions.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/changelog.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/concepts/backends.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/concepts/performance.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/contributing.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/getting-started/installation.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/getting-started/next-steps.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/guide/raw-sql.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/guide/relationships.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/guide/transactions.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/index.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/roadmap.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/stylesheets/extra.css +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/pages/why-ferro.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/plans/2026-04-24-001-refactor-multi-db-backend-architecture-plan.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/plans/2026-04-29-001-typed-null-binds-plan.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/plans/2026-04-29-002-feat-named-connections-plan.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/plans/2026-05-07-001-refactor-generic-model-connection-plan.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/plans/2026-05-08-001-feat-typed-query-predicates-plan.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/plans/2026-05-13-001-feat-configurable-column-storage-types-plan.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/plans/2026-05-25-001-fix-annotated-strenum-cold-hydration-plan.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/plans/ir-first-release-checklist.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/rfc/ir-contracts-v1.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/solutions/README.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/solutions/issues/pydantic-slots-missing-after-ferro-hydration.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/solutions/issues/python-3.14-deferred-annotation-typeerror-swallow.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/solutions/issues/sqlite-integer-decimal-hydrates-as-none.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/solutions/issues/sqlite-null-hydrates-as-int-zero.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/solutions/issues/typed-where-null-panics-is-null.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/solutions/patterns/configurable-column-storage-types.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/solutions/patterns/ddl-on-live-engine.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/solutions/patterns/foreign-key-index.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/solutions/patterns/index-unique-redundancy.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/solutions/patterns/ir-invariants.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/solutions/patterns/shadow-fk-columns.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/solutions/patterns/sqlite-alembic-reconnect-hydration-tests.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/docs/solutions/patterns/typed-null-binds.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/scripts/demo_queries.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/scripts/demo_queries_pre_v012.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/_annotation_utils.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/_deprecations.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/_shadow_fk_types.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/base.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/composite_indexes.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/composite_uniques.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/fields.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/ir/__init__.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/migrations/__init__.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/py.typed +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/src/ferro/session.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/__init__.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/db_backends.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/fixtures/ir_vectors/README.md +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/fixtures/ir_vectors/codec_registry_core_v1.json +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/fixtures/ir_vectors/query_user_compound_v1.json +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_alembic_db_type.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_alembic_nullability.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_alembic_type_mapping.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_db_backends.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_db_type_typing.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_db_type_validation.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_deprecations.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_docs_examples.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_schema_constraints.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_schema_db_type_metadata.py +0 -0
- {ferro_orm-0.12.3 → ferro_orm-0.14.0}/tests/test_schema_enum_annotations.py +0 -0
|
@@ -3,9 +3,8 @@ name: CI
|
|
|
3
3
|
on:
|
|
4
4
|
workflow_call:
|
|
5
5
|
pull_request:
|
|
6
|
-
branches: [main, feat/ir-first]
|
|
7
6
|
push:
|
|
8
|
-
branches: [main
|
|
7
|
+
branches: [main]
|
|
9
8
|
workflow_dispatch:
|
|
10
9
|
|
|
11
10
|
concurrency:
|
|
@@ -153,6 +152,10 @@ jobs:
|
|
|
153
152
|
run: |
|
|
154
153
|
uv run maturin develop
|
|
155
154
|
|
|
155
|
+
- name: Static type gate (ty, scoped)
|
|
156
|
+
run: |
|
|
157
|
+
uv run ty check src/ferro/query tests/test_query_typing.py tests/test_static_contracts.py
|
|
158
|
+
|
|
156
159
|
- name: Run IR vector contract harness
|
|
157
160
|
run: |
|
|
158
161
|
uv run pytest -v tests/test_ir_vectors_contract.py
|
|
@@ -27,18 +27,23 @@ For a single model, every emitter must agree on:
|
|
|
27
27
|
|
|
28
28
|
1. **Table name** — already handled by `model_name.lower()`.
|
|
29
29
|
2. **Column names** — including shadow `*_id` columns from `ForeignKey`.
|
|
30
|
-
3. **Column types** —
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
`
|
|
35
|
-
|
|
36
|
-
`tests/test_db_type_cross_emitter_parity.py
|
|
30
|
+
3. **Column types** — decided by ONE function:
|
|
31
|
+
`ferro_ddl_lowering::resolve_column_storage` (explicit `db_type` token →
|
|
32
|
+
native-enum resolution → the `canonical_from_parts` cascade). The Alembic
|
|
33
|
+
bridge consumes it mechanically over FFI (`_core._resolve_storage_type`)
|
|
34
|
+
and `_db_type_to_sa_type` is only the SA *rendering* of the shared token
|
|
35
|
+
vocabulary — never a second decision table. Pinned exhaustively by
|
|
36
|
+
`tests/test_db_type_cross_emitter_parity.py` (every token and every
|
|
37
|
+
derived annotation × both dialects). See
|
|
38
|
+
`docs/solutions/patterns/derived-type-and-naming-decision-table.md`.
|
|
37
39
|
4. **Index names** — `idx_<table>_<col>` for single-column indexes,
|
|
38
40
|
`idx_<table>_<col1>_<col2>...` for composite indexes.
|
|
39
41
|
5. **Unique constraint names** — `uq_<table>_<col>` for single-column,
|
|
40
42
|
`uq_<table>_<col1>_<col2>...` for composite.
|
|
41
|
-
6. **Foreign key constraint names** —
|
|
43
|
+
6. **Foreign key constraint names** — `fk_<table>_<col>_<to_table>`, always
|
|
44
|
+
emitted (both emitters render `SchemaForeignKey.name`; single-sourced in
|
|
45
|
+
`ferro_ddl_lowering::fk_name`). See
|
|
46
|
+
`docs/solutions/patterns/derived-type-and-naming-decision-table.md`.
|
|
42
47
|
7. **Primary key constraint names** — when explicitly named.
|
|
43
48
|
8. **Check constraint names** — `ck_<table>_<col>` for the single-column
|
|
44
49
|
`db_check=True` constraint; generated by `_ck_constraint_name` (Python)
|
|
@@ -91,7 +96,7 @@ If you add a new schema feature (e.g. partial indexes, exclusion constraints):
|
|
|
91
96
|
2. Implement it in **both** the Alembic and Rust paths in the same PR.
|
|
92
97
|
3. Add a parity test that asserts the names match.
|
|
93
98
|
4. Do not edit `CHANGELOG.md` manually — release tooling records entries at
|
|
94
|
-
release time (see I-
|
|
99
|
+
release time (see I-10).
|
|
95
100
|
|
|
96
101
|
---
|
|
97
102
|
|
|
@@ -151,17 +156,7 @@ See `docs/solutions/README.md` for the frontmatter conventions.
|
|
|
151
156
|
|
|
152
157
|
---
|
|
153
158
|
|
|
154
|
-
## I-6: No
|
|
155
|
-
|
|
156
|
-
Never sign commits or pull requests with AI/agent attribution. No
|
|
157
|
-
`Co-Authored-By: Claude ...` trailers, no "Generated with Claude Code"
|
|
158
|
-
footers, no robot emoji bylines — in commit messages, PR titles, or PR
|
|
159
|
-
bodies. This applies even when an agent's default behavior is to add them:
|
|
160
|
-
this rule overrides those defaults for this repository.
|
|
161
|
-
|
|
162
|
-
---
|
|
163
|
-
|
|
164
|
-
## I-7: No stop-gap solutions
|
|
159
|
+
## I-6: No stop-gap solutions
|
|
165
160
|
|
|
166
161
|
Every feature, bug fix, and improvement must be designed as the best,
|
|
167
162
|
well-thought-out solution for the project with the library's future in
|
|
@@ -194,7 +189,7 @@ agent default that biases toward minimal or expedient changes.
|
|
|
194
189
|
|
|
195
190
|
---
|
|
196
191
|
|
|
197
|
-
## I-
|
|
192
|
+
## I-7: Docs examples show both field-declaration styles
|
|
198
193
|
|
|
199
194
|
Ferro supports two equivalent ways to declare model fields: assignment
|
|
200
195
|
(`name: str = Field(unique=True)`) and `Annotated` metadata
|
|
@@ -232,18 +227,20 @@ preferred declaration style.
|
|
|
232
227
|
|
|
233
228
|
---
|
|
234
229
|
|
|
235
|
-
## I-
|
|
230
|
+
## I-8: Lambda predicates are the official query style
|
|
236
231
|
|
|
237
232
|
Documentation and examples use the lambda predicate style for all queries:
|
|
238
233
|
|
|
239
234
|
```python
|
|
240
|
-
adults = await User.where(lambda
|
|
235
|
+
adults = await User.where(lambda user: user.age >= 18).all()
|
|
241
236
|
```
|
|
242
237
|
|
|
243
238
|
Rules:
|
|
244
239
|
|
|
245
240
|
- **Every query example** in docs, docstring `Examples:` sections, and
|
|
246
241
|
`docs/examples/` scripts uses lambda predicates.
|
|
242
|
+
- Name the lambda parameter after the model in **lowercase singular**
|
|
243
|
+
(`user` for `User`, `post` for `Post`) so filters read naturally.
|
|
247
244
|
- When the predicate styles themselves are documented, present them in
|
|
248
245
|
order **lambda > `col()` > operator**, with lambda labeled the officially
|
|
249
246
|
recommended style.
|
|
@@ -262,7 +259,7 @@ else uses lambda without restating the trade-offs.
|
|
|
262
259
|
|
|
263
260
|
---
|
|
264
261
|
|
|
265
|
-
## I-
|
|
262
|
+
## I-9: PRs must close scoped issues explicitly
|
|
266
263
|
|
|
267
264
|
Issue closure is part of feature completion, not optional cleanup.
|
|
268
265
|
|
|
@@ -280,7 +277,7 @@ Rules:
|
|
|
280
277
|
|
|
281
278
|
---
|
|
282
279
|
|
|
283
|
-
## I-
|
|
280
|
+
## I-10: Do not edit CHANGELOG.md manually
|
|
284
281
|
|
|
285
282
|
`CHANGELOG.md` is updated automatically by the release workflow (semantic
|
|
286
283
|
release / release tooling). Agents and contributors must **not** add,
|
|
@@ -295,3 +292,29 @@ What to do instead:
|
|
|
295
292
|
If release tooling fails to capture a change, fix the release configuration or
|
|
296
293
|
commit message conventions — do not patch `CHANGELOG.md` by hand in ordinary
|
|
297
294
|
PRs.
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## I-11: Explain technical concepts in plain language, example-first
|
|
299
|
+
|
|
300
|
+
When explaining a concept, design, trade-off, or change to the maintainer, lead
|
|
301
|
+
with plain language and a concrete, user-facing example — not internal function
|
|
302
|
+
names and call graphs.
|
|
303
|
+
|
|
304
|
+
Rules:
|
|
305
|
+
|
|
306
|
+
- **Anchor on what the user sees.** Show a real model definition and the SQL (or
|
|
307
|
+
behavior) it produces, then explain the internal mechanics against that
|
|
308
|
+
anchor. "A `datetime` field becomes `timestamptz` — here's the `CREATE TABLE`"
|
|
309
|
+
beats "`canonical_from_parts` maps the logical type."
|
|
310
|
+
- **Introduce jargon only after the plain version.** Function and type names are
|
|
311
|
+
precise back-references once the idea is clear — not the primary explanation.
|
|
312
|
+
- **Use analogies for architecture.** "Two translation dictionaries that must
|
|
313
|
+
agree by hand" communicates a duplication smell faster than a module diagram.
|
|
314
|
+
- **Show, don't just tell.** Prefer before/after diffs, rendered SQL, and
|
|
315
|
+
concrete values over abstract prose (complements the show-don't-tell habit
|
|
316
|
+
used in issue/PR explanations).
|
|
317
|
+
|
|
318
|
+
This applies to brainstorming, design discussions, PR descriptions, issue
|
|
319
|
+
comments, and any explanation directed at the maintainer. It governs how work is
|
|
320
|
+
communicated, not what gets built.
|
|
@@ -1,6 +1,193 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## v0.14.0 (2026-07-07)
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
- **ff-g**: Make Postgres db_check ADD CONSTRAINT idempotent (G6, #176)
|
|
9
|
+
([#181](https://github.com/syn54x/ferro-orm/pull/181),
|
|
10
|
+
[`2c0e4cf`](https://github.com/syn54x/ferro-orm/commit/2c0e4cf6c922a73454198f6aa0aa75b30eb1f0c8))
|
|
11
|
+
|
|
12
|
+
### Chores
|
|
13
|
+
|
|
14
|
+
- **benchmarks**: Pinned async benchmark suite over the rich-type hot path
|
|
15
|
+
([#196](https://github.com/syn54x/ferro-orm/pull/196),
|
|
16
|
+
[`d9a656b`](https://github.com/syn54x/ferro-orm/commit/d9a656b320bd7fb6b613f4408a796161e9badc41))
|
|
17
|
+
|
|
18
|
+
### Documentation
|
|
19
|
+
|
|
20
|
+
- Consolidate migration guides into one evergreen upgrade guide
|
|
21
|
+
([#234](https://github.com/syn54x/ferro-orm/pull/234),
|
|
22
|
+
[`15c83db`](https://github.com/syn54x/ferro-orm/commit/15c83dbc6b1c057a78dfc425d70441e50c359f5d))
|
|
23
|
+
|
|
24
|
+
- Fixes roadmap
|
|
25
|
+
([`5718d02`](https://github.com/syn54x/ferro-orm/commit/5718d02630b6c84d3ced6f8a3080adf4e7fe2383))
|
|
26
|
+
|
|
27
|
+
- **fable-fixes**: Fold #176 into Epic FF-G as sub-task G6
|
|
28
|
+
([`b966e65`](https://github.com/syn54x/ferro-orm/commit/b966e65739d7c33ed666a7fd14086a27688516dd))
|
|
29
|
+
|
|
30
|
+
- **ff-a**: A5 — docs & migration guide for the mutation-surface changes
|
|
31
|
+
([#180](https://github.com/syn54x/ferro-orm/pull/180),
|
|
32
|
+
[`ffc5476`](https://github.com/syn54x/ferro-orm/commit/ffc5476f9ba72f03a35048f283b11390f813856b))
|
|
33
|
+
|
|
34
|
+
- **ff-b**: Tick FF-B sub-task and exit-gate boxes in the fable-fixes roadmap
|
|
35
|
+
([`29f9172`](https://github.com/syn54x/ferro-orm/commit/29f91724e2b6886f8299bbb42940c804c8e88141))
|
|
36
|
+
|
|
37
|
+
### Features
|
|
38
|
+
|
|
39
|
+
- **ff-a**: Create() is a real INSERT; save() distinguishes INSERT from UPDATE (A3+A4)
|
|
40
|
+
([#179](https://github.com/syn54x/ferro-orm/pull/179),
|
|
41
|
+
[`de3ec30`](https://github.com/syn54x/ferro-orm/commit/de3ec30196202ee14c42afc5b02f163f82a68451))
|
|
42
|
+
|
|
43
|
+
- **ff-a**: Reject limit/offset on mutating queries
|
|
44
|
+
([#178](https://github.com/syn54x/ferro-orm/pull/178),
|
|
45
|
+
[`67faf42`](https://github.com/syn54x/ferro-orm/commit/67faf421d49984c5be16d2163982f13ab86cc5e4))
|
|
46
|
+
|
|
47
|
+
- **ff-a**: Typed DBAPI-shaped exception hierarchy mapped from sqlx errors
|
|
48
|
+
([#177](https://github.com/syn54x/ferro-orm/pull/177),
|
|
49
|
+
[`9c306c5`](https://github.com/syn54x/ferro-orm/commit/9c306c549e716dd4a5158d655265aa7890e63c0b))
|
|
50
|
+
|
|
51
|
+
- **ff-b**: B1 canonical derived-type & naming decision table + refusal-rail scaffolding
|
|
52
|
+
([`8c879f7`](https://github.com/syn54x/ferro-orm/commit/8c879f77833a7e5a983d53012efc8332cca5b852))
|
|
53
|
+
|
|
54
|
+
- **ff-b**: B2+B6 one derived-type decision table; native PG enums + timestamptz/time parity; delete
|
|
55
|
+
bridge mirrors
|
|
56
|
+
([`bfdc1fd`](https://github.com/syn54x/ferro-orm/commit/bfdc1fda1eceebe70ae711e38b785af88b46e11e))
|
|
57
|
+
|
|
58
|
+
- **ff-b**: B3+B4 single-source artifact naming; both emitters emit named fk_/uq_ artifacts
|
|
59
|
+
([`6b771f3`](https://github.com/syn54x/ferro-orm/commit/6b771f38933c72e8f848013a5ae93708fabf5c7a))
|
|
60
|
+
|
|
61
|
+
- **ff-c**: C1 — per-model ColumnCodec plan; delete codec.rs schema sniffing (F5)
|
|
62
|
+
([#197](https://github.com/syn54x/ferro-orm/pull/197),
|
|
63
|
+
[`0e8e572`](https://github.com/syn54x/ferro-orm/commit/0e8e57252f4cca2d2bc9fffd06d9155338056cf3))
|
|
64
|
+
|
|
65
|
+
- **ff-c**: C2 — schema-epoch catalog cache; zero catalog queries on steady-state CRUD
|
|
66
|
+
([#200](https://github.com/syn54x/ferro-orm/pull/200),
|
|
67
|
+
[`8c6d6ed`](https://github.com/syn54x/ferro-orm/commit/8c6d6edf578cf55ed7ada0d49359a7e09528da1e))
|
|
68
|
+
|
|
69
|
+
- **ff-c**: C3+C4 — native typed Postgres decode; plan-driven enum hydration replaces _fix_types
|
|
70
|
+
([#198](https://github.com/syn54x/ferro-orm/pull/198),
|
|
71
|
+
[`05a008c`](https://github.com/syn54x/ferro-orm/commit/05a008cb73f6c4dc8b2478a441c99282d07bd41d))
|
|
72
|
+
|
|
73
|
+
- **ff-d**: Session-scoped weak identity map with refresh-on-load; single-handle routing
|
|
74
|
+
([#201](https://github.com/syn54x/ferro-orm/pull/201),
|
|
75
|
+
[`a328cfc`](https://github.com/syn54x/ferro-orm/commit/a328cfcd107e2cac998ddc8af50845857ec669a5))
|
|
76
|
+
|
|
77
|
+
- **ff-e**: Registry & model identity — qualified keys, configurable tables, O(N) import
|
|
78
|
+
([#209](https://github.com/syn54x/ferro-orm/pull/209),
|
|
79
|
+
[`6391805`](https://github.com/syn54x/ferro-orm/commit/6391805c1b4ee46c0590513ac6684237c18f7430))
|
|
80
|
+
|
|
81
|
+
- **ff-f**: Query builder 1.0 shape — immutable chaining, build-time column validation, lambda-only
|
|
82
|
+
predicates, QueryIR-only Rust ([#223](https://github.com/syn54x/ferro-orm/pull/223),
|
|
83
|
+
[`eb7fece`](https://github.com/syn54x/ferro-orm/commit/eb7fece8fbc2231220ecf9111616f803f2f987eb))
|
|
84
|
+
|
|
85
|
+
- **ff-g-a**: Hardening — hydration ABI guard, transactional PG migrate, correctness edges,
|
|
86
|
+
decode-path caching ([#232](https://github.com/syn54x/ferro-orm/pull/232),
|
|
87
|
+
[`22617e1`](https://github.com/syn54x/ferro-orm/commit/22617e1cfe5e2bc9d0a3d7a1fed5acf4d8589cef))
|
|
88
|
+
|
|
89
|
+
### Refactoring
|
|
90
|
+
|
|
91
|
+
- **ff-g-b**: Operations.rs dedup — ModelMeta + Executor (G2)
|
|
92
|
+
([#233](https://github.com/syn54x/ferro-orm/pull/233),
|
|
93
|
+
[`09c2c62`](https://github.com/syn54x/ferro-orm/commit/09c2c6214af9e2f9510d39d037935c53bd2e796d))
|
|
94
|
+
|
|
95
|
+
### Testing
|
|
96
|
+
|
|
97
|
+
- **ff-b**: B5 I-1 sentinel on the full backend matrix with a full-type fixture, zero filters
|
|
98
|
+
([`1141eb4`](https://github.com/syn54x/ferro-orm/commit/1141eb437b4843303e01556a5b24ddee9d0e0279))
|
|
99
|
+
|
|
100
|
+
- **ff-b**: Force psycopg v3 driver in the Postgres sentinel regardless of URL scheme
|
|
101
|
+
([`64f9845`](https://github.com/syn54x/ferro-orm/commit/64f98454bdb5e090a41bd214de06b7670974f4eb))
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
## v0.13.0 (2026-07-02)
|
|
105
|
+
|
|
106
|
+
### Bug Fixes
|
|
107
|
+
|
|
108
|
+
- **ir-p8.6**: Datetime/timestamptz coarseness — stop silent Postgres column reinterpretation (#154)
|
|
109
|
+
([#167](https://github.com/syn54x/ferro-orm/pull/167),
|
|
110
|
+
[`7182a57`](https://github.com/syn54x/ferro-orm/commit/7182a5744900abe7ed50915edbca7d5184b2c535))
|
|
111
|
+
|
|
112
|
+
- **ir-p8.6**: Stop false-positive BLOB drift warning on SQLite (#165)
|
|
113
|
+
([#168](https://github.com/syn54x/ferro-orm/pull/168),
|
|
114
|
+
[`d554ac4`](https://github.com/syn54x/ferro-orm/commit/d554ac4558286106bcb0908baec9fa3d49a2781d))
|
|
115
|
+
|
|
116
|
+
- **ir-p8.6**: Surface real PEP 649 deferred-annotation error (#155)
|
|
117
|
+
([#163](https://github.com/syn54x/ferro-orm/pull/163),
|
|
118
|
+
[`00976e7`](https://github.com/syn54x/ferro-orm/commit/00976e748d86246b8be47230229d19516d8bb3c0))
|
|
119
|
+
|
|
120
|
+
### Documentation
|
|
121
|
+
|
|
122
|
+
- Use model-named lambda predicates in examples
|
|
123
|
+
([#132](https://github.com/syn54x/ferro-orm/pull/132),
|
|
124
|
+
[`420ca6e`](https://github.com/syn54x/ferro-orm/commit/420ca6e1cb4a90d1acc556a83373c9da99b22bb3))
|
|
125
|
+
|
|
126
|
+
- **agents**: Add I-11 — explain concepts plainly, example-first
|
|
127
|
+
([`efc7ef5`](https://github.com/syn54x/ferro-orm/commit/efc7ef5678e2f6efacaa3a6e84c0575b0cdef51c))
|
|
128
|
+
|
|
129
|
+
- **ir-first**: Add Phase 8.6 post-8.5 cleanup backlog (epic #145)
|
|
130
|
+
([#147](https://github.com/syn54x/ferro-orm/pull/147),
|
|
131
|
+
[`e57b74b`](https://github.com/syn54x/ferro-orm/commit/e57b74b397bd51ebc4809f25d57536896540b9de))
|
|
132
|
+
|
|
133
|
+
- **ir-first**: Expand #144 scope — auto-migrate index/unique reconciliation
|
|
134
|
+
([#150](https://github.com/syn54x/ferro-orm/pull/150),
|
|
135
|
+
[`fdbac40`](https://github.com/syn54x/ferro-orm/commit/fdbac4003e9bd25fdc3f3cb0012c5dd9d562ee68))
|
|
136
|
+
|
|
137
|
+
- **ir-first**: Lowering-consolidation audit + Phase 8.5
|
|
138
|
+
([#138](https://github.com/syn54x/ferro-orm/pull/138),
|
|
139
|
+
[`c6ce53c`](https://github.com/syn54x/ferro-orm/commit/c6ce53c2409a1fd20a40c1de58d42e1e3d2e1344))
|
|
140
|
+
|
|
141
|
+
- **ir-p8.6**: Add #153 create-path IR unification spec
|
|
142
|
+
([`be4bb99`](https://github.com/syn54x/ferro-orm/commit/be4bb99b90e6d02a6e01bfc5807a7cb178055862))
|
|
143
|
+
|
|
144
|
+
- **ir-p8.6**: Add #153 create-path unification implementation plan
|
|
145
|
+
([`de3c427`](https://github.com/syn54x/ferro-orm/commit/de3c42794de821d8e47eb5ca94b582f8199992df))
|
|
146
|
+
|
|
147
|
+
- **ir-p8.6**: Sync roadmap — #153 merged, file #158 (db_check check-renderer)
|
|
148
|
+
([`62c80fa`](https://github.com/syn54x/ferro-orm/commit/62c80fa3fe7ac456169d280f3ee8795feac32a8c))
|
|
149
|
+
|
|
150
|
+
- **ir-p8.6**: Sync roadmap — #154 merged (datetime/timestamptz warn-and-skip); #145 now 6/7
|
|
151
|
+
([`31dbbb6`](https://github.com/syn54x/ferro-orm/commit/31dbbb6c0f1d3afa0ed452ed9ae34441df69c501))
|
|
152
|
+
|
|
153
|
+
- **ir-p8.6**: Sync roadmap — #162 merged (typed save/update bind), file #165
|
|
154
|
+
([`5ca76a1`](https://github.com/syn54x/ferro-orm/commit/5ca76a1e177f4847ded4fb19402841a9988b62d1))
|
|
155
|
+
|
|
156
|
+
- **ir-p8.6**: Sync roadmap — #165 merged (BLOB introspection); #145 complete 7/7, Phase 8.6 wrapped
|
|
157
|
+
([`1dbb278`](https://github.com/syn54x/ferro-orm/commit/1dbb27864881d77a68d5026ab5a9bb07f142c3c5))
|
|
158
|
+
|
|
159
|
+
- **rust**: Add detailed docstrings for all public APIs
|
|
160
|
+
([#130](https://github.com/syn54x/ferro-orm/pull/130),
|
|
161
|
+
[`8d5a951`](https://github.com/syn54x/ferro-orm/commit/8d5a95162568eef215ba03524a31b657df87e8c6))
|
|
162
|
+
|
|
163
|
+
### Features
|
|
164
|
+
|
|
165
|
+
- Ir cutover ([#137](https://github.com/syn54x/ferro-orm/pull/137),
|
|
166
|
+
[`0509c2a`](https://github.com/syn54x/ferro-orm/commit/0509c2a35b0f0200492143a52563146359550129))
|
|
167
|
+
|
|
168
|
+
- **ir-p8.6**: Route save/update/bulk value bind through the typed codec path (#162)
|
|
169
|
+
([#166](https://github.com/syn54x/ferro-orm/pull/166),
|
|
170
|
+
[`486e68c`](https://github.com/syn54x/ferro-orm/commit/486e68c110c03356fa579051849b44e8f4eae751))
|
|
171
|
+
|
|
172
|
+
### Refactoring
|
|
173
|
+
|
|
174
|
+
- Lowering consolidation & single-source-of-truth closeout (#139)
|
|
175
|
+
([#156](https://github.com/syn54x/ferro-orm/pull/156),
|
|
176
|
+
[`f76bec9`](https://github.com/syn54x/ferro-orm/commit/f76bec93651bc9741bea85171da927ddb8864a1a))
|
|
177
|
+
|
|
178
|
+
- Unify the CREATE TABLE path onto the Python SchemaIR (#153)
|
|
179
|
+
([#157](https://github.com/syn54x/ferro-orm/pull/157),
|
|
180
|
+
[`c9ce7b0`](https://github.com/syn54x/ferro-orm/commit/c9ce7b093fde350da8a1653cf7c42f522e0523b2))
|
|
181
|
+
|
|
182
|
+
- Unify the three dialect enums into one shared Dialect (#146)
|
|
183
|
+
([#159](https://github.com/syn54x/ferro-orm/pull/159),
|
|
184
|
+
[`4b0dfe6`](https://github.com/syn54x/ferro-orm/commit/4b0dfe6b9eca1a2a63631a54504c629f42f7c5e1))
|
|
185
|
+
|
|
186
|
+
- **ir-p8.6**: Single check-renderer for db_check (#158)
|
|
187
|
+
([#161](https://github.com/syn54x/ferro-orm/pull/161),
|
|
188
|
+
[`c04df1c`](https://github.com/syn54x/ferro-orm/commit/c04df1ce5aa4505f737864944855ff4170a4d350))
|
|
189
|
+
|
|
190
|
+
|
|
4
191
|
## v0.12.3 (2026-06-24)
|
|
5
192
|
|
|
6
193
|
### Bug Fixes
|