matrx-orm 3.1.201__tar.gz → 3.1.203__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.
Files changed (434) hide show
  1. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/PKG-INFO +2 -2
  2. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/session_context.py +78 -3
  3. matrx_orm-3.1.203/matrx_orm/pytest_production_door.py +353 -0
  4. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/diff_preview.py +7 -0
  5. matrx_orm-3.1.203/matrx_orm/schema_builder/excluded_targets.py +93 -0
  6. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/runner.py +7 -0
  7. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/schema_manager.py +26 -0
  8. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/pyproject.toml +3 -2
  9. matrx_orm-3.1.203/tests/schema/test_excluded_fk_targets.py +128 -0
  10. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/.gitignore +0 -0
  11. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/AGENTS.md +0 -0
  12. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/BASE_CLASS_METHODS.md +0 -0
  13. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/CHANGELOG.md +0 -0
  14. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/CLAUDE.md +0 -0
  15. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/MODEL_API.md +0 -0
  16. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/README.md +0 -0
  17. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/database/orm/extended/managers/ai_model_base.py +0 -0
  18. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/docs/migrations.md +0 -0
  19. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/FEATURE.md +0 -0
  20. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/MODULE_README.md +0 -0
  21. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/__init__.py +0 -0
  22. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/adapters/MODULE_README.md +0 -0
  23. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/adapters/__init__.py +0 -0
  24. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/adapters/async_postgresql.py +0 -0
  25. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/adapters/base_adapter.py +0 -0
  26. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/adapters/postgrest_client_adapter.py +0 -0
  27. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/adapters/supabase_adapter.py +0 -0
  28. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/admin/FEATURE.md +0 -0
  29. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/admin/__init__.py +0 -0
  30. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/admin/router.py +0 -0
  31. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/api/__init__.py +0 -0
  32. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/api/auth.py +0 -0
  33. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/api/config.py +0 -0
  34. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/api/handlers.py +0 -0
  35. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/api/protocol.py +0 -0
  36. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/api/server.py +0 -0
  37. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/associations.py +0 -0
  38. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/cache_debug.py +0 -0
  39. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/catalog.py +0 -0
  40. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/catalog_sql.py +0 -0
  41. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/client/MODULE_README.md +0 -0
  42. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/client/__init__.py +0 -0
  43. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/client/postgres_connection.py +0 -0
  44. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/client/postgrest.py +0 -0
  45. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/client/supabase_auth.py +0 -0
  46. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/client/supabase_config.py +0 -0
  47. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/client/supabase_manager.py +0 -0
  48. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/EXTENDED-TASK.md +0 -0
  49. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/FEATURE.md +0 -0
  50. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/MODULE_README.md +0 -0
  51. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/RELATIONS-TASKS.md +0 -0
  52. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/TASKS.md +0 -0
  53. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/__init__.py +0 -0
  54. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/admin_lane.py +0 -0
  55. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/async_db_manager.py +0 -0
  56. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/base.py +0 -0
  57. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/config.py +0 -0
  58. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/connections.py +0 -0
  59. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/db_function.py +0 -0
  60. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/diagnostics.py +0 -0
  61. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/expressions.py +0 -0
  62. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/extended.py +0 -0
  63. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/fields.py +0 -0
  64. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/introspection.py +0 -0
  65. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/listen.py +0 -0
  66. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/loop_filters.py +0 -0
  67. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/model_dto.py +0 -0
  68. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/model_view.py +0 -0
  69. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/one_database.py +0 -0
  70. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/paginator.py +0 -0
  71. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/pool_maintenance.py +0 -0
  72. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/pool_watch.py +0 -0
  73. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/pooler_role.py +0 -0
  74. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/pydantic_bridge.py +0 -0
  75. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/read_write.py +0 -0
  76. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/registry.py +0 -0
  77. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/relations.py +0 -0
  78. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/resilience.py +0 -0
  79. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/rls_session.py +0 -0
  80. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/signals.py +0 -0
  81. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/statement_ceiling.py +0 -0
  82. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/tls.py +0 -0
  83. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/transaction.py +0 -0
  84. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/types.py +0 -0
  85. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/write_queue.py +0 -0
  86. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/core/write_retry.py +0 -0
  87. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/entity.py +0 -0
  88. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/error_handling.py +0 -0
  89. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/exceptions.py +0 -0
  90. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/extended/__init__.py +0 -0
  91. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/extended/app_error_handler.py +0 -0
  92. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/identity_rule.py +0 -0
  93. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/local_sqlite.py +0 -0
  94. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/middleware/__init__.py +0 -0
  95. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/middleware/base.py +0 -0
  96. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/migrations/MODULE_README.md +0 -0
  97. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/migrations/__init__.py +0 -0
  98. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/migrations/cli.py +0 -0
  99. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/migrations/ddl.py +0 -0
  100. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/migrations/diff.py +0 -0
  101. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/migrations/executor.py +0 -0
  102. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/migrations/integration.py +0 -0
  103. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/migrations/loader.py +0 -0
  104. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/migrations/operations.py +0 -0
  105. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/migrations/state.py +0 -0
  106. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/migrations/table_filter.py +0 -0
  107. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/no_org_assignment.py +0 -0
  108. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/operations/FEATURE.md +0 -0
  109. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/operations/MODULE_README.md +0 -0
  110. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/operations/__init__.py +0 -0
  111. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/operations/bulk_update_values.py +0 -0
  112. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/operations/catalog_select.py +0 -0
  113. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/operations/conflict.py +0 -0
  114. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/operations/conflict_writes.py +0 -0
  115. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/operations/create.py +0 -0
  116. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/operations/db_functions.py +0 -0
  117. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/operations/delete.py +0 -0
  118. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/operations/dynamic_admin.py +0 -0
  119. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/operations/dynamic_crud.py +0 -0
  120. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/operations/graph_walk.py +0 -0
  121. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/operations/latest_rows.py +0 -0
  122. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/operations/queue_claim.py +0 -0
  123. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/operations/read.py +0 -0
  124. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/operations/relational_backfill.py +0 -0
  125. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/operations/staging_load.py +0 -0
  126. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/operations/update.py +0 -0
  127. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/platform_access.py +0 -0
  128. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/platform_db.py +0 -0
  129. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/py.typed +0 -0
  130. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/pytest_live_db_guard.py +0 -0
  131. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/pytest_lock_guard.py +0 -0
  132. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/pytest_plugin.py +0 -0
  133. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/python_sql/MODULE_README.md +0 -0
  134. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/python_sql/__init__.py +0 -0
  135. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/python_sql/db_objects.py +0 -0
  136. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/python_sql/table_detailed_relationships.py +0 -0
  137. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/python_sql/table_typescript_relationship.py +0 -0
  138. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/query/FEATURE.md +0 -0
  139. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/query/MODULE_README.md +0 -0
  140. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/query/__init__.py +0 -0
  141. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/query/builder.py +0 -0
  142. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/query/executor.py +0 -0
  143. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/resources/__init__.py +0 -0
  144. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/resources/additional-assigners-2026-09-12.json +0 -0
  145. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/resources/org_assignment_trigger_baseline.json +0 -0
  146. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/FEATURE.md +0 -0
  147. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/MODULE_README.md +0 -0
  148. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/__init__.py +0 -0
  149. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/code_handler.py +0 -0
  150. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/codegen_writer.py +0 -0
  151. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/columns.py +0 -0
  152. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/common.py +0 -0
  153. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/entity_capabilities.py +0 -0
  154. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/generator.py +0 -0
  155. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/helpers/__init__.py +0 -0
  156. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/helpers/base_generators.py +0 -0
  157. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/helpers/entity_generators.py +0 -0
  158. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/helpers/git_checker.py +0 -0
  159. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/package_wiring.py +0 -0
  160. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/relationships.py +0 -0
  161. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/schema.py +0 -0
  162. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/tables.py +0 -0
  163. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/schema_builder/views.py +0 -0
  164. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/secrets_battery/FEATURE.md +0 -0
  165. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/secrets_battery/__init__.py +0 -0
  166. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/secrets_battery/attachments.py +0 -0
  167. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/secrets_battery/backup_restore.py +0 -0
  168. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/secrets_battery/crypto.py +0 -0
  169. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/secrets_battery/host_authorization.py +0 -0
  170. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/secrets_battery/items.py +0 -0
  171. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/secrets_battery/model.py +0 -0
  172. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/secrets_battery/mutation_receipts.py +0 -0
  173. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/secrets_battery/native_enable.py +0 -0
  174. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/secrets_battery/native_lifecycle.py +0 -0
  175. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/secrets_battery/native_passkeys.py +0 -0
  176. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/secrets_battery/native_source.py +0 -0
  177. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/secrets_battery/org_service.py +0 -0
  178. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/secrets_battery/org_vault_gate.py +0 -0
  179. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/secrets_battery/service.py +0 -0
  180. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/secrets_battery/vault_history.py +0 -0
  181. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/session/README.md +0 -0
  182. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/session/__init__.py +0 -0
  183. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/session/coalesce.py +0 -0
  184. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/session/dag.py +0 -0
  185. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/session/errors.py +0 -0
  186. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/session/fallback.py +0 -0
  187. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/session/flush.py +0 -0
  188. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/session/lifecycle.py +0 -0
  189. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/session/managed.py +0 -0
  190. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/session/op.py +0 -0
  191. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/session/reads.py +0 -0
  192. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/session/session.py +0 -0
  193. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/session/telemetry.py +0 -0
  194. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/sql_executor/MODULE_README.md +0 -0
  195. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/sql_executor/__init__.py +0 -0
  196. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/sql_executor/executor.py +0 -0
  197. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/sql_executor/queries.py +0 -0
  198. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/sql_executor/registry.py +0 -0
  199. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/sql_executor/types.py +0 -0
  200. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/sql_executor/utils.py +0 -0
  201. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/state.py +0 -0
  202. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/utils/__init__.py +0 -0
  203. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/utils/sql_utils.py +0 -0
  204. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/utils/type_converters.py +0 -0
  205. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/matrx_orm/write_actor.py +0 -0
  206. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/scripts/git-branches.sh +0 -0
  207. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/scripts/publish.sh +0 -0
  208. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/scripts/release.sh +0 -0
  209. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/MODULE_README.md +0 -0
  210. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/__init__.py +0 -0
  211. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/conftest.py +0 -0
  212. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/MODULE_README.md +0 -0
  213. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/__init__.py +0 -0
  214. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_adapter_registry.py +0 -0
  215. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_admin_db_columns.py +0 -0
  216. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_admin_response_rendering.py +0 -0
  217. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_admin_search_negation.py +0 -0
  218. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_admin_search_sentinels.py +0 -0
  219. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_advisory_lock.py +0 -0
  220. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_agent_message.py +0 -0
  221. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_api_auth.py +0 -0
  222. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_api_config.py +0 -0
  223. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_api_handlers.py +0 -0
  224. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_api_protocol.py +0 -0
  225. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_array_agg_order_by.py +0 -0
  226. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_association_trigger_actor_naming.py +0 -0
  227. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_associations.py +0 -0
  228. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_associations_wiring.py +0 -0
  229. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_bulk_hydration_offload.py +0 -0
  230. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_bulk_update_by_pk.py +0 -0
  231. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_bulk_upsert_increment_set_fields.py +0 -0
  232. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_cache_debug.py +0 -0
  233. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_call_function.py +0 -0
  234. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_case_when.py +0 -0
  235. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_catalog.py +0 -0
  236. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_column_scoped_writes.py +0 -0
  237. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_committed_row_guard.py +0 -0
  238. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_composite_pk_filter.py +0 -0
  239. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_composite_pk_write_paths.py +0 -0
  240. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_config.py +0 -0
  241. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_conflict_target.py +0 -0
  242. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_conflict_writes.py +0 -0
  243. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_connection_codecs.py +0 -0
  244. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_connection_poison_guard.py +0 -0
  245. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_connection_primitives.py +0 -0
  246. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_count_composite_distinct.py +0 -0
  247. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_count_limit_param_leak.py +0 -0
  248. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_db_function_field.py +0 -0
  249. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_ddl_generator.py +0 -0
  250. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_deadlock_retry.py +0 -0
  251. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_derived_table.py +0 -0
  252. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_dirty_tracking.py +0 -0
  253. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_dynamic_crud.py +0 -0
  254. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_exceptions.py +0 -0
  255. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_execute_query_integrity_mapping.py +0 -0
  256. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_expression_primitives.py +0 -0
  257. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_fields.py +0 -0
  258. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_filter_jsonb_agg_array_index.py +0 -0
  259. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_fk_cycle_resolution.py +0 -0
  260. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_from_alias.py +0 -0
  261. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_fts.py +0 -0
  262. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_func_expression_args.py +0 -0
  263. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_graph_walk.py +0 -0
  264. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_having_annotate_alias.py +0 -0
  265. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_insert_ignore_and_admin_primitives.py +0 -0
  266. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_introspect_rls_policies.py +0 -0
  267. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_join_and_aggregate.py +0 -0
  268. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_latest_rows.py +0 -0
  269. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_listen_notify.py +0 -0
  270. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_local_sqlite.py +0 -0
  271. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_lock_contention_retry.py +0 -0
  272. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_managed_write_guard.py +0 -0
  273. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_matrx_entity.py +0 -0
  274. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_migration_diff_types.py +0 -0
  275. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_migration_loader.py +0 -0
  276. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_model_instance.py +0 -0
  277. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_model_meta.py +0 -0
  278. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_optimistic_concurrency.py +0 -0
  279. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_order_by_expression.py +0 -0
  280. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_org_assignment_inventory.py +0 -0
  281. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_orm_banners_are_client_safe.py +0 -0
  282. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_parameter_name_hydration.py +0 -0
  283. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_patch_jsonb_path.py +0 -0
  284. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_percentile_cont.py +0 -0
  285. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_persisted_count.py +0 -0
  286. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_person_scoped_session_bypasses_shared_cache.py +0 -0
  287. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_pool_create_never_wedges.py +0 -0
  288. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_pool_holder_census.py +0 -0
  289. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_pool_loop_recreation.py +0 -0
  290. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_pool_maintenance.py +0 -0
  291. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_postgrest_filters.py +0 -0
  292. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_pydantic_bridge.py +0 -0
  293. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_query_builder.py +0 -0
  294. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_query_error_detail.py +0 -0
  295. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_query_executor_sql.py +0 -0
  296. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_query_timeout.py +0 -0
  297. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_querybuilder_clone_semantics.py +0 -0
  298. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_queue_claim.py +0 -0
  299. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_read_connection_retry.py +0 -0
  300. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_read_write_declared.py +0 -0
  301. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_registry.py +0 -0
  302. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_registry_multi_database.py +0 -0
  303. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_registry_multi_schema.py +0 -0
  304. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_relational_backfill.py +0 -0
  305. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_relations.py +0 -0
  306. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_resilience.py +0 -0
  307. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_rls_session_scope.py +0 -0
  308. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_schema_exists.py +0 -0
  309. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_session_advisory_lock.py +0 -0
  310. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_standalone_write_session_context.py +0 -0
  311. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_state_cache.py +0 -0
  312. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_subquery_filter_raw.py +0 -0
  313. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_subquery_in_filter.py +0 -0
  314. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_subquery_nested_expressions.py +0 -0
  315. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_supabase_auth.py +0 -0
  316. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_supabase_config.py +0 -0
  317. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_tls.py +0 -0
  318. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_transaction_database_identity.py +0 -0
  319. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_transaction_gucs_one_round_trip.py +0 -0
  320. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_transaction_pool_release_sends_nothing.py +0 -0
  321. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_typed_join_projection.py +0 -0
  322. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_typed_predicates.py +0 -0
  323. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_update_case_expression.py +0 -0
  324. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_update_subquery.py +0 -0
  325. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_update_with_rebase.py +0 -0
  326. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_upsert_default_leak.py +0 -0
  327. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_upsert_with_conflict.py +0 -0
  328. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_values_jsonb_decode.py +0 -0
  329. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_watched_lifecycle.py +0 -0
  330. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_write_queue_deadline.py +0 -0
  331. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level1/test_write_retry_semantics.py +0 -0
  332. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level2/MODULE_README.md +0 -0
  333. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level2/__init__.py +0 -0
  334. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level2/conftest.py +0 -0
  335. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level2/test_bulk_ops.py +0 -0
  336. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level2/test_cache_integration.py +0 -0
  337. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level2/test_crud.py +0 -0
  338. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level2/test_foreign_keys.py +0 -0
  339. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level2/test_m2m.py +0 -0
  340. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level2/test_manager.py +0 -0
  341. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level2/test_migrations_live.py +0 -0
  342. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level2/test_query_execution.py +0 -0
  343. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level2/test_schema_diff.py +0 -0
  344. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/level2/verify_committed_row_guard_pg17.py +0 -0
  345. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/live_pooler_role.py +0 -0
  346. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/native_source_cases.py +0 -0
  347. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/native_source_oracle.rs +0 -0
  348. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/sample_project/.env.example +0 -0
  349. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/sample_project/README.md +0 -0
  350. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/sample_project/__init__.py +0 -0
  351. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/sample_project/generate.py +0 -0
  352. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/sample_project/generated/.gitkeep +0 -0
  353. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/sample_project/matrx_orm.yaml +0 -0
  354. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/sample_project/test_schema_generation.py +0 -0
  355. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/sample_project_desktop/.env.example +0 -0
  356. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/sample_project_desktop/README.md +0 -0
  357. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/sample_project_desktop/__init__.py +0 -0
  358. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/sample_project_desktop/client_example.py +0 -0
  359. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/sample_project_desktop/client_example.ts +0 -0
  360. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/sample_project_desktop/client_supabase_example.py +0 -0
  361. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/sample_project_desktop/server.py +0 -0
  362. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/schema/entity_tests.py +0 -0
  363. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/schema/test_base_generation.py +0 -0
  364. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/schema/test_composite_pk_fk_generation.py +0 -0
  365. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/schema/test_composite_unique_generation.py +0 -0
  366. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/schema/test_dto_identity_generation.py +0 -0
  367. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/schema/test_entity_capability_generation.py +0 -0
  368. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/schema/test_enum_ordering.py +0 -0
  369. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/schema/test_generate_schema.py +0 -0
  370. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/schema/test_junction_analysis.py +0 -0
  371. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/schema/test_multi_schema_output.py +0 -0
  372. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/schema/test_schema_analysis.py +0 -0
  373. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/schema/test_sql_expression_defaults.py +0 -0
  374. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/schema/test_table_relationships_query.py +0 -0
  375. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/schema/test_view_generation.py +0 -0
  376. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/schema_builder/test_array_default_parsing.py +0 -0
  377. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/schema_builder/test_focused_generation_plan.py +0 -0
  378. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/schema_builder/test_host_models_aggregator.py +0 -0
  379. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/schema_builder/test_never_filter_columns.py +0 -0
  380. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/session/__init__.py +0 -0
  381. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/session/conftest.py +0 -0
  382. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/session/test_a_failed_capture_still_names_the_failure.py +0 -0
  383. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/session/test_cache_no_downgrade.py +0 -0
  384. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/session/test_capture_poison_proof.py +0 -0
  385. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/session/test_coalesce.py +0 -0
  386. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/session/test_dag.py +0 -0
  387. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/session/test_disk_spill_fallback.py +0 -0
  388. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/session/test_flush_individual_fallback.py +0 -0
  389. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/session/test_governed_write.py +0 -0
  390. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/session/test_live_db_guard_plugin.py +0 -0
  391. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/session/test_managed.py +0 -0
  392. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/session/test_op_enqueue_site.py +0 -0
  393. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/session/test_reads.py +0 -0
  394. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/session/test_record_error_bounded_insert.py +0 -0
  395. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/session/test_record_error_storm.py +0 -0
  396. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/session/test_session.py +0 -0
  397. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/session/test_spill_guard_plugin.py +0 -0
  398. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_a_backend_handed_over_mid_transaction_never_takes_our_writes.py +0 -0
  399. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_a_read_only_backend_never_refuses_our_writes.py +0 -0
  400. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_array_arg_element_type.py +0 -0
  401. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_attachment_mutation_serialization.py +0 -0
  402. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_backup_alias_conflict.py +0 -0
  403. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_backup_history_restore.py +0 -0
  404. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_backup_restore_live.py +0 -0
  405. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_call_function_as.py +0 -0
  406. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_call_function_none_mode.py +0 -0
  407. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_composite_fk_is_not_a_column_fk.py +0 -0
  408. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_database_name_alias.py +0 -0
  409. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_db_functions.py +0 -0
  410. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_dsn_password_masking.py +0 -0
  411. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_dynamic_select_unregistered.py +0 -0
  412. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_immutable_insert_or_exact_verify.py +0 -0
  413. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_keyed_digest.py +0 -0
  414. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_model_cls_refactor.py +0 -0
  415. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_native_enable.py +0 -0
  416. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_native_lifecycle.py +0 -0
  417. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_native_lifecycle_fences.py +0 -0
  418. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_native_passkey_receipts.py +0 -0
  419. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_native_source.py +0 -0
  420. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_no_blocking_asyncpg_tls.py +0 -0
  421. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_one_database.py +0 -0
  422. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_order_by_desc_nulls_last.py +0 -0
  423. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_org_vault_gate.py +0 -0
  424. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_pooler_role_guard.py +0 -0
  425. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_secret_audit_names_its_organization.py +0 -0
  426. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_secrets_battery.py +0 -0
  427. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_secrets_minting_keys.py +0 -0
  428. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_shared_lock_guard.py +0 -0
  429. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_sql_param_casts.py +0 -0
  430. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_statement_ceiling_warning.py +0 -0
  431. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_sync_twins_guard.py +0 -0
  432. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_update_result_truthiness.py +0 -0
  433. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_user_visible_lookup.py +0 -0
  434. {matrx_orm-3.1.201 → matrx_orm-3.1.203}/tests/test_vault_aggregate_recovery_stateful.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: matrx-orm
