matrx-orm 3.1.76__tar.gz → 3.1.77__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/CLAUDE.md +1 -1
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/PKG-INFO +3 -2
- matrx_orm-3.1.77/matrx_orm/admin/FEATURE.md +23 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/admin/router.py +50 -15
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/pyproject.toml +3 -2
- matrx_orm-3.1.77/tests/level1/test_admin_response_rendering.py +61 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/.gitignore +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/AGENTS.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/BASE_CLASS_METHODS.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/MODEL_API.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/README.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/database/orm/extended/managers/ai_model_base.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/docs/migrations.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/MODULE_README.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/adapters/MODULE_README.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/adapters/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/adapters/async_postgresql.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/adapters/base_adapter.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/adapters/postgresql.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/adapters/postgrest_client_adapter.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/adapters/supabase_adapter.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/admin/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/api/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/api/auth.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/api/config.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/api/handlers.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/api/protocol.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/api/server.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/associations.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/cache_debug.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/catalog.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/catalog_sql.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/client/MODULE_README.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/client/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/client/postgres_connection.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/client/postgrest.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/client/supabase_auth.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/client/supabase_config.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/client/supabase_manager.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/EXTENDED-TASK.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/FEATURE.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/MODULE_README.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/RELATIONS-TASKS.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/TASKS.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/async_db_manager.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/base.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/config.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/connections.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/db_function.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/diagnostics.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/expressions.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/extended.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/fields.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/introspection.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/listen.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/loop_filters.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/model_dto.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/model_view.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/one_database.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/paginator.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/pool_maintenance.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/pool_watch.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/pooler_role.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/pydantic_bridge.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/registry.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/relations.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/resilience.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/rls_session.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/signals.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/tls.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/transaction.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/types.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/core/write_queue.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/entity.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/error_handling.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/exceptions.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/extended/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/extended/app_error_handler.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/identity_rule.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/middleware/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/middleware/base.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/migrations/MODULE_README.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/migrations/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/migrations/cli.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/migrations/ddl.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/migrations/diff.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/migrations/executor.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/migrations/integration.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/migrations/loader.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/migrations/operations.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/migrations/state.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/migrations/table_filter.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/operations/MODULE_README.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/operations/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/operations/bulk_update_values.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/operations/conflict.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/operations/conflict_writes.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/operations/create.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/operations/db_functions.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/operations/delete.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/operations/dynamic_admin.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/operations/dynamic_crud.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/operations/graph_walk.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/operations/latest_rows.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/operations/queue_claim.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/operations/read.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/operations/relational_backfill.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/operations/staging_load.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/operations/update.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/platform_db.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/py.typed +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/python_sql/MODULE_README.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/python_sql/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/python_sql/db_objects.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/python_sql/table_detailed_relationships.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/python_sql/table_typescript_relationship.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/query/FEATURE.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/query/MODULE_README.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/query/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/query/builder.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/query/executor.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/FEATURE.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/MODULE_README.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/code_handler.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/codegen_writer.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/columns.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/common.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/diff_preview.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/entity_capabilities.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/generator.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/helpers/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/helpers/base_generators.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/helpers/entity_generators.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/helpers/git_checker.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/package_wiring.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/relationships.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/runner.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/schema.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/schema_manager.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/tables.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/schema_builder/views.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/secrets_battery/FEATURE.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/secrets_battery/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/secrets_battery/attachments.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/secrets_battery/crypto.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/secrets_battery/items.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/secrets_battery/model.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/secrets_battery/org_service.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/secrets_battery/service.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/session/README.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/session/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/session/coalesce.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/session/dag.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/session/errors.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/session/fallback.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/session/flush.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/session/lifecycle.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/session/managed.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/session/op.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/session/reads.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/session/session.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/session/telemetry.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/sql_executor/MODULE_README.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/sql_executor/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/sql_executor/executor.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/sql_executor/queries.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/sql_executor/registry.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/sql_executor/types.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/sql_executor/utils.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/state.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/utils/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/utils/sql_utils.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/matrx_orm/utils/type_converters.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/scripts/git-branches.sh +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/scripts/publish.sh +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/scripts/release.sh +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/MODULE_README.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/conftest.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/MODULE_README.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_admin_db_columns.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_admin_search_negation.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_admin_search_sentinels.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_advisory_lock.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_agent_message.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_api_auth.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_api_config.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_api_handlers.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_api_protocol.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_array_agg_order_by.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_associations.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_bulk_hydration_offload.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_bulk_update_by_pk.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_bulk_upsert_increment_set_fields.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_cache_debug.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_call_function.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_case_when.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_catalog.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_composite_pk_filter.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_composite_pk_write_paths.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_config.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_conflict_target.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_conflict_writes.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_connection_codecs.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_connection_poison_guard.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_connection_primitives.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_count_composite_distinct.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_db_function_field.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_ddl_generator.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_derived_table.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_dirty_tracking.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_dynamic_crud.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_exceptions.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_execute_query_integrity_mapping.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_expression_primitives.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_fields.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_filter_jsonb_agg_array_index.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_from_alias.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_fts.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_func_expression_args.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_graph_walk.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_having_annotate_alias.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_insert_ignore_and_admin_primitives.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_introspect_rls_policies.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_join_and_aggregate.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_latest_rows.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_listen_notify.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_managed_write_guard.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_matrx_entity.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_migration_diff_types.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_migration_loader.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_model_instance.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_model_meta.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_optimistic_concurrency.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_order_by_expression.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_parameter_name_hydration.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_patch_jsonb_path.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_pool_holder_census.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_pool_loop_recreation.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_pool_maintenance.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_postgrest_filters.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_pydantic_bridge.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_query_builder.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_query_error_detail.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_query_executor_sql.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_query_timeout.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_querybuilder_clone_semantics.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_queue_claim.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_registry.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_registry_multi_database.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_registry_multi_schema.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_relational_backfill.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_relations.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_resilience.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_rls_session_scope.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_schema_exists.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_session_advisory_lock.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_state_cache.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_subquery_filter_raw.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_subquery_in_filter.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_supabase_auth.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_supabase_config.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_tls.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_typed_join_projection.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_typed_predicates.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_update_case_expression.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_update_subquery.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_update_with_rebase.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_upsert_default_leak.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_upsert_with_conflict.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_values_jsonb_decode.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_watched_lifecycle.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level1/test_write_retry_semantics.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level2/MODULE_README.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level2/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level2/conftest.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level2/test_bulk_ops.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level2/test_cache_integration.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level2/test_crud.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level2/test_foreign_keys.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level2/test_m2m.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level2/test_manager.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level2/test_migrations_live.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level2/test_query_execution.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/level2/test_schema_diff.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/live_pooler_role.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/sample_project/.env.example +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/sample_project/README.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/sample_project/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/sample_project/generate.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/sample_project/generated/.gitkeep +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/sample_project/matrx_orm.yaml +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/sample_project/test_schema_generation.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/sample_project_desktop/.env.example +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/sample_project_desktop/README.md +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/sample_project_desktop/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/sample_project_desktop/client_example.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/sample_project_desktop/client_example.ts +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/sample_project_desktop/client_supabase_example.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/sample_project_desktop/server.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/schema/entity_tests.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/schema/test_base_generation.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/schema/test_composite_pk_fk_generation.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/schema/test_composite_unique_generation.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/schema/test_dto_identity_generation.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/schema/test_entity_capability_generation.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/schema/test_generate_schema.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/schema/test_junction_analysis.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/schema/test_multi_schema_output.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/schema/test_sql_expression_defaults.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/schema/test_table_relationships_query.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/schema/test_view_generation.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/schema_builder/test_array_default_parsing.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/schema_builder/test_focused_generation_plan.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/schema_builder/test_host_models_aggregator.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/session/__init__.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/session/conftest.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/session/test_cache_no_downgrade.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/session/test_capture_poison_proof.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/session/test_coalesce.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/session/test_dag.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/session/test_disk_spill_fallback.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/session/test_flush_individual_fallback.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/session/test_governed_write.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/session/test_managed.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/session/test_op_enqueue_site.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/session/test_reads.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/session/test_session.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/test_database_name_alias.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/test_db_functions.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/test_model_cls_refactor.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/test_no_blocking_asyncpg_tls.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/test_one_database.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/test_pooler_role_guard.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/test_secrets_battery.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/test_sql_param_casts.py +0 -0
- {matrx_orm-3.1.76 → matrx_orm-3.1.77}/tests/test_sync_twins_guard.py +0 -0
|
@@ -39,7 +39,7 @@ Every table that becomes a Model needs row identity: a single-column primary key
|
|
|
39
39
|
models do not quadratically populate the process identity cache. Contract:
|
|
40
40
|
[`matrx_orm/query/FEATURE.md`](matrx_orm/query/FEATURE.md).
|
|
41
41
|
- **Migrations**: `MigrationDB`, `MigrationLoader`, `MigrationExecutor`, `makemigrations`, `migrate` — migrations declare explicit `dependencies` and apply in topological order (no multi-head/merge support yet).
|
|
42
|
-
- **Admin router** (FastAPI): `admin_router` exposes read/write endpoints for any registered model.
|
|
42
|
+
- **Admin router** (FastAPI): `admin_router` exposes read/write endpoints for any registered model; bulk response rendering stays off the event loop. Contract: [`matrx_orm/admin/FEATURE.md`](matrx_orm/admin/FEATURE.md).
|
|
43
43
|
- **API layer** (optional `[api]` extra): `APIServer`, `APIConfig`, `TokenAuth`.
|
|
44
44
|
- **Adapters**: `AsyncPostgreSQLAdapter`, `SupabaseAdapter`, `PostgRESTClientAdapter`.
|
|
45
45
|
- **Signals**: `pre_create`, `post_create`, `pre_save`, `post_save`, `pre_delete`, `post_delete`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: matrx-orm
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.77
|
|
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,13 +25,14 @@ Requires-Python: >=3.13
|
|
|
25
25
|
Requires-Dist: asyncpg>=0.31.0
|
|
26
26
|
Requires-Dist: cryptography>=43.0
|
|
27
27
|
Requires-Dist: gitpython>=3.1.40
|
|
28
|
-
Requires-Dist: matrx-utils>=2.0.
|
|
28
|
+
Requires-Dist: matrx-utils>=2.0.18
|
|
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
|
|
32
32
|
Requires-Dist: pyyaml>=6.0.3
|
|
33
33
|
Provides-Extra: admin
|
|
34
34
|
Requires-Dist: fastapi>=0.115; extra == 'admin'
|
|
35
|
+
Requires-Dist: orjson>=3.10; extra == 'admin'
|
|
35
36
|
Provides-Extra: api
|
|
36
37
|
Requires-Dist: aiohttp>=3.9.0; extra == 'api'
|
|
37
38
|
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Admin router
|
|
2
|
+
|
|
3
|
+
`router.py` exposes model-registry CRUD and cache operations through the optional
|
|
4
|
+
FastAPI admin surface.
|
|
5
|
+
|
|
6
|
+
## Response rendering
|
|
7
|
+
|
|
8
|
+
- **Bulk row rendering never runs on the event loop.** `list_rows` passes row
|
|
9
|
+
serialization and JSON encoding through `_render_list_rows_response`, which
|
|
10
|
+
offloads the CPU-bound work with `asyncio.to_thread`; `orjson` bounds the
|
|
11
|
+
GIL-held encoding section.
|
|
12
|
+
- **Keep both list aliases.** `data` and `rows` contain the same serialized rows;
|
|
13
|
+
admin clients use both shapes during compatibility transitions.
|
|
14
|
+
- **The page cap is 2,000 rows.** Keep `ADMIN_LIST_MAX_PAGE_SIZE` aligned with the
|
|
15
|
+
dashboard constant in `orm-proxy.ts`.
|
|
16
|
+
|
|
17
|
+
Verified against `router.py` and
|
|
18
|
+
`tests/level1/test_admin_response_rendering.py` on 2026-08-17.
|
|
19
|
+
|
|
20
|
+
## Change Log
|
|
21
|
+
|
|
22
|
+
- 2026-08-17 — Moved bulk row serialization and JSON encoding off the event
|
|
23
|
+
loop after a 1.1-second production stall.
|
|
@@ -24,6 +24,7 @@ Effective routes (relative to the mount prefix):
|
|
|
24
24
|
|
|
25
25
|
from __future__ import annotations
|
|
26
26
|
|
|
27
|
+
import asyncio
|
|
27
28
|
import base64
|
|
28
29
|
import binascii
|
|
29
30
|
import json
|
|
@@ -32,7 +33,8 @@ import math
|
|
|
32
33
|
import re
|
|
33
34
|
from typing import Any
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
import orjson
|
|
37
|
+
from fastapi import APIRouter, HTTPException, Query, Request, Response
|
|
36
38
|
from fastapi.responses import JSONResponse
|
|
37
39
|
|
|
38
40
|
from matrx_orm.core.expressions import Q
|
|
@@ -113,6 +115,46 @@ def _serialize(instance: Any) -> dict[str, Any]:
|
|
|
113
115
|
return complete
|
|
114
116
|
|
|
115
117
|
|
|
118
|
+
def _build_list_rows_response(
|
|
119
|
+
items: list[Any],
|
|
120
|
+
*,
|
|
121
|
+
total_count: int,
|
|
122
|
+
page: int,
|
|
123
|
+
page_size: int,
|
|
124
|
+
) -> Response:
|
|
125
|
+
data = [_serialize(row) for row in items]
|
|
126
|
+
total_pages = math.ceil(total_count / page_size) if page_size > 0 else 0
|
|
127
|
+
return Response(
|
|
128
|
+
content=orjson.dumps(
|
|
129
|
+
{
|
|
130
|
+
"data": data,
|
|
131
|
+
"rows": data,
|
|
132
|
+
"total": total_count,
|
|
133
|
+
"page": page,
|
|
134
|
+
"page_size": page_size,
|
|
135
|
+
"total_pages": total_pages,
|
|
136
|
+
}
|
|
137
|
+
),
|
|
138
|
+
media_type="application/json",
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
async def _render_list_rows_response(
|
|
143
|
+
items: list[Any],
|
|
144
|
+
*,
|
|
145
|
+
total_count: int,
|
|
146
|
+
page: int,
|
|
147
|
+
page_size: int,
|
|
148
|
+
) -> Response:
|
|
149
|
+
return await asyncio.to_thread(
|
|
150
|
+
_build_list_rows_response,
|
|
151
|
+
items,
|
|
152
|
+
total_count=total_count,
|
|
153
|
+
page=page,
|
|
154
|
+
page_size=page_size,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
|
|
116
158
|
def _decode_row_id(model: type, row_id: str) -> str | dict[str, Any]:
|
|
117
159
|
primary_keys = list(model._meta.primary_keys or ())
|
|
118
160
|
if len(primary_keys) <= 1:
|
|
@@ -605,7 +647,7 @@ async def list_rows(
|
|
|
605
647
|
sort_dir: str = Query("asc", pattern="^(asc|desc)$"),
|
|
606
648
|
search: str | None = Query(None, description="Column filters as 'col1:val1,col2:val2'"),
|
|
607
649
|
schema: str | None = Query(None, description="PostgreSQL schema name"),
|
|
608
|
-
) ->
|
|
650
|
+
) -> Response:
|
|
609
651
|
model = _require_model(table_name, schema)
|
|
610
652
|
log.info(
|
|
611
653
|
"list_rows: table=%s page=%d size=%d sort_by=%s sort_dir=%s search=%s",
|
|
@@ -629,25 +671,18 @@ async def list_rows(
|
|
|
629
671
|
paginator = Paginator(qb, per_page=page_size)
|
|
630
672
|
# page() is 1-based; our API uses 0-based pages
|
|
631
673
|
page_obj = await paginator.page(page + 1)
|
|
632
|
-
data = [_serialize(row) for row in page_obj.items]
|
|
633
|
-
total_pages = math.ceil(page_obj.total_count / page_size) if page_size > 0 else 0
|
|
634
|
-
|
|
635
674
|
log.info(
|
|
636
675
|
"list_rows: %s returned %d rows (total %d)",
|
|
637
676
|
table_name,
|
|
638
|
-
len(
|
|
677
|
+
len(page_obj.items),
|
|
639
678
|
page_obj.total_count,
|
|
640
679
|
)
|
|
641
680
|
|
|
642
|
-
return
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
"page": page,
|
|
648
|
-
"page_size": page_size,
|
|
649
|
-
"total_pages": total_pages,
|
|
650
|
-
}
|
|
681
|
+
return await _render_list_rows_response(
|
|
682
|
+
page_obj.items,
|
|
683
|
+
total_count=page_obj.total_count,
|
|
684
|
+
page=page,
|
|
685
|
+
page_size=page_size,
|
|
651
686
|
)
|
|
652
687
|
|
|
653
688
|
except ValueError:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "matrx-orm"
|
|
3
|
-
version = "3.1.
|
|
3
|
+
version = "3.1.77"
|
|
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.
|
|
44
|
+
"matrx-utils>=2.0.18",
|
|
45
45
|
"pyyaml>=6.0.3",
|
|
46
46
|
"python-dotenv>=1.0",
|
|
47
47
|
"cryptography>=43.0",
|
|
@@ -59,6 +59,7 @@ api = [
|
|
|
59
59
|
]
|
|
60
60
|
admin = [
|
|
61
61
|
"fastapi>=0.115",
|
|
62
|
+
"orjson>=3.10",
|
|
62
63
|
]
|
|
63
64
|
|
|
64
65
|
[project.scripts]
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import importlib
|
|
5
|
+
import json
|
|
6
|
+
import time
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
|
|
10
|
+
admin_router = importlib.import_module("matrx_orm.admin.router")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class _Row:
|
|
14
|
+
def __init__(self, row_id: int) -> None:
|
|
15
|
+
self.row_id = row_id
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_build_list_rows_response_preserves_admin_envelope(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
19
|
+
monkeypatch.setattr(admin_router, "_serialize", lambda row: {"id": row.row_id})
|
|
20
|
+
|
|
21
|
+
response = admin_router._build_list_rows_response(
|
|
22
|
+
[_Row(1), _Row(2)],
|
|
23
|
+
total_count=5,
|
|
24
|
+
page=1,
|
|
25
|
+
page_size=2,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
payload = json.loads(response.body)
|
|
29
|
+
assert payload == {
|
|
30
|
+
"data": [{"id": 1}, {"id": 2}],
|
|
31
|
+
"rows": [{"id": 1}, {"id": 2}],
|
|
32
|
+
"total": 5,
|
|
33
|
+
"page": 1,
|
|
34
|
+
"page_size": 2,
|
|
35
|
+
"total_pages": 3,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@pytest.mark.asyncio
|
|
40
|
+
async def test_render_list_rows_response_keeps_event_loop_responsive(
|
|
41
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
42
|
+
) -> None:
|
|
43
|
+
def slow_serialize(row: _Row) -> dict[str, int]:
|
|
44
|
+
time.sleep(0.05)
|
|
45
|
+
return {"id": row.row_id}
|
|
46
|
+
|
|
47
|
+
monkeypatch.setattr(admin_router, "_serialize", slow_serialize)
|
|
48
|
+
render_task = asyncio.create_task(
|
|
49
|
+
admin_router._render_list_rows_response(
|
|
50
|
+
[_Row(1)],
|
|
51
|
+
total_count=1,
|
|
52
|
+
page=0,
|
|
53
|
+
page_size=25,
|
|
54
|
+
)
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
await asyncio.sleep(0.01)
|
|
58
|
+
|
|
59
|
+
assert not render_task.done()
|
|
60
|
+
response = await render_task
|
|
61
|
+
assert json.loads(response.body)["data"] == [{"id": 1}]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|