ferro-orm 0.18.0__tar.gz → 0.20.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.18.0 → ferro_orm-0.20.0}/AGENTS.md +40 -2
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/CHANGELOG.md +28 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/CONTEXT.md +13 -1
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/Cargo.lock +102 -101
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/Cargo.toml +1 -1
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/PKG-INFO +1 -1
- ferro_orm-0.20.0/context7.json +4 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/crates/ferro-ddl-lowering/src/lib.rs +1007 -1
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/crates/ferro-migrate/src/emit.rs +99 -3
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/crates/ferro-migrate/src/lib.rs +142 -1
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/crates/ferro-migrate/src/tests.rs +477 -1
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/crates/ferro-schema-ir/src/lib.rs +206 -0
- ferro_orm-0.20.0/docs/adr/0012-table-checks-are-lambdas.md +12 -0
- ferro_orm-0.20.0/docs/adr/0013-table-check-reconciliation.md +12 -0
- ferro_orm-0.20.0/docs/adr/0014-table-checks-sqlite-create-only.md +11 -0
- ferro_orm-0.20.0/docs/adr/0015-table-check-body-drift.md +11 -0
- ferro_orm-0.20.0/docs/adr/0016-check-predicates-literals-only.md +11 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/predicates.py +38 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/predicates_annotated.py +27 -0
- ferro_orm-0.20.0/docs/examples/table_checks.py +45 -0
- ferro_orm-0.20.0/docs/examples/table_checks_annotated.py +42 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/api/exceptions.md +18 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/api/queries.md +1 -1
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/guide/migrations.md +7 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/guide/models-and-fields.md +32 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/guide/queries.md +27 -3
- ferro_orm-0.20.0/docs/solutions/issues/pg18-restrict-sqlstate-23001.md +33 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/pyproject.toml +1 -1
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/errors.rs +87 -7
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/__init__.py +2 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/_core.pyi +60 -1
- ferro_orm-0.20.0/src/ferro/checks.py +609 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/exceptions.py +6 -1
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/ir/compiler.py +55 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/migrations/alembic.py +254 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/models.py +12 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/query/builder.py +52 -11
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/query/wire.py +6 -2
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/introspect.rs +338 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/lib.rs +7 -1
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/migrate.rs +93 -9
- ferro_orm-0.20.0/src/naming_ffi.rs +241 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/operations.rs +155 -7
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/schema.rs +11 -3
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/state.rs +1 -0
- ferro_orm-0.20.0/tests/fixtures/ir_vectors/query_card_nulls_v7.json +44 -0
- ferro_orm-0.20.0/tests/test_check_predicate_dialect.py +348 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_exception_mapping.py +65 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_generation_counter_dirty_tracking.py +2 -10
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_ir_vectors_contract.py +5 -0
- ferro_orm-0.20.0/tests/test_live_table_checks.py +74 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_naming_single_source.py +19 -0
- ferro_orm-0.20.0/tests/test_order_by_nulls.py +209 -0
- ferro_orm-0.20.0/tests/test_order_by_nulls_wire.py +102 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_query_column_validation.py +118 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_query_wire_vectors.py +20 -0
- ferro_orm-0.20.0/tests/test_table_check_orphans.py +546 -0
- ferro_orm-0.20.0/tests/test_table_check_rebuild.py +532 -0
- ferro_orm-0.20.0/tests/test_table_check_reconcile.py +514 -0
- ferro_orm-0.20.0/tests/test_table_checks.py +599 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/uv.lock +1 -1
- ferro_orm-0.18.0/src/naming_ffi.rs +0 -115
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/.github/PERMISSIONS.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/.github/PYPI_CHECKLIST.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/.github/PYPI_SETUP.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/.github/generated/wheels.generated.yml +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/.github/pull_request_template.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/.github/workflows/ci.yml +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/.github/workflows/packaging-smoke.yml +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/.github/workflows/publish-docs.yml +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/.github/workflows/publish.yml +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/.github/workflows/release.yml +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/.gitignore +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/.pre-commit-config.yaml +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/.python-version +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/CONTRIBUTING.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/LICENSE +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/README.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/benchmarks/README.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/benchmarks/__init__.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/benchmarks/__main__.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/benchmarks/backends.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/benchmarks/baselines/postgres.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/benchmarks/baselines/sqlite.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/benchmarks/compare.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/benchmarks/harness.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/benchmarks/model.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/benchmarks/run.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/crates/ferro-ddl-lowering/Cargo.toml +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/crates/ferro-migrate/Cargo.toml +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/crates/ferro-migrate/src/order.rs +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/crates/ferro-schema-ir/Cargo.toml +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/adr/0001-resolved-epoch-registration.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/adr/0002-unified-column-fact-derivation.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/adr/0003-path-blind-db-type-validation.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/adr/0004-jsonb-postgres-only-canonical.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/adr/0005-jsonb-default-on-postgres.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/adr/0006-relation-traversal-inner-joins.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/adr/0007-materialization-plan-complete-instances.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/adr/0007-reverse-relations-tested-not-traversed.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/adr/0008-populated-relations-include.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/adr/0008-predicate-negation-uniform-not.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/adr/0009-aggregate-projections-derived-grouping.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/adr/0010-create-pass-owns-only-missing-tables.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/adr/0011-label-addition-update-gated-append-only.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/agents/domain.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/agents/issue-tracker.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/agents/triage-labels.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/architecture-review-2026-07-08.html +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-04-29-named-connections-role-routing-requirements.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-05-08-typed-query-predicates-requirements.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-05-13-configurable-column-storage-types-requirements.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-05-14-autogenerate-support-for-db-type-requirements.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-05-25-annotated-strenum-cold-hydration-requirements.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-06-24-ir-p8-119-wire-automigrate-requirements.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-06-25-ir-p8-120-parity-gate-requirements.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-06-26-ir-p8.5-140-shared-lowering-requirements.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-06-26-ir-p8.5-143-db-type-drop-requirements.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-06-26-ir-p8.5-144-reconcile-indexes-requirements.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-06-28-ir-p8.5-141-single-schema-ir-producer-requirements.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-06-29-ir-p8.6-146-dialect-enum-unification-requirements.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-06-29-ir-p8.6-153-create-path-ir-requirements.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-06-30-ir-p8.6-155-deferred-annotations-requirements.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-06-30-ir-p8.6-158-check-renderer-requirements.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-07-01-ir-p8.6-154-datetime-tz-coarseness-requirements.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-07-01-ir-p8.6-162-typed-save-bind-requirements.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-07-01-ir-p8.6-165-blob-introspection-false-positive-requirements.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-07-02-ff-c1-codec-plan-design.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/brainstorms/2026-07-06-upgrade-guide-consolidation-requirements.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/aggregations.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/aggregations_annotated.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/existence_tests.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/existence_tests_annotated.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/multiple_databases.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/mutations.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/pagination.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/partial_selects.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/partial_selects_annotated.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/populated_relations.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/populated_relations_annotated.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/quickstart.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/quickstart_annotated.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/raw_sql.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/relationships.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/relationships_annotated.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/soft_deletes.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/soft_deletes_annotated.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/testing_conftest.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/timestamps.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/timestamps_annotated.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/transactions.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/traversal.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/examples/traversal_annotated.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/api/connection.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/api/fields.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/api/migrations.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/api/model.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/api/raw-sql.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/api/relationships.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/api/transactions.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/changelog.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/concepts/architecture.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/concepts/backends.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/concepts/identity-map.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/concepts/performance.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/concepts/query-typing.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/concepts/type-safety.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/contributing.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/faq.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/getting-started/installation.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/getting-started/next-steps.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/getting-started/quickstart.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/guide/aggregations.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/guide/connections.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/guide/mutations.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/guide/raw-sql.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/guide/relationships.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/guide/transactions.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/howto/migrate-from-sqlalchemy.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/howto/multiple-databases.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/howto/pagination.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/howto/soft-deletes.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/howto/testing.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/howto/timestamps.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/howto/upgrade-guide.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/index.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/roadmap.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/stylesheets/extra.css +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/pages/why-ferro.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-04-24-001-refactor-multi-db-backend-architecture-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-04-29-001-typed-null-binds-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-04-29-002-feat-named-connections-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-05-07-001-refactor-generic-model-connection-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-05-08-001-feat-typed-query-predicates-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-05-13-001-feat-configurable-column-storage-types-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-05-25-001-fix-annotated-strenum-cold-hydration-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-06-19-001-ir-first-roadmap.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-06-24-001-feat-ir-p8-119-wire-automigrate-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-06-25-001-feat-ir-p8-120-parity-gate-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-06-26-001-feat-ir-p8.5-140-shared-lowering-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-06-26-002-feat-ir-p8.5-143-db-type-drop-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-06-26-003-feat-ir-p8.5-144-reconcile-indexes-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-06-28-001-feat-ir-p8.5-141-single-schema-ir-producer-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-06-29-001-refactor-ir-p8.6-153-create-path-unification-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-06-29-002-refactor-ir-p8.6-146-dialect-enum-unification-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-06-30-001-refactor-ir-p8.6-158-check-renderer-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-06-30-002-fix-ir-p8.6-155-deferred-annotations-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-07-01-001-feat-ir-p8.6-162-typed-save-bind-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-07-01-002-fix-ir-p8.6-154-datetime-tz-coarseness-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-07-01-003-fix-ir-p8.6-165-blob-introspection-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-07-02-001-fable-fixes-roadmap.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-07-02-002-feat-ff-a-172-typed-exceptions-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-07-02-003-ff-c-native-decode-design.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-07-02-004-ff-c-c2-catalog-cache-design.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-07-02-005-ff-d-identity-routing-design.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-07-02-006-ff-d-identity-routing-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-07-03-007-ff-e-registry-identity-design.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-07-03-008-ff-e-registry-identity-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-07-06-009-ff-f-query-builder-1.0-design.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-07-06-010-ff-f-query-builder-1.0-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-07-06-011-ff-g-hardening-design.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-07-06-012-ff-g-hardening-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-07-06-013-ff-g2-operations-dedup-design.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-07-06-014-ff-g2-operations-dedup-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-07-06-015-docs-upgrade-guide-consolidation-plan.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/2026-07-18-016-existence-tests-design.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/ir-first-migration-guide.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/plans/ir-first-release-checklist.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/rfc/ir-contracts-v1.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/README.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/architecture-patterns/ir-first-lowering-consolidation-audit.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/architecture-patterns/ir-first-merge-readiness-review.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/issues/pydantic-slots-missing-after-ferro-hydration.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/issues/python-3.14-deferred-annotation-typeerror-swallow.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/issues/sa-pk-column-nullable-divergence.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/issues/sa-vs-rust-unique-constraint-shape.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/issues/self-fk-evicts-component-from-create-order.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/issues/sqlite-integer-decimal-hydrates-as-none.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/issues/sqlite-null-hydrates-as-int-zero.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/issues/typed-where-null-panics-is-null.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/patterns/configurable-column-storage-types.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/patterns/cross-emitter-ddl-parity.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/patterns/ddl-on-live-engine.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/patterns/derived-type-and-naming-decision-table.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/patterns/foreign-key-index.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/patterns/index-unique-redundancy.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/patterns/ir-invariants.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/patterns/persistence-state.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/patterns/shadow-fk-columns.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/patterns/sqlite-alembic-reconnect-hydration-tests.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/docs/solutions/patterns/typed-null-binds.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/justfile +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/scripts/demo_queries.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/scripts/demo_queries_pre_v012.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/backend.rs +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/codec.rs +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/codec_plan.rs +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/connection.rs +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/_annotation_utils.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/_bind_payload.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/_deprecations.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/_shadow_fk_types.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/base.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/columns.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/composite_indexes.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/composite_uniques.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/fields.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/ir/__init__.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/metaclass.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/migrations/__init__.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/py.typed +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/query/__init__.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/query/nodes.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/query/rows.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/raw.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/registry.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/relations/__init__.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/relations/descriptors.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/session.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/ferro/state.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/hydration.rs +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/query.rs +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/src/schema_bind.rs +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/__init__.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/conftest.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/db_backends.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/README.md +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/codec_registry_core_v1.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/query_account_exists_v7.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/query_account_scoped_exists_v7.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/query_owner_nested_exists_v7.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/query_owner_not_exists_v7.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/query_transaction_aggregate_v7.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/query_transaction_global_aggregate_v7.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/query_transaction_include_v7.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/query_transaction_left_join_v7.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/query_transaction_record_v7.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/query_transaction_traversal_v7.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/query_transaction_traversed_record_v7.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/query_user_compound_v7.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/query_user_m2m_exists_v7.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/query_user_not_compound_v7.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/query_user_not_leaf_v7.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/schema_invoice_baseline_v1.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/schema_phase1_fixture_models_v1.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/fixtures/ir_vectors/schema_raw_str_pk_autoincrement_v1.json +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/static_fixtures/bad_includes.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/static_fixtures/bad_predicates.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/static_fixtures/bad_projections.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/static_fixtures/good_includes.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/static_fixtures/good_predicates.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/static_fixtures/good_projections.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_aggregation.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_alembic_autogenerate.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_alembic_bridge.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_alembic_db_type.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_alembic_nullability.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_alembic_type_mapping.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_annotation_utils.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_auto_migrate.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_bulk_create_chunking.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_bulk_install.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_bulk_update.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_catalog_cache.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_codec_plan.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_column_specs.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_compiled_query.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_composite_index.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_composite_unique.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_connection.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_connection_redaction.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_constraints.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_cross_emitter_parity.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_crud.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_db_backends.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_db_type_cross_emitter_parity.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_db_type_integration.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_db_type_typing.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_db_type_validation.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_deletion.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_deprecations.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_docs_examples.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_documentation_features.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_enum_cold_hydration.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_exceptions.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_field_wrapper.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_fk_target_pk.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_global_aggregates.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_grouped_aggregates.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_helpers.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_hydration.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_hydration_equivalence.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_identity_memory.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_identity_refresh.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_identity_scoped_invalidation.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_identity_weakref.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_import_budget.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_include.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_label_addition.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_metaclass_internals.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_metadata.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_migrate_plan.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_model_identity.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_models.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_mutation_pagination_guard.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_named_connections_integration.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_negation.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_one_to_one.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_operation_seam_sync.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_partial_selects.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_primary_key_facts.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_provisional_import.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_query_builder.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_query_exists.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_query_immutability.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_query_joins.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_query_typing.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_raw_sql.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_refresh.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_registry_entrypoints.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_registry_owner.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_relation_specs.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_relationship_engine.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_relationship_resolution_errors.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_route_single_site.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_routing_errors.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_save_pk_edges.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_save_semantics.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_schema.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_schema_constraints.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_schema_db_type_metadata.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_schema_enum_annotations.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_session.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_shadow_fk_types.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_sqlite_alembic_reconnect_hydration.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_static_contracts.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_string_search.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_structural_types.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_temporal_types.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_transactions.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_traversed_projection.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_typed_null_binds.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/tests/test_typed_save_bind.py +0 -0
- {ferro_orm-0.18.0 → ferro_orm-0.20.0}/zensical.toml +0 -0
|
@@ -46,8 +46,11 @@ For a single model, every emitter must agree on:
|
|
|
46
46
|
`docs/solutions/patterns/derived-type-and-naming-decision-table.md`.
|
|
47
47
|
7. **Primary key constraint names** — when explicitly named.
|
|
48
48
|
8. **Check constraint names** — `ck_<table>_<col>` for the single-column
|
|
49
|
-
`db_check=True` constraint;
|
|
50
|
-
|
|
49
|
+
`db_check=True` constraint; `ck_<table>_<suffix>` for table checks declared
|
|
50
|
+
in `__ferro_checks__`. Column checks use `_ddl_check_constraint_name`
|
|
51
|
+
(Python) and `db_check_constraint_name` (Rust); table checks use
|
|
52
|
+
`_ddl_table_check_constraint_name` (Python) and
|
|
53
|
+
`table_check_constraint_name` (Rust).
|
|
51
54
|
9. **Default values** — server-side defaults must serialize identically.
|
|
52
55
|
10. **Nullability** — must agree.
|
|
53
56
|
11. **Enum label additions** — the label-addition decision (which model-declared
|
|
@@ -60,6 +63,41 @@ For a single model, every emitter must agree on:
|
|
|
60
63
|
executes the byte-identical statements. Pinned by
|
|
61
64
|
`tests/test_cross_emitter_parity.py` and the ferro-ddl-lowering unit pins.
|
|
62
65
|
See ADR-0011 (append-only; update-gated; warn-never-act for extras).
|
|
66
|
+
12. **Check additions** — the missing-check decision (which declared `ck_*`
|
|
67
|
+
names — table checks, then column checks — a live table does not carry)
|
|
68
|
+
and the rendered ADD are decided by ONE pair of functions:
|
|
69
|
+
`ferro_ddl_lowering::missing_check_names` / `render_check_addition`.
|
|
70
|
+
The auto-migrate reconciliation pass consumes them through
|
|
71
|
+
`ferro_migrate::plan_missing_checks`; the Alembic autogenerate
|
|
72
|
+
comparator consumes them over FFI (`_core._plan_check_addition`) and
|
|
73
|
+
executes the byte-identical statements. Pinned by
|
|
74
|
+
`tests/test_table_check_reconcile.py`. See ADR-0013 (add on
|
|
75
|
+
`migrate_updates`; name-only comparison) and ADR-0014 (SQLite warn-skip).
|
|
76
|
+
13. **Check rebuilds** — the same-name body-drift decision (which declared
|
|
77
|
+
`ck_*` names exist live **and** whose catalog definition normalizes
|
|
78
|
+
unequal to the canonical rendering) and the rendered DROP + bare ADD
|
|
79
|
+
are decided by ONE pair of functions:
|
|
80
|
+
`ferro_ddl_lowering::drifted_check_names` / `render_check_rebuild`
|
|
81
|
+
(one normalizer: `normalize_check_definition`). The auto-migrate
|
|
82
|
+
reconciliation pass consumes them through
|
|
83
|
+
`ferro_migrate::plan_check_rebuilds`; the Alembic autogenerate
|
|
84
|
+
comparator consumes them over FFI (`_core._plan_check_rebuild`) and
|
|
85
|
+
executes the byte-identical statements. Pinned by
|
|
86
|
+
`tests/test_table_check_rebuild.py`. See ADR-0015 (canonical render vs
|
|
87
|
+
catalog, both through one normalizer) and ADR-0014 (SQLite warn-skip).
|
|
88
|
+
14. **Check leftovers / drops** — the leftover-name decision (which live
|
|
89
|
+
ferro-owned `ck_*` names a table carries that the model no longer
|
|
90
|
+
declares) and the rendered DROP are decided by ONE trio of functions:
|
|
91
|
+
`ferro_ddl_lowering::extra_check_names` /
|
|
92
|
+
`extra_check_names_warning` / `render_check_drop`. The auto-migrate
|
|
93
|
+
reconciliation pass consumes them through
|
|
94
|
+
`ferro_migrate::plan_check_drops` (ops only under
|
|
95
|
+
`migrate_destructive`; the warning always fires on `migrate_updates`).
|
|
96
|
+
The Alembic autogenerate comparator consumes them over FFI
|
|
97
|
+
(`_core._plan_check_drop`) with **no** destructive gate and executes
|
|
98
|
+
the byte-identical statements. Pinned by
|
|
99
|
+
`tests/test_table_check_orphans.py`. See ADR-0013 (leftover warning +
|
|
100
|
+
destructive ladder) and ADR-0014 (SQLite warn-skip).
|
|
63
101
|
|
|
64
102
|
### Why this invariant exists
|
|
65
103
|
|
|
@@ -1,6 +1,34 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## v0.20.0 (2026-08-29)
|
|
5
|
+
|
|
6
|
+
### Chores
|
|
7
|
+
|
|
8
|
+
- Add Context7 library config ([#357](https://github.com/syn54x/ferro-orm/pull/357),
|
|
9
|
+
[`ab8e79b`](https://github.com/syn54x/ferro-orm/commit/ab8e79b799e07fd64f7da8db09daa278af488877))
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
- **query**: Order_by nulls= first/last placement
|
|
14
|
+
([#369](https://github.com/syn54x/ferro-orm/pull/369),
|
|
15
|
+
[`ef6c8b4`](https://github.com/syn54x/ferro-orm/commit/ef6c8b4c458d47a88ace4407a5fb368a8d91200a))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## v0.19.0 (2026-08-18)
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
- Classify PG18 RESTRICT (23001) as ForeignKeyViolationError
|
|
23
|
+
([#338](https://github.com/syn54x/ferro-orm/pull/338),
|
|
24
|
+
[`4fa1153`](https://github.com/syn54x/ferro-orm/commit/4fa1153477802de8207c7987748db962b35c2f0f))
|
|
25
|
+
|
|
26
|
+
### Features
|
|
27
|
+
|
|
28
|
+
- Named table-level CHECK constraints ([#356](https://github.com/syn54x/ferro-orm/pull/356),
|
|
29
|
+
[`ba179e7`](https://github.com/syn54x/ferro-orm/commit/ba179e71e9bce4ab77a6fdbc1831661485de6799))
|
|
30
|
+
|
|
31
|
+
|
|
4
32
|
## v0.18.0 (2026-08-05)
|
|
5
33
|
|
|
6
34
|
### Documentation
|
|
@@ -145,5 +145,17 @@ The reconciliation-pass operation appending model-declared labels missing from a
|
|
|
145
145
|
_Avoid_: Enum sync, label reconciliation, enum evolution
|
|
146
146
|
|
|
147
147
|
**Constraint rebuild**:
|
|
148
|
-
Drop-and-recreate of a ferro-owned constraint whose live definition no longer matches the declared model — a foreign key's `on_delete`, its target, its columns. Metadata-only: rows are never touched. On a backend that cannot alter constraints, ferro warns loudly and skips; it never diverges silently.
|
|
148
|
+
Drop-and-recreate of a ferro-owned constraint whose live definition no longer matches the declared model — a foreign key's `on_delete`, its target, its columns, or a table check's predicate. Metadata-only: rows are never touched. On a backend that cannot alter constraints, ferro warns loudly and skips; it never diverges silently.
|
|
149
149
|
_Avoid_: Constraint alter, FK patch, in-place constraint update
|
|
150
|
+
|
|
151
|
+
**Column check**:
|
|
152
|
+
A single-column CHECK that restricts a closed-domain field to its declared labels (`Field(db_check=True)` → `col IN (...)`). Named `ck_<table>_<col>`; not a table check.
|
|
153
|
+
_Avoid_: enum check, db_check constraint, value check
|
|
154
|
+
|
|
155
|
+
**Table check**:
|
|
156
|
+
A named boolean invariant over one row of one table, declared on the model as a lambda and enforced by the database as a CHECK constraint. The live name is `ck_<table>_<suffix>`; the suffix is what the model declares.
|
|
157
|
+
_Avoid_: table-level check, multi-column check, composite check, row check
|
|
158
|
+
|
|
159
|
+
**Check predicate**:
|
|
160
|
+
The lambda body of a table check — a ferro predicate over that model's own columns (or a forward-FK null test on the relation or its shadow `*_id`), with literal values only. Relation traversal, existence tests, and aggregates are not check predicates.
|
|
161
|
+
_Avoid_: check SQL, constraint expression, check body
|