matrx-orm 3.1.69__tar.gz → 3.1.71__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 (332) hide show
  1. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/PKG-INFO +2 -2
  2. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/FEATURE.md +16 -0
  3. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/query/FEATURE.md +13 -0
  4. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/query/executor.py +14 -1
  5. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/state.py +8 -0
  6. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/pyproject.toml +2 -2
  7. matrx_orm-3.1.71/tests/level1/test_bulk_hydration_offload.py +38 -0
  8. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_managed_write_guard.py +2 -2
  9. matrx_orm-3.1.71/tests/level1/test_rls_session_scope.py +103 -0
  10. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_state_cache.py +11 -0
  11. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/.gitignore +0 -0
  12. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/AGENTS.md +0 -0
  13. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/BASE_CLASS_METHODS.md +0 -0
  14. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/CLAUDE.md +0 -0
  15. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/MODEL_API.md +0 -0
  16. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/README.md +0 -0
  17. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/database/orm/extended/managers/ai_model_base.py +0 -0
  18. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/docs/migrations.md +0 -0
  19. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/MODULE_README.md +0 -0
  20. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/__init__.py +0 -0
  21. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/adapters/MODULE_README.md +0 -0
  22. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/adapters/__init__.py +0 -0
  23. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/adapters/async_postgresql.py +0 -0
  24. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/adapters/base_adapter.py +0 -0
  25. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/adapters/postgresql.py +0 -0
  26. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/adapters/postgrest_client_adapter.py +0 -0
  27. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/adapters/supabase_adapter.py +0 -0
  28. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/admin/__init__.py +0 -0
  29. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/admin/router.py +0 -0
  30. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/api/__init__.py +0 -0
  31. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/api/auth.py +0 -0
  32. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/api/config.py +0 -0
  33. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/api/handlers.py +0 -0
  34. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/api/protocol.py +0 -0
  35. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/api/server.py +0 -0
  36. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/associations.py +0 -0
  37. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/cache_debug.py +0 -0
  38. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/catalog.py +0 -0
  39. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/catalog_sql.py +0 -0
  40. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/client/MODULE_README.md +0 -0
  41. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/client/__init__.py +0 -0
  42. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/client/postgres_connection.py +0 -0
  43. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/client/postgrest.py +0 -0
  44. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/client/supabase_auth.py +0 -0
  45. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/client/supabase_config.py +0 -0
  46. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/client/supabase_manager.py +0 -0
  47. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/EXTENDED-TASK.md +0 -0
  48. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/MODULE_README.md +0 -0
  49. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/RELATIONS-TASKS.md +0 -0
  50. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/TASKS.md +0 -0
  51. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/__init__.py +0 -0
  52. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/async_db_manager.py +0 -0
  53. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/base.py +0 -0
  54. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/config.py +0 -0
  55. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/connections.py +0 -0
  56. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/db_function.py +0 -0
  57. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/diagnostics.py +0 -0
  58. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/expressions.py +0 -0
  59. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/extended.py +0 -0
  60. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/fields.py +0 -0
  61. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/introspection.py +0 -0
  62. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/listen.py +0 -0
  63. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/loop_filters.py +0 -0
  64. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/model_dto.py +0 -0
  65. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/model_view.py +0 -0
  66. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/one_database.py +0 -0
  67. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/paginator.py +0 -0
  68. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/pool_maintenance.py +0 -0
  69. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/pydantic_bridge.py +0 -0
  70. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/registry.py +0 -0
  71. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/relations.py +0 -0
  72. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/resilience.py +0 -0
  73. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/rls_session.py +0 -0
  74. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/signals.py +0 -0
  75. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/tls.py +0 -0
  76. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/transaction.py +0 -0
  77. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/types.py +0 -0
  78. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/core/write_queue.py +0 -0
  79. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/entity.py +0 -0
  80. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/error_handling.py +0 -0
  81. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/exceptions.py +0 -0
  82. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/extended/__init__.py +0 -0
  83. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/extended/app_error_handler.py +0 -0
  84. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/identity_rule.py +0 -0
  85. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/middleware/__init__.py +0 -0
  86. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/middleware/base.py +0 -0
  87. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/migrations/MODULE_README.md +0 -0
  88. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/migrations/__init__.py +0 -0
  89. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/migrations/cli.py +0 -0
  90. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/migrations/ddl.py +0 -0
  91. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/migrations/diff.py +0 -0
  92. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/migrations/executor.py +0 -0
  93. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/migrations/integration.py +0 -0
  94. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/migrations/loader.py +0 -0
  95. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/migrations/operations.py +0 -0
  96. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/migrations/state.py +0 -0
  97. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/migrations/table_filter.py +0 -0
  98. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/operations/MODULE_README.md +0 -0
  99. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/operations/__init__.py +0 -0
  100. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/operations/bulk_update_values.py +0 -0
  101. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/operations/conflict.py +0 -0
  102. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/operations/conflict_writes.py +0 -0
  103. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/operations/create.py +0 -0
  104. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/operations/db_functions.py +0 -0
  105. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/operations/delete.py +0 -0
  106. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/operations/dynamic_admin.py +0 -0
  107. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/operations/dynamic_crud.py +0 -0
  108. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/operations/graph_walk.py +0 -0
  109. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/operations/latest_rows.py +0 -0
  110. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/operations/queue_claim.py +0 -0
  111. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/operations/read.py +0 -0
  112. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/operations/relational_backfill.py +0 -0
  113. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/operations/staging_load.py +0 -0
  114. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/operations/update.py +0 -0
  115. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/platform_db.py +0 -0
  116. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/py.typed +0 -0
  117. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/python_sql/MODULE_README.md +0 -0
  118. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/python_sql/__init__.py +0 -0
  119. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/python_sql/db_objects.py +0 -0
  120. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/python_sql/table_detailed_relationships.py +0 -0
  121. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/python_sql/table_typescript_relationship.py +0 -0
  122. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/query/MODULE_README.md +0 -0
  123. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/query/__init__.py +0 -0
  124. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/query/builder.py +0 -0
  125. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/MODULE_README.md +0 -0
  126. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/__init__.py +0 -0
  127. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/code_handler.py +0 -0
  128. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/codegen_writer.py +0 -0
  129. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/columns.py +0 -0
  130. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/common.py +0 -0
  131. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/diff_preview.py +0 -0
  132. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/entity_capabilities.py +0 -0
  133. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/generator.py +0 -0
  134. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/helpers/__init__.py +0 -0
  135. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/helpers/base_generators.py +0 -0
  136. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/helpers/entity_generators.py +0 -0
  137. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/helpers/git_checker.py +0 -0
  138. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/package_wiring.py +0 -0
  139. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/relationships.py +0 -0
  140. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/runner.py +0 -0
  141. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/schema.py +0 -0
  142. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/schema_manager.py +0 -0
  143. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/tables.py +0 -0
  144. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/schema_builder/views.py +0 -0
  145. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/secrets_battery/FEATURE.md +0 -0
  146. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/secrets_battery/__init__.py +0 -0
  147. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/secrets_battery/attachments.py +0 -0
  148. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/secrets_battery/crypto.py +0 -0
  149. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/secrets_battery/items.py +0 -0
  150. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/secrets_battery/model.py +0 -0
  151. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/secrets_battery/org_service.py +0 -0
  152. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/secrets_battery/service.py +0 -0
  153. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/session/README.md +0 -0
  154. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/session/__init__.py +0 -0
  155. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/session/coalesce.py +0 -0
  156. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/session/dag.py +0 -0
  157. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/session/errors.py +0 -0
  158. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/session/fallback.py +0 -0
  159. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/session/flush.py +0 -0
  160. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/session/lifecycle.py +0 -0
  161. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/session/managed.py +0 -0
  162. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/session/op.py +0 -0
  163. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/session/reads.py +0 -0
  164. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/session/session.py +0 -0
  165. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/session/telemetry.py +0 -0
  166. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/sql_executor/MODULE_README.md +0 -0
  167. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/sql_executor/__init__.py +0 -0
  168. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/sql_executor/executor.py +0 -0
  169. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/sql_executor/queries.py +0 -0
  170. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/sql_executor/registry.py +0 -0
  171. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/sql_executor/types.py +0 -0
  172. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/sql_executor/utils.py +0 -0
  173. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/utils/__init__.py +0 -0
  174. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/utils/sql_utils.py +0 -0
  175. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/matrx_orm/utils/type_converters.py +0 -0
  176. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/scripts/git-branches.sh +0 -0
  177. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/scripts/publish.sh +0 -0
  178. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/scripts/release.sh +0 -0
  179. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/MODULE_README.md +0 -0
  180. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/__init__.py +0 -0
  181. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/conftest.py +0 -0
  182. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/MODULE_README.md +0 -0
  183. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/__init__.py +0 -0
  184. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_admin_db_columns.py +0 -0
  185. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_admin_search_negation.py +0 -0
  186. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_admin_search_sentinels.py +0 -0
  187. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_advisory_lock.py +0 -0
  188. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_agent_message.py +0 -0
  189. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_api_auth.py +0 -0
  190. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_api_config.py +0 -0
  191. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_api_handlers.py +0 -0
  192. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_api_protocol.py +0 -0
  193. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_array_agg_order_by.py +0 -0
  194. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_associations.py +0 -0
  195. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_bulk_update_by_pk.py +0 -0
  196. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_bulk_upsert_increment_set_fields.py +0 -0
  197. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_cache_debug.py +0 -0
  198. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_call_function.py +0 -0
  199. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_case_when.py +0 -0
  200. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_catalog.py +0 -0
  201. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_composite_pk_filter.py +0 -0
  202. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_composite_pk_write_paths.py +0 -0
  203. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_config.py +0 -0
  204. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_conflict_target.py +0 -0
  205. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_conflict_writes.py +0 -0
  206. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_connection_codecs.py +0 -0
  207. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_connection_poison_guard.py +0 -0
  208. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_connection_primitives.py +0 -0
  209. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_count_composite_distinct.py +0 -0
  210. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_db_function_field.py +0 -0
  211. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_ddl_generator.py +0 -0
  212. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_derived_table.py +0 -0
  213. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_dirty_tracking.py +0 -0
  214. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_dynamic_crud.py +0 -0
  215. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_exceptions.py +0 -0
  216. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_execute_query_integrity_mapping.py +0 -0
  217. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_expression_primitives.py +0 -0
  218. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_fields.py +0 -0
  219. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_filter_jsonb_agg_array_index.py +0 -0
  220. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_from_alias.py +0 -0
  221. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_fts.py +0 -0
  222. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_func_expression_args.py +0 -0
  223. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_graph_walk.py +0 -0
  224. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_having_annotate_alias.py +0 -0
  225. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_insert_ignore_and_admin_primitives.py +0 -0
  226. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_introspect_rls_policies.py +0 -0
  227. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_join_and_aggregate.py +0 -0
  228. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_latest_rows.py +0 -0
  229. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_listen_notify.py +0 -0
  230. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_matrx_entity.py +0 -0
  231. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_migration_diff_types.py +0 -0
  232. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_migration_loader.py +0 -0
  233. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_model_instance.py +0 -0
  234. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_model_meta.py +0 -0
  235. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_optimistic_concurrency.py +0 -0
  236. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_order_by_expression.py +0 -0
  237. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_parameter_name_hydration.py +0 -0
  238. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_patch_jsonb_path.py +0 -0
  239. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_pool_loop_recreation.py +0 -0
  240. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_pool_maintenance.py +0 -0
  241. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_postgrest_filters.py +0 -0
  242. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_pydantic_bridge.py +0 -0
  243. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_query_builder.py +0 -0
  244. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_query_error_detail.py +0 -0
  245. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_query_executor_sql.py +0 -0
  246. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_query_timeout.py +0 -0
  247. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_querybuilder_clone_semantics.py +0 -0
  248. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_queue_claim.py +0 -0
  249. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_registry.py +0 -0
  250. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_registry_multi_database.py +0 -0
  251. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_registry_multi_schema.py +0 -0
  252. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_relational_backfill.py +0 -0
  253. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_relations.py +0 -0
  254. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_resilience.py +0 -0
  255. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_schema_exists.py +0 -0
  256. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_session_advisory_lock.py +0 -0
  257. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_subquery_filter_raw.py +0 -0
  258. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_subquery_in_filter.py +0 -0
  259. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_supabase_auth.py +0 -0
  260. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_supabase_config.py +0 -0
  261. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_tls.py +0 -0
  262. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_typed_join_projection.py +0 -0
  263. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_typed_predicates.py +0 -0
  264. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_update_case_expression.py +0 -0
  265. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_update_subquery.py +0 -0
  266. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_update_with_rebase.py +0 -0
  267. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_upsert_default_leak.py +0 -0
  268. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_upsert_with_conflict.py +0 -0
  269. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_values_jsonb_decode.py +0 -0
  270. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_watched_lifecycle.py +0 -0
  271. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level1/test_write_retry_semantics.py +0 -0
  272. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level2/MODULE_README.md +0 -0
  273. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level2/__init__.py +0 -0
  274. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level2/conftest.py +0 -0
  275. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level2/test_bulk_ops.py +0 -0
  276. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level2/test_cache_integration.py +0 -0
  277. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level2/test_crud.py +0 -0
  278. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level2/test_foreign_keys.py +0 -0
  279. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level2/test_m2m.py +0 -0
  280. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level2/test_manager.py +0 -0
  281. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level2/test_migrations_live.py +0 -0
  282. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level2/test_query_execution.py +0 -0
  283. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/level2/test_schema_diff.py +0 -0
  284. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/sample_project/.env.example +0 -0
  285. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/sample_project/README.md +0 -0
  286. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/sample_project/__init__.py +0 -0
  287. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/sample_project/generate.py +0 -0
  288. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/sample_project/generated/.gitkeep +0 -0
  289. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/sample_project/matrx_orm.yaml +0 -0
  290. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/sample_project/test_schema_generation.py +0 -0
  291. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/sample_project_desktop/.env.example +0 -0
  292. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/sample_project_desktop/README.md +0 -0
  293. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/sample_project_desktop/__init__.py +0 -0
  294. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/sample_project_desktop/client_example.py +0 -0
  295. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/sample_project_desktop/client_example.ts +0 -0
  296. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/sample_project_desktop/client_supabase_example.py +0 -0
  297. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/sample_project_desktop/server.py +0 -0
  298. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/schema/entity_tests.py +0 -0
  299. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/schema/test_base_generation.py +0 -0
  300. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/schema/test_composite_pk_fk_generation.py +0 -0
  301. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/schema/test_composite_unique_generation.py +0 -0
  302. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/schema/test_dto_identity_generation.py +0 -0
  303. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/schema/test_entity_capability_generation.py +0 -0
  304. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/schema/test_generate_schema.py +0 -0
  305. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/schema/test_junction_analysis.py +0 -0
  306. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/schema/test_multi_schema_output.py +0 -0
  307. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/schema/test_sql_expression_defaults.py +0 -0
  308. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/schema/test_table_relationships_query.py +0 -0
  309. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/schema/test_view_generation.py +0 -0
  310. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/schema_builder/test_focused_generation_plan.py +0 -0
  311. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/schema_builder/test_host_models_aggregator.py +0 -0
  312. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/session/__init__.py +0 -0
  313. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/session/conftest.py +0 -0
  314. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/session/test_cache_no_downgrade.py +0 -0
  315. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/session/test_capture_poison_proof.py +0 -0
  316. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/session/test_coalesce.py +0 -0
  317. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/session/test_dag.py +0 -0
  318. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/session/test_disk_spill_fallback.py +0 -0
  319. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/session/test_flush_individual_fallback.py +0 -0
  320. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/session/test_governed_write.py +0 -0
  321. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/session/test_managed.py +0 -0
  322. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/session/test_op_enqueue_site.py +0 -0
  323. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/session/test_reads.py +0 -0
  324. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/session/test_session.py +0 -0
  325. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/test_database_name_alias.py +0 -0
  326. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/test_db_functions.py +0 -0
  327. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/test_model_cls_refactor.py +0 -0
  328. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/test_no_blocking_asyncpg_tls.py +0 -0
  329. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/test_one_database.py +0 -0
  330. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/test_secrets_battery.py +0 -0
  331. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/test_sql_param_casts.py +0 -0
  332. {matrx_orm-3.1.69 → matrx_orm-3.1.71}/tests/test_sync_twins_guard.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: matrx-orm