3
- Version: 3.1.201
3
+ Version: 3.1.203
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.58
29
+ Requires-Dist: matrx-utils>=2.0.59
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
@@ -200,11 +200,81 @@ def declared_actor_gucs() -> dict[str, str]:
200
200
  Empty when nothing declared an actor: the DB resolver then applies its
201
201
  documented default (``human`` with an identity present, ``code`` without)
202
202
  and logs that it did.
203
+
204
+ The WORKFLOW CHAIN rides the same provider (it is part of "who is writing":
205
+ the store copies it onto every record-changed event's ``actor.chain``), so a
206
+ host that wired this provider stamps run writes with no second wiring.
203
207
  """
204
208
  actor = _current_actor.get()
205
- if actor is None:
206
- return {}
207
- return actor.as_gucs()
209
+ out = actor.as_gucs() if actor is not None else {}
210
+ chain = _current_chain.get()
211
+ if chain is not None:
212
+ out[WORKFLOW_CHAIN_GUC] = chain.as_json()
213
+ return out
214
+
215
+
216
+ # ---------------------------------------------------------------------------
217
+ # THE WORKFLOW CHAIN — which workflow run is writing (lane CHAIR-RECORD-CHANGED).
218
+ #
219
+ # A record write made by a workflow run's step carries ``{run_id, root_run, depth}``
220
+ # in the transaction-local GUC ``custom.workflow_chain``; the store's record-changed
221
+ # emitter copies it onto the event (``actor.chain``). A run started BY such an event
222
+ # declares the event's chain one level deeper, so a consumer can cap a chain's depth
223
+ # and see a loop (the same root_run coming back) without reading run history.
224
+ # ---------------------------------------------------------------------------
225
+
226
+ WORKFLOW_CHAIN_GUC = "custom.workflow_chain"
227
+
228
+
229
+ @dataclass(frozen=True, slots=True)
230
+ class WorkflowChain:
231
+ """The workflow run writing now, the run that started the chain, and how deep it is."""
232
+
233
+ run_id: str
234
+ root_run: str
235
+ depth: int = 1
236
+
237
+ def as_json(self) -> str:
238
+ import json
239
+
240
+ return json.dumps(
241
+ {"run_id": self.run_id, "root_run": self.root_run, "depth": self.depth},
242
+ separators=(",", ":"),
243
+ )
244
+
245
+
246
+ def workflow_chain_for_run(run_id: str, caused_by: Mapping[str, Any] | None = None) -> WorkflowChain:
247
+ """The chain a run declares: one level below the change that started it, else a new root."""
248
+ if caused_by:
249
+ root = str(caused_by.get("root_run") or caused_by.get("run_id") or run_id)
250
+ try:
251
+ depth = int(caused_by.get("depth") or 0) + 1
252
+ except (TypeError, ValueError):
253
+ depth = 1
254
+ return WorkflowChain(run_id=str(run_id), root_run=root, depth=depth)
255
+ return WorkflowChain(run_id=str(run_id), root_run=str(run_id), depth=1)
256
+
257
+
258
+ _current_chain: ContextVar[WorkflowChain | None] = ContextVar("_workflow_chain", default=None)
259
+
260
+
261
+ def current_workflow_chain() -> WorkflowChain | None:
262
+ """The workflow chain declared by the innermost open declaration, if any."""
263
+ return _current_chain.get()
264
+
265
+
266
+ @contextmanager
267
+ def declaring_workflow_chain(chain: WorkflowChain | None) -> Iterator[WorkflowChain | None]:
268
+ """Every transaction opened inside this block stamps its writes with ``chain``.
269
+
270
+ A ContextVar, like the actor: tasks spawned inside the block inherit it, work
271
+ running beside it does not. ``None`` clears an outer declaration for the block.
272
+ """
273
+ token = _current_chain.set(chain)
274
+ try:
275
+ yield chain
276
+ finally:
277
+ _current_chain.reset(token)
208
278
 
209
279
 
210
280
  def _validated_actor(tier: str, system: str, agent: str | None, *, caller: str) -> ActorRef:
@@ -279,6 +349,11 @@ async def declared_actor(
279
349
 
280
350
 
281
351
  __all__ = [
352
+ "WORKFLOW_CHAIN_GUC",
353
+ "WorkflowChain",
354
+ "current_workflow_chain",
355
+ "declaring_workflow_chain",
356
+ "workflow_chain_for_run",
282
357
  "ACTOR_AGENT_GUC",
283
358
  "ACTOR_SYSTEM_GUC",
284
359
  "ACTOR_TIER_GUC",
@@ -0,0 +1,353 @@
1
+ """Session-wide door: a pytest process never opens a connection to PRODUCTION (lane ONE-HOME, 2026-10-02).
2
+
3
+ Registered as a ``pytest11`` entry point (``matrx_production_door``), so pytest loads it in every suite
4
+ regardless of rootdir — the same mechanism as this package's spill, lock and live-db guards; the aidream
5
+ root ``conftest.py`` also registers it when the entry point is missing (stale install metadata). This is the
6
+ NINTH cross-suite hazard; the others are catalogued in the aidream repo-root ``conftest.py``.
7
+
8
+ WHY A DRIVER-LEVEL DOOR. A static census of test sources cannot win: a production ref split in two and
9
+ concatenated, a DSN read from JSON or a dotenv file, libpq's own ``PG*`` environment behind a no-argument
10
+ ``connect()``, asyncpg keyword arguments, sqlalchemy URLs, SQL read from a file, writing functions called
11
+ through ``select``, aliased imports and ``psql`` in a subprocess all slip past every pattern. Every one of them
12
+ reaches a driver. So the driver is the door: at CONNECT time the effective host, user and database — the DSN
13
+ text, the keyword arguments and libpq's environment defaults merged the way libpq merges them — are compared
14
+ with production's identity (ref ``brsgrqvjdzwihsvnfqkf`` in the pooler user or host, or
15
+ ``db.matrxserver.com``), and a production connection is refused by name.
16
+
17
+ WHAT IS WRAPPED: ``psycopg.Connection.connect`` / ``psycopg.AsyncConnection.connect`` (so ``psycopg.connect``
18
+ and every ``psycopg_pool`` pool), ``psycopg2.connect``, ``asyncpg.connect`` / ``create_pool`` (and the
19
+ ``asyncpg.connection.connect`` a pool dials), sqlalchemy ``create_engine`` / ``create_async_engine``,
20
+ ``matrx_orm``'s database registration, and ``subprocess.Popen`` of ``psql``. A module imported after this
21
+ plugin loads is patched on import.
22
+
23
+ THE ONE EXCEPTION: ``db.pooled_read.read_only("production")`` opens its connection inside
24
+ :func:`production_read_only` and then runs ``begin read only`` before handing out a cursor, so a production
25
+ read in a test is a transaction that cannot write. Nothing else — no flag, no environment variable — opens
26
+ this door. Not covered: a libpq service file or ``~/.pgpass`` host that the environment does not name.
27
+
28
+ Guard: ``aidream/tests/test_tests_never_write_production.py`` (plants per bypass class).
29
+ """
30
+
31
+ from __future__ import annotations
32
+
33
+ import contextvars
34
+ import importlib.abc
35
+ import importlib.util
36
+ import os
37
+ import subprocess
38
+ import sys
39
+ from collections.abc import Iterator
40
+ from contextlib import contextmanager
41
+ from typing import Any
42
+ from urllib.parse import parse_qs, unquote, urlsplit
43
+
44
+ PRODUCTION_REF = "brsgrqvjdzwihsvnfqkf"
45
+ PRODUCTION_MARKERS = (PRODUCTION_REF, "db.matrxserver.com")
46
+ #: libpq's environment defaults, by the connection parameter each one supplies.
47
+ LIBPQ_ENV = {"host": "PGHOST", "hostaddr": "PGHOSTADDR", "user": "PGUSER", "dbname": "PGDATABASE", "service": "PGSERVICE"}
48
+
49
+ _READ_ONLY_PRODUCTION: contextvars.ContextVar[bool] = contextvars.ContextVar("production_read_only", default=False)
50
+
51
+
52
+ class ProductionDoorRefusal(RuntimeError):
53
+ """A connection opened under pytest named the production database."""
54
+
55
+
56
+ @contextmanager
57
+ def production_read_only() -> Iterator[None]:
58
+ """Open ONE production connection that the caller turns into ``begin read only`` before any statement."""
59
+ token = _READ_ONLY_PRODUCTION.set(True)
60
+ try:
61
+ yield
62
+ finally:
63
+ _READ_ONLY_PRODUCTION.reset(token)
64
+
65
+
66
+ def _parse_dsn(text: str) -> dict[str, str]:
67
+ """Connection parameters from a URL (any ``scheme://``) or a libpq ``key=value`` string."""
68
+ text = (text or "").strip()
69
+ if not text:
70
+ return {}
71
+ if "://" in text:
72
+ try:
73
+ u = urlsplit(text)
74
+ out = {"host": u.hostname or "", "user": unquote(u.username or ""), "dbname": (u.path or "").lstrip("/")}
75
+ for k, v in parse_qs(u.query).items():
76
+ out[k] = v[0]
77
+ return {k: v for k, v in out.items() if v}
78
+ except ValueError:
79
+ return {}
80
+ out: dict[str, str] = {}
81
+ for part in text.split():
82
+ k, sep, v = part.partition("=")
83
+ if sep:
84
+ out[k.strip()] = v.strip().strip("'\"")
85
+ return out
86
+
87
+
88
+ def effective_identity(dsn: Any = None, **kwargs: Any) -> dict[str, str]:
89
+ """What libpq would connect to: environment defaults, overlaid by the DSN, overlaid by keyword arguments."""
90
+ params = {k: os.environ[v] for k, v in LIBPQ_ENV.items() if os.environ.get(v)}
91
+ params.update(_parse_dsn(str(dsn)) if dsn else {})
92
+ for k in ("host", "hostaddr", "user", "dbname", "database", "service"):
93
+ if kwargs.get(k):
94
+ params["dbname" if k == "database" else k] = str(kwargs[k])
95
+ return params
96
+
97
+
98
+ def names_production(dsn: Any = None, **kwargs: Any) -> str | None:
99
+ """The production marker this connection carries (in the DSN text or its effective identity), else None."""
100
+ texts = [str(dsn or "")] + list(effective_identity(dsn, **kwargs).values())
101
+ blob = " ".join(texts).lower()
102
+ return next((m for m in PRODUCTION_MARKERS if m in blob), None)
103
+
104
+
105
+ def check(what: str, dsn: Any = None, **kwargs: Any) -> None:
106
+ """Refuse a production connection unless it is the read-only one :func:`production_read_only` opens."""
107
+ if _READ_ONLY_PRODUCTION.get():
108
+ return
109
+ marker = names_production(dsn, **kwargs)
110
+ if marker:
111
+ raise ProductionDoorRefusal(
112
+ f"refused under pytest: {what} reaches the PRODUCTION database ({marker}). Tests never write "
113
+ "production — open the nightly clone (db.pooled_read.clone_writer_dsn()); a read-only production "
114
+ "check goes through db.pooled_read.read_only('production')."
115
+ )
116
+
117
+
118
+ # ── the wrappers ─────────────────────────────────────────────────────────────────────────────────────
119
+
120
+
121
+ def _patch_psycopg(mod: Any) -> None:
122
+ for cls_name in ("Connection", "AsyncConnection"):
123
+ cls = getattr(mod, cls_name, None)
124
+ if cls is None or getattr(cls.connect, "_production_door", False):
125
+ continue
126
+ original = cls.__dict__["connect"].__func__
127
+ if cls_name == "Connection":
128
+
129
+ def connect(cls: Any, conninfo: str = "", _o: Any = original, **kw: Any) -> Any:
130
+ check("psycopg.connect", conninfo, **kw)
131
+ return _o(cls, conninfo, **kw)
132
+ else:
133
+
134
+ async def connect(cls: Any, conninfo: str = "", _o: Any = original, **kw: Any) -> Any: # type: ignore[misc]
135
+ check("psycopg.AsyncConnection.connect", conninfo, **kw)
136
+ return await _o(cls, conninfo, **kw)
137
+
138
+ connect._production_door = True # type: ignore[attr-defined]
139
+ cls.connect = classmethod(connect)
140
+ mod.connect = mod.Connection.connect
141
+
142
+
143
+ def _patch_psycopg2(mod: Any) -> None:
144
+ original = mod.connect
145
+ if getattr(original, "_production_door", False):
146
+ return
147
+
148
+ def connect(dsn: Any = None, connection_factory: Any = None, cursor_factory: Any = None, **kw: Any) -> Any:
149
+ check("psycopg2.connect", dsn, **kw)
150
+ return original(dsn, connection_factory, cursor_factory, **kw)
151
+
152
+ connect._production_door = True # type: ignore[attr-defined]
153
+ mod.connect = connect
154
+
155
+
156
+ def _patch_asyncpg(mod: Any) -> None:
157
+ import asyncpg.connection as connection_mod
158
+ import asyncpg.pool as pool_mod
159
+
160
+ original = connection_mod.connect
161
+ if getattr(original, "_production_door", False):
162
+ return
163
+
164
+ async def connect(dsn: Any = None, *args: Any, **kw: Any) -> Any:
165
+ check("asyncpg.connect", dsn, **kw)
166
+ return await original(dsn, *args, **kw)
167
+
168
+ original_pool = pool_mod.create_pool
169
+
170
+ def create_pool(dsn: Any = None, *args: Any, **kw: Any) -> Any:
171
+ check("asyncpg.create_pool", dsn, **kw)
172
+ return original_pool(dsn, *args, **kw)
173
+
174
+ connect._production_door = True # type: ignore[attr-defined]
175
+ create_pool._production_door = True # type: ignore[attr-defined]
176
+ connection_mod.connect = connect
177
+ mod.connect = connect
178
+ pool_mod.create_pool = create_pool
179
+ mod.create_pool = create_pool
180
+
181
+
182
+ def _patch_sqlalchemy(mod: Any) -> None:
183
+ import sqlalchemy.engine as engine_mod
184
+
185
+ original = engine_mod.create_engine
186
+ if getattr(original, "_production_door", False):
187
+ return
188
+
189
+ def create_engine(url: Any, *args: Any, **kw: Any) -> Any:
190
+ check("sqlalchemy.create_engine", _render_url(url))
191
+ return original(url, *args, **kw)
192
+
193
+ create_engine._production_door = True # type: ignore[attr-defined]
194
+ engine_mod.create_engine = create_engine
195
+ mod.create_engine = create_engine
196
+
197
+
198
+ def _patch_sqlalchemy_asyncio(mod: Any) -> None:
199
+ original = mod.create_async_engine
200
+ if getattr(original, "_production_door", False):
201
+ return
202
+
203
+ def create_async_engine(url: Any, *args: Any, **kw: Any) -> Any:
204
+ check("sqlalchemy.create_async_engine", _render_url(url))
205
+ return original(url, *args, **kw)
206
+
207
+ create_async_engine._production_door = True # type: ignore[attr-defined]
208
+ mod.create_async_engine = create_async_engine
209
+ engine = sys.modules.get("sqlalchemy.ext.asyncio.engine")
210
+ if engine is not None:
211
+ engine.create_async_engine = create_async_engine
212
+
213
+
214
+ def _patch_psycopg_pool(mod: Any) -> None:
215
+ # A pool's worker swallows a connect error into retries; refuse at construction so the refusal is said.
216
+ for cls_name in ("ConnectionPool", "AsyncConnectionPool", "NullConnectionPool", "AsyncNullConnectionPool"):
217
+ cls = getattr(mod, cls_name, None)
218
+ if cls is None or getattr(cls.__init__, "_production_door", False):
219
+ continue
220
+ original = cls.__init__
221
+
222
+ def __init__(self: Any, conninfo: str = "", *a: Any, _o: Any = original, _n: str = cls_name, **kw: Any) -> None:
223
+ check(f"psycopg_pool.{_n}", conninfo, **(kw.get("kwargs") or {}))
224
+ _o(self, conninfo, *a, **kw)
225
+
226
+ __init__._production_door = True # type: ignore[attr-defined]
227
+ cls.__init__ = __init__
228
+
229
+
230
+ def _render_url(url: Any) -> str:
231
+ render = getattr(url, "render_as_string", None)
232
+ return render(hide_password=True) if callable(render) else str(url)
233
+
234
+
235
+ def _patch_orm_registry(mod: Any) -> None:
236
+ registry_cls = getattr(mod, "DatabaseRegistry", None) or type(getattr(mod, "_registry", None) or object())
237
+ original = getattr(registry_cls, "register", None)
238
+ if original is None or getattr(original, "_production_door", False):
239
+ return
240
+
241
+ def register(self: Any, config: Any) -> None:
242
+ check(
243
+ f"matrx_orm database registration {getattr(config, 'name', '?')!r}",
244
+ None,
245
+ host=getattr(config, "host", None),
246
+ user=getattr(config, "user", None),
247
+ dbname=getattr(config, "database_name", None),
248
+ )
249
+ return original(self, config)
250
+
251
+ register._production_door = True # type: ignore[attr-defined]
252
+ registry_cls.register = register
253
+
254
+
255
+ def _psql_argv(args: Any, shell: bool) -> list[str] | None:
256
+ """The command line as words when it runs ``psql`` (directly or inside a shell string), else None."""
257
+ words = args.split() if isinstance(args, str | bytes) else [str(a) for a in args] if args else []
258
+ words = [w.decode() if isinstance(w, bytes) else w for w in words]
259
+ if any(os.path.basename(w) == "psql" for w in words):
260
+ return words
261
+ return None
262
+
263
+
264
+ def _patch_subprocess() -> None:
265
+ original = subprocess.Popen.__init__
266
+ if getattr(original, "_production_door", False):
267
+ return
268
+
269
+ def __init__(self: Any, args: Any, *a: Any, **kw: Any) -> None:
270
+ words = _psql_argv(args, bool(kw.get("shell")))
271
+ if words is not None:
272
+ env = kw.get("env")
273
+ saved = dict(os.environ)
274
+ try:
275
+ if env is not None: # psql sees the child's environment, not ours
276
+ os.environ.clear()
277
+ os.environ.update({str(k): str(v) for k, v in env.items()})
278
+ flags = {"-h": "host", "--host": "host", "-U": "user", "--username": "user", "-d": "dbname", "--dbname": "dbname"}
279
+ kwargs = {flags[w]: words[i + 1] for i, w in enumerate(words[:-1]) if w in flags}
280
+ check("psql (subprocess)", " ".join(words), **kwargs)
281
+ finally:
282
+ if env is not None:
283
+ os.environ.clear()
284
+ os.environ.update(saved)
285
+ original(self, args, *a, **kw)
286
+
287
+ __init__._production_door = True # type: ignore[attr-defined]
288
+ subprocess.Popen.__init__ = __init__ # type: ignore[method-assign]
289
+
290
+
291
+ _PATCHERS = {
292
+ "psycopg": _patch_psycopg,
293
+ "psycopg_pool": _patch_psycopg_pool,
294
+ "psycopg2": _patch_psycopg2,
295
+ "asyncpg": _patch_asyncpg,
296
+ "sqlalchemy": _patch_sqlalchemy,
297
+ "sqlalchemy.ext.asyncio": _patch_sqlalchemy_asyncio,
298
+ "matrx_orm.core.config": _patch_orm_registry,
299
+ }
300
+
301
+
302
+ class _PatchOnImport(importlib.abc.MetaPathFinder, importlib.abc.Loader):
303
+ """Patch a driver the moment it is first imported (for drivers this plugin did not import itself)."""
304
+
305
+ def find_spec(self, fullname: str, path: Any, target: Any = None) -> Any:
306
+ if fullname not in _PATCHERS or fullname in sys.modules:
307
+ return None
308
+ sys.meta_path.remove(self)
309
+ try:
310
+ spec = importlib.util.find_spec(fullname)
311
+ finally:
312
+ sys.meta_path.insert(0, self)
313
+ if spec is None or spec.loader is None:
314
+ return None
315
+ loader = spec.loader
316
+
317
+ class _Loader(importlib.abc.Loader):
318
+ def create_module(self, s: Any) -> Any:
319
+ return loader.create_module(s)
320
+
321
+ def exec_module(self, module: Any) -> None:
322
+ loader.exec_module(module)
323
+ _PATCHERS[fullname](module)
324
+
325
+ spec.loader = _Loader()
326
+ return spec
327
+
328
+
329
+ def install() -> None:
330
+ """Wrap every driver already imported, and every one imported later. Idempotent."""
331
+ _patch_subprocess()
332
+ for name, patch in _PATCHERS.items():
333
+ if name in sys.modules:
334
+ patch(sys.modules[name])
335
+ if not any(isinstance(f, _PatchOnImport) for f in sys.meta_path):
336
+ sys.meta_path.insert(0, _PatchOnImport())
337
+ for name in ("psycopg", "asyncpg"): # the two drivers every suite has: patch them now
338
+ try:
339
+ importlib.import_module(name)
340
+ except ImportError:
341
+ pass
342
+
343
+
344
+
345
+ # ── pytest hooks: install before any conftest or test module is imported ─────────────────────────────
346
+
347
+
348
+ def pytest_load_initial_conftests(early_config: Any, parser: Any, args: Any) -> None:
349
+ install()
350
+
351
+
352
+ def pytest_configure(config: Any) -> None:
353
+ install() # idempotent: covers a registration through the root conftest's fallback
@@ -725,6 +725,7 @@ def preview_schema_changes(
725
725
  from matrx_orm.core.config import register_database_from_env
726
726
  from matrx_orm.schema_builder.common import DEBUG_CONFIG, OutputConfig
727
727
  from matrx_orm.schema_builder.schema import entry_manager_flags
728
+ from matrx_orm.schema_builder.excluded_targets import excluded_targets, modeled_schemas
728
729
  from matrx_orm.schema_builder.schema_manager import SchemaManager
729
730
 
730
731
  caller_dir = Path(sys.argv[0]).parent.resolve()
@@ -804,6 +805,12 @@ def preview_schema_changes(
804
805
  include_tables=include_tables,
805
806
  exclude_tables=exclude_tables,
806
807
  manager_flags=manager_flags,
808
+ excluded_fk_targets=excluded_targets(cfg.get("generate", []), db_name),
809
+ modeled_schemas=modeled_schemas(
810
+ cfg.get("generate", []),
811
+ db_name,
812
+ next((d.get("additional_schemas") or [] for d in cfg.get("databases", []) if d.get("name") == db_name), []),
813
+ ),
807
814
  )
808
815
  manager.initialize()
809
816
 
@@ -0,0 +1,93 @@
1
+ """A table excluded from generation is excluded as a REFERENCE target too.
2
+
3
+ ``exclude_tables`` under a schema's ``generate[]`` entry keeps that table's model out of the
4
+ schema's file. A table in ANOTHER schema (or the same one) whose foreign key points at it would
5
+ still emit ``ForeignKey(to_model='<Excluded>')`` and a ``get_*_with_related('<schema>.<table>')``
6
+ manager method — a lazy reference that resolves to nothing at runtime and a relation that reads a
7
+ table the host chose not to model. So every reference to an excluded table is dropped at load:
8
+ the column generates as its plain type, and the relation (both directions) is not emitted.
9
+
10
+ The excluded set is qualified (``schema.table``) and spans every ``generate[]`` entry of the same
11
+ database, because the referencing table usually lives in another schema's run.
12
+
13
+ The same holds for a table in a schema the host never models: a foreign key follows its table's
14
+ oid, so once a retired table moves to ``graveyard`` every reference to it reads
15
+ ``to_schema='graveyard'`` — a class the registry can never hold. A reference whose target schema
16
+ is neither generated nor one of the database's ``additional_schemas`` is dropped the same way.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ from collections.abc import Iterable
22
+ from typing import Any
23
+
24
+
25
+ def excluded_targets(generate_list: Iterable[dict[str, Any]], database: str) -> frozenset[str]:
26
+ """Every ``schema.table`` an ``exclude_tables`` list names for ``database``."""
27
+ out: set[str] = set()
28
+ for entry in generate_list:
29
+ if entry.get("database") != database:
30
+ continue
31
+ schema = entry.get("schema") or "public"
32
+ for table in entry.get("exclude_tables") or ():
33
+ out.add(f"{schema}.{table}")
34
+ return frozenset(out)
35
+
36
+
37
+ def modeled_schemas(
38
+ generate_list: Iterable[dict[str, Any]], database: str, additional_schemas: Iterable[str] = ()
39
+ ) -> frozenset[str]:
40
+ """Every schema the host models for ``database``: the generated ones and its additional schemas."""
41
+ out = {"public", *additional_schemas}
42
+ out.update(e.get("schema") or "public" for e in generate_list if e.get("database") == database)
43
+ return frozenset(out)
44
+
45
+
46
+ def drop_references_to(
47
+ excluded: frozenset[str] | set[str],
48
+ *,
49
+ schema: str,
50
+ processed_objects: list[dict[str, Any]],
51
+ full_relationships: list[dict[str, Any]],
52
+ modeled: frozenset[str] | set[str] | None = None,
53
+ ) -> list[str]:
54
+ """Remove every reference to an excluded table, or into a schema outside ``modeled``, in place.
55
+
56
+ Returns what was dropped, for the log. ``modeled=None`` keeps every schema.
57
+ """
58
+ if not excluded and modeled is None:
59
+ return []
60
+
61
+ def gone(target_schema: str, table: str) -> bool:
62
+ return f"{target_schema}.{table}" in excluded or (modeled is not None and target_schema not in modeled)
63
+
64
+ dropped: list[str] = []
65
+ for obj in processed_objects:
66
+ for column in obj.get("table_columns") or ():
67
+ fk = column.get("foreign_key_reference")
68
+ if not isinstance(fk, dict) or not fk.get("table"):
69
+ continue
70
+ target_schema = fk.get("schema") or "public"
71
+ if gone(target_schema, fk["table"]):
72
+ column["foreign_key_reference"] = None
73
+ dropped.append(
74
+ f"{obj.get('schema')}.{obj.get('name')}.{column.get('name')} -> {target_schema}.{fk['table']}"
75
+ )
76
+ for rel in full_relationships:
77
+ fks = rel.get("foreign_keys")
78
+ if isinstance(fks, dict):
79
+ for key in [
80
+ k
81
+ for k, v in fks.items()
82
+ if isinstance(v, dict) and gone(v.get("foreign_schema") or schema, v.get("foreign_table") or k)
83
+ ]:
84
+ fks.pop(key)
85
+ refs = rel.get("referenced_by")
86
+ if isinstance(refs, dict):
87
+ # Keys of referenced_by are always tables of THIS schema (bare names).
88
+ for key in [k for k in refs if f"{schema}.{k}" in excluded]:
89
+ refs.pop(key)
90
+ return dropped
91
+
92
+
93
+ __all__ = ["drop_references_to", "excluded_targets", "modeled_schemas"]
@@ -19,6 +19,7 @@ from dotenv import load_dotenv
19
19
  from matrx_utils import vcprint
20
20
 
21
21
  from matrx_orm.core.config import DatabaseConfigError, register_database_from_env
22
+ from matrx_orm.schema_builder.excluded_targets import excluded_targets, modeled_schemas
22
23
  from matrx_orm.schema_builder.common import (
23
24
  DEBUG_CONFIG,
24
25
  GenerationOutputOverrides,
@@ -386,6 +387,12 @@ def run_schema_generation(
386
387
  output_config=output_config,
387
388
  include_tables=include_tables,
388
389
  exclude_tables=exclude_tables,
390
+ excluded_fk_targets=excluded_targets(cfg.get("generate", []), db_name),
391
+ modeled_schemas=modeled_schemas(
392
+ cfg.get("generate", []),
393
+ db_name,
394
+ next((d.get("additional_schemas") or [] for d in cfg.get("databases", []) if d.get("name") == db_name), []),
395
+ ),
389
396
  manager_flags=manager_flags,
390
397
  skip_unchanged_managers=skip_unchanged_managers,
391
398
  output_overrides=output_overrides,
@@ -39,6 +39,8 @@ class SchemaManager:
39
39
  manager_flags: dict | None = None,
40
40
  skip_unchanged_managers: bool = False,
41
41
  output_overrides: GenerationOutputOverrides | None = None,
42
+ excluded_fk_targets: frozenset[str] | set[str] | None = None,
43
+ modeled_schemas: frozenset[str] | set[str] | None = None,
42
44
  ):
43
45
  if additional_schemas is None:
44
46
  # Read from the registered database config if a project name is provided;
@@ -93,6 +95,13 @@ class SchemaManager:
93
95
  self._exclude_tables: set[str] | None = (
94
96
  set(exclude_tables) if exclude_tables is not None else None
95
97
  )
98
+ #: ``schema.table`` names excluded from generation in ANY generate[] entry of this database:
99
+ #: a reference to one is dropped at load (``excluded_targets.drop_references_to``).
100
+ self._excluded_fk_targets: frozenset[str] = frozenset(excluded_fk_targets or ())
101
+ #: Schemas the host models; a reference into any other (``graveyard``) is dropped the same way.
102
+ self._modeled_schemas: frozenset[str] | None = (
103
+ frozenset(modeled_schemas) if modeled_schemas is not None else None
104
+ )
96
105
 
97
106
  vcprint(
98
107
  self.schema, title="SCHEMA MANAGER] with schema", verbose=self.verbose, color="blue"
@@ -160,6 +169,23 @@ class SchemaManager:
160
169
  self.overview_analysis,
161
170
  ) = get_db_objects(self.schema.name, self.database_project)
162
171
 
172
+ if self._excluded_fk_targets or self._modeled_schemas is not None:
173
+ from matrx_orm.schema_builder.excluded_targets import drop_references_to
174
+
175
+ dropped = drop_references_to(
176
+ self._excluded_fk_targets,
177
+ schema=self.schema.name or "public",
178
+ processed_objects=self.processed_objects,
179
+ full_relationships=self.full_relationships,
180
+ modeled=self._modeled_schemas,
181
+ )
182
+ if dropped:
183
+ vcprint(
184
+ f"[MATRX ORM] {len(dropped)} reference(s) to an excluded or unmodeled table generate as plain "
185
+ f"columns: {', '.join(dropped)}",
186
+ color="yellow",
187
+ )
188
+
163
189
  # NOTE: no filtering here — all relationship/overview data loads in full so
164
190
  # that topological sort, FK resolution, and relationship analysis are always
165
191
  # correct. The filter is applied in Schema.generate_models() just before
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "matrx-orm"
3
- version = "3.1.201"
3
+ version = "3.1.203"
4
4
  description = "Async-first PostgreSQL ORM with bidirectional migrations, schema introspection, many-to-many relationships, and built-in state caching"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -41,7 +41,7 @@ dependencies = [
41
41
  "gitpython>=3.1.40",
42
42
  "psycopg[binary]>=3.2.5",
43
43
  "psycopg-pool>=3.2.5",
44
- "matrx-utils>=2.0.58",
44
+ "matrx-utils>=2.0.59",
45
45
  "pyyaml>=6.0.3",
46
46
  "python-dotenv>=1.0",
47
47
  "cryptography>=43.0",
@@ -52,6 +52,7 @@ dependencies = [
52
52
  matrx_write_spill_guard = "matrx_orm.pytest_plugin"
53
53
  matrx_shared_lock_guard = "matrx_orm.pytest_lock_guard"
54
54
  matrx_live_db_guard = "matrx_orm.pytest_live_db_guard"
55
+ matrx_production_door = "matrx_orm.pytest_production_door"
55
56
 
56
57
  [project.urls]
57
58
  Homepage = "https://github.com/AI-Matrix-Engine/aidream-current"