matrx-orm 3.1.236__tar.gz → 3.1.238__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.
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/BASE_CLASS_METHODS.md +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/CLAUDE.md +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/PKG-INFO +2 -2
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/adapters/async_postgresql.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/associations.py +3 -3
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/FEATURE.md +4 -4
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/TASKS.md +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/async_db_manager.py +6 -6
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/base.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/config.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/diagnostics.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/expressions.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/extended.py +41 -4
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/fields.py +2 -2
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/foreign_session_state.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/model_view.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/pooler_role.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/resilience.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/session_context.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/transaction.py +2 -2
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/write_retry.py +4 -4
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/exceptions.py +5 -5
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/operations/conflict.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/operations/conflict_writes.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/operations/create.py +3 -3
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/platform_access.py +3 -3
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/pytest_lock_guard.py +6 -6
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/query/executor.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/columns.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/runner.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/schema.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/secrets_battery/service.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/session/flush.py +20 -11
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/session/reads.py +51 -7
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/session/session.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/state.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/pyproject.toml +2 -2
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_associations.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_borrowed_role_never_reaches_server_calls.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_cache_debug.py +1 -1
- matrx_orm-3.1.238/tests/level1/test_fetch_on_init_holds_whole_table.py +116 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_lock_contention_retry.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_pool_create_never_wedges.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema_builder/test_array_default_parsing.py +1 -1
- matrx_orm-3.1.238/tests/session/test_a_grouped_update_writes_only_each_rows_own_fields.py +36 -0
- matrx_orm-3.1.238/tests/session/test_pending_insert_honors_operator_filters.py +65 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_array_arg_element_type.py +2 -2
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_first_asks_the_database_for_one_row.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_secrets_battery.py +1 -1
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_shared_lock_guard.py +2 -2
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/.gitignore +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/AGENTS.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/CHANGELOG.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/MODEL_API.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/README.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/database/orm/extended/managers/ai_model_base.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/docs/migrations.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/FEATURE.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/MODULE_README.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/adapters/MODULE_README.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/adapters/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/adapters/base_adapter.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/adapters/postgrest_client_adapter.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/adapters/supabase_adapter.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/admin/FEATURE.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/admin/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/admin/router.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/api/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/api/auth.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/api/config.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/api/handlers.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/api/protocol.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/api/server.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/cache_debug.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/catalog.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/catalog_sql.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/client/MODULE_README.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/client/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/client/postgres_connection.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/client/postgrest.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/client/supabase_auth.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/client/supabase_config.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/client/supabase_manager.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/EXTENDED-TASK.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/MODULE_README.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/RELATIONS-TASKS.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/admin_lane.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/connections.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/db_function.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/introspection.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/listen.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/loop_filters.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/model_dto.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/one_database.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/paginator.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/pool_maintenance.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/pool_watch.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/pydantic_bridge.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/read_write.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/registry.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/relations.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/rls_session.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/signals.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/statement_ceiling.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/tls.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/types.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/core/write_queue.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/entity.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/error_handling.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/extended/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/extended/app_error_handler.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/identity_rule.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/local_sqlite.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/middleware/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/middleware/base.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/migrations/MODULE_README.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/migrations/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/migrations/cli.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/migrations/ddl.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/migrations/diff.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/migrations/executor.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/migrations/integration.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/migrations/loader.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/migrations/operations.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/migrations/state.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/migrations/table_filter.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/no_org_assignment.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/operations/FEATURE.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/operations/MODULE_README.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/operations/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/operations/bulk_update_values.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/operations/catalog_select.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/operations/db_functions.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/operations/delete.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/operations/dynamic_admin.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/operations/dynamic_crud.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/operations/graph_walk.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/operations/latest_rows.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/operations/queue_claim.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/operations/read.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/operations/relational_backfill.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/operations/staging_load.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/operations/update.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/platform_db.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/py.typed +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/pytest_plugin.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/python_sql/MODULE_README.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/python_sql/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/python_sql/db_objects.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/python_sql/table_detailed_relationships.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/python_sql/table_typescript_relationship.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/query/FEATURE.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/query/MODULE_README.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/query/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/query/builder.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/resources/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/resources/additional-assigners-2026-09-12.json +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/resources/org_assignment_trigger_baseline.json +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/FEATURE.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/MODULE_README.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/code_handler.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/codegen_writer.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/common.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/diff_preview.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/entity_capabilities.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/excluded_targets.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/generator.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/helpers/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/helpers/base_generators.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/helpers/entity_generators.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/helpers/git_checker.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/package_wiring.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/relationships.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/schema_manager.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/tables.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/schema_builder/views.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/secrets_battery/FEATURE.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/secrets_battery/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/secrets_battery/attachments.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/secrets_battery/backup_restore.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/secrets_battery/crypto.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/secrets_battery/host_authorization.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/secrets_battery/items.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/secrets_battery/model.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/secrets_battery/mutation_receipts.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/secrets_battery/native_enable.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/secrets_battery/native_lifecycle.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/secrets_battery/native_passkeys.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/secrets_battery/native_source.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/secrets_battery/org_service.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/secrets_battery/org_vault_gate.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/secrets_battery/vault_history.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/session/README.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/session/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/session/coalesce.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/session/dag.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/session/errors.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/session/fallback.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/session/lifecycle.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/session/managed.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/session/op.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/session/telemetry.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/sql_executor/MODULE_README.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/sql_executor/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/sql_executor/executor.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/sql_executor/queries.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/sql_executor/registry.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/sql_executor/types.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/sql_executor/utils.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/utils/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/utils/sql_utils.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/utils/type_converters.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/matrx_orm/write_actor.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/scripts/git-branches.sh +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/scripts/publish.sh +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/scripts/release.sh +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/MODULE_README.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/conftest.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/MODULE_README.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_adapter_registry.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_admin_db_columns.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_admin_response_rendering.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_admin_search_negation.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_admin_search_sentinels.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_advisory_lock.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_agent_message.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_api_auth.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_api_config.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_api_handlers.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_api_protocol.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_array_agg_order_by.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_association_trigger_actor_naming.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_associations_wiring.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_bulk_hydration_offload.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_bulk_update_by_pk.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_bulk_upsert_increment_set_fields.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_call_function.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_case_when.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_catalog.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_column_scoped_writes.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_committed_row_guard.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_composite_pk_filter.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_composite_pk_write_paths.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_config.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_conflict_target.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_conflict_writes.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_connection_codecs.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_connection_poison_guard.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_connection_primitives.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_count_composite_distinct.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_count_limit_param_leak.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_db_function_field.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_ddl_generator.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_deadlock_retry.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_derived_table.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_dirty_tracking.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_dynamic_crud.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_exceptions.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_execute_query_integrity_mapping.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_expression_primitives.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_fields.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_filter_jsonb_agg_array_index.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_fk_cycle_resolution.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_from_alias.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_fts.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_func_expression_args.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_graph_walk.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_having_annotate_alias.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_insert_ignore_and_admin_primitives.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_introspect_rls_policies.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_join_and_aggregate.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_latest_rows.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_listen_notify.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_local_sqlite.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_managed_write_guard.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_matrx_entity.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_migration_diff_types.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_migration_loader.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_model_instance.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_model_meta.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_optimistic_concurrency.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_order_by_expression.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_org_assignment_inventory.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_orm_banners_are_client_safe.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_parameter_name_hydration.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_patch_jsonb_path.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_percentile_cont.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_persisted_count.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_person_scoped_session_bypasses_shared_cache.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_pool_holder_census.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_pool_loop_recreation.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_pool_maintenance.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_postgrest_filters.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_pydantic_bridge.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_query_builder.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_query_error_detail.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_query_executor_sql.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_query_timeout.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_querybuilder_clone_semantics.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_queue_claim.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_read_connection_retry.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_read_write_declared.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_registry.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_registry_multi_database.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_registry_multi_schema.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_relational_backfill.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_relations.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_resilience.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_rls_session_scope.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_schema_exists.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_session_advisory_lock.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_standalone_write_session_context.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_state_cache.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_subquery_filter_raw.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_subquery_in_filter.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_subquery_nested_expressions.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_supabase_auth.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_supabase_config.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_tls.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_transaction_database_identity.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_transaction_gucs_one_round_trip.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_transaction_pool_release_sends_nothing.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_typed_join_projection.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_typed_predicates.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_update_case_expression.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_update_subquery.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_update_with_rebase.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_upsert_default_leak.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_upsert_with_conflict.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_values_jsonb_decode.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_watched_lifecycle.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_write_queue_deadline.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level1/test_write_retry_semantics.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level2/MODULE_README.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level2/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level2/conftest.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level2/test_bulk_ops.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level2/test_cache_integration.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level2/test_crud.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level2/test_foreign_keys.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level2/test_m2m.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level2/test_manager.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level2/test_migrations_live.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level2/test_query_execution.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level2/test_schema_diff.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/level2/verify_committed_row_guard_pg17.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/live_pooler_role.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/native_source_cases.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/native_source_oracle.rs +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/sample_project/.env.example +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/sample_project/README.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/sample_project/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/sample_project/generate.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/sample_project/generated/.gitkeep +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/sample_project/matrx_orm.yaml +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/sample_project/test_schema_generation.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/sample_project_desktop/.env.example +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/sample_project_desktop/README.md +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/sample_project_desktop/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/sample_project_desktop/client_example.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/sample_project_desktop/client_example.ts +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/sample_project_desktop/client_supabase_example.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/sample_project_desktop/server.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema/entity_tests.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema/test_base_generation.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema/test_composite_pk_fk_generation.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema/test_composite_unique_generation.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema/test_dto_identity_generation.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema/test_entity_capability_generation.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema/test_enum_ordering.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema/test_excluded_fk_targets.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema/test_generate_schema.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema/test_junction_analysis.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema/test_multi_schema_output.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema/test_schema_analysis.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema/test_sql_expression_defaults.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema/test_table_relationships_query.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema/test_view_generation.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema_builder/test_enum_array_column.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema_builder/test_focused_generation_plan.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema_builder/test_host_models_aggregator.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/schema_builder/test_never_filter_columns.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/session/__init__.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/session/conftest.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/session/test_a_failed_capture_still_names_the_failure.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/session/test_cache_no_downgrade.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/session/test_capture_poison_proof.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/session/test_coalesce.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/session/test_dag.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/session/test_disk_spill_fallback.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/session/test_flush_individual_fallback.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/session/test_governed_write.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/session/test_managed.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/session/test_op_enqueue_site.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/session/test_reads.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/session/test_record_error_bounded_insert.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/session/test_record_error_storm.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/session/test_session.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/session/test_spill_guard_plugin.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/session/test_tests_never_write_live_system_error.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_a_backend_handed_over_mid_transaction_never_takes_our_writes.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_a_bulk_cache_never_stalls_the_loop.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_a_keyword_column_refuses_generation.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_a_list_of_uuids_binds_as_uuid_array.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_a_read_only_backend_never_refuses_our_writes.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_a_sealed_field_shows_no_character_of_its_value.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_attachment_mutation_serialization.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_backup_alias_conflict.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_backup_history_restore.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_backup_restore_live.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_call_function_as.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_call_function_none_mode.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_composite_fk_is_not_a_column_fk.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_database_name_alias.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_db_functions.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_dsn_password_masking.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_dynamic_select_unregistered.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_foreign_session_state.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_immutable_insert_or_exact_verify.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_keyed_digest.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_model_cls_refactor.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_native_enable.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_native_lifecycle.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_native_lifecycle_fences.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_native_passkey_receipts.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_native_source.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_no_blocking_asyncpg_tls.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_one_database.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_order_by_desc_nulls_last.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_org_vault_gate.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_package_wiring_views.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_pooler_role_guard.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_secret_audit_names_its_organization.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_secrets_minting_keys.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_sql_param_casts.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_state_cache_sweeps_stale.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_statement_ceiling_warning.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_sync_twins_guard.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_update_result_truthiness.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_user_visible_lookup.py +0 -0
- {matrx_orm-3.1.236 → matrx_orm-3.1.238}/tests/test_vault_aggregate_recovery_stateful.py +0 -0
|
@@ -508,7 +508,7 @@ for want of this (`packages/matrx-rag/matrx_rag/search.py::_entity_recall` /
|
|
|
508
508
|
`ArrayAny`, `Exists`, or an `&` / `|` / `~` composition).
|
|
509
509
|
- `then=` / `default=` — a bound literal or typed expression (`F`, another
|
|
510
510
|
`Func`, a nested `Case`, ...). `default=None` omits the `ELSE` clause entirely
|
|
511
|
-
(Postgres already evaluates an unmatched `CASE` to `NULL` —
|
|
511
|
+
(Postgres already evaluates an unmatched `CASE` to `NULL` — behaviorally identical to
|
|
512
512
|
an explicit `ELSE NULL`, so there's no ambiguity with "no default supplied").
|
|
513
513
|
|
|
514
514
|
Composable anywhere an expression with `.as_sql(params)` is accepted:
|
|
@@ -52,7 +52,7 @@ Every table that becomes a Model needs row identity: a single-column primary key
|
|
|
52
52
|
- **Schema builder** (`matrx_orm.schema_builder`): code generation for Python + TypeScript type definitions from the DB schema. Postgres **VIEWs** are emitted as **read-only `Model` classes** into the same schema models file (on by default; per-entry `output.include_views: false` opts a schema out, `output.exclude_views: [...]` skips individual views). View models get no manager/DTO/base-class/auto_config (views are not writable), synthesize `_primary_keys` from an `id` column (else the first column, for cache-key/`load_by_id` only), and emit plain typed fields with **no `ForeignKey`** (views carry no FK metadata — nothing cross-schema to resolve). Never hand-write a view model again.
|
|
53
53
|
- **Secrets battery** (`matrx_orm.secrets_battery`): the ONE canonical user-credential vault — `users.user_secrets` CRUD + the platform's single Fernet primitive, keyed by `CREDENTIALS_ENCRYPTION_KEY`. Any package: `configure_secrets(db_config_name=...)` once, then `await require_user_secret(user_id, key)`. No package ever calls another service to resolve a credential. Contract: [`matrx_orm/secrets_battery/FEATURE.md`](matrx_orm/secrets_battery/FEATURE.md).
|
|
54
54
|
- **Polymorphic associations** (`matrx_orm.associations`): `EntityRegistry` (token→Model) + `Associations` — a registry-driven, **access-gated** edge engine over a host's polymorphic edge table. Every `source→target` hop is org-scoped *and* each resolved endpoint is re-authorized against the ACTOR (fail-closed, screams on a genuine leak), so a hop can't widen access past what the actor may reach. 🚨 **The gate is `access_check` (wire `matrx_orm.platform_access_check` → `iam.has_access_for`), NEVER an org-column comparison** — a person belongs to several orgs on purpose, so org-equality denies her own data across her own workspaces (2026-08-30 incident) while granting any co-member of a private row. The edge's `org_id` is a TENANCY stamp, not a permission. Org-equality survives only for UNATTENDED writes (no actor) as an integrity guard, and **system vocabulary is exempt entirely** (existence still required): a model generated with `_rls_variant="system"` is platform-shared dictionary data (seo.keyword/topic) every tenant legitimately links to. Hardcodes no table names — the host wires its own edge + token-registry models. A token whose rows have no Model (a record store's Records) resolves to an **entity door** (`is_entity_door`: `load_by_ids(ids, *, actor_id)`), read as the actor — never by a service identity.
|
|
55
|
-
- **The host's declared session context** (`matrx_orm.core.session_context`): `configure_session_context(provider)` once at startup, and every **top-level** `transaction()` — including the one `rls_session` opens, before it drops to the restricted role — emits whatever the provider returns as transaction-local GUCs. This is how an application-level declaration reaches Postgres at all: a GUC set outside a transaction has no meaning, so the BEGIN is the only place it can land. aidream wires it to its provenance declaration (`app.actor_tier` / `app.actor_system`, read by `platform.actor_tier()`, the history capture and the tier rule). A nested entry is a savepoint inside a transaction that already carries them and emits nothing. A standalone write (`execute_write` outside any transaction) made while the provider has something to say opens its own transaction for that one statement — and still goes through the write queue, inside a copy of the caller's context, so the queue's concurrency gate is kept and the drain task's foreign context cannot hide the declaration (`tests/level1/test_standalone_write_session_context.py`). No provider configured ⇒ no GUCs (standalone
|
|
55
|
+
- **The host's declared session context** (`matrx_orm.core.session_context`): `configure_session_context(provider)` once at startup, and every **top-level** `transaction()` — including the one `rls_session` opens, before it drops to the restricted role — emits whatever the provider returns as transaction-local GUCs. This is how an application-level declaration reaches Postgres at all: a GUC set outside a transaction has no meaning, so the BEGIN is the only place it can land. aidream wires it to its provenance declaration (`app.actor_tier` / `app.actor_system`, read by `platform.actor_tier()`, the history capture and the tier rule). A nested entry is a savepoint inside a transaction that already carries them and emits nothing. A standalone write (`execute_write` outside any transaction) made while the provider has something to say opens its own transaction for that one statement — and still goes through the write queue, inside a copy of the caller's context, so the queue's concurrency gate is kept and the drain task's foreign context cannot hide the declaration (`tests/level1/test_standalone_write_session_context.py`). No provider configured ⇒ no GUCs (standalone behavior unchanged); a provider that raises fails the transaction loudly rather than committing rows with a false provenance.
|
|
56
56
|
- **The platform access policy** (`matrx_orm.platform_access`): `platform_access_check(actor, token, id, level)` → `iam.has_access_for`. The ONE answer to "may this actor touch this row?", shared with RLS and the file-access gate. Fails closed. Never re-derive it from `organization_id` or `created_by` — both are strict subsets that deny legitimate access.
|
|
57
57
|
|
|
58
58
|
Public API is defined explicitly in `matrx_orm/__init__.py` (100+ exports). Treat changes there as semver-breaking.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: matrx-orm
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.238
|
|
4
4
|
Summary: Async-first PostgreSQL ORM with bidirectional migrations, schema introspection, many-to-many relationships, and built-in state caching
|
|
5
5
|
Project-URL: Homepage, https://github.com/AI-Matrix-Engine/aidream-current
|
|
6
6
|
Project-URL: Repository, https://github.com/AI-Matrix-Engine/aidream-current
|
|
@@ -26,7 +26,7 @@ Requires-Dist: asyncpg>=0.31.0
|
|
|
26
26
|
Requires-Dist: cbor2<7,>=6.1.3
|
|
27
27
|
Requires-Dist: cryptography>=43.0
|
|
28
28
|
Requires-Dist: gitpython>=3.1.40
|
|
29
|
-
Requires-Dist: matrx-utils>=2.0.
|
|
29
|
+
Requires-Dist: matrx-utils>=2.0.78
|
|
30
30
|
Requires-Dist: psycopg-pool>=3.2.5
|
|
31
31
|
Requires-Dist: psycopg[binary]>=3.2.5
|
|
32
32
|
Requires-Dist: python-dotenv>=1.0
|
|
@@ -7,7 +7,7 @@ explicit adapter is registered for a given database project.
|
|
|
7
7
|
|
|
8
8
|
All the real work (pool creation, write-queue routing, exponential-backoff retry,
|
|
9
9
|
pgvector codec registration, event-loop lifecycle) stays in ``AsyncDatabaseManager``
|
|
10
|
-
so existing
|
|
10
|
+
so existing behavior is 100% preserved. This class is a thin, config-scoped
|
|
11
11
|
delegation layer.
|
|
12
12
|
"""
|
|
13
13
|
|
|
@@ -53,7 +53,7 @@ because the upload had silently landed in an organization picked for him while t
|
|
|
53
53
|
conversation was in a team org. Both rows were his; the platform policy said yes
|
|
54
54
|
to both; the edge write said no.)
|
|
55
55
|
|
|
56
|
-
Hosts without an ``access_check`` wired keep the legacy org-equality
|
|
56
|
+
Hosts without an ``access_check`` wired keep the legacy org-equality behavior
|
|
57
57
|
for UNATTENDED writes only (no actor in context) — those are trusted server
|
|
58
58
|
paths where the check was never an authorization decision to begin with.
|
|
59
59
|
|
|
@@ -278,7 +278,7 @@ class Associations:
|
|
|
278
278
|
# restore brings exactly those edges back. Where the column exists EVERY
|
|
279
279
|
# read here is live-only — a tombstoned edge conveys nothing, so handing
|
|
280
280
|
# one back is an access leak. A minimal host edge table without the
|
|
281
|
-
# column keeps the old unfiltered
|
|
281
|
+
# column keeps the old unfiltered behavior.
|
|
282
282
|
self._soft_delete = soft_delete_field
|
|
283
283
|
self._soft_delete_available = False # refined by _validate_field_bindings
|
|
284
284
|
# Optional edge-document columns (platform.associations carries them;
|
|
@@ -697,7 +697,7 @@ class Associations:
|
|
|
697
697
|
round trips: measured 2026-09-18 against the live database on a
|
|
698
698
|
3-connection pool, one Library of 533 YouTube sources spent **177 s in
|
|
699
699
|
533 identical single-row SELECTs** out of a 182 s call — and the media
|
|
700
|
-
|
|
700
|
+
catalog makes that call three times per selection job. The gate
|
|
701
701
|
itself is unchanged and still runs per row; only the FETCH is batched,
|
|
702
702
|
so nothing about what survives this method moved. Guard:
|
|
703
703
|
``packages/matrx-orm/tests/level1/test_associations.py::
|
|
@@ -60,7 +60,7 @@ Added 2026-09-12 after a 1.1 MB `workflow.checkpoint` row timed out at 10s under
|
|
|
60
60
|
load and killed a paid-for workflow run. Guard:
|
|
61
61
|
`tests/level1/test_query_timeout.py::TestInsertStatementTimeout`.
|
|
62
62
|
|
|
63
|
-
**A statement the SERVER
|
|
63
|
+
**A statement the SERVER canceled to break a lock collision is re-issued — the
|
|
64
64
|
second and last replay-safe failure, and it covers READS.** SQLSTATE `40P01`
|
|
65
65
|
(`deadlock_detected`), `40001` (`serialization_failure`) and `55P03`
|
|
66
66
|
(`lock_not_available`) are the statuses where Postgres aborted the statement IN
|
|
@@ -69,7 +69,7 @@ at-least-once hazard that makes a statement timeout or a mid-query disconnect
|
|
|
69
69
|
unretryable. Class-40 siblings stay out by name — `40003`
|
|
70
70
|
(`StatementCompletionUnknownError`) is literally "the server cannot say whether
|
|
71
71
|
this completed", and `40002` is a constraint failure wearing a class-40 code.
|
|
72
|
-
The victim is often innocent of any write: a multi-table READ is
|
|
72
|
+
The victim is often innocent of any write: a multi-table READ is canceled
|
|
73
73
|
whenever a concurrent DDL session wants AccessExclusiveLock on a table it already
|
|
74
74
|
holds a lock on, which reached a person as "listConversations: deadlock detected"
|
|
75
75
|
on /chat.
|
|
@@ -401,7 +401,7 @@ what is exhausted or hung when a watchdog needs to speak.
|
|
|
401
401
|
- 2026-10-01: `ReadWriteConnection` rolls back a stranger's open transaction it was handed (statement reply or 25001 on BEGIN), re-runs our statement in its own transaction, and names a repeat `InheritedTransactionError`.
|
|
402
402
|
- 2026-10-01: `ReadWriteConnection` for transaction-mode pools — every BEGIN declares READ WRITE and a read-only-refused autocommit statement re-runs once in one; a pooled backend another client left read-only at session level no longer fails the platform's writes.
|
|
403
403
|
- 2026-09-30: Fewer round trips per request (agent-launch latency, lane deep): one-statement proof of a clean empty read; ceilings + declared context + `rls_session` settings in ONE BEGIN-time `set_config` statement (`transaction(opening_gucs=)`, `set_local_gucs`, `emit_local_gucs`); transaction-mode pools release with no reset statement. 435 → ~200 round trips on a flashcard launch.
|
|
404
|
-
- 2026-09-30: `statement_ceiling.py` — a driver timeout above the server's statement ceiling is logged once per call site; `SERVER_CEILING` sentinel. ~19 callers passed 60-600 s under the 30 s `postgres` ceiling (the nightly keyword classifier was
|
|
404
|
+
- 2026-09-30: `statement_ceiling.py` — a driver timeout above the server's statement ceiling is logged once per call site; `SERVER_CEILING` sentinel. ~19 callers passed 60-600 s under the 30 s `postgres` ceiling (the nightly keyword classifier was canceled at 30 s for eight days).
|
|
405
405
|
- 2026-09-12 (later): ONE retry mechanism. Two independent lock-retry
|
|
406
406
|
implementations for the same class landed hours apart — a `LockContentionError`
|
|
407
407
|
+ constant-budget loop inside `execute_query`, and a `TransientTransactionError`
|
|
@@ -410,7 +410,7 @@ what is exhausted or hung when a watchdog needs to speak.
|
|
|
410
410
|
55P03 too), the loop lives once in `write_retry.run_with_lock_retry` and is used
|
|
411
411
|
by `execute_query` AND `call_function`, its budget is the `orm.write_retry`
|
|
412
412
|
knob rows (never a constant), and `TransientTransactionError` is deleted.
|
|
413
|
-
- 2026-09-12: A statement Postgres
|
|
413
|
+
- 2026-09-12: A statement Postgres canceled to break a lock collision
|
|
414
414
|
(40P01/40001/55P03) is re-issued on a fresh connection instead of failing the
|
|
415
415
|
caller. Before this it fell to the catch-all as `UnknownDatabaseError` and
|
|
416
416
|
killed the request: four parallel `ai.agent.start` invocations deadlocked on
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
## Done (this session)
|
|
4
4
|
- Added `TYPE_CHECKING`-guarded `__get__` overloads to all major field classes so that
|
|
5
5
|
accessing a field on a model instance returns the correct Python type to static
|
|
6
|
-
|
|
6
|
+
analyzers (pyright, mypy) without any runtime behavior change:
|
|
7
7
|
- `Field` → `Any`
|
|
8
8
|
- `CharField`, `TextField` → `str | None`
|
|
9
9
|
- `UUIDField` → `str | None`
|
|
@@ -144,8 +144,8 @@ READ_TIMEOUT_RETRIES = 1 # extra attempts for a timed-out read; total = 1 + thi
|
|
|
144
144
|
READ_TIMEOUT_RETRY_BACKOFF = 0.25 # seconds before the read retry
|
|
145
145
|
|
|
146
146
|
# ── lock collisions (40P01 / 40001 / 55P03) ──────────────────────────────────
|
|
147
|
-
# Postgres breaks a lock cycle by
|
|
148
|
-
# back IN FULL — no part of the
|
|
147
|
+
# Postgres breaks a lock cycle by CANCELING one party, and the victim is rolled
|
|
148
|
+
# back IN FULL — no part of the canceled statement survives. That makes a single
|
|
149
149
|
# statement (outside a caller-managed transaction) provably safe to re-issue,
|
|
150
150
|
# writes included, and re-issuing it is what every serious ORM does.
|
|
151
151
|
#
|
|
@@ -437,7 +437,7 @@ async def _transaction_pool_release(_conn: Any) -> None:
|
|
|
437
437
|
laptop's 170 ms). asyncpg still rolls back an open transaction before this
|
|
438
438
|
hook (``Connection._reset``), and a session-mode pool keeps the full default
|
|
439
439
|
reset. ``RESET ALL`` never reset a borrowed ROLE either (``role`` is
|
|
440
|
-
``GUC_NO_RESET_ALL``) — that
|
|
440
|
+
``GUC_NO_RESET_ALL``) — that defense is ``pooler_role``.
|
|
441
441
|
"""
|
|
442
442
|
return None
|
|
443
443
|
|
|
@@ -562,7 +562,7 @@ class AsyncDatabaseManager:
|
|
|
562
562
|
|
|
563
563
|
if pool_loop_id != current_loop_id:
|
|
564
564
|
# Pool is from a different event loop. It cannot be awaited
|
|
565
|
-
# or directly
|
|
565
|
+
# or directly canceled from this loop; stop its controller
|
|
566
566
|
# on the owner loop when possible, then terminate the pool.
|
|
567
567
|
old_pool = cls._pools[config_name]
|
|
568
568
|
old_task = cls._keepalive_tasks.pop(config_name, None)
|
|
@@ -1200,7 +1200,7 @@ class AsyncDatabaseManager:
|
|
|
1200
1200
|
#
|
|
1201
1201
|
# POISON-GUARD: a connection must NEVER be handed out while it is still
|
|
1202
1202
|
# inside a transaction. If a prior holder's teardown was interrupted (a
|
|
1203
|
-
#
|
|
1203
|
+
# canceled task can skip its ROLLBACK, and asyncpg's reset-on-release
|
|
1204
1204
|
# can itself be skipped under cancellation), the connection comes back
|
|
1205
1205
|
# "poisoned" — its server-side transaction still open/aborted. The next
|
|
1206
1206
|
# consumer's very FIRST statement then fails with
|
|
@@ -1326,7 +1326,7 @@ class AsyncDatabaseManager:
|
|
|
1326
1326
|
still cancels at its ceiling, and a value above it is logged once per
|
|
1327
1327
|
call site (``matrx_orm.core.statement_ceiling``).
|
|
1328
1328
|
"""
|
|
1329
|
-
# Layer 1 of the pooler-role
|
|
1329
|
+
# Layer 1 of the pooler-role defense: SQL that would leave a borrowed role
|
|
1330
1330
|
# on a shared server connection never reaches Postgres. See
|
|
1331
1331
|
# matrx_orm/core/pooler_role.py for what that contamination does to reads.
|
|
1332
1332
|
assert_no_session_role_change(query)
|
|
@@ -201,7 +201,7 @@ class ModelMeta(type):
|
|
|
201
201
|
# `_abstract = True` — otherwise a future `if model._abstract: skip` silently
|
|
202
202
|
# drops every entity. Stamp the real answer on the class.
|
|
203
203
|
attrs["_abstract"] = is_abstract
|
|
204
|
-
# Also
|
|
204
|
+
# Also honor abstract declared on a parent's Meta
|
|
205
205
|
for base in bases:
|
|
206
206
|
base_meta = getattr(base, "_meta", None)
|
|
207
207
|
if base_meta is None:
|
|
@@ -670,7 +670,7 @@ def get_code_config(
|
|
|
670
670
|
# Schema-aware Python output paths.
|
|
671
671
|
#
|
|
672
672
|
# ``public`` keeps the canonical single-schema paths so the generated
|
|
673
|
-
# artifacts stay byte-identical to the historical
|
|
673
|
+
# artifacts stay byte-identical to the historical behavior. Any non-public
|
|
674
674
|
# schema (e.g. ``rag``) is written to namespaced files / subpackages so
|
|
675
675
|
# multiple schemas of the SAME database can be generated without clobbering
|
|
676
676
|
# each other's ``db/models.py`` and ``db/managers/`` output:
|
|
@@ -246,7 +246,7 @@ def describe_transactions(rows: list[dict[str, Any]]) -> str:
|
|
|
246
246
|
# HERE — one fixed, parametrized statement in the ORM — rather than as a SQL
|
|
247
247
|
# literal in the aidream service that consumes it. aidream keeps ZERO raw SQL
|
|
248
248
|
# outside db/migrations; a missing capability is a todo for the ORM, never a
|
|
249
|
-
#
|
|
249
|
+
# license to write SQL in application code.
|
|
250
250
|
#
|
|
251
251
|
# clock_timestamp(), not now(): `now()` is frozen at transaction start, so a
|
|
252
252
|
# backend whose `state_change` lands after our snapshot reports a NEGATIVE age.
|
|
@@ -1395,7 +1395,7 @@ class Case:
|
|
|
1395
1395
|
expression composition.
|
|
1396
1396
|
|
|
1397
1397
|
``default=None`` omits the ``ELSE`` clause entirely (Postgres already
|
|
1398
|
-
evaluates an unmatched CASE to NULL, so this is
|
|
1398
|
+
evaluates an unmatched CASE to NULL, so this is behaviorally identical
|
|
1399
1399
|
to an explicit ``ELSE NULL`` — no ambiguity with "no default").
|
|
1400
1400
|
|
|
1401
1401
|
Usage::
|
|
@@ -36,6 +36,9 @@ class BaseManager(Generic[ModelT]):
|
|
|
36
36
|
# for that manager. Has no effect when Pydantic is not installed.
|
|
37
37
|
validate_input: bool = True
|
|
38
38
|
|
|
39
|
+
# Knob: hard ceiling for fetch-on-init (rows). Reaching it raises; never truncates.
|
|
40
|
+
fetch_on_init_max_rows: int = 50_000
|
|
41
|
+
|
|
39
42
|
def __init__(
|
|
40
43
|
self,
|
|
41
44
|
model: type[ModelT],
|
|
@@ -1744,6 +1747,43 @@ class BaseManager(Generic[ModelT]):
|
|
|
1744
1747
|
|
|
1745
1748
|
run_sync(self._auto_fetch_on_init_async())
|
|
1746
1749
|
|
|
1750
|
+
async def _fetch_whole_table(self) -> list[ModelT]:
|
|
1751
|
+
"""Return EVERY row of the table, never a truncated prefix.
|
|
1752
|
+
|
|
1753
|
+
``fetch_on_init_limit`` is the PAGE SIZE (a knob), not a cap: a
|
|
1754
|
+
fetch-on-init cache that claims to hold the table must hold all of it
|
|
1755
|
+
(2026-10 defect: a 300 cap silently dropped 84 of 384 ai.model_definition
|
|
1756
|
+
rows). Single-PK tables page by keyset (``pk > last``); composite-PK
|
|
1757
|
+
tables page by offset over a full-PK order. Past
|
|
1758
|
+
``fetch_on_init_max_rows`` the fetch RAISES (loud at boot) instead of
|
|
1759
|
+
continuing with partial data — switch such a manager to load-on-miss.
|
|
1760
|
+
"""
|
|
1761
|
+
page = int(self.fetch_on_init_limit)
|
|
1762
|
+
pks = list(self.model._meta.primary_keys or ["id"])
|
|
1763
|
+
ceiling = int(self.fetch_on_init_max_rows)
|
|
1764
|
+
rows: list[ModelT] = []
|
|
1765
|
+
last: Any = None
|
|
1766
|
+
while True:
|
|
1767
|
+
qb = self.model.filter()
|
|
1768
|
+
if len(pks) == 1:
|
|
1769
|
+
if last is not None:
|
|
1770
|
+
qb = qb.filter(**{f"{pks[0]}__gt": last})
|
|
1771
|
+
qb = qb.order_by(pks[0]).limit(page)
|
|
1772
|
+
else:
|
|
1773
|
+
qb = qb.order_by(*pks).limit(page).offset(len(rows))
|
|
1774
|
+
batch = await qb.all()
|
|
1775
|
+
rows.extend(batch)
|
|
1776
|
+
if len(rows) > ceiling:
|
|
1777
|
+
raise RuntimeError(
|
|
1778
|
+
f"[{self.model.__name__}] fetch-on-init exceeded fetch_on_init_max_rows="
|
|
1779
|
+
f"{ceiling}; this table is too large to cache whole — make the manager "
|
|
1780
|
+
"load-on-miss (fetch_on_init_limit=0) or raise the knob deliberately."
|
|
1781
|
+
)
|
|
1782
|
+
if len(batch) < page:
|
|
1783
|
+
return rows
|
|
1784
|
+
if len(pks) == 1:
|
|
1785
|
+
last = getattr(batch[-1], pks[0])
|
|
1786
|
+
|
|
1747
1787
|
async def _auto_fetch_on_init_async(self) -> None:
|
|
1748
1788
|
"""Fetch items on initialization (async version with full DTO support)."""
|
|
1749
1789
|
if int(self.fetch_on_init_limit) <= 0:
|
|
@@ -1751,7 +1791,7 @@ class BaseManager(Generic[ModelT]):
|
|
|
1751
1791
|
|
|
1752
1792
|
start_time = time.perf_counter()
|
|
1753
1793
|
|
|
1754
|
-
items = await self.
|
|
1794
|
+
items = await self._fetch_whole_table()
|
|
1755
1795
|
initialized_items: list[ModelT] = []
|
|
1756
1796
|
for item in items:
|
|
1757
1797
|
result = await self._initialize_item_runtime(item)
|
|
@@ -1797,9 +1837,6 @@ class BaseManager(Generic[ModelT]):
|
|
|
1797
1837
|
color="red",
|
|
1798
1838
|
)
|
|
1799
1839
|
|
|
1800
|
-
if count >= (self.fetch_on_init_limit - 5):
|
|
1801
|
-
self._trigger_limit_reached_warning(count, initialized_items)
|
|
1802
|
-
|
|
1803
1840
|
if not warnings_suppressed and count > warning_limit_threshold:
|
|
1804
1841
|
self._trigger_fetch_warnings(count, initialized_items, warning_limit_threshold)
|
|
1805
1842
|
|
|
@@ -1016,7 +1016,7 @@ class JSONBField(Field, Generic[_JT]):
|
|
|
1016
1016
|
automatically deserialized to that model on load and serialized back to a
|
|
1017
1017
|
dict on write. Pydantic validates structure and types at both boundaries.
|
|
1018
1018
|
|
|
1019
|
-
Without ``schema``,
|
|
1019
|
+
Without ``schema``, behavior is identical to the original implementation —
|
|
1020
1020
|
Pydantic is not required and this field remains a zero-dependency passthrough.
|
|
1021
1021
|
|
|
1022
1022
|
Example::
|
|
@@ -1294,7 +1294,7 @@ class JSONBField(Field, Generic[_JT]):
|
|
|
1294
1294
|
if isinstance(value, str):
|
|
1295
1295
|
if not value.strip():
|
|
1296
1296
|
return None
|
|
1297
|
-
# If the string is already valid JSON, round-trip it to
|
|
1297
|
+
# If the string is already valid JSON, round-trip it to normalize
|
|
1298
1298
|
# formatting. If it is not (e.g. a bare string value stored in a
|
|
1299
1299
|
# JSONB column), encode it as a JSON string so Postgres accepts it.
|
|
1300
1300
|
try:
|
|
@@ -15,7 +15,7 @@ Measured 2026-10-05 05:49-09:04 UTC: ~50 platform errors (SEO runs list, mandate
|
|
|
15
15
|
resolution, membership checks, file downloads), each pinned to a few poisoned
|
|
16
16
|
backends that kept failing for minutes.
|
|
17
17
|
|
|
18
|
-
THE
|
|
18
|
+
THE DEFENSE (two halves, both here so they cannot drift apart):
|
|
19
19
|
|
|
20
20
|
1. Every ORM transaction clears the setting transaction-locally at BEGIN
|
|
21
21
|
(:data:`CLEARED_GUCS`, merged into ``transaction._opening_statement_gucs``).
|
|
@@ -130,7 +130,7 @@ class ModelView(Generic[ModelT], metaclass=ModelViewMeta):
|
|
|
130
130
|
2. Run all computed-field coroutines concurrently.
|
|
131
131
|
3. Apply inline_fk substitutions.
|
|
132
132
|
4. Register exclude / inline_fk metadata on the model so to_dict()
|
|
133
|
-
can
|
|
133
|
+
can honor them without re-reading the view class.
|
|
134
134
|
|
|
135
135
|
Returns the same model instance for convenience (chainable).
|
|
136
136
|
"""
|
|
@@ -21,7 +21,7 @@ reconciler, digest and monitor in the platform: a broken read reports a quiet we
|
|
|
21
21
|
forever and every scheduled run stays green. ``db/pooler_session.py`` already says
|
|
22
22
|
it for the migration tools — **a privilege error must never be recorded as
|
|
23
23
|
absence** — and this module extends that to every ORM read, because a per-caller
|
|
24
|
-
|
|
24
|
+
defense does not scale.
|
|
25
25
|
|
|
26
26
|
TWO INDEPENDENT LAYERS, each sufficient alone, each screaming when it fires:
|
|
27
27
|
|
|
@@ -8,7 +8,7 @@ read-mostly transaction, a batch flush) and have it survive a transient DB
|
|
|
8
8
|
hiccup — a command-timeout under event-loop/pool starvation, a pool-acquire
|
|
9
9
|
timeout under saturation — instead of crashing a 500-item job on the first blip.
|
|
10
10
|
|
|
11
|
-
This is CALLER-OPT-IN by design. It does NOT change the
|
|
11
|
+
This is CALLER-OPT-IN by design. It does NOT change the behavior of any query.
|
|
12
12
|
The caller asserts, by wrapping, that re-running the factory is safe:
|
|
13
13
|
|
|
14
14
|
from matrx_orm import retry_on_transient, transaction
|
|
@@ -146,7 +146,7 @@ ACTOR_SYSTEM_GUC = "app.actor_system"
|
|
|
146
146
|
# through ``platform.declared_actor_agent()`` and names the ``agent`` rung when
|
|
147
147
|
# it resolves ``records.confirmation.agent_write_born_confirmed`` -- which is
|
|
148
148
|
# what makes a per-agent born-confirmed exception a real setting instead of a
|
|
149
|
-
# control that saves a value nothing
|
|
149
|
+
# control that saves a value nothing honors.
|
|
150
150
|
ACTOR_AGENT_GUC = "app.actor_agent"
|
|
151
151
|
|
|
152
152
|
VALID_TIERS: frozenset[str] = frozenset({"system", "agent", "user"})
|
|
@@ -30,7 +30,7 @@ supports ``.execute(sql)`` and ``.fetch(sql, *args)``.
|
|
|
30
30
|
The ``_active_connection`` ContextVar is typed as ``Any`` so the rest of the
|
|
31
31
|
ORM can hold a reference to the active connection without depending on asyncpg.
|
|
32
32
|
``AsyncDatabaseManager.execute_query`` reads ``get_active_connection()`` and
|
|
33
|
-
reuses the connection when present — this
|
|
33
|
+
reuses the connection when present — this behavior is unchanged.
|
|
34
34
|
"""
|
|
35
35
|
|
|
36
36
|
from __future__ import annotations
|
|
@@ -408,7 +408,7 @@ class TransactionContext:
|
|
|
408
408
|
# SHIELD the teardown so an in-flight cancellation (hard-deadline,
|
|
409
409
|
# client disconnect, shutdown) can never SKIP the ROLLBACK and leak a
|
|
410
410
|
# poisoned (in-transaction) connection back to the pool. The shielded
|
|
411
|
-
# teardown runs to completion even when the outer await is
|
|
411
|
+
# teardown runs to completion even when the outer await is canceled.
|
|
412
412
|
try:
|
|
413
413
|
await asyncio.shield(_teardown())
|
|
414
414
|
except Exception:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""The retry policy for a statement Postgres
|
|
1
|
+
"""The retry policy for a statement Postgres canceled to break a lock collision.
|
|
2
2
|
|
|
3
3
|
ONE place owns "how hard do we re-issue a statement Postgres rolled back for
|
|
4
4
|
contention": the knob read here plus the ONE loop (``run_with_lock_retry``) that
|
|
@@ -229,7 +229,7 @@ async def run_with_lock_retry[T](
|
|
|
229
229
|
query: str,
|
|
230
230
|
args: Any = None,
|
|
231
231
|
) -> T:
|
|
232
|
-
"""Re-issue ``attempt`` when Postgres
|
|
232
|
+
"""Re-issue ``attempt`` when Postgres canceled it to break a lock collision.
|
|
233
233
|
|
|
234
234
|
THE one lock-retry loop. Both doors into the database use it —
|
|
235
235
|
``AsyncDatabaseManager.execute_query`` (every statement, read or write) and
|
|
@@ -274,7 +274,7 @@ async def run_with_lock_retry[T](
|
|
|
274
274
|
) from None
|
|
275
275
|
backoff = policy.backoff_seconds(attempts)
|
|
276
276
|
logger.warning(
|
|
277
|
-
"[lock-retry] attempt %d/%d
|
|
277
|
+
"[lock-retry] attempt %d/%d canceled by a lock collision "
|
|
278
278
|
"(SQLSTATE %s) on '%s' — rolled back in full, re-issuing in "
|
|
279
279
|
"%.3fs: %s",
|
|
280
280
|
attempts + 1,
|
|
@@ -289,7 +289,7 @@ async def run_with_lock_retry[T](
|
|
|
289
289
|
else:
|
|
290
290
|
if attempts:
|
|
291
291
|
logger.warning(
|
|
292
|
-
"[lock-retry] HEALED on attempt %d after Postgres
|
|
292
|
+
"[lock-retry] HEALED on attempt %d after Postgres canceled the "
|
|
293
293
|
"statement to break a lock collision: %s",
|
|
294
294
|
attempts + 1,
|
|
295
295
|
query[:120],
|
|
@@ -1123,7 +1123,7 @@ class PoolAcquireTimeoutError(DatabaseError):
|
|
|
1123
1123
|
One of exactly TWO transient database errors that are provably safe to
|
|
1124
1124
|
retry for write operations: by definition no connection was acquired and
|
|
1125
1125
|
no SQL was sent to the server. (The other is a lock collision Postgres
|
|
1126
|
-
|
|
1126
|
+
canceled — SQLSTATE 40P01/40001/55P03 — where the server itself rolled
|
|
1127
1127
|
the statement back in full; that one is retried a layer lower, inside
|
|
1128
1128
|
``execute_query``, and surfaces as :class:`LockContentionError` only once
|
|
1129
1129
|
its budget is spent.) Any other "transient-looking" error
|
|
@@ -1189,11 +1189,11 @@ class PoolAcquireTimeoutError(DatabaseError):
|
|
|
1189
1189
|
|
|
1190
1190
|
|
|
1191
1191
|
class LockContentionError(DatabaseError):
|
|
1192
|
-
"""Raised when Postgres
|
|
1192
|
+
"""Raised when Postgres canceled a statement to break a lock collision.
|
|
1193
1193
|
|
|
1194
1194
|
SQLSTATE 40P01 (deadlock_detected), 40001 (serialization_failure) and 55P03
|
|
1195
1195
|
(lock_not_available). The victim is rolled back IN FULL — no part of the
|
|
1196
|
-
|
|
1196
|
+
canceled statement survives — so a single statement outside a
|
|
1197
1197
|
caller-managed transaction is provably safe to re-issue, reads AND writes,
|
|
1198
1198
|
and THE ONE retry loop (``matrx_orm.core.write_retry.run_with_lock_retry``,
|
|
1199
1199
|
used by ``AsyncDatabaseManager.execute_query`` and by ``call_function``)
|
|
@@ -1243,7 +1243,7 @@ class LockContentionError(DatabaseError):
|
|
|
1243
1243
|
)
|
|
1244
1244
|
super().__init__(
|
|
1245
1245
|
message=(
|
|
1246
|
-
f"Postgres
|
|
1246
|
+
f"Postgres canceled this statement to break a lock collision "
|
|
1247
1247
|
f"({sqlstate or 'lock contention'}) {where}: {original_error}"
|
|
1248
1248
|
),
|
|
1249
1249
|
model=None,
|
|
@@ -1258,7 +1258,7 @@ class LockContentionError(DatabaseError):
|
|
|
1258
1258
|
lines.append(self.message)
|
|
1259
1259
|
lines.append("")
|
|
1260
1260
|
lines.append("Hint:")
|
|
1261
|
-
lines.append(" - NOTHING of the
|
|
1261
|
+
lines.append(" - NOTHING of the canceled statement committed; re-running is safe.")
|
|
1262
1262
|
if details.get("in_transaction"):
|
|
1263
1263
|
lines.append(" - It ran inside an explicit transaction(), so the ORM did NOT")
|
|
1264
1264
|
lines.append(" re-run it: the rest of the transaction is yours. Wrap the whole")
|
|
@@ -52,7 +52,7 @@ class ConflictTarget:
|
|
|
52
52
|
_typed_token: object | None = field(default=None, repr=False, compare=False)
|
|
53
53
|
|
|
54
54
|
def __post_init__(self) -> None:
|
|
55
|
-
#
|
|
55
|
+
# Normalize to a tuple so the dataclass stays hashable + immutable.
|
|
56
56
|
if not isinstance(self.expressions, tuple):
|
|
57
57
|
object.__setattr__(self, "expressions", tuple(self.expressions))
|
|
58
58
|
if not self.expressions:
|
|
@@ -445,7 +445,7 @@ async def upsert_with_conflict(
|
|
|
445
445
|
value is dropped from the INSERT column list (falls back to the
|
|
446
446
|
column's default) — Postgres still resolves ``EXCLUDED.<col>``
|
|
447
447
|
for an omitted column to that same default/NULL, so omitting a
|
|
448
|
-
``None`` field here is
|
|
448
|
+
``None`` field here is behaviorally identical to inserting it
|
|
449
449
|
explicitly.
|
|
450
450
|
on_conflict: plain column list OR a :class:`ConflictTarget`
|
|
451
451
|
(required for an expression/partial-index target).
|
|
@@ -16,7 +16,7 @@ if TYPE_CHECKING:
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
# The ``on_conflict`` parameter accepts either form:
|
|
19
|
-
# * ``list[str]`` of plain column names (the original, unchanged
|
|
19
|
+
# * ``list[str]`` of plain column names (the original, unchanged behavior)
|
|
20
20
|
# * ``ConflictTarget`` with ``expressions`` (+ optional ``where``) for
|
|
21
21
|
# expression / partial unique indexes
|
|
22
22
|
OnConflictArg = Union[list[str], "ConflictTarget"]
|
|
@@ -255,7 +255,7 @@ async def upsert(
|
|
|
255
255
|
"""INSERT ... ON CONFLICT (...) DO UPDATE SET ... RETURNING *
|
|
256
256
|
|
|
257
257
|
``on_conflict`` accepts either a ``list[str]`` of column names (the
|
|
258
|
-
original
|
|
258
|
+
original behavior) OR a :class:`ConflictTarget` describing an
|
|
259
259
|
expression / partial unique index.
|
|
260
260
|
|
|
261
261
|
``returning`` names the only columns read back: the instance then carries
|
|
@@ -316,7 +316,7 @@ async def bulk_upsert(
|
|
|
316
316
|
"""Bulk INSERT ... ON CONFLICT DO UPDATE for multiple rows.
|
|
317
317
|
|
|
318
318
|
``on_conflict`` accepts either a ``list[str]`` of column names (the
|
|
319
|
-
original
|
|
319
|
+
original behavior) OR a :class:`ConflictTarget` describing an
|
|
320
320
|
expression / partial unique index.
|
|
321
321
|
"""
|
|
322
322
|
if not objects_data:
|
|
@@ -55,7 +55,7 @@ from typing import Literal
|
|
|
55
55
|
#
|
|
56
56
|
# ``PERMISSION_LEVELS`` (the CODE ladder) deliberately runs WIDER than
|
|
57
57
|
# ``DB_PERMISSION_LEVELS`` (what ``public.permission_level`` holds today):
|
|
58
|
-
# ``commenter`` is not in the database enum yet. Reading, ranking and
|
|
58
|
+
# ``commenter`` is not in the database enum yet. Reading, ranking and labeling
|
|
59
59
|
# always use the code ladder, so nothing needs an edit the day the enum gains
|
|
60
60
|
# it; nothing breaks meanwhile, because the value simply never arrives. WRITING
|
|
61
61
|
# a level to the database narrows through ``to_db_permission_level`` first.
|
|
@@ -310,7 +310,7 @@ async def verify_platform_access_wiring(*, probe_user_id: str | None = None) ->
|
|
|
310
310
|
# 🚨 Creating an edge is not always a read. Some edges CONVEY access: the
|
|
311
311
|
# ``trg_associations_reachability`` trigger on ``platform.associations`` writes
|
|
312
312
|
# ``platform.reachability`` rows for them, and ``iam.has_access_for_base``
|
|
313
|
-
#
|
|
313
|
+
# honors those rows. Writing such an edge therefore GRANTS other people read
|
|
314
314
|
# access to the attached row — a permission-granting act performed by whoever
|
|
315
315
|
# wrote the edge.
|
|
316
316
|
#
|
|
@@ -354,7 +354,7 @@ CONVEYING_EDGE = EdgeAccessRequirement((("editor", "editor"),))
|
|
|
354
354
|
NON_CONVEYING_EDGE = EdgeAccessRequirement((("editor", "viewer"), ("viewer", "editor")))
|
|
355
355
|
|
|
356
356
|
#: Fail-safe for an unregistered pair: assume it conveys. An edge type nobody
|
|
357
|
-
#: declared is not a
|
|
357
|
+
#: declared is not a license to be lenient.
|
|
358
358
|
UNKNOWN_EDGE = CONVEYING_EDGE
|
|
359
359
|
|
|
360
360
|
_container_side_cache: dict[tuple[str, str], str | None] = {}
|
|
@@ -4,7 +4,7 @@ Registered as a ``pytest11`` entry point so pytest auto-loads it in every suite
|
|
|
4
4
|
**regardless of rootdir** — same mechanism, same reason, as
|
|
5
5
|
``matrx_orm.pytest_plugin`` (the spill guard), ``matrx_connect.pytest_plugin``
|
|
6
6
|
and ``matrx_utils.pytest_plugin``. This is the SIXTH cross-suite hazard; the
|
|
7
|
-
other five are
|
|
7
|
+
other five are cataloged in the repo-root ``conftest.py``.
|
|
8
8
|
|
|
9
9
|
WHY IT EXISTS — production chat outage, 2026-09-15 23:45–23:52 UTC.
|
|
10
10
|
------------------------------------------------------------------
|
|
@@ -137,7 +137,7 @@ def mask_dsn_password(text: str) -> str:
|
|
|
137
137
|
|
|
138
138
|
Used both to build ``RedactedDSN.__repr__`` and, in the pytest hooks below, as
|
|
139
139
|
a blanket backstop over captured tracebacks and stdout — belt AND suspenders,
|
|
140
|
-
because a backstop that only fires on a type it
|
|
140
|
+
because a backstop that only fires on a type it recognizes is not a backstop.
|
|
141
141
|
"""
|
|
142
142
|
return _DSN_PASSWORD_RE.sub(r"\1***\3", text)
|
|
143
143
|
|
|
@@ -162,7 +162,7 @@ class RedactedDSN(str):
|
|
|
162
162
|
# this repo bans).
|
|
163
163
|
|
|
164
164
|
#: How long a reader-blocking lock on a pre-existing relation may be held before
|
|
165
|
-
#: the holder is
|
|
165
|
+
#: the holder is canceled and the test is failed. 2s is far longer than any
|
|
166
166
|
#: legitimate test DDL on a shared object, and far shorter than a user notices.
|
|
167
167
|
HOLD_CEILING_SECONDS = 2.0
|
|
168
168
|
|
|
@@ -170,7 +170,7 @@ HOLD_CEILING_SECONDS = 2.0
|
|
|
170
170
|
#: to ``pg_terminate_backend`` at this age.
|
|
171
171
|
TERMINATE_AFTER_SECONDS = 10.0
|
|
172
172
|
|
|
173
|
-
#: Sampling interval. One tiny
|
|
173
|
+
#: Sampling interval. One tiny catalog query per tick, on one connection.
|
|
174
174
|
SAMPLE_INTERVAL_SECONDS = 1.0
|
|
175
175
|
|
|
176
176
|
#: Ceilings emitted as ``SET LOCAL`` on every transaction this pytest process
|
|
@@ -454,7 +454,7 @@ def pytest_addoption(parser: pytest.Parser) -> None:
|
|
|
454
454
|
metavar="SECONDS",
|
|
455
455
|
help=(
|
|
456
456
|
"Seconds a test may hold a reader-blocking lock on a pre-existing "
|
|
457
|
-
f"relation before it is
|
|
457
|
+
f"relation before it is canceled and failed (default {HOLD_CEILING_SECONDS})."
|
|
458
458
|
),
|
|
459
459
|
)
|
|
460
460
|
group.addoption(
|
|
@@ -532,7 +532,7 @@ def pytest_runtest_call(item: pytest.Item):
|
|
|
532
532
|
new = offenses()[before:]
|
|
533
533
|
if not new:
|
|
534
534
|
return
|
|
535
|
-
# Do not mask a real failure the
|
|
535
|
+
# Do not mask a real failure the canceled statement already produced — but a
|
|
536
536
|
# test that swallowed the cancellation and passed must still go red.
|
|
537
537
|
if outcome.excinfo is None:
|
|
538
538
|
pytest.fail(
|
|
@@ -1182,7 +1182,7 @@ class QueryExecutor:
|
|
|
1182
1182
|
"""Call execute_write_dict on the adapter.
|
|
1183
1183
|
|
|
1184
1184
|
Returns ``NotImplemented`` if the adapter does not override the hook
|
|
1185
|
-
(default ``BaseAdapter``
|
|
1185
|
+
(default ``BaseAdapter`` behavior) so callers can fall through to the
|
|
1186
1186
|
SQL path.
|
|
1187
1187
|
"""
|
|
1188
1188
|
from matrx_orm.session.managed import assert_model_write_allowed
|
|
@@ -1174,7 +1174,7 @@ class Column:
|
|
|
1174
1174
|
# Both are the same question — "what list does this default mean?" —
|
|
1175
1175
|
# so both go through one parser that answers it. Anything it cannot
|
|
1176
1176
|
# confidently parse returns an EMPTY list rather than a guess, which
|
|
1177
|
-
# is the pre-existing (conservative)
|
|
1177
|
+
# is the pre-existing (conservative) behavior, never a syntax error.
|
|
1178
1178
|
elif value.startswith("ARRAY[") or (
|
|
1179
1179
|
value.startswith("'{") and "}'::" in value and value.endswith("[]")
|
|
1180
1180
|
):
|
|
@@ -361,7 +361,7 @@ def run_schema_generation(
|
|
|
361
361
|
|
|
362
362
|
# skip_unchanged_managers: when True, manager files for tables whose
|
|
363
363
|
# model definition has not changed are not rewritten. Default False
|
|
364
|
-
# preserves the existing
|
|
364
|
+
# preserves the existing behavior of regenerating everything.
|
|
365
365
|
skip_unchanged_managers = bool(entry.get("skip_unchanged_managers", False))
|
|
366
366
|
|
|
367
367
|
# output: per-entry overrides so generation can target a package tree
|
|
@@ -978,7 +978,7 @@ class Schema:
|
|
|
978
978
|
# Apply table filter at the last possible moment — all dependency resolution
|
|
979
979
|
# and topological sorting above ran on the full table set so relationships are
|
|
980
980
|
# always correct. When no filter is configured this block is a no-op and the
|
|
981
|
-
#
|
|
981
|
+
# behavior is 100% identical to an unfiltered run.
|
|
982
982
|
if self._include_tables is not None:
|
|
983
983
|
sorted_tables = [t for t in sorted_tables if t in self._include_tables]
|
|
984
984
|
elif self._exclude_tables is not None:
|