3
- Version: 3.1.69
3
+ Version: 3.1.71
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.13
28
+ Requires-Dist: matrx-utils>=2.0.14
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
@@ -55,8 +55,24 @@ Pinned by `tests/level1/test_pool_maintenance.py`.
55
55
 
56
56
  Verified against code: 2026-08-13.
57
57
 
58
+ ## Transaction-pooled role scope
59
+
60
+ **A restricted role is always transaction-local.** `rls_session()` opens the
61
+ outermost `transaction()` before it sets JWT claims with
62
+ `set_config(..., true)` and issues `SET LOCAL ROLE`. Success and early return
63
+ commit; exceptions roll back; cancellation-shielded teardown finishes before
64
+ the connection returns to the pool. No path can leave `authenticated` on a
65
+ reused server connection.
66
+
67
+ Pinned by `tests/level1/test_rls_session_scope.py` and
68
+ `tests/level1/test_connection_poison_guard.py`.
69
+
70
+ Verified against code: 2026-08-15.
71
+
58
72
  ## Change log
59
73
 
74
+ - 2026-08-15: Pinned transaction-local RLS role cleanup across success,
75
+ exception, and early-return paths.
60
76
  - 2026-08-14: Public models now render `public.table` SQL targets; bare public
61
77
  relation names can no longer disable application logs or write-failure capture.
