matrx-orm 3.1.152__tar.gz → 3.1.154__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.152 → matrx_orm-3.1.154}/PKG-INFO +2 -2
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/__init__.py +2 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/FEATURE.md +29 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/diagnostics.py +122 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/rls_session.py +10 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/transaction.py +36 -0
- matrx_orm-3.1.154/matrx_orm/pytest_lock_guard.py +510 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/state.py +42 -1
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/pyproject.toml +4 -2
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_rls_session_scope.py +32 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_state_cache.py +50 -0
- matrx_orm-3.1.154/tests/test_shared_lock_guard.py +251 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/.gitignore +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/AGENTS.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/BASE_CLASS_METHODS.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/CLAUDE.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/MODEL_API.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/README.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/database/orm/extended/managers/ai_model_base.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/docs/migrations.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/FEATURE.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/MODULE_README.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/adapters/MODULE_README.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/adapters/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/adapters/async_postgresql.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/adapters/base_adapter.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/adapters/postgresql.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/adapters/postgrest_client_adapter.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/adapters/supabase_adapter.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/admin/FEATURE.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/admin/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/admin/router.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/api/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/api/auth.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/api/config.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/api/handlers.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/api/protocol.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/api/server.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/associations.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/cache_debug.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/catalog.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/catalog_sql.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/client/MODULE_README.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/client/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/client/postgres_connection.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/client/postgrest.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/client/supabase_auth.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/client/supabase_config.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/client/supabase_manager.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/EXTENDED-TASK.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/MODULE_README.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/RELATIONS-TASKS.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/TASKS.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/async_db_manager.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/base.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/config.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/connections.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/db_function.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/expressions.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/extended.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/fields.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/introspection.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/listen.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/loop_filters.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/model_dto.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/model_view.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/one_database.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/paginator.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/pool_maintenance.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/pool_watch.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/pooler_role.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/pydantic_bridge.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/registry.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/relations.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/resilience.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/session_context.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/signals.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/tls.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/types.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/write_queue.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/core/write_retry.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/entity.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/error_handling.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/exceptions.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/extended/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/extended/app_error_handler.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/identity_rule.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/local_sqlite.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/middleware/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/middleware/base.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/migrations/MODULE_README.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/migrations/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/migrations/cli.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/migrations/ddl.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/migrations/diff.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/migrations/executor.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/migrations/integration.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/migrations/loader.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/migrations/operations.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/migrations/state.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/migrations/table_filter.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/no_org_assignment.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/operations/FEATURE.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/operations/MODULE_README.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/operations/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/operations/bulk_update_values.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/operations/catalog_select.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/operations/conflict.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/operations/conflict_writes.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/operations/create.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/operations/db_functions.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/operations/delete.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/operations/dynamic_admin.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/operations/dynamic_crud.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/operations/graph_walk.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/operations/latest_rows.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/operations/queue_claim.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/operations/read.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/operations/relational_backfill.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/operations/staging_load.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/operations/update.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/platform_access.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/platform_db.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/py.typed +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/pytest_plugin.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/python_sql/MODULE_README.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/python_sql/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/python_sql/db_objects.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/python_sql/table_detailed_relationships.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/python_sql/table_typescript_relationship.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/query/FEATURE.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/query/MODULE_README.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/query/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/query/builder.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/query/executor.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/resources/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/resources/additional-assigners-2026-09-12.json +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/resources/org_assignment_trigger_baseline.json +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/FEATURE.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/MODULE_README.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/code_handler.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/codegen_writer.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/columns.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/common.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/diff_preview.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/entity_capabilities.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/generator.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/helpers/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/helpers/base_generators.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/helpers/entity_generators.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/helpers/git_checker.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/package_wiring.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/relationships.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/runner.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/schema.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/schema_manager.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/tables.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/schema_builder/views.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/secrets_battery/FEATURE.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/secrets_battery/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/secrets_battery/attachments.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/secrets_battery/crypto.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/secrets_battery/host_authorization.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/secrets_battery/items.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/secrets_battery/model.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/secrets_battery/mutation_receipts.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/secrets_battery/org_service.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/secrets_battery/service.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/session/README.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/session/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/session/coalesce.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/session/dag.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/session/errors.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/session/fallback.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/session/flush.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/session/lifecycle.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/session/managed.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/session/op.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/session/reads.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/session/session.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/session/telemetry.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/sql_executor/MODULE_README.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/sql_executor/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/sql_executor/executor.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/sql_executor/queries.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/sql_executor/registry.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/sql_executor/types.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/sql_executor/utils.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/utils/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/utils/sql_utils.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/matrx_orm/utils/type_converters.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/scripts/git-branches.sh +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/scripts/publish.sh +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/scripts/release.sh +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/MODULE_README.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/conftest.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/MODULE_README.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_adapter_registry.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_admin_db_columns.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_admin_response_rendering.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_admin_search_negation.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_admin_search_sentinels.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_advisory_lock.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_agent_message.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_api_auth.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_api_config.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_api_handlers.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_api_protocol.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_array_agg_order_by.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_associations.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_associations_wiring.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_bulk_hydration_offload.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_bulk_update_by_pk.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_bulk_upsert_increment_set_fields.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_cache_debug.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_call_function.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_case_when.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_catalog.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_committed_row_guard.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_composite_pk_filter.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_composite_pk_write_paths.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_config.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_conflict_target.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_conflict_writes.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_connection_codecs.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_connection_poison_guard.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_connection_primitives.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_count_composite_distinct.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_count_limit_param_leak.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_db_function_field.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_ddl_generator.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_deadlock_retry.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_derived_table.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_dirty_tracking.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_dynamic_crud.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_exceptions.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_execute_query_integrity_mapping.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_expression_primitives.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_fields.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_filter_jsonb_agg_array_index.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_from_alias.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_fts.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_func_expression_args.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_graph_walk.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_having_annotate_alias.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_insert_ignore_and_admin_primitives.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_introspect_rls_policies.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_join_and_aggregate.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_latest_rows.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_listen_notify.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_local_sqlite.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_lock_contention_retry.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_managed_write_guard.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_matrx_entity.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_migration_diff_types.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_migration_loader.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_model_instance.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_model_meta.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_optimistic_concurrency.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_order_by_expression.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_org_assignment_inventory.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_parameter_name_hydration.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_patch_jsonb_path.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_persisted_count.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_pool_holder_census.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_pool_loop_recreation.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_pool_maintenance.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_postgrest_filters.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_pydantic_bridge.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_query_builder.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_query_error_detail.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_query_executor_sql.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_query_timeout.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_querybuilder_clone_semantics.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_queue_claim.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_read_connection_retry.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_registry.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_registry_multi_database.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_registry_multi_schema.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_relational_backfill.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_relations.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_resilience.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_schema_exists.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_session_advisory_lock.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_standalone_write_session_context.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_subquery_filter_raw.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_subquery_in_filter.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_subquery_nested_expressions.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_supabase_auth.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_supabase_config.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_tls.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_transaction_database_identity.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_typed_join_projection.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_typed_predicates.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_update_case_expression.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_update_subquery.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_update_with_rebase.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_upsert_default_leak.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_upsert_with_conflict.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_values_jsonb_decode.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_watched_lifecycle.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_write_queue_deadline.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level1/test_write_retry_semantics.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level2/MODULE_README.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level2/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level2/conftest.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level2/test_bulk_ops.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level2/test_cache_integration.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level2/test_crud.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level2/test_foreign_keys.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level2/test_m2m.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level2/test_manager.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level2/test_migrations_live.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level2/test_query_execution.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level2/test_schema_diff.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/level2/verify_committed_row_guard_pg17.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/live_pooler_role.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/sample_project/.env.example +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/sample_project/README.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/sample_project/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/sample_project/generate.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/sample_project/generated/.gitkeep +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/sample_project/matrx_orm.yaml +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/sample_project/test_schema_generation.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/sample_project_desktop/.env.example +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/sample_project_desktop/README.md +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/sample_project_desktop/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/sample_project_desktop/client_example.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/sample_project_desktop/client_example.ts +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/sample_project_desktop/client_supabase_example.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/sample_project_desktop/server.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/schema/entity_tests.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/schema/test_base_generation.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/schema/test_composite_pk_fk_generation.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/schema/test_composite_unique_generation.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/schema/test_dto_identity_generation.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/schema/test_entity_capability_generation.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/schema/test_enum_ordering.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/schema/test_generate_schema.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/schema/test_junction_analysis.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/schema/test_multi_schema_output.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/schema/test_schema_analysis.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/schema/test_sql_expression_defaults.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/schema/test_table_relationships_query.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/schema/test_view_generation.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/schema_builder/test_array_default_parsing.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/schema_builder/test_focused_generation_plan.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/schema_builder/test_host_models_aggregator.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/session/__init__.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/session/conftest.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/session/test_cache_no_downgrade.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/session/test_capture_poison_proof.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/session/test_coalesce.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/session/test_dag.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/session/test_disk_spill_fallback.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/session/test_flush_individual_fallback.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/session/test_governed_write.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/session/test_managed.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/session/test_op_enqueue_site.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/session/test_reads.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/session/test_record_error_bounded_insert.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/session/test_record_error_storm.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/session/test_session.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/session/test_spill_guard_plugin.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/test_array_arg_element_type.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/test_database_name_alias.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/test_db_functions.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/test_dynamic_select_unregistered.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/test_immutable_insert_or_exact_verify.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/test_keyed_digest.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/test_model_cls_refactor.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/test_no_blocking_asyncpg_tls.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/test_one_database.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/test_order_by_desc_nulls_last.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/test_pooler_role_guard.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/test_secrets_battery.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/test_secrets_minting_keys.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/test_sql_param_casts.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/test_sync_twins_guard.py +0 -0
- {matrx_orm-3.1.152 → matrx_orm-3.1.154}/tests/test_user_visible_lookup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: matrx-orm
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.154
|
|
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
|
|
@@ -25,7 +25,7 @@ Requires-Python: >=3.13
|
|
|
25
25
|
Requires-Dist: asyncpg>=0.31.0
|
|
26
26
|
Requires-Dist: cryptography>=43.0
|
|
27
27
|
Requires-Dist: gitpython>=3.1.40
|
|
28
|
-
Requires-Dist: matrx-utils>=2.0.
|
|
28
|
+
Requires-Dist: matrx-utils>=2.0.42
|
|
29
29
|
Requires-Dist: psycopg-pool>=3.2.5
|
|
30
30
|
Requires-Dist: psycopg[binary]>=3.2.5
|
|
31
31
|
Requires-Dist: python-dotenv>=1.0
|
|
@@ -60,6 +60,7 @@ from .core.diagnostics import (
|
|
|
60
60
|
collect_pool_diagnostics,
|
|
61
61
|
describe_transaction,
|
|
62
62
|
describe_transactions,
|
|
63
|
+
introspect_lock_waits,
|
|
63
64
|
log_pool_diagnostics,
|
|
64
65
|
long_transactions,
|
|
65
66
|
long_transactions_sql,
|
|
@@ -447,6 +448,7 @@ __all__ = [
|
|
|
447
448
|
"OneDatabaseReport",
|
|
448
449
|
"PoolIdentity",
|
|
449
450
|
"introspect_columns",
|
|
451
|
+
"introspect_lock_waits",
|
|
450
452
|
"introspect_rls_policies",
|
|
451
453
|
"schema_exists",
|
|
452
454
|
# ── LISTEN/NOTIFY ──────────────────────────────────────────────────────────
|
|
@@ -214,6 +214,15 @@ commit; exceptions roll back; cancellation-shielded teardown finishes before
|
|
|
214
214
|
the connection returns to the pool. No path can leave `authenticated` on a
|
|
215
215
|
reused server connection.
|
|
216
216
|
|
|
217
|
+
**A DDL block needs `lock_timeout_ms`.** `rls_session(..., statement_timeout_ms=…)`
|
|
218
|
+
bounds execution, not the WAIT for a lock: a `CREATE TABLE` queued behind a dump or a
|
|
219
|
+
sweep is not executing, so `statement_timeout` never fires and an unbounded waiter
|
|
220
|
+
blocks everyone behind it. `lock_timeout_ms` (default `None` = leave the server
|
|
221
|
+
default) is `SET LOCAL` like the role and the claims, so it cannot outlive the
|
|
222
|
+
transaction. First consumer: aidream's table-provisioning lane B
|
|
223
|
+
(`aidream/services/provisioning/`), whose new tables carry FKs into two of the busiest
|
|
224
|
+
relations on the platform database.
|
|
225
|
+
|
|
217
226
|
**Empty-to-nonempty is not contamination proof.** A READ COMMITTED row can be
|
|
218
227
|
created between the original empty query and its reproof (`guest_executions`
|
|
219
228
|
does this under concurrent first requests). `reprove_empty_read` captures the
|
|
@@ -270,6 +279,26 @@ everywhere: tight ceiling for application sessions, explicit exemption for the
|
|
|
270
279
|
backup session, and the exemption VERIFIED before the dump starts rather than
|
|
271
280
|
assumed (`db/mirror/refresh.py::resolve_dump_endpoint`).
|
|
272
281
|
|
|
282
|
+
**A ceiling that must survive a pooler is `SET LOCAL`, and the transaction is
|
|
283
|
+
where it goes.** The split above left a gap: behind Supavisor neither the
|
|
284
|
+
`server_settings` default nor `PGOPTIONS` reaches the server, so any caller that
|
|
285
|
+
must bound what IT does — rather than what the deployment allows — had nowhere to
|
|
286
|
+
put a ceiling. `set_transaction_ceilings({...})` /`transaction_ceilings()`
|
|
287
|
+
(`matrx_orm.core.transaction`) close it: the named GUCs are emitted with
|
|
288
|
+
`set_config(name, value, true)` immediately after every top-level `BEGIN`, before
|
|
289
|
+
the host's session context and before `rls_session` drops to the restricted role,
|
|
290
|
+
and they die with the transaction, so nothing can leak onto a pooled connection.
|
|
291
|
+
A block that needs more says `SET LOCAL` later and wins.
|
|
292
|
+
|
|
293
|
+
Empty in production — these are deployment settings there. The one caller is
|
|
294
|
+
`matrx_orm.pytest_lock_guard`, the pytest11 guard that bounds what a test run may
|
|
295
|
+
do to a SHARED database after a test transaction held ACCESS EXCLUSIVE on
|
|
296
|
+
`platform.reachability` for 77s and stopped production chat on 2026-09-15
|
|
297
|
+
(root-`conftest.py`, the sixth cross-suite hazard). Verified against the live
|
|
298
|
+
database 2026-09-16: `lock_timeout`, `idle_in_transaction_session_timeout` and a
|
|
299
|
+
tagged `application_name` all land through the pooler this way, and the same
|
|
300
|
+
connection asked for them as startup options gets `0` and `"Supavisor"`.
|
|
301
|
+
|
|
273
302
|
**`long_transactions()` names the blocker.** `matrx_orm.long_transactions`
|
|
274
303
|
(async) and `matrx_orm.long_transactions_sql` (a parameter-free SQL string, so
|
|
275
304
|
sync psycopg tooling runs the identical query) return every transaction open
|
|
@@ -217,3 +217,125 @@ def describe_transaction(row: dict[str, Any]) -> str:
|
|
|
217
217
|
def describe_transactions(rows: list[dict[str, Any]]) -> str:
|
|
218
218
|
"""Multi-line blocker report, newest last. Empty string when there are none."""
|
|
219
219
|
return "\n".join(f" - {describe_transaction(r)}" for r in rows)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
# ---------------------------------------------------------------------------
|
|
223
|
+
# LOCK WAITS — who is BLOCKED, on what, and who is holding it.
|
|
224
|
+
#
|
|
225
|
+
# Sibling to `long_transactions` above and deliberately NOT a duplicate of it:
|
|
226
|
+
# that one answers "who has a transaction open too long" (one row per session,
|
|
227
|
+
# no graph); this one answers "is a CROWD queued behind somebody right now, and
|
|
228
|
+
# which somebody" — the blocking graph, the contended relations and the lock
|
|
229
|
+
# modes. A long transaction that blocks nobody is a vacuum problem; a short one
|
|
230
|
+
# holding ACCESS EXCLUSIVE on a hot table is an outage. They live in the same
|
|
231
|
+
# module because this is the ONE place matrx-orm reads `pg_stat_activity`.
|
|
232
|
+
#
|
|
233
|
+
# 2026-09-15 23:45–23:52 UTC, production: `platform.rebuild_reachability()`
|
|
234
|
+
# does `TRUNCATE platform.reachability` (ACCESS EXCLUSIVE on the hottest read
|
|
235
|
+
# table) and fires from an AFTER trigger on `platform.association_types`. An
|
|
236
|
+
# integration-test transaction inserted an association type and then kept
|
|
237
|
+
# working for 77 seconds while holding that lock; 12–18 PostgREST sessions
|
|
238
|
+
# queued on relation locks and every production chat turn returned
|
|
239
|
+
# QueryTimeoutError. NOBODY WAS TOLD — the storm was invisible until a human
|
|
240
|
+
# opened `pg_stat_activity` by hand.
|
|
241
|
+
#
|
|
242
|
+
# "Who is blocked, on what, and who is holding it" is a fact about POSTGRES,
|
|
243
|
+
# not a row in an application table: `pg_locks` / `pg_stat_activity` /
|
|
244
|
+
# `pg_blocking_pids()` have no Model and never will. That is exactly the shape
|
|
245
|
+
# this module exists for (see the module docstring), so the statement lives
|
|
246
|
+
# HERE — one fixed, parametrized statement in the ORM — rather than as a SQL
|
|
247
|
+
# literal in the aidream service that consumes it. aidream keeps ZERO raw SQL
|
|
248
|
+
# outside db/migrations; a missing capability is a todo for the ORM, never a
|
|
249
|
+
# licence to write SQL in application code.
|
|
250
|
+
#
|
|
251
|
+
# clock_timestamp(), not now(): `now()` is frozen at transaction start, so a
|
|
252
|
+
# backend whose `state_change` lands after our snapshot reports a NEGATIVE age.
|
|
253
|
+
# A sampler must never report a hold as "-0.1 seconds old".
|
|
254
|
+
_LOCK_WAITS_SQL = """
|
|
255
|
+
WITH waiters AS (
|
|
256
|
+
SELECT l.pid AS waiter_pid,
|
|
257
|
+
l.mode AS requested_mode,
|
|
258
|
+
l.relation AS relation_oid,
|
|
259
|
+
a.application_name AS waiter_application_name,
|
|
260
|
+
a.state AS waiter_state,
|
|
261
|
+
a.query AS waiter_query,
|
|
262
|
+
a.query_start AS waiter_query_start,
|
|
263
|
+
pg_blocking_pids(l.pid) AS blocking_pids
|
|
264
|
+
FROM pg_locks l
|
|
265
|
+
JOIN pg_stat_activity a ON a.pid = l.pid
|
|
266
|
+
WHERE NOT l.granted
|
|
267
|
+
AND l.locktype = 'relation'
|
|
268
|
+
AND l.pid <> pg_backend_pid()
|
|
269
|
+
AND a.query_start IS NOT NULL
|
|
270
|
+
AND clock_timestamp() - a.query_start >= make_interval(secs => $1::float8)
|
|
271
|
+
)
|
|
272
|
+
SELECT w.waiter_pid,
|
|
273
|
+
w.waiter_application_name,
|
|
274
|
+
w.waiter_state,
|
|
275
|
+
left(coalesce(w.waiter_query, ''), $2::int) AS waiter_query,
|
|
276
|
+
w.requested_mode,
|
|
277
|
+
CASE WHEN w.relation_oid IS NOT NULL
|
|
278
|
+
THEN rn.nspname || '.' || rc.relname END AS relation,
|
|
279
|
+
extract(epoch FROM (clock_timestamp() - w.waiter_query_start))::float8
|
|
280
|
+
AS waiter_waiting_seconds,
|
|
281
|
+
b.blocker_pid,
|
|
282
|
+
ba.application_name AS blocker_application_name,
|
|
283
|
+
ba.state AS blocker_state,
|
|
284
|
+
left(coalesce(ba.query, ''), $2::int) AS blocker_query,
|
|
285
|
+
extract(epoch FROM (clock_timestamp() - ba.xact_start))::float8
|
|
286
|
+
AS blocker_xact_age_seconds,
|
|
287
|
+
extract(epoch FROM (clock_timestamp() - ba.state_change))::float8
|
|
288
|
+
AS blocker_state_age_seconds,
|
|
289
|
+
bm.held_modes AS blocker_held_modes
|
|
290
|
+
FROM waiters w
|
|
291
|
+
LEFT JOIN LATERAL unnest(w.blocking_pids) AS b(blocker_pid) ON true
|
|
292
|
+
LEFT JOIN pg_class rc ON rc.oid = w.relation_oid
|
|
293
|
+
LEFT JOIN pg_namespace rn ON rn.oid = rc.relnamespace
|
|
294
|
+
LEFT JOIN pg_stat_activity ba ON ba.pid = b.blocker_pid
|
|
295
|
+
LEFT JOIN LATERAL (
|
|
296
|
+
SELECT string_agg(DISTINCT bl.mode, ',' ORDER BY bl.mode) AS held_modes
|
|
297
|
+
FROM pg_locks bl
|
|
298
|
+
WHERE bl.pid = b.blocker_pid
|
|
299
|
+
AND bl.granted
|
|
300
|
+
AND bl.relation IS NOT DISTINCT FROM w.relation_oid
|
|
301
|
+
) bm ON true
|
|
302
|
+
ORDER BY waiter_waiting_seconds DESC
|
|
303
|
+
"""
|
|
304
|
+
|
|
305
|
+
#: How much of a query text one sampled row carries. A cap, not a filter — the
|
|
306
|
+
#: alarm names the blocker, it does not archive its statement.
|
|
307
|
+
LOCK_WAIT_QUERY_CHARS = 400
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
async def introspect_lock_waits(
|
|
311
|
+
database: str,
|
|
312
|
+
*,
|
|
313
|
+
waiting_longer_than_seconds: float = 0.0,
|
|
314
|
+
query_chars: int = LOCK_WAIT_QUERY_CHARS,
|
|
315
|
+
) -> list[dict[str, Any]]:
|
|
316
|
+
"""Every session WAITING on a relation lock, with who is blocking it.
|
|
317
|
+
|
|
318
|
+
One row per (waiter, blocker) edge — a waiter blocked by three holders
|
|
319
|
+
yields three rows, and a waiter whose blocker has already vanished still
|
|
320
|
+
yields one row with ``blocker_pid`` ``None`` (the ``LEFT JOIN LATERAL`` is
|
|
321
|
+
deliberate: a waiter must never disappear from the sample because the
|
|
322
|
+
catalog raced us).
|
|
323
|
+
|
|
324
|
+
Columns: ``waiter_pid``, ``waiter_application_name``, ``waiter_state``,
|
|
325
|
+
``waiter_query``, ``requested_mode``, ``relation`` (``schema.table``),
|
|
326
|
+
``waiter_waiting_seconds``, ``blocker_pid``, ``blocker_application_name``,
|
|
327
|
+
``blocker_state``, ``blocker_query``, ``blocker_xact_age_seconds``,
|
|
328
|
+
``blocker_state_age_seconds``, ``blocker_held_modes``.
|
|
329
|
+
|
|
330
|
+
Read-only, parameter-bound, and takes no lock of its own — safe to call
|
|
331
|
+
DURING the storm it is describing, which is the only moment it is useful.
|
|
332
|
+
"""
|
|
333
|
+
from matrx_orm.core.async_db_manager import AsyncDatabaseManager
|
|
334
|
+
|
|
335
|
+
rows = await AsyncDatabaseManager.execute_query(
|
|
336
|
+
database,
|
|
337
|
+
_LOCK_WAITS_SQL,
|
|
338
|
+
float(waiting_longer_than_seconds),
|
|
339
|
+
int(query_chars),
|
|
340
|
+
)
|
|
341
|
+
return [dict(r) for r in rows]
|
|
@@ -59,11 +59,19 @@ async def rls_session(
|
|
|
59
59
|
role: str,
|
|
60
60
|
database: str | None = None,
|
|
61
61
|
statement_timeout_ms: int | None = DEFAULT_STATEMENT_TIMEOUT_MS,
|
|
62
|
+
lock_timeout_ms: int | None = None,
|
|
62
63
|
) -> AsyncIterator[None]:
|
|
63
64
|
"""Run the enclosed block as ``role`` with ``request.jwt.claims`` set to ``claims``.
|
|
64
65
|
|
|
65
66
|
All ORM/raw queries inside the block are subject to Postgres RLS as that role.
|
|
66
67
|
``claims`` must at minimum carry ``sub`` (the user id ``auth.uid()`` returns).
|
|
68
|
+
|
|
69
|
+
``lock_timeout_ms`` bounds how long a statement inside the block waits for a lock
|
|
70
|
+
(``None`` leaves the server default alone). A block that issues DDL needs it: the
|
|
71
|
+
wait for an ``ACCESS EXCLUSIVE`` on a busy relation is not statement execution, so
|
|
72
|
+
``statement_timeout`` does not bound it, and an unbounded waiter queues behind the
|
|
73
|
+
dump or sweep that is already running while blocking everyone behind it. Like the
|
|
74
|
+
role and the claims it is ``SET LOCAL`` — it cannot outlive the transaction.
|
|
67
75
|
"""
|
|
68
76
|
if not _ROLE_RE.match(role):
|
|
69
77
|
raise DatabaseError(
|
|
@@ -95,5 +103,7 @@ async def rls_session(
|
|
|
95
103
|
await conn.execute("select set_config('request.jwt.claims', $1, true)", claims_json)
|
|
96
104
|
if statement_timeout_ms is not None:
|
|
97
105
|
await conn.execute(f"SET LOCAL statement_timeout = {int(statement_timeout_ms)}")
|
|
106
|
+
if lock_timeout_ms is not None:
|
|
107
|
+
await conn.execute(f"SET LOCAL lock_timeout = {int(lock_timeout_ms)}")
|
|
98
108
|
await conn.execute(f"SET LOCAL ROLE {role}")
|
|
99
109
|
yield
|
|
@@ -287,6 +287,7 @@ class TransactionContext:
|
|
|
287
287
|
from matrx_orm.core.session_context import apply_session_context
|
|
288
288
|
|
|
289
289
|
try:
|
|
290
|
+
await _apply_transaction_ceilings(conn)
|
|
290
291
|
await apply_session_context(conn)
|
|
291
292
|
except BaseException as e:
|
|
292
293
|
await self.__aexit__(type(e), e, e.__traceback__)
|
|
@@ -372,6 +373,41 @@ class TransactionContext:
|
|
|
372
373
|
return False # never suppress exceptions
|
|
373
374
|
|
|
374
375
|
|
|
376
|
+
# ── Process-wide transaction ceilings ───────────────────────────────────────────
|
|
377
|
+
# Emitted as ``SET LOCAL`` immediately after every top-level ``BEGIN``.
|
|
378
|
+
#
|
|
379
|
+
# WHY THIS EXISTS AND WHY IT IS *HERE*, not in `server_settings`. We reach Postgres
|
|
380
|
+
# through Supavisor in TRANSACTION mode. Measured 2026-09-16 against production:
|
|
381
|
+
# Supavisor DISCARDS libpq startup options and asyncpg `server_settings` outright
|
|
382
|
+
# (`show lock_timeout` → 0, `show application_name` → "Supavisor"), and a plain
|
|
383
|
+
# `SET` does not survive the COMMIT because the next transaction may land on a
|
|
384
|
+
# different server connection. The ONLY unit of session state that is real on this
|
|
385
|
+
# path is the transaction — so a ceiling that is not `SET LOCAL` is a ceiling that
|
|
386
|
+
# is not there. (That is also why the ORM's declared 60s
|
|
387
|
+
# `idle_in_transaction_session_timeout` was inert during the 2026-09-15 outage.)
|
|
388
|
+
#
|
|
389
|
+
# ONE caller today: `matrx_orm.pytest_lock_guard`, bounding what a test run may do
|
|
390
|
+
# to a shared database. Empty in production, where these are deployment settings.
|
|
391
|
+
_TRANSACTION_CEILINGS: dict[str, str] = {}
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
def set_transaction_ceilings(ceilings: "dict[str, str] | None") -> None:
|
|
395
|
+
"""Replace the GUCs emitted as ``SET LOCAL`` after every top-level BEGIN."""
|
|
396
|
+
_TRANSACTION_CEILINGS.clear()
|
|
397
|
+
if ceilings:
|
|
398
|
+
_TRANSACTION_CEILINGS.update({str(k): str(v) for k, v in ceilings.items()})
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
def transaction_ceilings() -> dict[str, str]:
|
|
402
|
+
"""The ceilings currently in force (a copy)."""
|
|
403
|
+
return dict(_TRANSACTION_CEILINGS)
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
async def _apply_transaction_ceilings(conn: Any) -> None:
|
|
407
|
+
for name, value in _TRANSACTION_CEILINGS.items():
|
|
408
|
+
await conn.execute("SELECT set_config($1, $2, true)", name, value)
|
|
409
|
+
|
|
410
|
+
|
|
375
411
|
def transaction(database: str | None = None) -> TransactionContext:
|
|
376
412
|
"""Return a ``TransactionContext`` async context manager.
|
|
377
413
|
|