ferro-orm 0.10.5__tar.gz → 0.12.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.10.5 → ferro_orm-0.12.0}/.github/PERMISSIONS.md +2 -2
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/.github/pull_request_template.md +9 -1
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/.github/workflows/ci.yml +101 -3
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/.github/workflows/publish-docs.yml +3 -3
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/.gitignore +1 -1
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/AGENTS.md +130 -1
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/CHANGELOG.md +34 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/CONTRIBUTING.md +3 -3
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/Cargo.lock +77 -251
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/Cargo.toml +6 -1
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/PKG-INFO +2 -2
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/README.md +1 -1
- ferro_orm-0.12.0/crates/ferro-migrate/Cargo.toml +7 -0
- ferro_orm-0.12.0/crates/ferro-migrate/src/lib.rs +271 -0
- ferro_orm-0.12.0/crates/ferro-schema-ir/Cargo.toml +8 -0
- ferro_orm-0.12.0/crates/ferro-schema-ir/src/lib.rs +195 -0
- ferro_orm-0.12.0/docs/examples/multiple_databases.py +45 -0
- ferro_orm-0.12.0/docs/examples/mutations.py +49 -0
- ferro_orm-0.12.0/docs/examples/pagination.py +47 -0
- ferro_orm-0.12.0/docs/examples/predicates.py +92 -0
- ferro_orm-0.12.0/docs/examples/predicates_annotated.py +36 -0
- ferro_orm-0.12.0/docs/examples/quickstart.py +111 -0
- ferro_orm-0.12.0/docs/examples/quickstart_annotated.py +48 -0
- ferro_orm-0.12.0/docs/examples/raw_sql.py +43 -0
- ferro_orm-0.12.0/docs/examples/relationships.py +128 -0
- ferro_orm-0.12.0/docs/examples/relationships_annotated.py +108 -0
- ferro_orm-0.12.0/docs/examples/soft_deletes.py +61 -0
- ferro_orm-0.12.0/docs/examples/soft_deletes_annotated.py +58 -0
- ferro_orm-0.12.0/docs/examples/testing_conftest.py +33 -0
- ferro_orm-0.12.0/docs/examples/timestamps.py +53 -0
- ferro_orm-0.12.0/docs/examples/timestamps_annotated.py +50 -0
- ferro_orm-0.12.0/docs/examples/transactions.py +58 -0
- ferro_orm-0.12.0/docs/pages/api/connection.md +21 -0
- ferro_orm-0.12.0/docs/pages/api/exceptions.md +5 -0
- ferro_orm-0.12.0/docs/pages/api/fields.md +15 -0
- ferro_orm-0.12.0/docs/pages/api/migrations.md +7 -0
- ferro_orm-0.12.0/docs/pages/api/model.md +5 -0
- ferro_orm-0.12.0/docs/pages/api/queries.md +11 -0
- ferro_orm-0.12.0/docs/pages/api/raw-sql.md +9 -0
- ferro_orm-0.12.0/docs/pages/api/relationships.md +11 -0
- ferro_orm-0.12.0/docs/pages/api/transactions.md +7 -0
- ferro_orm-0.12.0/docs/pages/changelog.md +1 -0
- ferro_orm-0.12.0/docs/pages/concepts/architecture.md +234 -0
- ferro_orm-0.12.0/docs/pages/concepts/backends.md +107 -0
- ferro_orm-0.12.0/docs/pages/concepts/identity-map.md +151 -0
- ferro_orm-0.12.0/docs/pages/concepts/performance.md +108 -0
- {ferro_orm-0.10.5/docs → ferro_orm-0.12.0/docs/pages}/concepts/query-typing.md +34 -33
- ferro_orm-0.12.0/docs/pages/concepts/type-safety.md +110 -0
- ferro_orm-0.12.0/docs/pages/contributing.md +5 -0
- ferro_orm-0.12.0/docs/pages/faq.md +103 -0
- ferro_orm-0.12.0/docs/pages/getting-started/installation.md +76 -0
- ferro_orm-0.12.0/docs/pages/getting-started/next-steps.md +56 -0
- ferro_orm-0.12.0/docs/pages/getting-started/quickstart.md +103 -0
- ferro_orm-0.12.0/docs/pages/guide/connections.md +192 -0
- ferro_orm-0.12.0/docs/pages/guide/migrations.md +164 -0
- ferro_orm-0.12.0/docs/pages/guide/models-and-fields.md +477 -0
- ferro_orm-0.12.0/docs/pages/guide/mutations.md +145 -0
- ferro_orm-0.12.0/docs/pages/guide/queries.md +177 -0
- ferro_orm-0.12.0/docs/pages/guide/raw-sql.md +109 -0
- ferro_orm-0.12.0/docs/pages/guide/relationships.md +240 -0
- ferro_orm-0.12.0/docs/pages/guide/transactions.md +121 -0
- ferro_orm-0.12.0/docs/pages/howto/migrate-from-sqlalchemy.md +270 -0
- ferro_orm-0.12.0/docs/pages/howto/migrating-to-v0-12-0.md +147 -0
- ferro_orm-0.12.0/docs/pages/howto/multiple-databases.md +71 -0
- ferro_orm-0.12.0/docs/pages/howto/pagination.md +122 -0
- ferro_orm-0.12.0/docs/pages/howto/soft-deletes.md +63 -0
- ferro_orm-0.12.0/docs/pages/howto/testing.md +169 -0
- ferro_orm-0.12.0/docs/pages/howto/timestamps.md +56 -0
- ferro_orm-0.12.0/docs/pages/index.md +12 -0
- ferro_orm-0.12.0/docs/pages/roadmap.md +22 -0
- ferro_orm-0.12.0/docs/pages/why-ferro.md +89 -0
- ferro_orm-0.12.0/docs/plans/2026-06-19-001-ir-first-roadmap.md +626 -0
- ferro_orm-0.12.0/docs/plans/ir-first-migration-guide.md +165 -0
- ferro_orm-0.12.0/docs/plans/ir-first-release-checklist.md +46 -0
- ferro_orm-0.12.0/docs/rfc/ir-contracts-v1.md +228 -0
- ferro_orm-0.12.0/docs/solutions/architecture-patterns/ir-first-merge-readiness-review.md +235 -0
- ferro_orm-0.12.0/docs/solutions/issues/sqlite-integer-decimal-hydrates-as-none.md +87 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/solutions/issues/sqlite-null-hydrates-as-int-zero.md +1 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/solutions/patterns/configurable-column-storage-types.md +8 -6
- ferro_orm-0.12.0/docs/solutions/patterns/ddl-on-live-engine.md +68 -0
- ferro_orm-0.12.0/docs/solutions/patterns/ir-invariants.md +182 -0
- ferro_orm-0.12.0/docs/solutions/patterns/sqlite-alembic-reconnect-hydration-tests.md +58 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/solutions/patterns/typed-null-binds.md +34 -28
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/pyproject.toml +8 -7
- ferro_orm-0.12.0/scripts/demo_queries.py +271 -0
- ferro_orm-0.10.5/scripts/demo_queries.py → ferro_orm-0.12.0/scripts/demo_queries_pre_v012.py +20 -22
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/backend.rs +365 -11
- ferro_orm-0.12.0/src/codec.rs +517 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/connection.rs +43 -39
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/__init__.py +40 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/_core.pyi +78 -11
- ferro_orm-0.12.0/src/ferro/_deprecations.py +100 -0
- ferro_orm-0.12.0/src/ferro/ir/__init__.py +13 -0
- ferro_orm-0.12.0/src/ferro/ir/compiler.py +439 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/metaclass.py +3 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/migrations/alembic.py +184 -14
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/models.py +119 -73
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/query/builder.py +100 -44
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/query/nodes.py +86 -13
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/raw.py +28 -22
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/relations/__init__.py +2 -0
- ferro_orm-0.12.0/src/ferro/session.py +43 -0
- ferro_orm-0.12.0/src/ferro/state.py +146 -0
- ferro_orm-0.12.0/src/hydration.rs +57 -0
- ferro_orm-0.12.0/src/introspect.rs +334 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/lib.rs +43 -2
- ferro_orm-0.12.0/src/migrate.rs +1481 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/operations.rs +641 -596
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/query.rs +311 -230
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/schema.rs +370 -210
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/state.rs +45 -0
- ferro_orm-0.12.0/tests/fixtures/ir_vectors/README.md +45 -0
- ferro_orm-0.12.0/tests/fixtures/ir_vectors/codec_registry_core_v1.json +100 -0
- ferro_orm-0.12.0/tests/fixtures/ir_vectors/query_user_compound_v1.json +58 -0
- ferro_orm-0.12.0/tests/fixtures/ir_vectors/schema_invoice_baseline_v1.json +101 -0
- ferro_orm-0.12.0/tests/fixtures/ir_vectors/schema_phase1_fixture_models_v1.json +215 -0
- ferro_orm-0.12.0/tests/fixtures/shadow_reports/postgres.json +47 -0
- ferro_orm-0.12.0/tests/fixtures/shadow_reports/sqlite.json +47 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_alembic_bridge.py +26 -0
- ferro_orm-0.12.0/tests/test_auto_migrate.py +582 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_connection.py +7 -4
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_cross_emitter_parity.py +99 -3
- ferro_orm-0.12.0/tests/test_deprecated_operator_inventory.py +51 -0
- ferro_orm-0.12.0/tests/test_deprecations.py +74 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_docs_examples.py +39 -5
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_documentation_features.py +27 -22
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_hydration.py +71 -4
- ferro_orm-0.12.0/tests/test_ir_vectors_contract.py +334 -0
- ferro_orm-0.12.0/tests/test_migrate_plan.py +225 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_query_builder.py +51 -24
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_query_typing.py +20 -10
- ferro_orm-0.12.0/tests/test_session.py +104 -0
- ferro_orm-0.12.0/tests/test_shadow_reports.py +112 -0
- ferro_orm-0.12.0/tests/test_static_contracts.py +8 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_typed_null_binds.py +42 -6
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/uv.lock +90 -131
- ferro_orm-0.12.0/zensical.toml +145 -0
- ferro_orm-0.10.5/docs/TEST_RESULTS.md +0 -210
- ferro_orm-0.10.5/docs/api/exceptions.md +0 -15
- ferro_orm-0.10.5/docs/api/fields.md +0 -21
- ferro_orm-0.10.5/docs/api/model.md +0 -31
- ferro_orm-0.10.5/docs/api/query.md +0 -97
- ferro_orm-0.10.5/docs/api/raw-sql.md +0 -124
- ferro_orm-0.10.5/docs/api/relationships.md +0 -35
- ferro_orm-0.10.5/docs/api/transactions.md +0 -36
- ferro_orm-0.10.5/docs/api/utilities.md +0 -73
- ferro_orm-0.10.5/docs/changelog.md +0 -46
- ferro_orm-0.10.5/docs/coming-soon.md +0 -509
- ferro_orm-0.10.5/docs/concepts/architecture.md +0 -332
- ferro_orm-0.10.5/docs/concepts/identity-map.md +0 -285
- ferro_orm-0.10.5/docs/concepts/performance.md +0 -222
- ferro_orm-0.10.5/docs/concepts/type-safety.md +0 -183
- ferro_orm-0.10.5/docs/contributing.md +0 -3
- ferro_orm-0.10.5/docs/faq.md +0 -262
- ferro_orm-0.10.5/docs/getting-started/installation.md +0 -86
- ferro_orm-0.10.5/docs/getting-started/next-steps.md +0 -159
- ferro_orm-0.10.5/docs/getting-started/tutorial.md +0 -388
- ferro_orm-0.10.5/docs/guide/backend.md +0 -404
- ferro_orm-0.10.5/docs/guide/database.md +0 -340
- ferro_orm-0.10.5/docs/guide/migrations.md +0 -445
- ferro_orm-0.10.5/docs/guide/models-and-fields.md +0 -272
- ferro_orm-0.10.5/docs/guide/mutations.md +0 -478
- ferro_orm-0.10.5/docs/guide/queries.md +0 -395
- ferro_orm-0.10.5/docs/guide/relationships.md +0 -393
- ferro_orm-0.10.5/docs/guide/transactions.md +0 -380
- ferro_orm-0.10.5/docs/howto/multiple-databases.md +0 -74
- ferro_orm-0.10.5/docs/howto/pagination.md +0 -355
- ferro_orm-0.10.5/docs/howto/soft-deletes.md +0 -86
- ferro_orm-0.10.5/docs/howto/testing.md +0 -205
- ferro_orm-0.10.5/docs/howto/timestamps.md +0 -57
- ferro_orm-0.10.5/docs/index.md +0 -142
- ferro_orm-0.10.5/docs/migration-sqlalchemy.md +0 -173
- ferro_orm-0.10.5/docs/why-ferro.md +0 -206
- ferro_orm-0.10.5/mkdocs.yml +0 -170
- ferro_orm-0.10.5/src/ferro/state.py +0 -19
- ferro_orm-0.10.5/tests/test_auto_migrate.py +0 -200
- ferro_orm-0.10.5/tests/test_static_contracts.py +0 -8
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/.github/PYPI_CHECKLIST.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/.github/PYPI_SETUP.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/.github/generated/wheels.generated.yml +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/.github/workflows/packaging-smoke.yml +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/.github/workflows/publish.yml +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/.github/workflows/release.yml +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/.pre-commit-config.yaml +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/.python-version +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/LICENSE +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/brainstorms/2026-04-29-named-connections-role-routing-requirements.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/brainstorms/2026-05-08-typed-query-predicates-requirements.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/brainstorms/2026-05-13-configurable-column-storage-types-requirements.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/brainstorms/2026-05-14-autogenerate-support-for-db-type-requirements.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/brainstorms/2026-05-25-annotated-strenum-cold-hydration-requirements.md +0 -0
- {ferro_orm-0.10.5/docs → ferro_orm-0.12.0/docs/pages}/stylesheets/extra.css +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/plans/2026-04-24-001-refactor-multi-db-backend-architecture-plan.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/plans/2026-04-29-001-typed-null-binds-plan.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/plans/2026-04-29-002-feat-named-connections-plan.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/plans/2026-05-07-001-refactor-generic-model-connection-plan.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/plans/2026-05-08-001-feat-typed-query-predicates-plan.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/plans/2026-05-13-001-feat-configurable-column-storage-types-plan.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/plans/2026-05-25-001-fix-annotated-strenum-cold-hydration-plan.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/solutions/README.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/solutions/issues/pydantic-slots-missing-after-ferro-hydration.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/solutions/issues/python-3.14-deferred-annotation-typeerror-swallow.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/solutions/issues/sa-pk-column-nullable-divergence.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/solutions/issues/sa-vs-rust-unique-constraint-shape.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/solutions/issues/typed-where-null-panics-is-null.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/solutions/patterns/cross-emitter-ddl-parity.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/solutions/patterns/foreign-key-index.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/solutions/patterns/index-unique-redundancy.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/docs/solutions/patterns/shadow-fk-columns.md +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/justfile +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/_annotation_utils.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/_shadow_fk_types.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/base.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/composite_indexes.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/composite_uniques.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/exceptions.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/fields.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/migrations/__init__.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/py.typed +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/query/__init__.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/relations/descriptors.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/ferro/schema_metadata.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/src/schema_bind.rs +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/__init__.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/conftest.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/db_backends.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_aggregation.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_alembic_autogenerate.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_alembic_db_type.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_alembic_nullability.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_alembic_type_mapping.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_bulk_update.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_composite_index.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_composite_unique.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_connection_redaction.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_constraints.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_crud.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_db_backends.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_db_type_cross_emitter_parity.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_db_type_integration.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_db_type_typing.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_db_type_validation.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_deletion.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_enum_cold_hydration.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_field_wrapper.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_helpers.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_metaclass_internals.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_metadata.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_models.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_named_connections_integration.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_one_to_one.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_raw_sql.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_refresh.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_relationship_engine.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_schema.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_schema_constraints.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_schema_db_type_metadata.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_schema_enum_annotations.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_shadow_fk_types.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_sqlite_alembic_reconnect_hydration.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_string_search.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_structural_types.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_temporal_types.py +0 -0
- {ferro_orm-0.10.5 → ferro_orm-0.12.0}/tests/test_transactions.py +0 -0
|
@@ -133,12 +133,12 @@ permissions:
|
|
|
133
133
|
|
|
134
134
|
**Why These Permissions:**
|
|
135
135
|
- `pages: write` - Allows the workflow to:
|
|
136
|
-
- Deploy the generated
|
|
136
|
+
- Deploy the generated Zensical static site to GitHub Pages
|
|
137
137
|
- Update the Pages deployment for the repository
|
|
138
138
|
- `id-token: write` - Allows secure OIDC auth for Pages deployment
|
|
139
139
|
|
|
140
140
|
**What It Does:**
|
|
141
|
-
- Builds
|
|
141
|
+
- Builds Zensical docs
|
|
142
142
|
- Deploys docs to GitHub Pages
|
|
143
143
|
|
|
144
144
|
---
|
|
@@ -33,4 +33,12 @@
|
|
|
33
33
|
|
|
34
34
|
## Related Issues
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
- Closes #
|
|
37
|
+
- Closes #
|
|
38
|
+
|
|
39
|
+
<!-- Use one line per completed issue: Closes #123 / Fixes #123 / Resolves #123 -->
|
|
40
|
+
|
|
41
|
+
## Exit Steps
|
|
42
|
+
|
|
43
|
+
- [ ] Related completed issues are linked above with Closes/Fixes/Resolves
|
|
44
|
+
- [ ] Issue statuses are updated/auto-close on merge
|
|
@@ -3,9 +3,9 @@ name: CI
|
|
|
3
3
|
on:
|
|
4
4
|
workflow_call:
|
|
5
5
|
pull_request:
|
|
6
|
-
branches: [main]
|
|
6
|
+
branches: [main, feat/ir-first]
|
|
7
7
|
push:
|
|
8
|
-
branches: [main]
|
|
8
|
+
branches: [main, feat/ir-first]
|
|
9
9
|
workflow_dispatch:
|
|
10
10
|
|
|
11
11
|
concurrency:
|
|
@@ -16,6 +16,33 @@ permissions:
|
|
|
16
16
|
contents: read
|
|
17
17
|
|
|
18
18
|
jobs:
|
|
19
|
+
changed-shadow-paths:
|
|
20
|
+
name: Detect Shadow-Report Paths
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
if: github.event_name == 'pull_request'
|
|
23
|
+
outputs:
|
|
24
|
+
requires_shadow_reports: ${{ steps.filter.outputs.shadow }}
|
|
25
|
+
steps:
|
|
26
|
+
- name: Checkout repository
|
|
27
|
+
uses: actions/checkout@v4
|
|
28
|
+
|
|
29
|
+
- name: Detect planner/IR path changes
|
|
30
|
+
id: filter
|
|
31
|
+
uses: dorny/paths-filter@v3
|
|
32
|
+
with:
|
|
33
|
+
filters: |
|
|
34
|
+
shadow:
|
|
35
|
+
- 'src/operations.rs'
|
|
36
|
+
- 'src/query.rs'
|
|
37
|
+
- 'src/schema.rs'
|
|
38
|
+
- 'src/migrate.rs'
|
|
39
|
+
- 'src/backend.rs'
|
|
40
|
+
- 'src/connection.rs'
|
|
41
|
+
- 'src/ferro/ir/**'
|
|
42
|
+
- 'crates/ferro-schema-ir/**'
|
|
43
|
+
- 'tests/test_shadow_reports.py'
|
|
44
|
+
- 'tests/fixtures/shadow_reports/**'
|
|
45
|
+
|
|
19
46
|
lint-and-format:
|
|
20
47
|
name: Lint & Format (Pre-commit / Prek)
|
|
21
48
|
runs-on: ubuntu-latest
|
|
@@ -126,6 +153,10 @@ jobs:
|
|
|
126
153
|
run: |
|
|
127
154
|
uv run maturin develop
|
|
128
155
|
|
|
156
|
+
- name: Run IR vector contract harness
|
|
157
|
+
run: |
|
|
158
|
+
uv run pytest -v tests/test_ir_vectors_contract.py
|
|
159
|
+
|
|
129
160
|
- name: Run pytest
|
|
130
161
|
run: |
|
|
131
162
|
uv run pytest -v --cov=src --cov-report=xml --cov-report=term
|
|
@@ -169,6 +200,10 @@ jobs:
|
|
|
169
200
|
run: |
|
|
170
201
|
uv run maturin develop
|
|
171
202
|
|
|
203
|
+
- name: Run IR vector contract harness
|
|
204
|
+
run: |
|
|
205
|
+
uv run pytest -v tests/test_ir_vectors_contract.py
|
|
206
|
+
|
|
172
207
|
- name: Run pytest
|
|
173
208
|
run: |
|
|
174
209
|
uv run pytest -v --cov=src --cov-report=xml --cov-report=term
|
|
@@ -236,6 +271,64 @@ jobs:
|
|
|
236
271
|
run: |
|
|
237
272
|
uv run pytest -v -m "backend_matrix or postgres_only" --db-backends=sqlite,postgres
|
|
238
273
|
|
|
274
|
+
test-shadow-reports-pr:
|
|
275
|
+
name: Shadow reports (touched paths)
|
|
276
|
+
runs-on: ubuntu-latest
|
|
277
|
+
needs: [changed-shadow-paths]
|
|
278
|
+
if: github.event_name == 'pull_request' && needs.changed-shadow-paths.outputs.requires_shadow_reports == 'true'
|
|
279
|
+
services:
|
|
280
|
+
postgres:
|
|
281
|
+
image: postgres:17
|
|
282
|
+
env:
|
|
283
|
+
POSTGRES_USER: ferro
|
|
284
|
+
POSTGRES_PASSWORD: ferro
|
|
285
|
+
POSTGRES_DB: ferro
|
|
286
|
+
ports:
|
|
287
|
+
- 5432:5432
|
|
288
|
+
options: >-
|
|
289
|
+
--health-cmd "pg_isready -U ferro -d ferro"
|
|
290
|
+
--health-interval 10s
|
|
291
|
+
--health-timeout 5s
|
|
292
|
+
--health-retries 5
|
|
293
|
+
env:
|
|
294
|
+
FERRO_SUPABASE_URL: postgresql://ferro:ferro@127.0.0.1:5432/ferro?sslmode=disable
|
|
295
|
+
FERRO_SHADOW_RUNTIME: "1"
|
|
296
|
+
FERRO_SHADOW_RUNTIME_STRICT: "1"
|
|
297
|
+
steps:
|
|
298
|
+
- name: Checkout repository
|
|
299
|
+
uses: actions/checkout@v4
|
|
300
|
+
|
|
301
|
+
- name: Set up Python
|
|
302
|
+
uses: actions/setup-python@v5
|
|
303
|
+
with:
|
|
304
|
+
python-version: '3.13'
|
|
305
|
+
|
|
306
|
+
- name: Install UV
|
|
307
|
+
uses: astral-sh/setup-uv@v5
|
|
308
|
+
with:
|
|
309
|
+
enable-cache: true
|
|
310
|
+
|
|
311
|
+
- name: Set up Rust
|
|
312
|
+
uses: dtolnay/rust-toolchain@stable
|
|
313
|
+
|
|
314
|
+
- name: Cache Rust build
|
|
315
|
+
uses: Swatinem/rust-cache@v2
|
|
316
|
+
with:
|
|
317
|
+
prefix-key: v1
|
|
318
|
+
cache-on-failure: true
|
|
319
|
+
|
|
320
|
+
- name: Install dependencies
|
|
321
|
+
run: |
|
|
322
|
+
uv sync --only-group ci-test --no-install-project --python 3.13
|
|
323
|
+
|
|
324
|
+
- name: Build Rust extension
|
|
325
|
+
run: |
|
|
326
|
+
uv run maturin develop
|
|
327
|
+
|
|
328
|
+
- name: Verify stable shadow reports
|
|
329
|
+
run: |
|
|
330
|
+
uv run pytest -v tests/test_shadow_reports.py::test_shadow_report_fixture_stable --db-backends=sqlite,postgres
|
|
331
|
+
|
|
239
332
|
check-conventional-commits:
|
|
240
333
|
name: Check Conventional Commits
|
|
241
334
|
runs-on: ubuntu-latest
|
|
@@ -285,7 +378,7 @@ jobs:
|
|
|
285
378
|
|
|
286
379
|
all-checks:
|
|
287
380
|
name: All Checks Passed
|
|
288
|
-
needs: [lint-and-format, test-python-pr, test-python-main, test-python-backend-matrix, test-rust]
|
|
381
|
+
needs: [changed-shadow-paths, lint-and-format, test-python-pr, test-python-main, test-python-backend-matrix, test-shadow-reports-pr, test-rust]
|
|
289
382
|
runs-on: ubuntu-latest
|
|
290
383
|
if: always()
|
|
291
384
|
steps:
|
|
@@ -294,10 +387,15 @@ jobs:
|
|
|
294
387
|
run: |
|
|
295
388
|
ok() { [[ "$1" == "success" || "$1" == "skipped" ]]; }
|
|
296
389
|
|
|
390
|
+
if [[ "${{ needs.changed-shadow-paths.result }}" == "failure" ]]; then
|
|
391
|
+
echo "Shadow path detection failed; refusing to treat shadow gate as passed."
|
|
392
|
+
exit 1
|
|
393
|
+
fi
|
|
297
394
|
if ! ok "${{ needs.lint-and-format.result }}"; then exit 1; fi
|
|
298
395
|
if ! ok "${{ needs.test-python-pr.result }}"; then exit 1; fi
|
|
299
396
|
if ! ok "${{ needs.test-python-main.result }}"; then exit 1; fi
|
|
300
397
|
if ! ok "${{ needs.test-python-backend-matrix.result }}"; then exit 1; fi
|
|
398
|
+
if ! ok "${{ needs.test-shadow-reports-pr.result }}"; then exit 1; fi
|
|
301
399
|
if ! ok "${{ needs.test-rust.result }}"; then exit 1; fi
|
|
302
400
|
|
|
303
401
|
echo "All checks passed!"
|
|
@@ -18,7 +18,7 @@ permissions:
|
|
|
18
18
|
|
|
19
19
|
jobs:
|
|
20
20
|
build-docs:
|
|
21
|
-
name: Build docs (
|
|
21
|
+
name: Build docs (Zensical)
|
|
22
22
|
runs-on: ubuntu-latest
|
|
23
23
|
steps:
|
|
24
24
|
- name: Checkout repository
|
|
@@ -40,9 +40,9 @@ jobs:
|
|
|
40
40
|
run: |
|
|
41
41
|
uv sync --only-group docs --no-install-project --python 3.13
|
|
42
42
|
|
|
43
|
-
- name: Build
|
|
43
|
+
- name: Build Zensical site
|
|
44
44
|
run: |
|
|
45
|
-
uv run --no-sync
|
|
45
|
+
uv run --no-sync zensical build --clean
|
|
46
46
|
|
|
47
47
|
- name: Upload Pages artifact
|
|
48
48
|
uses: actions/upload-pages-artifact@v3
|
|
@@ -32,7 +32,7 @@ For a single model, every emitter must agree on:
|
|
|
32
32
|
includes the canonical `db_type` vocabulary (`text`, `varchar(N)`,
|
|
33
33
|
`smallint`, `int`, `bigint`, `uuid`, `timestamp`, `timestamptz`, `date`,
|
|
34
34
|
`time`) — duplicated in `_db_type_to_sa_type` (Python) and
|
|
35
|
-
`
|
|
35
|
+
`db_type_token_to_canonical` (Rust), pinned by
|
|
36
36
|
`tests/test_db_type_cross_emitter_parity.py`.
|
|
37
37
|
4. **Index names** — `idx_<table>_<col>` for single-column indexes,
|
|
38
38
|
`idx_<table>_<col1>_<col2>...` for composite indexes.
|
|
@@ -147,3 +147,132 @@ search this directory before starting work.
|
|
|
147
147
|
`docs/solutions/issues/` — debugging stories and known footguns.
|
|
148
148
|
|
|
149
149
|
See `docs/solutions/README.md` for the frontmatter conventions.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## I-6: No AI attribution in commits or PRs
|
|
154
|
+
|
|
155
|
+
Never sign commits or pull requests with AI/agent attribution. No
|
|
156
|
+
`Co-Authored-By: Claude ...` trailers, no "Generated with Claude Code"
|
|
157
|
+
footers, no robot emoji bylines — in commit messages, PR titles, or PR
|
|
158
|
+
bodies. This applies even when an agent's default behavior is to add them:
|
|
159
|
+
this rule overrides those defaults for this repository.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## I-7: No stop-gap solutions
|
|
164
|
+
|
|
165
|
+
Every feature, bug fix, and improvement must be designed as the best,
|
|
166
|
+
well-thought-out solution for the project with the library's future in
|
|
167
|
+
mind — as if time and money were no object. No stop-gaps, hacks,
|
|
168
|
+
quick-fixes, or otherwise lesser solves.
|
|
169
|
+
|
|
170
|
+
What this means in practice:
|
|
171
|
+
|
|
172
|
+
- **Prefer first-class, reusable primitives over local patches.** If a fix
|
|
173
|
+
only works for the immediate symptom while leaving the underlying
|
|
174
|
+
capability gap in place, build the capability instead. (Precedent:
|
|
175
|
+
`EngineHandle::refresh_pool()` was built as an engine-level schema-epoch
|
|
176
|
+
primitive rather than a migration-local statement-cache flush.)
|
|
177
|
+
- **Fail loudly over degrading silently.** "Skip with a warning and
|
|
178
|
+
continue", "best effort", and "documented residual risk" are not
|
|
179
|
+
acceptable resolutions for correctness gaps. Either the operation
|
|
180
|
+
succeeds completely or it aborts with a clear, actionable error.
|
|
181
|
+
- **Treat certain phrases as redesign triggers.** If a plan, comment, or PR
|
|
182
|
+
description contains "best-effort", "partial mitigation", "documented
|
|
183
|
+
residual risk", "good enough for now", "temporary workaround", or
|
|
184
|
+
"fallback if X turns out to be hard" — that part of the design is not
|
|
185
|
+
finished. Redesign it before presenting or implementing it.
|
|
186
|
+
- **Scoped-down is fine; hollowed-out is not.** Deliberately excluding
|
|
187
|
+
something from scope (with the boundary stated and a real path for the
|
|
188
|
+
excluded case, e.g. "renames are Alembic territory") is good design.
|
|
189
|
+
Shipping a half-working version of something that is *in* scope is not.
|
|
190
|
+
|
|
191
|
+
This rule binds human contributors and AI agents equally, and overrides any
|
|
192
|
+
agent default that biases toward minimal or expedient changes.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## I-8: Docs examples show both field-declaration styles
|
|
197
|
+
|
|
198
|
+
Ferro supports two equivalent ways to declare model fields: assignment
|
|
199
|
+
(`name: str = Field(unique=True)`) and `Annotated` metadata
|
|
200
|
+
(`name: Annotated[str, Field(unique=True)]`). Every documentation example
|
|
201
|
+
that declares model fields with `Field()`/`FerroField()` options must show
|
|
202
|
+
**both** styles, side by side, as content tabs:
|
|
203
|
+
|
|
204
|
+
=== "Assignment"
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
--8<-- "docs/examples/<example>.py:models"
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
=== "Annotated"
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
--8<-- "docs/examples/<example>_annotated.py:models"
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Rules:
|
|
217
|
+
|
|
218
|
+
- Both tabs must be backed by real, runnable code. Snippet-embedded model
|
|
219
|
+
definitions get a runnable `<name>_annotated.py` companion in
|
|
220
|
+
`docs/examples/` (exercised by `tests/test_docs_examples.py`); inline
|
|
221
|
+
blocks are written in both styles and compile-checked by the same test.
|
|
222
|
+
- Constructs with only one valid form appear identically in both tabs and
|
|
223
|
+
are not tabbed on their own: forward FKs are always
|
|
224
|
+
`Annotated[Target, ForeignKey(...)]`, and `BackRef()` / `ManyToMany()`
|
|
225
|
+
are always assignments.
|
|
226
|
+
- Code blocks that do not declare fields (queries, mutations, transactions,
|
|
227
|
+
usage snippets) are not affected by this rule.
|
|
228
|
+
|
|
229
|
+
This keeps users from ever wondering whether something is possible in their
|
|
230
|
+
preferred declaration style.
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## I-9: Lambda predicates are the official query style
|
|
235
|
+
|
|
236
|
+
Documentation and examples use the lambda predicate style for all queries:
|
|
237
|
+
|
|
238
|
+
```python
|
|
239
|
+
adults = await User.where(lambda t: t.age >= 18).all()
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Rules:
|
|
243
|
+
|
|
244
|
+
- **Every query example** in docs, docstring `Examples:` sections, and
|
|
245
|
+
`docs/examples/` scripts uses lambda predicates.
|
|
246
|
+
- When the predicate styles themselves are documented, present them in
|
|
247
|
+
order **lambda > `col()` > operator**, with lambda labeled the officially
|
|
248
|
+
recommended style.
|
|
249
|
+
- **Operator style** (`User.where(User.age >= 18)`) is compatible today but
|
|
250
|
+
is slated for deprecation in a future release and fails static type
|
|
251
|
+
checking (`User.age >= 18` types as `bool`; `where()` expects
|
|
252
|
+
`QueryNode | Predicate`). Docs say so explicitly wherever the style is
|
|
253
|
+
shown.
|
|
254
|
+
- **`order_by` is not a predicate** and keeps attribute style
|
|
255
|
+
(`order_by(User.age, "desc")`). Passing a lambda to `order_by` silently
|
|
256
|
+
produces a junk column name — never show it.
|
|
257
|
+
|
|
258
|
+
The canonical comparisons live in `docs/pages/guide/queries.md`
|
|
259
|
+
("Predicate Styles") and `docs/pages/concepts/query-typing.md`; everywhere
|
|
260
|
+
else uses lambda without restating the trade-offs.
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## I-10: PRs must close scoped issues explicitly
|
|
265
|
+
|
|
266
|
+
Issue closure is part of feature completion, not optional cleanup.
|
|
267
|
+
|
|
268
|
+
Rules:
|
|
269
|
+
|
|
270
|
+
- Every PR that completes scoped work **must** include GitHub auto-close
|
|
271
|
+
keywords in the PR body for each completed issue, e.g.
|
|
272
|
+
`Closes #89`, `Fixes #90`, `Resolves #91`.
|
|
273
|
+
- Do not rely on manual post-merge issue triage when the work is already done
|
|
274
|
+
in the PR; encode closure directly in the PR body.
|
|
275
|
+
- PRs must include an explicit exit-steps checklist item confirming issue status
|
|
276
|
+
updates are complete before merge.
|
|
277
|
+
- AI agents and human contributors follow the same requirement. If issue status
|
|
278
|
+
closure is missing, the PR is not done.
|
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## v0.12.0 (2026-06-23)
|
|
5
|
+
|
|
6
|
+
### Documentation
|
|
7
|
+
|
|
8
|
+
- Rewrite site on Zensical with runnable examples
|
|
9
|
+
([#70](https://github.com/syn54x/ferro-orm/pull/70),
|
|
10
|
+
[`da86911`](https://github.com/syn54x/ferro-orm/commit/da869118c55314363139a021c139a52a2bc8d1fb))
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
- IR-first architecture program (Phases 0–7) ([#116](https://github.com/syn54x/ferro-orm/pull/116),
|
|
15
|
+
[`1c22857`](https://github.com/syn54x/ferro-orm/commit/1c228577aa663c4630a5c8a33f0bb000ebe288b2))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## v0.11.0 (2026-06-11)
|
|
19
|
+
|
|
20
|
+
### Chores
|
|
21
|
+
|
|
22
|
+
- Solution quality requirements
|
|
23
|
+
([`c62770b`](https://github.com/syn54x/ferro-orm/commit/c62770b6d3073e8d596c30f29895bccddc2a4d7f))
|
|
24
|
+
|
|
25
|
+
### Documentation
|
|
26
|
+
|
|
27
|
+
- Compound SQLite hydration learnings (#56, #58)
|
|
28
|
+
([#60](https://github.com/syn54x/ferro-orm/pull/60),
|
|
29
|
+
[`b609e72`](https://github.com/syn54x/ferro-orm/commit/b609e7274e1886cc5d8564c7adb52fc3c79ffc8d))
|
|
30
|
+
|
|
31
|
+
### Features
|
|
32
|
+
|
|
33
|
+
- Extend auto_migrate with column updates and destructive drops
|
|
34
|
+
([#69](https://github.com/syn54x/ferro-orm/pull/69),
|
|
35
|
+
[`a76cb0f`](https://github.com/syn54x/ferro-orm/commit/a76cb0f2451dab79303353f2c77d74ca3e1ad4a5))
|
|
36
|
+
|
|
37
|
+
|
|
4
38
|
## v0.10.5 (2026-05-25)
|
|
5
39
|
|
|
6
40
|
### Bug Fixes
|
|
@@ -37,7 +37,7 @@ This will install all development dependencies including:
|
|
|
37
37
|
- Testing tools (pytest, pytest-asyncio, pytest-cov)
|
|
38
38
|
- Linting and formatting tools (ruff, prek)
|
|
39
39
|
- Build tools (maturin)
|
|
40
|
-
- Documentation tools (
|
|
40
|
+
- Documentation tools (zensical)
|
|
41
41
|
- Release tools (commitizen, python-semantic-release)
|
|
42
42
|
|
|
43
43
|
### 3. Install Pre-commit Hooks
|
|
@@ -102,10 +102,10 @@ cargo clippy # Rust linting
|
|
|
102
102
|
|
|
103
103
|
```bash
|
|
104
104
|
# Serve documentation locally (with live reload)
|
|
105
|
-
uv run
|
|
105
|
+
uv run zensical serve
|
|
106
106
|
|
|
107
107
|
# Build documentation
|
|
108
|
-
uv run
|
|
108
|
+
uv run zensical build
|
|
109
109
|
|
|
110
110
|
# Documentation will be available at http://127.0.0.1:8000/
|
|
111
111
|
```
|