62
78
  - 2026-08-13: Registry, admin, recovery, catalog, and diagnostic identities are now exact `schema.table`; bare names are accepted only as uncached discovery terms and ambiguity fails loudly.
@@ -11,6 +11,14 @@ remain fast. A large reconciliation, export, or historical scan must call
11
11
  merges pending session state, but it does not insert every result into the
12
12
  process identity cache.
13
13
 
14
+ Hydration of 200 or more rows runs in a worker thread. Model construction,
15
+ relationship attachment, and identity-cache insertion are synchronous Python
16
+ work and must not monopolize an API event loop for a large result set. Complete
17
+ primary-key cache misses are O(1): after the direct dictionary lookup misses,
18
+ the state manager never scans the cache for an identity it already knows is
19
+ absent. Historical/request-local scans should still use `use_cache=False` so
20
+ they do not grow the process cache with rows that will not be reused.
21
+
14
22
  `Model.all(use_cache=False)` exposes the same behavior. The default remains
15
23
  `True` for compatibility. The cache bypass controls only cache population; it
16
24
  does not weaken database authorization, filters, hydration, or transaction
@@ -23,3 +31,8 @@ inherits the model query's default `*` projection. A grouped aggregate with no
23
31
  explicit `.values(...)` projects the grouped columns plus its aggregate
