quadkit-sql 0.0.44__tar.gz → 0.0.46__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.
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/PKG-INFO +6 -6
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/README.md +1 -1
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/pyproject.toml +5 -5
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/__init__.py +2 -0
- quadkit_sql-0.0.46/src/quadkit/sql/admin/registration.py +84 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/generators/database_repository.py +12 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/generators/service.py +28 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/templates/database_repository.py.jinja2 +50 -18
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/templates/entity_migration.py.jinja2 +3 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/templates/entity_model.py.jinja2 +5 -1
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/templates/health_check.py.jinja2 +6 -1
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/templates/seeder.py.jinja2 +6 -1
- quadkit_sql-0.0.46/src/quadkit/sql/cli/templates/service.py.jinja2 +159 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/di/_registration.py +56 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/di/provider.py +29 -22
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/migrations/introspector.py +23 -3
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/migrations/runner.py +31 -8
- quadkit_sql-0.0.46/src/quadkit/sql/orm/__init__.py +14 -0
- quadkit_sql-0.0.46/src/quadkit/sql/orm/executor.py +98 -0
- quadkit_sql-0.0.46/src/quadkit/sql/orm/session.py +180 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/outbox/publisher.py +70 -5
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/outbox/store.py +17 -1
- quadkit_sql-0.0.46/src/quadkit/sql/pool/engine.py +321 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/providers/base_provider.py +0 -14
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/providers/crud_operations.py +9 -11
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/cli/test_repository_generator_staged.py +38 -0
- quadkit_sql-0.0.46/tests/unit/cli/test_service_generator.py +116 -0
- quadkit_sql-0.0.46/tests/unit/migrations/test_pending_on_unstamped_database.py +126 -0
- quadkit_sql-0.0.46/tests/unit/outbox/test_outbox_transactional_relay.py +165 -0
- quadkit_sql-0.0.46/tests/unit/test_engine_pool.py +148 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_generic_repository_mapping.py +33 -6
- quadkit_sql-0.0.46/tests/unit/test_orm_session_factory.py +156 -0
- quadkit_sql-0.0.44/src/quadkit/sql/cli/templates/service.py.jinja2 +0 -104
- quadkit_sql-0.0.44/tests/unit/cli/test_service_generator.py +0 -29
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/.gitignore +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/LICENSE +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/NOTICE +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/alembic.ini +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/example.yaml +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/py.typed +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/abstractions/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/abstractions/connection.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/abstractions/py.typed +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/admin/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/admin/audit_store.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/admin/contributor.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/admin/handlers/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/admin/handlers/migration_status.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/admin/handlers/pool_utilization.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/admin/handlers/query_stats.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/admin/pages/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/admin/pages/migrations.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/admin/pages/overview.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/admin/pages/queries.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/admin/widgets/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/api/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/api/engine.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/api/protocols.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/audit/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/audit/mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/audit/py.typed +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/backends/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/backends/_postgres_connection.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/backends/_ssl.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/backends/cockroachdb.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/backends/mysql/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/backends/mysql/_connection.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/backends/mysql/_pool.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/backends/mysql/_shims.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/backends/postgres.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/backends/py.typed +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/backends/sqlite/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/backends/sqlite/_connection.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/backends/sqlite/_pool.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/backends/sqlite/_shims.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/backup/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/backup/backup_manager.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/backup/maintenance.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/backup/py.typed +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/checks.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/commands.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/contributor.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/doctor.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/generators/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/generators/base.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/generators/entity_migration.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/generators/entity_model.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/generators/filter.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/generators/health_check.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/generators/seeder.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/generators/type_map.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/manager.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/shell.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/templates/filter.py.jinja2 +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/config.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/constants.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/context/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/context/db_context.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/context/keys.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/context/manager.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/context/tasks.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/decorators.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/di/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/di/py.typed +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/events.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/exceptions.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/hooks.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/identifiers.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/lib/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/lib/helpers.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/lib/retry.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/logging/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/logging/loggers.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/managers/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/managers/manager.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/mappers/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/mappers/base.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/mappers/domain_mapper.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/mappers/py.typed +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/middleware/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/middleware/base.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/middleware/builtins.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/middleware/models.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/middleware/pipeline.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/migrations/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/migrations/api.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/migrations/base.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/migrations/engine.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/migrations/generator.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/migrations/manager/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/migrations/manager/_alembic.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/migrations/manager/_simple.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/migrations/model_analyzer.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/migrations/orchestrator.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/migrations/py.typed +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/migrations/types.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/module.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/monitoring/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/monitoring/database_monitor/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/monitoring/database_monitor/facade.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/monitoring/database_monitor/health.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/monitoring/database_monitor/pool.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/monitoring/database_monitor/query.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/monitoring/database_monitor/transaction.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/monitoring/metrics.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/monitoring/py.typed +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/monitoring/query_analyzer.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/orm.pyi +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/outbox/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/pagination/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/pagination/cursor.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/pagination/offset.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/performance/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/performance/batch_processor.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/performance/engine_pragmas.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/performance/statement_cache.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/pool/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/pool/connection.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/pool/py.typed +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/pool/replica.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/protocols.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/providers/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/providers/_connection_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/providers/_health_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/providers/_lazy.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/providers/_query_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/providers/connection_manager.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/providers/database_service.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/providers/health_monitor.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/providers/mysql_provider.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/providers/postgres_provider.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/providers/py.typed +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/providers/query_builder_manager.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/providers/query_executor.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/providers/schema_manager.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/providers/sqlite_provider.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/providers/transaction_manager.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/py.typed +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/query/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/query/_sql_build_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/query/_sql_core_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/query/_sql_join_aggregate_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/query/_sql_where_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/query/admin_builder.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/query/builder.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/query/compiler.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/query/cursor.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/query/operators.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/query/sql_builder.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/query/sql_types.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/repositories/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/repositories/_advanced_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/repositories/_filter_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/repositories/_read_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/repositories/_rls_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/repositories/_write_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/repositories/append_log.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/repositories/base.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/repositories/cached.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/repositories/cursor.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/repositories/decorators.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/repositories/filter_objects.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/repositories/filters.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/repositories/generic_repository.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/repositories/py.typed +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/repositories/scopes.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/resilience/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/resilience/core.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/row_level_security.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/schema/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/schema/descriptors.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/schema/field_types.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/schema/hooks.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/schema/model.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/search/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/search/full_text.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/seeds/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/seeds/api.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/seeds/factory.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/seeds/manager.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/seeds/py.typed +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/specification/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/specification/memory.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/specification/sql.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/storage/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/storage/postgres.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/stores/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/stores/locks.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/stores/secrets.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/stores/state.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/types.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/unit_of_work/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/unit_of_work/base.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/unit_of_work/decorators.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/unit_of_work/identity_map.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/unit_of_work/manager.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/unit_of_work/py.typed +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/unit_of_work/simple/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/unit_of_work/simple/_operations.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/unit_of_work/simple/_uow.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/validation/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/validation/protocols.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/validation/py.typed +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/conftest.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/fixtures/test.db +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/integration/test_add_previous_passwords_migration.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/integration/test_apply_previous_passwords_migration.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/integration/test_migrations.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/integration/test_monitoring_metrics.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/integration/test_monitoring_slow_query.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/integration/test_postgres_provider_lifecycle.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/integration/test_postgres_repository_compliance.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/integration/test_provider_resilience_integration.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/integration/test_sqlite_provider_integration.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/admin/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/admin/handlers/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/admin/handlers/test_migration_status.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/admin/handlers/test_pool_utilization.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/admin/handlers/test_query_stats.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/admin/test_audit_store.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/admin/test_queries_page.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/admin/test_sql_contributor.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/audit/test_audit_repository_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/backends/test_cockroachdb_backend.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/backends/test_postgres_connection.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/cli/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/cli/test_entity_migration_generator.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/cli/test_entity_model_generator.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/cli/test_generators_contract.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/cli/test_health_generator.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/cli/test_type_map.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/context/test_db_context.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/di/test_config_alignment.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/migrations/test_alembic_config_path_separator.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/migrations/test_migration_model_analyzer.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/migrations/test_simple_migration_manager.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/outbox/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/outbox/test_outbox_publisher.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/outbox/test_outbox_store.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/performance/test_batch_processor.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/performance/test_engine_pragmas.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/providers/test_connection_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/providers/test_health_monitor.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/providers/test_query_builder_manager.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/providers/test_query_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/query/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/query/test_async_builder_identifier_safety.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/query/test_core_mixin_dml.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/query/test_join_aggregate_rendering.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/query/test_predicate_compiler.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/query/test_query_operators.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/query/test_sort_whitelist.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/query/test_sql_build_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/query/test_sql_query_builder.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/repositories/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/repositories/test_advanced_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/repositories/test_filter_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/repositories/test_filter_objects.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/repositories/test_read_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/repositories/test_rls_mixin.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/repositories/test_tenant_scoping_read.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/repositories/test_write_mixin_core.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/repositories/test_write_mixin_optimistic.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/repositories/test_write_mixin_tenant_scoping.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/schema/test_descriptors.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/schema/test_field_types.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/stores/test_db_lock_secret_stores.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_api.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_append_log.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_backup_manager.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_backup_models.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_backup_strategy.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_base_provider_pool.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_base_provider_query.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_base_provider_table_exists.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_base_provider_transaction_rollback_logging.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_cached_repository.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_cli_contributor.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_config_quadkit_db.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_connection_lifecycle_regressions.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_connection_pool_base.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_connection_pool_validation.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_crud_json_binding.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_database_maintenance.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_database_monitor_connection_pool.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_database_monitor_facade.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_database_monitor_health.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_database_monitor_health_checker.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_database_monitor_more.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_database_monitor_pool.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_database_monitor_query.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_database_monitor_transactions.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_database_provider.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_database_provider_multi.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_db_constants.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_db_context_propagation.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_db_exceptions.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_db_full_text.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_db_module.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_db_protocols.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_db_query_types.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_db_types.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_domain_mapper.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_domain_mapper_extended.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_domain_mapper_more.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_driver_errors.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_driver_monitoring_integration.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_drivers_smoke.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_exception_hierarchy_scenario.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_exceptions_quadkit_db.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_execute_commit_regression.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_filter_objects.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_generic_repository_counts.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_generic_repository_reads.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_generic_repository_writes.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_identity_map.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_instrumentation_db.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_mappers.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_mappers_base.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_mappers_simple.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_metrics_collector.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_migration_definitions.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_migration_generator.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_migration_generator_extra.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_migration_manager.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_migration_manager_behaviour.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_migration_runner.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_migrations_api.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_migrations_apply_migration.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_migrations_manager.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_migrations_rollback_recording_logs.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_model_analyzer.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_mysql_backend_scenario.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_mysql_driver_connection.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_mysql_driver_health.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_mysql_driver_pool.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_mysql_driver_resilience.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_named_database_config.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_package_hooks_p2.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_package_structure_p0.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_package_structure_p1.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_pool.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_postgres_driver_connection.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_postgres_driver_health.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_postgres_driver_pool.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_postgres_driver_resilience.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_protocol_validation.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_provider_connection.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_provider_health_check_error_logs.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_provider_instrumentation_edgecases.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_provider_resilience.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_provider_scoped_cleanup.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_query.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_query_log_single_emission.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_query_logger_backends.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_query_logger_entry_base.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_query_logger_integration.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_query_middleware.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_redis_lock.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_redis_secrets.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_redis_state.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_replica_pool.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_repository_failures.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_repository_hooks.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_repository_reads.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_repository_uuid_params.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_repository_writes.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_request_context_query_logging.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_resilience.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_round25_hardening.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_round41_hardening.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_schema_model.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_scoped_unit_of_work.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_seed_manager.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_simple_connection_pool.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_simple_transaction_manager.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_smoke_sqlalchemy.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_sort_whitelist.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_specification_identifier_safety.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_specification_memory_scenario.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_sql_config.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_sql_constants.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_sql_exceptions.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_sql_hooks_runtime.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_sql_types.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_sqlite_driver_connection.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_sqlite_driver_detailed.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_sqlite_driver_health.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_sqlite_driver_pool.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_sqlite_driver_resilience.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_sqlite_provider.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_sqlite_provider_fixture.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_sqlite_stale_file.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_statement_cache.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_testing.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_threads_teardown.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_transaction_manager_task_isolation.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_unit_of_work_commit.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_unit_of_work_operations.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_uow_base.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/test_uow_lifecycle_hooks.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/unit_of_work/__init__.py +0 -0
- {quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/tests/unit/unit_of_work/test_uow_outbox.py +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: quadkit-sql
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.46
|
|
4
4
|
Summary: SQL database abstractions for Quadkit Framework — Postgres, MySQL, SQLite with migrations, repositories, and query building
|
|
5
|
-
Project-URL: Homepage, https://
|
|
5
|
+
Project-URL: Homepage, https://oridecon.dev
|
|
6
6
|
Project-URL: Repository, https://github.com/dbtinoy-/quadkit
|
|
7
|
-
Project-URL: Documentation, https://
|
|
7
|
+
Project-URL: Documentation, https://oridecon.dev/quadkit/
|
|
8
8
|
Project-URL: Issues, https://github.com/dbtinoy-/quadkit/issues
|
|
9
9
|
Project-URL: Changelog, https://github.com/dbtinoy-/quadkit/blob/main/CHANGELOG.md
|
|
10
|
-
Author-email: Quadkit Framework Team <
|
|
11
|
-
Maintainer-email: Quadkit Framework Team <
|
|
10
|
+
Author-email: Quadkit Framework Team <hello@oridecon.dev>
|
|
11
|
+
Maintainer-email: Quadkit Framework Team <hello@oridecon.dev>
|
|
12
12
|
License: Apache-2.0
|
|
13
13
|
License-File: LICENSE
|
|
14
14
|
License-File: NOTICE
|
|
@@ -75,7 +75,7 @@ SQL database abstractions for Quadkit Framework — Postgres, MySQL, SQLite with
|
|
|
75
75
|
---
|
|
76
76
|
|
|
77
77
|
|
|
78
|
-
> Full documentation: [
|
|
78
|
+
> Full documentation: [oridecon.dev/quadkit](https://oridecon.dev/quadkit)
|
|
79
79
|
## Install
|
|
80
80
|
|
|
81
81
|
```bash
|
|
@@ -11,7 +11,7 @@ SQL database abstractions for Quadkit Framework — Postgres, MySQL, SQLite with
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
> Full documentation: [
|
|
14
|
+
> Full documentation: [oridecon.dev/quadkit](https://oridecon.dev/quadkit)
|
|
15
15
|
## Install
|
|
16
16
|
|
|
17
17
|
```bash
|
|
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "quadkit-sql"
|
|
9
|
-
version = "0.0.
|
|
9
|
+
version = "0.0.46"
|
|
10
10
|
description = "SQL database abstractions for Quadkit Framework — Postgres, MySQL, SQLite with migrations, repositories, and query building"
|
|
11
11
|
readme = "README.md"
|
|
12
12
|
requires-python = ">=3.11"
|
|
@@ -49,10 +49,10 @@ dependencies = [
|
|
|
49
49
|
"anyio>=4.0.0",
|
|
50
50
|
]
|
|
51
51
|
authors = [
|
|
52
|
-
{ name = "Quadkit Framework Team", email = "
|
|
52
|
+
{ name = "Quadkit Framework Team", email = "hello@oridecon.dev" },
|
|
53
53
|
]
|
|
54
54
|
maintainers = [
|
|
55
|
-
{ name = "Quadkit Framework Team", email = "
|
|
55
|
+
{ name = "Quadkit Framework Team", email = "hello@oridecon.dev" },
|
|
56
56
|
]
|
|
57
57
|
|
|
58
58
|
[project.license]
|
|
@@ -93,9 +93,9 @@ all = [
|
|
|
93
93
|
]
|
|
94
94
|
|
|
95
95
|
[project.urls]
|
|
96
|
-
Homepage = "https://
|
|
96
|
+
Homepage = "https://oridecon.dev"
|
|
97
97
|
Repository = "https://github.com/dbtinoy-/quadkit"
|
|
98
|
-
Documentation = "https://
|
|
98
|
+
Documentation = "https://oridecon.dev/quadkit/"
|
|
99
99
|
Issues = "https://github.com/dbtinoy-/quadkit/issues"
|
|
100
100
|
Changelog = "https://github.com/dbtinoy-/quadkit/blob/main/CHANGELOG.md"
|
|
101
101
|
|
|
@@ -157,6 +157,7 @@ _LAZY_IMPORTS: dict[str, tuple[str, str]] = {
|
|
|
157
157
|
"DatabaseConfig": ("quadkit.sql.config", "DatabaseConfig"),
|
|
158
158
|
"DatabaseError": ("quadkit.sql.exceptions", "DatabaseError"),
|
|
159
159
|
"DatabaseModule": ("quadkit.sql.module", "DatabaseModule"),
|
|
160
|
+
"SessionFactory": ("quadkit.sql.orm.session", "SessionFactory"),
|
|
160
161
|
"DatabaseProvider": ("quadkit.sql.di.provider", "DatabaseProvider"),
|
|
161
162
|
"DatabaseMonitor": ("quadkit.sql.monitoring.database_monitor", "DatabaseMonitor"),
|
|
162
163
|
"DatabaseService": ("quadkit.sql.providers", "DatabaseService"),
|
|
@@ -322,6 +323,7 @@ __all__ = [
|
|
|
322
323
|
"SQLiteProvider",
|
|
323
324
|
"Schema",
|
|
324
325
|
"ScopeColumn",
|
|
326
|
+
"SessionFactory",
|
|
325
327
|
"SimpleConnectionPool",
|
|
326
328
|
"SimpleMigrationManager",
|
|
327
329
|
"SimpleTransactionManager",
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""Public registration of the SQL admin widget handlers.
|
|
2
|
+
|
|
3
|
+
``SqlAdminContributor`` resolves its three widget handlers from the DI
|
|
4
|
+
container in ``on_admin_boot``. The contributor itself is discovered through
|
|
5
|
+
the ``the optional provider module`` entry-point group, so it mounts in *any*
|
|
6
|
+
application that installs ``quadkit-sql`` — including applications that own
|
|
7
|
+
their database provider instead of using
|
|
8
|
+
:class:`~quadkit.sql.di.provider.DatabaseProvider`. Those applications still
|
|
9
|
+
have to register the handlers, or the contributor boots into a
|
|
10
|
+
``UnresolvableDependencyError`` and the Database widgets render nothing.
|
|
11
|
+
|
|
12
|
+
This module owns that registration so it lives in exactly one place: the
|
|
13
|
+
framework provider delegates to it, and applications with their own provider
|
|
14
|
+
call it directly.
|
|
15
|
+
|
|
16
|
+
Example:
|
|
17
|
+
```python
|
|
18
|
+
from quadkit.sql.admin.registration import register_admin_widget_handlers
|
|
19
|
+
|
|
20
|
+
register_admin_widget_handlers(container, db=my_database_provider)
|
|
21
|
+
```
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
from typing import TYPE_CHECKING, Any
|
|
27
|
+
|
|
28
|
+
from quadkit.logging import get_logger
|
|
29
|
+
|
|
30
|
+
if TYPE_CHECKING: # pragma: no cover — typing only
|
|
31
|
+
from quadkit.contracts.core.di import ContainerRegistrarProtocol
|
|
32
|
+
|
|
33
|
+
logger = get_logger(__name__)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def register_admin_widget_handlers(
|
|
37
|
+
container: ContainerRegistrarProtocol,
|
|
38
|
+
*,
|
|
39
|
+
db: Any = None,
|
|
40
|
+
migration_manager: Any = None,
|
|
41
|
+
migration_runner: Any = None,
|
|
42
|
+
) -> None:
|
|
43
|
+
"""Register the SQL admin widget handlers as container singletons.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
container: DI registrar to bind the handlers into.
|
|
47
|
+
db: Database provider exposing ``get_primary_pool()``. ``None`` is
|
|
48
|
+
accepted — the pool widgets then report ``Unavailable`` instead of
|
|
49
|
+
failing, which is the honest answer when no pool is wired.
|
|
50
|
+
migration_manager: Migration manager behind the migration-status
|
|
51
|
+
widget. ``None`` renders the widget as unavailable.
|
|
52
|
+
migration_runner: Optional runner used to compute pending migrations.
|
|
53
|
+
"""
|
|
54
|
+
from quadkit.sql.admin.handlers.migration_status import (
|
|
55
|
+
MigrationStatusWidgetHandler,
|
|
56
|
+
)
|
|
57
|
+
from quadkit.sql.admin.handlers.pool_utilization import (
|
|
58
|
+
PoolUtilizationWidgetHandler,
|
|
59
|
+
)
|
|
60
|
+
from quadkit.sql.admin.handlers.query_stats import QueryStatsWidgetHandler
|
|
61
|
+
|
|
62
|
+
container.singleton(
|
|
63
|
+
PoolUtilizationWidgetHandler,
|
|
64
|
+
lambda: PoolUtilizationWidgetHandler(db=db),
|
|
65
|
+
)
|
|
66
|
+
container.singleton(
|
|
67
|
+
QueryStatsWidgetHandler,
|
|
68
|
+
lambda: QueryStatsWidgetHandler(db=db),
|
|
69
|
+
)
|
|
70
|
+
container.singleton(
|
|
71
|
+
MigrationStatusWidgetHandler,
|
|
72
|
+
lambda: MigrationStatusWidgetHandler(
|
|
73
|
+
migration_manager=migration_manager,
|
|
74
|
+
migration_runner=migration_runner,
|
|
75
|
+
),
|
|
76
|
+
)
|
|
77
|
+
logger.info(
|
|
78
|
+
"sql.admin_widgets_registered",
|
|
79
|
+
pool_widgets=db is not None,
|
|
80
|
+
migration_widget=migration_manager is not None,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
__all__ = ["register_admin_widget_handlers"]
|
{quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/generators/database_repository.py
RENAMED
|
@@ -70,6 +70,18 @@ class DatabaseRepositoryGenerator(GeneratorBase):
|
|
|
70
70
|
),
|
|
71
71
|
key_field=str(options.get("key_field") or "id"),
|
|
72
72
|
needs_datetime=any(f["import_datetime"] for f in fields),
|
|
73
|
+
# The not-found error the repository returns. The built-in
|
|
74
|
+
# default is the contracts family member, so a standalone CLI
|
|
75
|
+
# render behaves exactly as before; an app whose exceptions live
|
|
76
|
+
# in its own module (the generated modular layout) passes the
|
|
77
|
+
# class name and import root — the class is the one named type
|
|
78
|
+
# for the outcome, and R6's one lineage keeps the Result
|
|
79
|
+
# bridge's status mapping uniform.
|
|
80
|
+
not_found_error=str(options.get("not_found_error") or "NotFoundError"),
|
|
81
|
+
exceptions_module=str(
|
|
82
|
+
options.get("exceptions_module") or "quadkit.contracts.exceptions"
|
|
83
|
+
),
|
|
84
|
+
exceptions_first_party=bool(options.get("exceptions_first_party") or False),
|
|
73
85
|
)
|
|
74
86
|
|
|
75
87
|
self.stage(file_path, content)
|
|
@@ -64,6 +64,34 @@ class ServiceGenerator(GeneratorBase):
|
|
|
64
64
|
for field in fields
|
|
65
65
|
],
|
|
66
66
|
}
|
|
67
|
+
context.update(
|
|
68
|
+
{
|
|
69
|
+
# One named error type per outcome, declared once: the
|
|
70
|
+
# class, its import root, and the service's declared union.
|
|
71
|
+
# The standalone-CLI defaults keep the contracts family;
|
|
72
|
+
# a modular app passes its per-context exceptions module so
|
|
73
|
+
# the lineage runs one entity-named type end to end.
|
|
74
|
+
"not_found_error": str(
|
|
75
|
+
options.get("not_found_error") or "NotFoundError"
|
|
76
|
+
),
|
|
77
|
+
"exceptions_module": str(
|
|
78
|
+
options.get("exceptions_module") or "quadkit.contracts.exceptions"
|
|
79
|
+
),
|
|
80
|
+
"service_error_union": str(
|
|
81
|
+
options.get("service_error_union")
|
|
82
|
+
or options.get("not_found_error")
|
|
83
|
+
or "NotFoundError"
|
|
84
|
+
),
|
|
85
|
+
# Isort groups change with first-party membership: the
|
|
86
|
+
# framework's contracts module sorts inside the third-party
|
|
87
|
+
# block; a generated app's own exceptions module ships
|
|
88
|
+
# ``[tool.ruff] src = ["src"]``, so it is first-party and
|
|
89
|
+
# earns the trailing group. One template, one profile each.
|
|
90
|
+
"exceptions_first_party": bool(
|
|
91
|
+
options.get("exceptions_first_party") or False
|
|
92
|
+
),
|
|
93
|
+
}
|
|
94
|
+
)
|
|
67
95
|
content = self.render_template("service.py.jinja2", context)
|
|
68
96
|
file_path = self.output_dir / f"{snake_name}_service.py"
|
|
69
97
|
self.stage(file_path, content)
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Convention followed: **Repository pattern** — this module owns the
|
|
2
|
+
row<->entity mapping only; every read/write goes through
|
|
3
|
+
``GenericRepository`` plus the injected provider.
|
|
4
|
+
|
|
5
|
+
{{ entity_name }} repository."""
|
|
2
6
|
|
|
3
7
|
from __future__ import annotations
|
|
4
8
|
|
|
@@ -8,16 +12,19 @@ import uuid as _uuid
|
|
|
8
12
|
{% endif %}
|
|
9
13
|
from quadkit import clock
|
|
10
14
|
from quadkit.contracts import DatabaseProviderProtocol
|
|
11
|
-
|
|
15
|
+
{% if not exceptions_first_party %}from {{ exceptions_module }} import {{ not_found_error }}
|
|
16
|
+
{% endif %}from quadkit.result import Err, Ok, Result
|
|
17
|
+
from quadkit.serialization.domain import json_serialize
|
|
12
18
|
from quadkit.sql.repositories.generic_repository import GenericRepository
|
|
19
|
+
{% if exceptions_first_party %}
|
|
20
|
+
|
|
21
|
+
from {{ exceptions_module }} import {{ not_found_error }}
|
|
22
|
+
{% endif %}
|
|
13
23
|
|
|
14
24
|
|
|
15
25
|
class {{ entity_name }}Entity:
|
|
16
26
|
"""{{ entity_name }} row entity (plain attrs; swap for a model later)."""
|
|
17
|
-
|
|
18
|
-
{% for field in fields %}
|
|
19
|
-
{{ field.name }}: {{ field.py_type }}{% if not field.required %} | None = None{% endif %}
|
|
20
|
-
|
|
27
|
+
{% for field in fields %} {{ field.name }}: {{ field.py_type }}{% if not field.required %} | None = None{% endif %}
|
|
21
28
|
{% endfor %}
|
|
22
29
|
def __init__(self, **kwargs: Any) -> None:
|
|
23
30
|
for key, value in kwargs.items():
|
|
@@ -27,8 +34,12 @@ class {{ entity_name }}Entity:
|
|
|
27
34
|
class _{{ repo_name }}Inner(GenericRepository[{{ entity_name }}Entity, str]):
|
|
28
35
|
"""Row mapper bridge over the generic SQL repository."""
|
|
29
36
|
|
|
30
|
-
def
|
|
31
|
-
|
|
37
|
+
def _serialize_entity(self, entity: {{ entity_name }}Entity) -> dict[str, Any]:
|
|
38
|
+
"""Row dict via the framework serializer (datetime/UUID/enum-safe)."""
|
|
39
|
+
serialized = json_serialize(entity)
|
|
40
|
+
if isinstance(serialized, dict):
|
|
41
|
+
return serialized
|
|
42
|
+
return {"value": serialized}
|
|
32
43
|
|
|
33
44
|
def _row_to_entity(self, row: dict[str, Any]) -> {{ entity_name }}Entity:
|
|
34
45
|
return self.entity_class(**dict(row))
|
|
@@ -70,17 +81,28 @@ class {{ repo_name }}Repository:
|
|
|
70
81
|
)
|
|
71
82
|
return found
|
|
72
83
|
|
|
73
|
-
async def get(self, key: str) -> dict[str, Any]
|
|
84
|
+
async def get(self, key: str) -> Result[dict[str, Any], {{ not_found_error }}]:
|
|
85
|
+
"""A row that is not there is an expected outcome: absence travels
|
|
86
|
+
as ``Err({{ not_found_error }})`` — a value — never as ``None`` (R6)."""
|
|
74
87
|
entity = await self._inner.find_by_id(key)
|
|
75
88
|
if entity is None:
|
|
76
|
-
return
|
|
77
|
-
|
|
89
|
+
return Err(
|
|
90
|
+
{{ not_found_error }}(f"{{ entity_name }} not found with id: {key}")
|
|
91
|
+
)
|
|
92
|
+
return Ok(self._inner._serialize_entity(entity))
|
|
78
93
|
|
|
79
94
|
async def list(self, limit: int = 50) -> list[dict[str, Any]]:
|
|
80
95
|
entities = await self._inner.find(limit=limit)
|
|
81
|
-
return [self._inner.
|
|
82
|
-
|
|
83
|
-
async def update(
|
|
96
|
+
return [self._inner._serialize_entity(e) for e in entities]
|
|
97
|
+
|
|
98
|
+
async def update(
|
|
99
|
+
self, key: str, data: dict[str, Any]
|
|
100
|
+
) -> Result[dict[str, Any], {{ not_found_error }}]:
|
|
101
|
+
existing = await self._inner.find_by_id(key)
|
|
102
|
+
if existing is None:
|
|
103
|
+
return Err(
|
|
104
|
+
{{ not_found_error }}(f"{{ entity_name }} not found with id: {key}")
|
|
105
|
+
)
|
|
84
106
|
async with self._provider.transaction():
|
|
85
107
|
row = {
|
|
86
108
|
**data,
|
|
@@ -90,7 +112,17 @@ class {{ repo_name }}Repository:
|
|
|
90
112
|
await self._provider.execute_update(
|
|
91
113
|
"{{ table_name }}", row, '"{{ key_field }}" = ?', [key]
|
|
92
114
|
)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
async def delete(self, key: str) -> bool:
|
|
96
|
-
|
|
115
|
+
return await self.get(key)
|
|
116
|
+
|
|
117
|
+
async def delete(self, key: str) -> Result[bool, {{ not_found_error }}]:
|
|
118
|
+
"""Deleting a row that is not there is an expected outcome, so it
|
|
119
|
+
travels as ``Err({{ not_found_error }})`` — one named error type for the
|
|
120
|
+
outcome, defined once, instead of a truthiness every caller must
|
|
121
|
+
re-read (R6). Harder faults (a dead connection) stay on the throw
|
|
122
|
+
path."""
|
|
123
|
+
removed = await self._inner.delete_by_id(key)
|
|
124
|
+
if not removed:
|
|
125
|
+
return Err(
|
|
126
|
+
{{ not_found_error }}(f"{{ entity_name }} not found with id: {key}")
|
|
127
|
+
)
|
|
128
|
+
return Ok(True)
|
{quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/templates/entity_model.py.jinja2
RENAMED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Convention followed: **Domain model pattern** — one shape per
|
|
2
|
+
entity: the model carries the stored fields, the Create/Update DTOs
|
|
3
|
+
carry the write shapes; repository and controller share them.
|
|
4
|
+
|
|
5
|
+
{{ entity_name }} entity model.
|
|
2
6
|
{% if extra_dependencies %}
|
|
3
7
|
|
|
4
8
|
Requires: {{ extra_dependencies | join(', ') }} — install it alongside pydantic
|
{quadkit_sql-0.0.44 → quadkit_sql-0.0.46}/src/quadkit/sql/cli/templates/health_check.py.jinja2
RENAMED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
"""Health
|
|
1
|
+
"""Health check for {{ snake_name }}.
|
|
2
|
+
|
|
3
|
+
Reports HEALTHY/UNHEALTHY through the result object — failures are
|
|
4
|
+
captured, never raised, so one sick component cannot take down the
|
|
5
|
+
readiness endpoint.
|
|
6
|
+
"""
|
|
2
7
|
|
|
3
8
|
from quadkit.contracts.core import HealthCheckResult, HealthStatus
|
|
4
9
|
from quadkit.monitor.health import HealthCheck
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
"""Database seeder for {{ model_name }}.
|
|
1
|
+
"""Database seeder for {{ model_name }}.
|
|
2
|
+
|
|
3
|
+
Starter rows live in ``SEED_DATA``; ``run()`` inserts them once and
|
|
4
|
+
skips when the table is already populated. Edit ``SEED_DATA`` to
|
|
5
|
+
change what a fresh database contains.
|
|
6
|
+
"""
|
|
2
7
|
|
|
3
8
|
from __future__ import annotations
|
|
4
9
|
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"""Convention followed: **Service pattern** — domain logic behind a
|
|
2
|
+
small class the provider binds; controllers call the service, never
|
|
3
|
+
the provider. Writes commit through the unit of work, reads go
|
|
4
|
+
straight through. Handlers that can fail on *expected* domain
|
|
5
|
+
outcomes (a row that is not there) return ``Result[T, E]``
|
|
6
|
+
(Convention: **Result + ProblemDetail**) instead of ``None``: the
|
|
7
|
+
web layer's Result bridge renders ``Err(NotFoundError)`` as a
|
|
8
|
+
404 RFC-9457 ``ProblemDetail``. Infra faults (a dead connection) stay
|
|
9
|
+
on the throw path — they are not domain outcomes.
|
|
10
|
+
|
|
11
|
+
Application service for {{ resource_name }} backed by the SQL unit of work.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from typing import Any
|
|
17
|
+
|
|
18
|
+
from quadkit.contracts import DatabaseProviderProtocol
|
|
19
|
+
{% if not exceptions_first_party %}from {{ exceptions_module }} import {{ not_found_error }}{% if service_error_union != not_found_error %}, {{ service_error_union }}{% endif %}
|
|
20
|
+
{% endif %}from quadkit.logging import get_logger
|
|
21
|
+
from quadkit.result import Err, Ok, Result
|
|
22
|
+
from quadkit.sql.unit_of_work import SimpleUnitOfWork
|
|
23
|
+
{% if exceptions_first_party %}
|
|
24
|
+
|
|
25
|
+
from {{ exceptions_module }} import {{ not_found_error }}{% if service_error_union != not_found_error %}, {{ service_error_union }}{% endif %}
|
|
26
|
+
{% endif %}
|
|
27
|
+
logger = get_logger(__name__)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class {{ entity_class_name }}:
|
|
31
|
+
"""Row entity for the ``{{ table_name }}`` table."""
|
|
32
|
+
|
|
33
|
+
__table_name__ = "{{ table_name }}"
|
|
34
|
+
|
|
35
|
+
def __init__(self, **data: Any) -> None:
|
|
36
|
+
"""Populate row attributes from *data*."""
|
|
37
|
+
for key, value in data.items():
|
|
38
|
+
setattr(self, key, value)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class {{ class_name }}Service:
|
|
42
|
+
"""Service for {{ resource_name }}.
|
|
43
|
+
|
|
44
|
+
Write operations use :class:`~quadkit.sql.SimpleUnitOfWork` so entity
|
|
45
|
+
changes and domain events commit atomically. Single-statement reads go
|
|
46
|
+
straight through the injected :class:`~quadkit.contracts.DatabaseProviderProtocol`.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
def __init__(self, provider: DatabaseProviderProtocol) -> None:
|
|
50
|
+
"""Initialize the service.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
provider: Database provider (typically resolved from DI after
|
|
54
|
+
registering :class:`~quadkit.sql.di.provider.DatabaseProvider`).
|
|
55
|
+
"""
|
|
56
|
+
self._provider = provider
|
|
57
|
+
|
|
58
|
+
async def create(
|
|
59
|
+
self, data: dict[str, Any]
|
|
60
|
+
) -> Result[dict[str, Any], {{ service_error_union }}]:
|
|
61
|
+
"""Persist a new ``{{ table_name }}`` row.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
data: Row values{% if fields %} (keys: {% for field in fields %}{{ field.name }}{% if not loop.last %}, {% endif %}{% endfor %}){% endif %}.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
``Ok(row)`` — the persisted row data. Writes that cannot
|
|
68
|
+
legitimately fail still answer with the service's union so every
|
|
69
|
+
consumer chains: ``get(...).map(...)`` and
|
|
70
|
+
``create(...).and_then(...)`` share one shape.
|
|
71
|
+
"""
|
|
72
|
+
async with SimpleUnitOfWork(self._provider) as uow:
|
|
73
|
+
uow.register_new({{ entity_class_name }}(**data))
|
|
74
|
+
await uow.commit()
|
|
75
|
+
logger.info("{{ snake_name }}_created", table="{{ table_name }}")
|
|
76
|
+
return Ok(data)
|
|
77
|
+
|
|
78
|
+
async def get(
|
|
79
|
+
self, entity_id: Any
|
|
80
|
+
) -> Result[dict[str, Any], {{ service_error_union }}]:
|
|
81
|
+
"""Fetch a ``{{ table_name }}`` row by primary key.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
entity_id: Primary key value.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
``Ok(row)`` when the row exists, ``Err(...)`` when it
|
|
88
|
+
does not — absence is an expected outcome, so it travels as a
|
|
89
|
+
value, never as ``None``.
|
|
90
|
+
"""
|
|
91
|
+
result = await self._provider.execute_query(
|
|
92
|
+
"SELECT * FROM {{ table_name }} WHERE id = ?",
|
|
93
|
+
params=[entity_id],
|
|
94
|
+
)
|
|
95
|
+
if not result.rows:
|
|
96
|
+
return Err(
|
|
97
|
+
{{ not_found_error }}(f"{{ table_name }} row not found with id: {entity_id}")
|
|
98
|
+
)
|
|
99
|
+
return Ok(result.rows[0])
|
|
100
|
+
|
|
101
|
+
async def update(
|
|
102
|
+
self, entity_id: Any, data: dict[str, Any]
|
|
103
|
+
) -> Result[dict[str, Any], {{ service_error_union }}]:
|
|
104
|
+
"""Merge *data* into one ``{{ table_name }}`` row by primary key.
|
|
105
|
+
|
|
106
|
+
The row being gone is the same expected outcome as ``get`` — the
|
|
107
|
+
Err arm comes straight through — so the write happens only for a
|
|
108
|
+
row that answered ``Ok``.
|
|
109
|
+
"""
|
|
110
|
+
existing = await self.get(entity_id)
|
|
111
|
+
if existing.is_err():
|
|
112
|
+
return Err(existing.unwrap_err())
|
|
113
|
+
async with SimpleUnitOfWork(self._provider) as uow:
|
|
114
|
+
uow.register_dirty({{ entity_class_name }}(id=entity_id, **data))
|
|
115
|
+
await uow.commit()
|
|
116
|
+
logger.info("{{ snake_name }}_updated", table="{{ table_name }}")
|
|
117
|
+
return Ok(data)
|
|
118
|
+
|
|
119
|
+
async def list(
|
|
120
|
+
self,
|
|
121
|
+
limit: int = 100,
|
|
122
|
+
offset: int = 0,
|
|
123
|
+
) -> Result[list[dict[str, Any]], {{ service_error_union }}]:
|
|
124
|
+
"""List ``{{ table_name }}`` rows with pagination.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
limit: Maximum number of rows.
|
|
128
|
+
offset: Number of rows to skip.
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
``Ok(rows)``. An empty page is a value, and its uniform arm
|
|
132
|
+
keeps reads chainable with the outcome-bearing methods.
|
|
133
|
+
"""
|
|
134
|
+
result = await self._provider.execute_query(
|
|
135
|
+
"SELECT * FROM {{ table_name }} LIMIT ? OFFSET ?",
|
|
136
|
+
params=[limit, offset],
|
|
137
|
+
)
|
|
138
|
+
return Ok(result.rows)
|
|
139
|
+
|
|
140
|
+
async def delete(
|
|
141
|
+
self, entity_id: Any
|
|
142
|
+
) -> Result[bool, {{ service_error_union }}]:
|
|
143
|
+
"""Delete a ``{{ table_name }}`` row by primary key.
|
|
144
|
+
|
|
145
|
+
The existence check travels as the ``Err`` arm: deleting a missing
|
|
146
|
+
row answers ``Err`` (the bridge renders 404), a real
|
|
147
|
+
delete answers ``Ok(True)``.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
entity_id: Primary key value.
|
|
151
|
+
"""
|
|
152
|
+
existing = await self.get(entity_id)
|
|
153
|
+
if existing.is_err():
|
|
154
|
+
return Err(existing.unwrap_err())
|
|
155
|
+
async with SimpleUnitOfWork(self._provider) as uow:
|
|
156
|
+
uow.register_deleted({{ entity_class_name }}(id=entity_id))
|
|
157
|
+
await uow.commit()
|
|
158
|
+
logger.info("{{ snake_name }}_deleted", table="{{ table_name }}")
|
|
159
|
+
return Ok(True)
|
|
@@ -112,6 +112,25 @@ class _DatabaseRegistrationMixin:
|
|
|
112
112
|
# Register admin widget services
|
|
113
113
|
self._register_admin_widgets(container)
|
|
114
114
|
|
|
115
|
+
def _make_session_factory(self, name: str, backend: Any) -> Any:
|
|
116
|
+
"""Build (once) the ORM session factory for one backend.
|
|
117
|
+
|
|
118
|
+
Memoised so repeated resolution shares the engine rather than
|
|
119
|
+
quietly opening another pool — which is the very problem this
|
|
120
|
+
feature exists to remove.
|
|
121
|
+
"""
|
|
122
|
+
from quadkit.sql.orm.session import SessionFactory
|
|
123
|
+
|
|
124
|
+
existing = self._session_factories.get(name)
|
|
125
|
+
if existing is not None:
|
|
126
|
+
return existing
|
|
127
|
+
factory = SessionFactory(
|
|
128
|
+
backend.url.get_secret_value(),
|
|
129
|
+
echo=bool(getattr(backend, "echo", False)),
|
|
130
|
+
)
|
|
131
|
+
self._session_factories[name] = factory
|
|
132
|
+
return factory
|
|
133
|
+
|
|
115
134
|
async def _register_single_backend(
|
|
116
135
|
self,
|
|
117
136
|
container: ContainerRegistrarProtocol,
|
|
@@ -125,6 +144,7 @@ class _DatabaseRegistrationMixin:
|
|
|
125
144
|
QueryLoggerProtocol,
|
|
126
145
|
UnitOfWorkProtocol,
|
|
127
146
|
)
|
|
147
|
+
from quadkit.sql.orm.session import SessionFactory
|
|
128
148
|
|
|
129
149
|
self._db_provider = self._db_provider or DatabaseService(
|
|
130
150
|
config, clock=self._clock, id_generator=self._id_generator
|
|
@@ -132,6 +152,21 @@ class _DatabaseRegistrationMixin:
|
|
|
132
152
|
container.singleton(DatabaseService, self._db_provider)
|
|
133
153
|
container.singleton(DatabaseProviderProtocol, self._db_provider)
|
|
134
154
|
|
|
155
|
+
# ORM session factory: one engine and one pool shared with the raw
|
|
156
|
+
# providers, so an application mapping declarative models does not
|
|
157
|
+
# build a second engine against the same database
|
|
158
|
+
# (Improve-QuadKit #1).
|
|
159
|
+
#
|
|
160
|
+
# Registered as a FACTORY, not an instance: the engine is built
|
|
161
|
+
# only if something resolves it. Building eagerly would also fail
|
|
162
|
+
# for apps configured with a sync driver (`sqlite://` rather than
|
|
163
|
+
# `sqlite+aiosqlite://`), which use the raw providers happily and
|
|
164
|
+
# never ask for an ORM session.
|
|
165
|
+
container.singleton(
|
|
166
|
+
SessionFactory,
|
|
167
|
+
factory=lambda: self._make_session_factory("default", config.backend),
|
|
168
|
+
)
|
|
169
|
+
|
|
135
170
|
# Protocol bindings for optional collaborators
|
|
136
171
|
container.singleton(
|
|
137
172
|
ConnectionPoolProtocol,
|
|
@@ -212,12 +247,15 @@ class _DatabaseRegistrationMixin:
|
|
|
212
247
|
QueryLoggerProtocol,
|
|
213
248
|
UnitOfWorkProtocol,
|
|
214
249
|
)
|
|
250
|
+
from quadkit.sql.orm.session import SessionFactory
|
|
215
251
|
|
|
216
252
|
backends = config.backends
|
|
217
253
|
primary_entry = next((b for b in backends if b.primary), backends[0])
|
|
218
254
|
|
|
219
255
|
self._db_services = []
|
|
256
|
+
self._session_factories: dict[str, Any] = {}
|
|
220
257
|
primary_svc: Any = None
|
|
258
|
+
primary_factory: Any = None
|
|
221
259
|
|
|
222
260
|
for entry in backends:
|
|
223
261
|
db_cfg = DatabaseConfig.from_named(entry, base=config)
|
|
@@ -263,13 +301,31 @@ class _DatabaseRegistrationMixin:
|
|
|
263
301
|
container, db_svc, entry.migration_dir, name=entry.name
|
|
264
302
|
)
|
|
265
303
|
|
|
304
|
+
# ORM session factory: one engine and one pool per backend, so
|
|
305
|
+
# an application mapping declarative models does not build a
|
|
306
|
+
# second engine against the same database (Improve-QuadKit #1).
|
|
307
|
+
# Engine construction is lazy — no connection is opened here.
|
|
308
|
+
container.singleton(
|
|
309
|
+
SessionFactory,
|
|
310
|
+
name=entry.name,
|
|
311
|
+
factory=lambda e=entry: self._make_session_factory(e.name, e.backend),
|
|
312
|
+
)
|
|
313
|
+
|
|
266
314
|
if entry.name == primary_entry.name:
|
|
267
315
|
primary_svc = db_svc
|
|
316
|
+
primary_factory = entry
|
|
268
317
|
|
|
269
318
|
# Primary backend also gets the unnamed bindings (backward compat)
|
|
270
319
|
self._db_provider = primary_svc
|
|
271
320
|
container.singleton(DatabaseProviderProtocol, instance=primary_svc)
|
|
272
321
|
container.singleton(DatabaseService, instance=primary_svc)
|
|
322
|
+
if primary_factory is not None:
|
|
323
|
+
container.singleton(
|
|
324
|
+
SessionFactory,
|
|
325
|
+
factory=lambda e=primary_factory: self._make_session_factory(
|
|
326
|
+
e.name, e.backend
|
|
327
|
+
),
|
|
328
|
+
)
|
|
273
329
|
|
|
274
330
|
container.scoped(UnitOfWorkProtocol, primary_svc.get_unit_of_work) # type: ignore[type-abstract]
|
|
275
331
|
|