24
32
  expressions. These shapes keep every generated aggregate valid in PostgreSQL
25
33
  without forcing callers to add a redundant projection.
34
+
35
+ ## Change log
36
+
37
+ - 2026-08-15 — Moved bulk hydration off the event loop, made complete-primary-key
38
+ misses constant-time, and documented cache bypass for request-local scans.
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import asyncio
3
4
  import json
4
5
  import re
5
6
  from types import NotImplementedType
@@ -24,6 +25,11 @@ if TYPE_CHECKING:
24
25
 
25
26
  debug = False
26
27
 
28
+ # Model hydration is synchronous Python work. Small result sets stay inline;
29
+ # large sets move to a worker thread so one read cannot freeze every coroutine
30
+ # on the process event loop.
31
+ _BULK_HYDRATION_THREAD_THRESHOLD = 200
32
+
27
33
  _SKIP_PARAM = object()
28
34
 
29
35
  _PARAM_RE = re.compile(r"\$(\d+)")
@@ -264,6 +270,9 @@ class QueryExecutor:
264
270
  hydrate = getattr(self.model, "_hydrate", None)
265
271
  return hydrate(row) if hydrate is not None else self.model(**row)
266
272
 
273
+ def _hydrate_rows(self, rows: list[dict[str, Any]]) -> list[Any]:
274
+ return [self._make(row) for row in rows]
275
+
267
276
  def _decode_row_dict(self, row: dict[str, Any]) -> dict[str, Any]:
268
277
  """Apply field ``from_db_value`` so ``.values()`` matches Model hydration.
269
278
 
@@ -1521,8 +1530,12 @@ class QueryExecutor:
1521
1530
  return []
1522
1531
  select_related = self._full_query_dict.get("select_related", [])
1523
1532
  if select_related:
1533
+ if len(results) >= _BULK_HYDRATION_THREAD_THRESHOLD:
1534
+ return await asyncio.to_thread(self._hydrate_with_select_related, results)
1524
1535
  return self._hydrate_with_select_related(results)
1525
- return [self._make(row) for row in results]
1536
+ if len(results) >= _BULK_HYDRATION_THREAD_THRESHOLD:
1537
+ return await asyncio.to_thread(self._hydrate_rows, results)
1538
+ return self._hydrate_rows(results)
1526
1539
 
1527
1540
  async def first(self) -> Any:
1528
1541
  """Fetch the first matching row as a model instance."""
@@ -154,6 +154,14 @@ class ModelState:
154
154
  original_error=e,
155
155
  ) from e
156
156
 
157
+ # A complete primary-key lookup has exactly one possible
158
+ # cache slot. If that direct key missed (or was stale), a
159
+ # full scan cannot find a different valid match. Falling
160
+ # through to _find_in_cache made cache_bulk O(n²): every new
161
+ # row scanned every row already cached for the model.
162
+ if cache_key is not None:
163
+ return None
164
+
157
165
  # Try finding by criteria if direct lookup fails
158
166
  try:
159
167
  cached_record = self._find_in_cache(**kwargs)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "matrx-orm"
3
- version = "3.1.69"
3
+ version = "3.1.71"
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.13",
44
+ "matrx-utils>=2.0.14",
45
45
  "pyyaml>=6.0.3",
46
46
  "python-dotenv>=1.0",
47
47
  "cryptography>=43.0",
@@ -0,0 +1,38 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import threading
5
+
6
+ import pytest
7
+
8
+ from matrx_orm.query.executor import (
9
+ _BULK_HYDRATION_THREAD_THRESHOLD,
10
+ QueryExecutor,
11
+ )
12
+
13
+
14
+ @pytest.mark.asyncio
15
+ async def test_large_result_hydration_runs_off_the_event_loop() -> None:
16
+ loop_thread = threading.get_ident()
17
+ hydration_threads: list[int] = []
18
+
19
+ class ModelStub:
20
+ @staticmethod
21
+ def _hydrate(row):
22
+ hydration_threads.append(threading.get_ident())
23
+ return row
24
+
25
+ executor = object.__new__(QueryExecutor)
26
+ executor.model = ModelStub
27
+ executor._full_query_dict = {}
28
+ rows = [{"id": index} for index in range(_BULK_HYDRATION_THREAD_THRESHOLD)]
29
+
30
+ async def execute():
31
+ await asyncio.sleep(0)
32
+ return rows
33
+
34
+ executor._execute = execute
35
+
36
+ assert await executor.all() == rows
37
+ assert hydration_threads
38
+ assert loop_thread not in hydration_threads
@@ -77,8 +77,8 @@ class TestStrictGuard:
77
77
  M.assert_managed_write_allowed("INSERT INTO public.cx_message (id) VALUES ($1)")
78
78
 
79
79
  def test_same_bare_name_in_another_schema_does_not_match(self):
80
- M._STRICT_TABLES.add("chat.message")
81
- M.assert_managed_write_allowed("UPDATE public.message SET x=1")
80
+ M._STRICT_TABLES.add("agent.definition")
81
+ M.assert_managed_write_allowed("UPDATE tool.definition SET x=1")
82
82
 
83
83
  def test_quoted_qualified_target_matches_exact_key(self):
84
84
  M._STRICT_TABLES.add("chat.message")
@@ -0,0 +1,103 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ import pytest
6
+
7
+ from matrx_orm.adapters import AdapterRegistry
8
+ from matrx_orm.core.rls_session import rls_session
9
+
10
+
11
+ class _Connection:
12
+ def __init__(self) -> None:
13
+ self.calls: list[tuple[str, tuple[Any, ...]]] = []
14
+ self.terminated = False
15
+
16
+ async def execute(self, sql: str, *args: Any) -> None:
17
+ self.calls.append((sql, args))
18
+
19
+ def terminate(self) -> None:
20
+ self.terminated = True
21
+
22
+
23
+ class _ConnectionContext:
24
+ def __init__(self, conn: _Connection) -> None:
25
+ self.conn = conn
26
+ self.exited = False
27
+
28
+ async def __aenter__(self) -> _Connection:
29
+ return self.conn
30
+
31
+ async def __aexit__(self, *_exc: Any) -> None:
32
+ self.exited = True
33
+
34
+
35
+ class _Adapter:
36
+ def __init__(self, conn: _Connection) -> None:
37
+ self.context = _ConnectionContext(conn)
38
+
39
+ def get_connection(self) -> _ConnectionContext:
40
+ return self.context
41
+
42
+
43
+ def _install_adapter(monkeypatch: pytest.MonkeyPatch) -> tuple[_Connection, _Adapter]:
44
+ conn = _Connection()
45
+ adapter = _Adapter(conn)
46
+ monkeypatch.setattr(AdapterRegistry, "get", lambda _database: adapter)
47
+ return conn, adapter
48
+
49
+
50
+ @pytest.mark.asyncio
51
+ async def test_rls_session_commits_transaction_local_role(monkeypatch: pytest.MonkeyPatch) -> None:
52
+ conn, adapter = _install_adapter(monkeypatch)
53
+
54
+ async with rls_session(
55
+ {"sub": "user-id", "role": "authenticated"},
56
+ role="authenticated",
57
+ database="test",
58
+ ):
59
+ pass
60
+
61
+ assert [sql for sql, _args in conn.calls] == [
62
+ "BEGIN",
63
+ "select set_config('request.jwt.claims', $1, true)",
64
+ "SET LOCAL statement_timeout = 30000",
65
+ "SET LOCAL ROLE authenticated",
66
+ "COMMIT",
67
+ ]
68
+ assert adapter.context.exited is True
69
+ assert conn.terminated is False
70
+
71
+
72
+ @pytest.mark.asyncio
73
+ async def test_rls_session_rolls_back_on_exception(monkeypatch: pytest.MonkeyPatch) -> None:
74
+ conn, adapter = _install_adapter(monkeypatch)
75
+
76
+ with pytest.raises(LookupError):
77
+ async with rls_session(
78
+ {"sub": "user-id", "role": "authenticated"},
79
+ role="authenticated",
80
+ database="test",
81
+ ):
82
+ raise LookupError("abort")
83
+
84
+ assert conn.calls[-1][0] == "ROLLBACK"
85
+ assert all(sql != "COMMIT" for sql, _args in conn.calls)
86
+ assert adapter.context.exited is True
87
+
88
+
89
+ @pytest.mark.asyncio
90
+ async def test_rls_session_early_return_still_closes_scope(monkeypatch: pytest.MonkeyPatch) -> None:
91
+ conn, adapter = _install_adapter(monkeypatch)
92
+
93
+ async def return_from_inside_scope() -> str:
94
+ async with rls_session(
95
+ {"sub": "user-id", "role": "authenticated"},
96
+ role="authenticated",
97
+ database="test",
98
+ ):
99
+ return "done"
100
+
101
+ assert await return_from_inside_scope() == "done"
102
+ assert conn.calls[-1][0] == "COMMIT"
103
+ assert adapter.context.exited is True
@@ -176,6 +176,17 @@ class TestStaleness:
176
176
 
177
177
 
178
178
  class TestFindInCache:
179
+ def test_complete_primary_key_miss_never_scans_the_whole_cache(self):
180
+ M = _make_model("FICPK")
181
+ state = ModelState(M)
182
+ _run(state.cache(M(id=str(uuid4()), name="cached")))
183
+
184
+ def fail_if_scanned(**_kwargs):
185
+ raise AssertionError("complete PK misses must stay O(1)")
186
+
187
+ state._find_in_cache = fail_if_scanned
188
+ assert _run(state.get(id=str(uuid4()))) is None
189
+
179
190
  def test_find_by_criteria(self):
180
191
  M = _make_model("FIC")
181
192
  state = ModelState(M)
File without changes
File without changes
File without changes
File without changes
File without changes