loom-kernel 2.22.2__tar.gz → 3.0.0__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.
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/CHANGELOG.md +68 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/PKG-INFO +3 -3
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/README.md +2 -2
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/model/introspection.py +26 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/mixins.py +4 -11
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/filters.py +17 -3
- loom_kernel-3.0.0/src/loom/core/repository/sqlalchemy/values.py +51 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/use_case/rule.py +21 -12
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/__init__.py +2 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/compiler.py +141 -6
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/config.py +21 -2
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/fastapi/router_runtime.py +117 -32
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/model.py +44 -1
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/.gitignore +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/LICENSE +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/pyproject.toml +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/_concurrency.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/_filters.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/_paths.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/_roles.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/_startup.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/_transport.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/_usecase.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/a2a/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/a2a/_binding.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/a2a/_handlers.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/a2a/_rpc.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/a2a/card.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/a2a/events.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/a2a/server.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/abc.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/bootstrap.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/compiler/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/compiler/_compiler.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/compiler/_fingerprint.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/compiler/_plan.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/compiler/phases/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/compiler/phases/_capabilities.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/compiler/phases/_conversation.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/compiler/phases/_feedable.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/compiler/phases/_hook.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/compiler/phases/_instructions.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/compiler/phases/_limits.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/compiler/phases/_model_role.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/compiler/phases/_output.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/compiler/phases/_state.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/config.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/declarative/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/declarative/_envelope.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/declarative/_schema.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/declarative/_v1.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/declarative/schemas/agent-spec-v1.schema.json +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/describe.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/_a2a.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/_capabilities.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/_engine.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/_errors.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/_escape.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/_events.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/_guards.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/_history.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/_instructions.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/_limits.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/_mcp.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/_models.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/_native.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/_output.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/_returns.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/_schemas.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/_spec.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/extras/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/extras/a2a.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/extras/handlebars.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/extras/mcp.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/extras/skills.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/provider.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/providers/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/providers/_shared.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/providers/anthropic.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/providers/bedrock.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/providers/gateway.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/providers/openai.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/engines/pydantic_ai/providers/typesafe.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/errors.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/etl/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/etl/_batch.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/etl/_columns.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/etl/_frames.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/etl/_ledger.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/etl/_runner.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/etl/_validation.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/fastapi/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/fastapi/endpoints.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/fastapi/response.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/fastapi/streaming.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/inference.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/pricing.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/registry.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/remote_auth.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/runtime/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/runtime/_bounded.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/runtime/_chain.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/runtime/_conversation.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/runtime/_grants.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/runtime/_handle.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/runtime/_health.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/runtime/_hooks.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/runtime/_lifecycle.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/runtime/_limits.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/runtime/_mcp.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/validate/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/ai/validate/__main__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/celery/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/celery/auto.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/celery/bootstrap.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/celery/config.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/celery/constants.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/celery/runner.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/celery/service.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/cli/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/cli/app.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/cli/schema.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/async_bridge.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/authz/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/authz/_decide.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/authz/_grants.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/authz/_roles.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/authz/_scope.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/authz/elevation.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/authz/product.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/backend/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/backend/core_model.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/backend/protocol.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/backend/scoped_ddl.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/backend/sqlalchemy.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/bootstrap/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/bootstrap/bootstrap.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/bootstrap/kernel.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/cache/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/cache/_batching.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/cache/_single_flight.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/cache/abc/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/cache/abc/backend.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/cache/abc/config.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/cache/abc/dependency.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/cache/calls.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/cache/codec.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/cache/decorators.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/cache/dependency.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/cache/errors.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/cache/gateway.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/cache/keys.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/cache/memory.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/cache/repository.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/cache/result_codec.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/cache/serializer.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/cache/wiring.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/command/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/command/adapter.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/command/base.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/command/field.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/command/introspection.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/compiler.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/config/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/config/_boto3.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/config/_includes.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/config/_resolver_utils.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/config/binder.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/config/configurable.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/config/context.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/config/errors.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/config/keys.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/config/loader.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/config/model.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/config/observability.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/config/resolver.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/config/secrets.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/config/ssm.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/contracts/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/contracts/manifest.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/di/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/di/container.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/di/scope.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/discovery/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/discovery/_utils.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/discovery/base.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/discovery/interfaces.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/discovery/manifest.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/discovery/modules.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/engine/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/engine/compilable.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/engine/compiler.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/engine/events.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/engine/executor.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/engine/metrics.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/engine/plan.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/engine/post_commit.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/errors/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/errors/codes.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/errors/errors.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/expr/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/expr/eval.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/expr/nodes.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/expr/refs.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/identity/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/identity/context.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/identity/identity.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/identity/issuer.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/identity/wire.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/introspection/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/introspection/base.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/introspection/describe.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/job/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/job/callback.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/job/context.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/job/handle.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/job/job.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/job/service.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/locator.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/logger/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/logger/abc.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/logger/config.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/logger/registry.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/logger/structlogger.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/model/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/model/_json_schema.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/model/_loom_type.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/model/base.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/model/convert.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/model/enums.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/model/field.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/model/partition.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/model/privilege.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/model/projection.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/model/relation.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/model/scoped.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/model/struct.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/model/timestamped.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/model/types.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/model/types_postgres.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/observability/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/observability/config.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/observability/event.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/observability/observer/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/observability/observer/noop.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/observability/observer/otel.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/observability/observer/structlog.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/observability/otel_ids.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/observability/protocol.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/observability/runtime.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/observability/span.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/observability/topology.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/persistence/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/persistence/abc.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/persistence/none.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/persistence/registry.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/plugins/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/plugins/entrypoints.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/plugins/optional.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/projection/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/projection/loaders.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/projection/runtime.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/abc/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/abc/cursor.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/abc/errors.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/abc/query.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/abc/query_compiler.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/abc/repo_for.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/abc/repository.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/abc/session_scope.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/dynamodb/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/dynamodb/backend.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/dynamodb/registry.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/dynamodb/repository.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/dynamodb/uow.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/mongo/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/mongo/backend.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/mongo/ids.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/mongo/query_compiler.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/mongo/registry.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/mongo/repository.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/mongo/uow.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/mongo/values.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/mutation.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/registration.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/registry.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/backend.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/integrity.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/loaders.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/migrations/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/migrations/env_template.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/migrations/hook.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/migrations/operations.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/migrations/runners.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/model.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/profile_loader.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/projection.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/compiler.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/cursor.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/errors.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/ordering.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/paths.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/subquery.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/registry.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/repository.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/rls/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/rls/bootstrap.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/rls/config.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/rls/elevate.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/rls/guard/0001.sql +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/rls/guard/0002.sql +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/rls/guard/preflight.sql +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/rls/guard_manifest.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/rls/integrity.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/rls/partitions.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/rls/provider.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/rls/schema.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/rls/sources.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/rls/verify.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/session_manager.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/session_settings.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/transactional.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/repository/sqlalchemy/uow.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/response/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/response/base.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/routing/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/routing/ref.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/routing/resolver.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/runner.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/schema/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/schema/schema_mode.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/schema_names.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/sql/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/sql/abc/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/sql/abc/contracts.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/sql/abc/errors.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/sql/caller_bound.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/sql/clickhouse/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/sql/clickhouse/_client.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/sql/clickhouse/executor.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/sql/clickhouse/registry.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/sql/config.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/sql/roles.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/sql/service.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/symbols.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/tracing/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/tracing/context.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/transaction.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/transport/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/transport/adapter.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/uow/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/uow/abc.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/uow/context.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/use_case/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/use_case/_predicates.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/use_case/agent_markers.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/use_case/compute.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/use_case/constants.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/use_case/factory.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/use_case/field_ref.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/use_case/invoker.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/use_case/keys.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/use_case/markers.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/use_case/mcp_markers.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/use_case/outcome.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/use_case/registry.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/core/use_case/use_case.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/_uri.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/_format_registry.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/_historify/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/_historify/_common.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/_historify/_log.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/_historify/_ops.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/_historify/_snapshot.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/_historify/_transform.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/_merge.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/_path_template.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/_predicate.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/_schema_aligner/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/_schema_aligner/_aligner.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/_schema_aligner/_policy.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/_write_policy.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/polars/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/polars/_dtype.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/polars/_file_writer.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/polars/_frame.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/polars/_historify.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/polars/_predicate.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/polars/_reader.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/polars/_schema.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/polars/_schema_aligner.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/polars/_streaming.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/polars/_writer.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/polars/provider.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/spark/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/spark/_dtype.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/spark/_historify.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/spark/_reader.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/spark/_schema.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/spark/_schema_aligner.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/spark/_writer.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/backends/spark/provider.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/checkpoint/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/checkpoint/_backends/_polars.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/checkpoint/_backends/_spark.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/checkpoint/_cleaners.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/checkpoint/_options.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/checkpoint/_paths.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/checkpoint/_scope.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/checkpoint/_store.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/compiler/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/compiler/_binding.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/compiler/_compiler.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/compiler/_errors.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/compiler/_filter.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/compiler/_plan.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/compiler/_validators.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/compiler/_validators_agents.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/compiler/_validators_config.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/compiler/_validators_plan.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/compiler/_validators_step.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/_format.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/_read_options.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/_utils.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/_with_agent.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/_write_options.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/expr/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/expr/_params.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/expr/_predicate.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/expr/_predicate_dialect.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/expr/_refs.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/source/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/source/_from.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/source/_from_clickhouse.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/source/_from_config.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/source/_from_dynamodb.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/source/_from_mongo.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/source/_specs.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/target/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/target/_client.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/target/_errors.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/target/_file.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/target/_history/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/target/_history/_builder.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/target/_history/_enums.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/target/_history/_errors.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/target/_history/_report.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/target/_history/_spec.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/target/_into.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/target/_schema_mode.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/target/_table.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/declarative/target/_temp.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/executor/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/executor/_agents.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/executor/_dispatcher.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/executor/_executor.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/io/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/io/_registry.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/io/sources/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/io/sources/_clickhouse.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/io/sources/_dynamodb.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/io/sources/_dynamodb_items.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/io/sources/_dynamodb_predicate.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/io/sources/_mongo.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/io/sources/_mongo_batch.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/io/sources/_mongo_bson.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/io/sources/_mongo_predicate.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/io/sources/_serialization.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/io/targets/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/io/targets/_clickhouse.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/lineage/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/lineage/_config.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/lineage/_observer.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/lineage/_records.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/lineage/sinks/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/lineage/sinks/_protocol.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/lineage/sinks/_table.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/lineage/sinks/_writer.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/maintenance/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/maintenance/_builder.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/maintenance/_ops.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/maintenance/_protocol.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/maintenance/_runner.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/maintenance/_step.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/maintenance/backends/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/maintenance/backends/_delta_rs.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/pipeline/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/pipeline/_generics.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/pipeline/_params.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/pipeline/_pipeline.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/pipeline/_process.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/pipeline/_sql.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/pipeline/_step.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/pipeline/_step_client.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/pipeline/_step_sql.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/runner/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/runner/_agents.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/runner/_providers.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/runner/_wiring.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/runner/config_loader.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/runner/core.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/runner/errors.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/runner/filtering.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/runtime/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/runtime/_config_values.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/runtime/contracts.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/schema/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/schema/_contract.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/schema/_schema.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/storage/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/storage/_config.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/storage/_file_locator.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/storage/_locator.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/storage/routing.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/testing/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/testing/_result.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/testing/_runners.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/testing/_scenario.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/testing/_stubs.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/etl/testing/spark.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/_async.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/_config.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/_ctx.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/_flow_yaml.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/_meta.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/_placeholders.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/_summary.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/deploy/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/deploy/_discovery.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/deploy/_schedule.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/deploy/_yaml_etls.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/deploy/entrypoint.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/flow/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/flow/_assemble.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/flow/_backfill.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/flow/_backfill_body.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/flow/_body.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/flow/_common.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/flow/_factory.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/flow/_hooks.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/flow/_maintenance.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/flow/_params.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/flow/_run_name.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/flow/_runtime.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/flow/_signature.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/flow/_stages.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/manifest/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/manifest/_model.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/manifest/_s3.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/manifest/_store.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/notify/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/notify/_event.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/notify/_factory.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/notify/_format.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/notify/_port.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/notify/_slack.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/notify/_sns.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/observer/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/observer/_flow.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/observer/_logging_bridge.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/observer/_manifest.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prefect/observer/_task_run.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prometheus/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prometheus/_instruments.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prometheus/adapter.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prometheus/kafka.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prometheus/lifecycle.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/prometheus/middleware.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/py.typed +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/_body.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/adapter.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/auth/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/auth/abc.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/auth/config.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/auth/jwt.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/auth/middleware.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/autocrud.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/constants.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/cors.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/errors.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/fastapi/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/fastapi/_errors.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/fastapi/_exclusions.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/fastapi/app.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/fastapi/auto.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/fastapi/health.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/fastapi/openapi.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/fastapi/response.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/fastapi/sql.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/middleware.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/rest/rest_adapter.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/_adapter.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/_batch_spans.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/_commit_tracker.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/_dlq.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/_error_boundary.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/_errors.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/_operators.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/_resource_manager.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/_runtime_io.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/_sink_registry.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/handlers/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/handlers/_shared.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/handlers/boundary.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/handlers/dispatcher.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/handlers/routing.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/handlers/scopes.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/handlers/shapes.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/handlers/steps.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/handlers/storage.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/bytewax/runner.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/compiler/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/compiler/_bindings.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/compiler/_compiler.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/compiler/_errors.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/compiler/_plan.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/compiler/phases/build_plan.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/compiler/phases/validate.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/core/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/core/_errors.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/core/_exceptions.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/core/_message.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/core/_tracing.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/core/_typing.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/graph/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/graph/_flow.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/kafka/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/kafka/_codec.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/kafka/_config.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/kafka/_errors.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/kafka/_key_resolver.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/kafka/_message.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/kafka/_record.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/kafka/_wire.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/kafka/client/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/kafka/client/_consumer.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/kafka/client/_producer.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/kafka/client/_protocol.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/kafka/client/_retry.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/kafka/message/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/kafka/message/_consumer.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/kafka/message/_producer.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/kafka/message/_protocol.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/mongo/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/mongo/_bytewax_source.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/mongo/_config.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/mongo/_event.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/mongo/_normalize.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/_boundary.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/_branches.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/_broadcast.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/_capabilities.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/_decompose.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/_expand_routes.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/_expr_eval.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/_fork.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/_helpers.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/_mongo.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/_protocols.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/_router.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/_shape.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/_sink.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/_step.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/_table/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/_table/common.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/_table/config.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/_with.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/nodes/refs.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/streaming/testing.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/testing/__init__.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/testing/agents.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/testing/golden.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/testing/http_harness.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/testing/in_memory.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/testing/repository_harness.py +0 -0
- {loom_kernel-2.22.2 → loom_kernel-3.0.0}/src/loom/testing/runner.py +0 -0
|
@@ -459,6 +459,14 @@
|
|
|
459
459
|
|
|
460
460
|
### core
|
|
461
461
|
|
|
462
|
+
- **core:** `Rule.check(..., via=fn)` takes the violation from `fn`: a `str`
|
|
463
|
+
(the message) or a `RuleViolation` fails the rule, `None` passes it. A `bool`
|
|
464
|
+
or any other result raises `TypeError` naming the field, instead of `True`
|
|
465
|
+
failing the rule and `False` passing it. The `message=` parameter of
|
|
466
|
+
`Rule.check` is removed. `Rule.forbid` keeps its boolean condition; a `str`
|
|
467
|
+
or `RuleViolation` it returns no longer fails the rule. Migrate
|
|
468
|
+
`Rule.check(F(Order).total, via=lambda v: v <= 0, message="total must be > 0")`
|
|
469
|
+
to `Rule.check(F(Order).total, via=lambda v: "total must be > 0" if v <= 0 else None)`.
|
|
462
470
|
- **core:** the `LoomType` protocol gains `from_query(params)`, which
|
|
463
471
|
validates query-string values strictly. A number takes the JSON number
|
|
464
472
|
grammar and must be finite, an integer its integer subset within
|
|
@@ -594,6 +602,37 @@
|
|
|
594
602
|
|
|
595
603
|
### rest
|
|
596
604
|
|
|
605
|
+
- **rest:** a `QuerySpec` route filters and sorts only on the columns it
|
|
606
|
+
declares. Before, a client could filter or sort on any field the repository
|
|
607
|
+
could resolve. Now a filter on an undeclared column answers
|
|
608
|
+
`400 unsupported_query` naming the field, and so does a sort on one, with the
|
|
609
|
+
same answer whether or not the column exists. The primary key, which the
|
|
610
|
+
route orders by when the client names no sort, needs no declaration.
|
|
611
|
+
Declare `filterable` and `sortable` on the interface (its auto-CRUD `list`
|
|
612
|
+
route included) or on a route, which overrides it, as field references or
|
|
613
|
+
column names:
|
|
614
|
+
|
|
615
|
+
```python
|
|
616
|
+
class OrderRestInterface(RestInterface[Order]):
|
|
617
|
+
prefix = "/orders"
|
|
618
|
+
auto = True
|
|
619
|
+
filterable = (F(Order).status, F(Order).total)
|
|
620
|
+
sortable = (F(Order).created_at,)
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
In `app.rest.interfaces` both take column names (`[status, total]`).
|
|
624
|
+
`ALL` (`all` in YAML) keeps every scalar column and logs a warning naming
|
|
625
|
+
the route at startup. Only scalar columns of the use case's own model
|
|
626
|
+
(`UseCase[Model, ...]`) qualify. A related model's column (`warehouse.code`)
|
|
627
|
+
is refused, and so are JSON, array and text-search columns; lists, dicts
|
|
628
|
+
and structs, and an `Enum` or `Literal` declared without a column type, are
|
|
629
|
+
JSON. `InterfaceCompilationError` names the route and the field. It is also
|
|
630
|
+
raised for a declaration on a use case with no model, and for a route-level
|
|
631
|
+
declaration on a route without a `QuerySpec`; an inherited one is ignored.
|
|
632
|
+
`exists` and `not_exists` answer `400 unsupported_query`, and so do `like`
|
|
633
|
+
and `ilike` on a column that is not `str`. The repository's
|
|
634
|
+
`allowed_filter_fields` is unchanged: programmatic callers are not
|
|
635
|
+
restricted.
|
|
597
636
|
- **rest:** every route now resolves its request parameters and decodes its
|
|
598
637
|
body before the use case is built, so a request refused at that point
|
|
599
638
|
never runs the use case's constructor.
|
|
@@ -759,6 +798,12 @@
|
|
|
759
798
|
|
|
760
799
|
### core
|
|
761
800
|
|
|
801
|
+
- **core:** the SQLAlchemy query compiler converts a filter value, and each
|
|
802
|
+
`in` item, as the repository converts a value it writes
|
|
803
|
+
(`loom.core.repository.sqlalchemy.values.to_column_value`, now shared by
|
|
804
|
+
both): an `Enum` member is bound as its value, a JSON column's value is
|
|
805
|
+
reduced to builtins. A plain `Enum` member as the value of a filter on a
|
|
806
|
+
string column failed to bind.
|
|
762
807
|
- **core:** a `BoundaryValidationError` no longer echoes the rejected value
|
|
763
808
|
(#347). msgspec's `Invalid enum value 'x'` (an `Enum`, `IntEnum` or `Literal`
|
|
764
809
|
field or dict key) and `Invalid value 'x'` (a tagged-union tag) become
|
|
@@ -945,6 +990,29 @@
|
|
|
945
990
|
|
|
946
991
|
### rest
|
|
947
992
|
|
|
993
|
+
- **rest:** `?sort=` accepted any column. A cursor page put the sort
|
|
994
|
+
column's raw value of its last row in `nextCursor` (base64 JSON), so any
|
|
995
|
+
column, a secret one included, could be read through it, and a forged
|
|
996
|
+
cursor could range-probe it. Offset pages leaked its order, and an unknown
|
|
997
|
+
column answered `400 unsupported_query` (`Unknown filter field path`) while
|
|
998
|
+
a known one answered `200`, so the model's columns could be enumerated. A
|
|
999
|
+
route now sorts only by its declared `sortable` columns and its primary
|
|
1000
|
+
key, so a cursor carries only those values.
|
|
1001
|
+
- **rest:** a `page` whose offset, `(page - 1) * limit`, exceeds the largest
|
|
1002
|
+
signed 64-bit integer answers `400 query_validation` on `page` before any
|
|
1003
|
+
query runs.
|
|
1004
|
+
- **rest:** a `QuerySpec` filter value was typed by its spelling: `true` and
|
|
1005
|
+
`false` became booleans, text with a `.` a float and digits an integer,
|
|
1006
|
+
whatever the filtered field declared. `?code=0123` on a `str` field compared
|
|
1007
|
+
against `123`, and on Postgres a number bound to a text column answered
|
|
1008
|
+
`500`. Values of `eq`, `ne`, `gt`, `gte`, `lt`, `lte` and each item of `in`
|
|
1009
|
+
are now converted by the type of the declared filterable field, with the
|
|
1010
|
+
strict grammar of `Query()`: a `str` field keeps the text as sent, a
|
|
1011
|
+
boolean accepts only `true` or `false`, an `Enum` or `Literal` only its
|
|
1012
|
+
values, and a value its field's type refuses answers `400 query_validation`
|
|
1013
|
+
with `violations` naming the field. The field's constraints
|
|
1014
|
+
(`msgspec.Meta`) do not apply to a filter value, so `rank__gt=0` is valid
|
|
1015
|
+
on a column declared `ge=1`. `like` and `ilike` keep their pattern as text.
|
|
948
1016
|
- **rest:** the OpenAPI `limit` parameter of a `QuerySpec` route published
|
|
949
1017
|
`maximum: 1000` and `default: 50` whatever `RestApiDefaults.max_limit` said,
|
|
950
1018
|
while the router clamped `?limit=` to `max_limit`. The schema now publishes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: loom-kernel
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.0
|
|
4
4
|
Summary: Loom Python project
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -524,8 +524,8 @@ class PricingPreviewUseCase(UseCase[Record, PricingPreviewResponse]):
|
|
|
524
524
|
),
|
|
525
525
|
)
|
|
526
526
|
rules = (
|
|
527
|
-
Rule.check(F(PricingCommand).unit_price, via=lambda v:
|
|
528
|
-
Rule.check(F(PricingCommand).country, via=lambda v: v
|
|
527
|
+
Rule.check(F(PricingCommand).unit_price, via=lambda v: "unit_price must be > 0" if v <= 0 else None),
|
|
528
|
+
Rule.check(F(PricingCommand).country, via=lambda v: None if v in TAX_RATES else "Unsupported country"),
|
|
529
529
|
)
|
|
530
530
|
|
|
531
531
|
async def execute(self, record_id: int, cmd: PricingCommand = Input()) -> PricingPreviewResponse:
|
|
@@ -400,8 +400,8 @@ class PricingPreviewUseCase(UseCase[Record, PricingPreviewResponse]):
|
|
|
400
400
|
),
|
|
401
401
|
)
|
|
402
402
|
rules = (
|
|
403
|
-
Rule.check(F(PricingCommand).unit_price, via=lambda v:
|
|
404
|
-
Rule.check(F(PricingCommand).country, via=lambda v: v
|
|
403
|
+
Rule.check(F(PricingCommand).unit_price, via=lambda v: "unit_price must be > 0" if v <= 0 else None),
|
|
404
|
+
Rule.check(F(PricingCommand).country, via=lambda v: None if v in TAX_RATES else "Unsupported country"),
|
|
405
405
|
)
|
|
406
406
|
|
|
407
407
|
async def execute(self, record_id: int, cmd: PricingCommand = Input()) -> PricingPreviewResponse:
|
|
@@ -316,6 +316,32 @@ def generic_type_arg(annotation: Any, origin: Any) -> type | None:
|
|
|
316
316
|
return args[0]
|
|
317
317
|
|
|
318
318
|
|
|
319
|
+
_NON_SCALAR_COLUMN_TYPES = frozenset(
|
|
320
|
+
{"JSON", "Postgres.JSONB", "Postgres.ARRAY", "Postgres.TSVECTOR"}
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def scalar_column_annotations(model: type) -> dict[str, Any]:
|
|
325
|
+
"""Return the annotation of each scalar column of *model*, ``Annotated`` metadata removed.
|
|
326
|
+
|
|
327
|
+
A JSON, array or text-search column is not scalar; lists, dicts and
|
|
328
|
+
structs, and an ``Enum`` or ``Literal`` declared without a column type,
|
|
329
|
+
are inferred as JSON.
|
|
330
|
+
|
|
331
|
+
Args:
|
|
332
|
+
model: Model whose columns are read.
|
|
333
|
+
|
|
334
|
+
Returns:
|
|
335
|
+
Mapping of column name to its annotation, in declaration order.
|
|
336
|
+
"""
|
|
337
|
+
hints = get_type_hints(model)
|
|
338
|
+
return {
|
|
339
|
+
name: hints[name]
|
|
340
|
+
for name, info in get_column_fields(model).items()
|
|
341
|
+
if info.column_type.type_name not in _NON_SCALAR_COLUMN_TYPES
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
|
|
319
345
|
def _extract_origin_type(annotation: Any) -> type[Any]:
|
|
320
346
|
"""Return the base type from ``Annotated[T, ...]``."""
|
|
321
347
|
origin = getattr(annotation, "__origin__", None)
|
|
@@ -3,10 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
from abc import abstractmethod
|
|
4
4
|
from collections.abc import Sequence
|
|
5
5
|
from contextlib import AbstractAsyncContextManager
|
|
6
|
-
from datetime import date, datetime, time
|
|
7
|
-
from decimal import Decimal
|
|
8
6
|
from typing import Any, ClassVar, Generic, cast
|
|
9
|
-
from uuid import UUID
|
|
10
7
|
|
|
11
8
|
import msgspec
|
|
12
9
|
from sqlalchemy import and_, exists, func, insert, inspect, select, tuple_
|
|
@@ -36,11 +33,9 @@ from loom.core.repository.mutation import MutationEvent
|
|
|
36
33
|
from loom.core.repository.sqlalchemy.integrity import handle_integrity_errors
|
|
37
34
|
from loom.core.repository.sqlalchemy.query_compiler.compiler import QuerySpecCompiler
|
|
38
35
|
from loom.core.repository.sqlalchemy.transactional import record_mutation
|
|
36
|
+
from loom.core.repository.sqlalchemy.values import is_json_column, to_column_value
|
|
39
37
|
|
|
40
38
|
_SENTINEL = object()
|
|
41
|
-
# Values SQLAlchemy binds natively; encoding them to strings breaks typed columns.
|
|
42
|
-
_NATIVE_COLUMN_TYPES = (bytes, datetime, date, time, Decimal, UUID)
|
|
43
|
-
_JSON_TYPE_NAMES = frozenset({"JSON", "Postgres.JSONB"})
|
|
44
39
|
_TOTAL_COUNT_ALIAS = "__loom_total_count"
|
|
45
40
|
|
|
46
41
|
|
|
@@ -77,9 +72,7 @@ class SQLAlchemyContextMixin(Generic[OutputT, IdT]):
|
|
|
77
72
|
column_field_names = frozenset(column_fields.keys())
|
|
78
73
|
self._column_field_names = column_field_names
|
|
79
74
|
self._json_column_names = frozenset(
|
|
80
|
-
name
|
|
81
|
-
for name, info in column_fields.items()
|
|
82
|
-
if info.column_type.type_name in _JSON_TYPE_NAMES
|
|
75
|
+
name for name in column_fields if is_json_column(getattr(sa, name, None))
|
|
83
76
|
)
|
|
84
77
|
self._relations_cache = get_relations(self.model)
|
|
85
78
|
self._core_model = get_compiled_core(self.model)
|
|
@@ -165,7 +158,7 @@ class SQLAlchemyContextMixin(Generic[OutputT, IdT]):
|
|
|
165
158
|
|
|
166
159
|
def _serialize_input(self, data: msgspec.Struct | dict[str, Any]) -> dict[str, Any]:
|
|
167
160
|
if isinstance(data, msgspec.Struct):
|
|
168
|
-
builtins =
|
|
161
|
+
builtins = to_column_value(data)
|
|
169
162
|
if not isinstance(builtins, dict):
|
|
170
163
|
raise TypeError("Struct payload must serialize to dict")
|
|
171
164
|
return self._encode_json_columns(_to_internal_field_names(type(data), builtins))
|
|
@@ -174,7 +167,7 @@ class SQLAlchemyContextMixin(Generic[OutputT, IdT]):
|
|
|
174
167
|
def _encode_json_columns(self, values: dict[str, Any]) -> dict[str, Any]:
|
|
175
168
|
"""Reduce JSON-column payloads to JSON-serialisable builtins."""
|
|
176
169
|
for key in self._json_column_names.intersection(values):
|
|
177
|
-
values[key] =
|
|
170
|
+
values[key] = to_column_value(values[key], json=True)
|
|
178
171
|
return values
|
|
179
172
|
|
|
180
173
|
def _column_for_field(self, field: str) -> Any:
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from collections.abc import Callable
|
|
5
|
+
from collections.abc import Callable, Iterable
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
8
|
from sqlalchemy import and_, or_
|
|
9
|
+
from sqlalchemy.sql.expression import ClauseElement
|
|
9
10
|
|
|
10
11
|
from loom.core.repository.abc.query import FilterGroup, FilterOp, FilterSpec
|
|
11
12
|
from loom.core.repository.sqlalchemy.query_compiler.errors import UnsafeFilterError
|
|
@@ -14,6 +15,7 @@ from loom.core.repository.sqlalchemy.query_compiler.subquery import (
|
|
|
14
15
|
compile_exists,
|
|
15
16
|
compile_not_exists,
|
|
16
17
|
)
|
|
18
|
+
from loom.core.repository.sqlalchemy.values import is_json_column, to_column_value
|
|
17
19
|
|
|
18
20
|
_RELATION_OPS = frozenset([FilterOp.EXISTS, FilterOp.NOT_EXISTS])
|
|
19
21
|
_SIMPLE_OPS: dict[FilterOp, Callable[[Any, Any], Any]] = {
|
|
@@ -74,7 +76,19 @@ def _compile_spec(
|
|
|
74
76
|
|
|
75
77
|
|
|
76
78
|
def _apply_op(col: Any, op: FilterOp, value: Any) -> Any:
|
|
79
|
+
"""Apply *op*, converting *value* as the repository converts a value it writes.
|
|
80
|
+
|
|
81
|
+
A SQLAlchemy expression, and an ``IN`` value that is a string or not
|
|
82
|
+
iterable, reach SQLAlchemy as they are.
|
|
83
|
+
"""
|
|
77
84
|
handler = _SIMPLE_OPS.get(op)
|
|
78
|
-
if handler is
|
|
85
|
+
if handler is None:
|
|
86
|
+
raise ValueError(f"Unsupported FilterOp: {op!r}")
|
|
87
|
+
if isinstance(value, ClauseElement):
|
|
88
|
+
return handler(col, value)
|
|
89
|
+
json = is_json_column(col)
|
|
90
|
+
if op is not FilterOp.IN:
|
|
91
|
+
return handler(col, to_column_value(value, json=json))
|
|
92
|
+
if isinstance(value, str | bytes) or not isinstance(value, Iterable):
|
|
79
93
|
return handler(col, value)
|
|
80
|
-
|
|
94
|
+
return handler(col, [to_column_value(item, json=json) for item in value])
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Column form of model values in SQLAlchemy rows.
|
|
2
|
+
|
|
3
|
+
SQLAlchemy binds ``bytes``, ``datetime``, ``date``, ``time``, ``Decimal`` and
|
|
4
|
+
``UUID`` natively; every other value is reduced to msgspec builtins (an
|
|
5
|
+
``Enum`` to its value, a struct to a dict). A JSON column holds builtins only,
|
|
6
|
+
so its values are reduced completely.
|
|
7
|
+
|
|
8
|
+
:func:`to_column_value` is the conversion the repository applies to a value it
|
|
9
|
+
writes and the query compiler to a filter value, so a filter compares against
|
|
10
|
+
exactly what the row holds.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from datetime import date, datetime, time
|
|
16
|
+
from decimal import Decimal
|
|
17
|
+
from typing import Any
|
|
18
|
+
from uuid import UUID
|
|
19
|
+
|
|
20
|
+
import msgspec
|
|
21
|
+
from sqlalchemy import JSON
|
|
22
|
+
|
|
23
|
+
# Values SQLAlchemy binds natively; encoding them to strings breaks typed columns.
|
|
24
|
+
_NATIVE_COLUMN_TYPES = (bytes, datetime, date, time, Decimal, UUID)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def to_column_value(value: object, *, json: bool = False) -> Any:
|
|
28
|
+
"""Return the form ``value`` takes in a column.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
value: A model value or a filter value.
|
|
32
|
+
json: ``True`` when the column is a JSON column.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
``value`` reduced to msgspec builtins, keeping the natively bound
|
|
36
|
+
types unless the column is a JSON column.
|
|
37
|
+
"""
|
|
38
|
+
if json:
|
|
39
|
+
return msgspec.to_builtins(value)
|
|
40
|
+
return msgspec.to_builtins(value, builtin_types=_NATIVE_COLUMN_TYPES)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def is_json_column(column: object) -> bool:
|
|
44
|
+
"""Whether *column*, a SQLAlchemy column or mapped attribute, holds JSON.
|
|
45
|
+
|
|
46
|
+
``JSON`` and the dialect types derived from it (Postgres ``JSONB``) count.
|
|
47
|
+
"""
|
|
48
|
+
return isinstance(getattr(column, "type", None), JSON)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
__all__ = ["is_json_column", "to_column_value"]
|
|
@@ -47,7 +47,6 @@ class RuleBuilderFn(RuleFn, Protocol):
|
|
|
47
47
|
class _RuleSpec:
|
|
48
48
|
evaluator: Callable[..., Any]
|
|
49
49
|
field: str | None = None
|
|
50
|
-
message: str | None = None
|
|
51
50
|
command_sources: tuple[FieldRef, ...] = ()
|
|
52
51
|
param_names: tuple[str, ...] = ()
|
|
53
52
|
include_command: bool = False
|
|
@@ -101,13 +100,19 @@ class _RuleSpec:
|
|
|
101
100
|
raise ValueError(f"Missing runtime context keys for rule: {', '.join(missing)}")
|
|
102
101
|
args.extend(context[n] for n in self.param_names)
|
|
103
102
|
|
|
104
|
-
|
|
103
|
+
self._raise_outcome(self.evaluator(*args), command)
|
|
104
|
+
|
|
105
|
+
def _raise_outcome(self, result: object, command: Command) -> None:
|
|
105
106
|
if isinstance(result, RuleViolation):
|
|
106
107
|
raise result
|
|
107
108
|
if isinstance(result, str):
|
|
108
109
|
raise RuleViolation(self._resolved_field(command), result)
|
|
109
|
-
if result is
|
|
110
|
-
raise
|
|
110
|
+
if result is not None:
|
|
111
|
+
raise TypeError(
|
|
112
|
+
f"Rule.check on field '{self._resolved_field(command)}': the evaluator "
|
|
113
|
+
f"returned {type(result).__name__}; return the violation message (str), "
|
|
114
|
+
"a RuleViolation, or None when the value is valid."
|
|
115
|
+
)
|
|
111
116
|
|
|
112
117
|
def _resolved_field(self, command: Command) -> str:
|
|
113
118
|
candidates = (
|
|
@@ -118,9 +123,6 @@ class _RuleSpec:
|
|
|
118
123
|
)
|
|
119
124
|
return next((c for c in candidates if c is not None), type(command).__name__)
|
|
120
125
|
|
|
121
|
-
def _resolved_message(self) -> str:
|
|
122
|
-
return self.message or "Rule check failed"
|
|
123
|
-
|
|
124
126
|
|
|
125
127
|
@dataclass(frozen=True, slots=True)
|
|
126
128
|
class _RequirePresentSpec:
|
|
@@ -152,15 +154,19 @@ class Rule:
|
|
|
152
154
|
@staticmethod
|
|
153
155
|
def check(
|
|
154
156
|
*targets: FieldRef,
|
|
155
|
-
via: Callable[...,
|
|
156
|
-
message: str | None = None,
|
|
157
|
+
via: Callable[..., str | RuleViolation | None],
|
|
157
158
|
) -> RuleBuilderFn:
|
|
159
|
+
"""Validate fields with ``via``, which receives the targets' values.
|
|
160
|
+
|
|
161
|
+
``via`` returns the violation message (``str``), a ``RuleViolation``, or
|
|
162
|
+
``None`` when the values are valid. Any other result, a ``bool``
|
|
163
|
+
included, raises ``TypeError``.
|
|
164
|
+
"""
|
|
158
165
|
if not targets:
|
|
159
166
|
raise ValueError("Rule.check(...) requires at least one target.")
|
|
160
167
|
return _RuleSpec(
|
|
161
168
|
evaluator=via,
|
|
162
169
|
field=targets[0].leaf,
|
|
163
|
-
message=message,
|
|
164
170
|
command_sources=tuple(targets),
|
|
165
171
|
)
|
|
166
172
|
|
|
@@ -170,9 +176,12 @@ class Rule:
|
|
|
170
176
|
*,
|
|
171
177
|
message: str,
|
|
172
178
|
) -> RuleBuilderFn:
|
|
179
|
+
def _violation(*args: Any) -> str | None:
|
|
180
|
+
# Only boolean True signals failure, not any truthy value.
|
|
181
|
+
return message if condition(*args) is True else None
|
|
182
|
+
|
|
173
183
|
return _RuleSpec(
|
|
174
|
-
evaluator=
|
|
175
|
-
message=message,
|
|
184
|
+
evaluator=_violation,
|
|
176
185
|
include_command=True,
|
|
177
186
|
include_fields_set=True,
|
|
178
187
|
)
|
|
@@ -19,6 +19,7 @@ from loom.rest.config import RestInterfaceConfigError
|
|
|
19
19
|
from loom.rest.errors import HttpErrorMapper
|
|
20
20
|
from loom.rest.middleware import TraceIdMiddleware
|
|
21
21
|
from loom.rest.model import (
|
|
22
|
+
ALL,
|
|
22
23
|
PaginationMode,
|
|
23
24
|
RestApiDefaults,
|
|
24
25
|
RestInterface,
|
|
@@ -27,6 +28,7 @@ from loom.rest.model import (
|
|
|
27
28
|
from loom.rest.rest_adapter import LoomRestAdapter
|
|
28
29
|
|
|
29
30
|
__all__ = [
|
|
31
|
+
"ALL",
|
|
30
32
|
"CompiledRoute",
|
|
31
33
|
"HttpErrorMapper",
|
|
32
34
|
"InterfaceCompilationError",
|
|
@@ -21,6 +21,10 @@ Compilation steps per interface:
|
|
|
21
21
|
- Read the fields of a ``Query()`` parameter, refusing a non-scalar field,
|
|
22
22
|
a name shared with a path parameter or ``profile``, or a ``QuerySpec``
|
|
23
23
|
parameter next to it.
|
|
24
|
+
- Resolve the filterable and sortable columns of a ``QuerySpec`` route
|
|
25
|
+
(route → interface) against its use case's model, refusing a field
|
|
26
|
+
reference rooted elsewhere, a name that is not a scalar column of that
|
|
27
|
+
model, and a route-level declaration on a route without a ``QuerySpec``.
|
|
24
28
|
- Refuse ``expose_profile`` without ``allowed_profiles``.
|
|
25
29
|
"""
|
|
26
30
|
|
|
@@ -28,6 +32,7 @@ from __future__ import annotations
|
|
|
28
32
|
|
|
29
33
|
import functools
|
|
30
34
|
import inspect
|
|
35
|
+
import logging
|
|
31
36
|
import operator
|
|
32
37
|
import types
|
|
33
38
|
import typing
|
|
@@ -40,12 +45,23 @@ from typing import Any, NamedTuple
|
|
|
40
45
|
from loom.core.engine.compiler import UseCaseCompiler
|
|
41
46
|
from loom.core.engine.metrics import MetricsAdapter
|
|
42
47
|
from loom.core.engine.plan import ExecutionPlan
|
|
43
|
-
from loom.core.model import loom_type
|
|
48
|
+
from loom.core.model import UnsupportedBoundaryType, get_column_fields, loom_type, msgspec_type
|
|
44
49
|
from loom.core.model._json_schema import DEFS, DEFS_PREFIX, REF, definition, without_null
|
|
50
|
+
from loom.core.model.introspection import scalar_column_annotations
|
|
45
51
|
from loom.core.repository.abc.query import QuerySpec
|
|
52
|
+
from loom.core.use_case.field_ref import FieldRef
|
|
46
53
|
from loom.core.use_case.outcome import Created
|
|
47
54
|
from loom.rest.constants import QueryParam
|
|
48
|
-
from loom.rest.model import
|
|
55
|
+
from loom.rest.model import (
|
|
56
|
+
ALL,
|
|
57
|
+
DeclaredFields,
|
|
58
|
+
PaginationMode,
|
|
59
|
+
RestApiDefaults,
|
|
60
|
+
RestInterface,
|
|
61
|
+
RestRoute,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
_logger = logging.getLogger(__name__)
|
|
49
65
|
|
|
50
66
|
|
|
51
67
|
class _RouteOrigin(Enum):
|
|
@@ -333,6 +349,11 @@ class CompiledRoute:
|
|
|
333
349
|
parameter of this route.
|
|
334
350
|
query_fields: Parameters the route's ``Query()`` declares; empty
|
|
335
351
|
when the use case declares none.
|
|
352
|
+
filter_fields: ``(column, annotation)`` of each column a client may
|
|
353
|
+
filter the route's ``QuerySpec`` on, the annotation without its
|
|
354
|
+
``Annotated`` metadata; empty when the route filters nothing.
|
|
355
|
+
sort_fields: Columns a client may sort the route's ``QuerySpec`` by:
|
|
356
|
+
the declared ``sortable`` ones and the primary key.
|
|
336
357
|
result_type: Result type of ``execute`` without its ``Created``
|
|
337
358
|
member, answered with the route's ``status_code``.
|
|
338
359
|
created_type: Type a ``Created`` result wraps, answered with ``201``;
|
|
@@ -356,10 +377,109 @@ class CompiledRoute:
|
|
|
356
377
|
effective_requires_roles: tuple[str, ...] = ()
|
|
357
378
|
effective_max_limit: int = 1000
|
|
358
379
|
query_fields: tuple[QueryField, ...] = ()
|
|
380
|
+
filter_fields: tuple[tuple[str, Any], ...] = ()
|
|
381
|
+
sort_fields: tuple[str, ...] = ()
|
|
359
382
|
result_type: Any = Any
|
|
360
383
|
created_type: Any = None
|
|
361
384
|
|
|
362
385
|
|
|
386
|
+
@dataclass(frozen=True)
|
|
387
|
+
class _ColumnPolicy:
|
|
388
|
+
"""Resolves the columns a route lets a client filter or sort on (route → interface).
|
|
389
|
+
|
|
390
|
+
Args:
|
|
391
|
+
where: Route label used in compilation errors and warnings.
|
|
392
|
+
model: The use case's model, ``None`` when it declares none.
|
|
393
|
+
takes_query_spec: Whether the use case takes a ``QuerySpec``.
|
|
394
|
+
"""
|
|
395
|
+
|
|
396
|
+
where: str
|
|
397
|
+
model: type[Any] | None
|
|
398
|
+
takes_query_spec: bool
|
|
399
|
+
|
|
400
|
+
def resolve(
|
|
401
|
+
self, kind: str, on_route: DeclaredFields | None, on_interface: DeclaredFields | None
|
|
402
|
+
) -> dict[str, Any]:
|
|
403
|
+
"""Return ``{column: annotation}`` for the declared *kind* (``filterable``/``sortable``).
|
|
404
|
+
|
|
405
|
+
A declaration inherited by a route without a ``QuerySpec`` is ignored.
|
|
406
|
+
|
|
407
|
+
Raises:
|
|
408
|
+
InterfaceCompilationError: The route itself declares *kind* but
|
|
409
|
+
takes no ``QuerySpec``, the use case declares no model, or an
|
|
410
|
+
entry is not a scalar column of the route's model.
|
|
411
|
+
"""
|
|
412
|
+
if on_route is not None and not self.takes_query_spec:
|
|
413
|
+
raise InterfaceCompilationError(
|
|
414
|
+
f"{self.where} declares {kind} fields, but its use case takes no QuerySpec."
|
|
415
|
+
)
|
|
416
|
+
declared = on_route if on_route is not None else on_interface
|
|
417
|
+
if not declared or not self.takes_query_spec:
|
|
418
|
+
return {}
|
|
419
|
+
if self.model is None:
|
|
420
|
+
source = "declares" if on_route is not None else "inherits"
|
|
421
|
+
raise InterfaceCompilationError(
|
|
422
|
+
f"{self.where} {source} {kind} fields, but its use case declares no model; "
|
|
423
|
+
"declare it as UseCase[Model, ...]."
|
|
424
|
+
)
|
|
425
|
+
columns = scalar_column_annotations(self.model)
|
|
426
|
+
if declared is ALL:
|
|
427
|
+
_logger.warning(
|
|
428
|
+
"%s makes every scalar column of %s %s (ALL); declare the columns instead.",
|
|
429
|
+
self.where,
|
|
430
|
+
self.model.__name__,
|
|
431
|
+
kind,
|
|
432
|
+
)
|
|
433
|
+
return columns
|
|
434
|
+
resolved: dict[str, Any] = {}
|
|
435
|
+
for entry in declared:
|
|
436
|
+
name = self._column_name(kind, entry)
|
|
437
|
+
if name not in columns:
|
|
438
|
+
raise InterfaceCompilationError(
|
|
439
|
+
f"{self.where}: {kind} field {name!r} is not a scalar column of "
|
|
440
|
+
f"{self.model.__name__}."
|
|
441
|
+
)
|
|
442
|
+
resolved[name] = columns[name]
|
|
443
|
+
return resolved
|
|
444
|
+
|
|
445
|
+
def filter_fields(
|
|
446
|
+
self, on_route: DeclaredFields | None, on_interface: DeclaredFields | None
|
|
447
|
+
) -> tuple[tuple[str, Any], ...]:
|
|
448
|
+
"""Resolve ``filterable``, refusing a column whose type a query value cannot decode.
|
|
449
|
+
|
|
450
|
+
Raises:
|
|
451
|
+
InterfaceCompilationError: As :meth:`resolve`, or msgspec cannot
|
|
452
|
+
describe a declared column's type.
|
|
453
|
+
"""
|
|
454
|
+
columns = self.resolve("filterable", on_route, on_interface)
|
|
455
|
+
for name, annotation in columns.items():
|
|
456
|
+
try:
|
|
457
|
+
msgspec_type(annotation).schema()
|
|
458
|
+
except (TypeError, UnsupportedBoundaryType) as exc:
|
|
459
|
+
raise InterfaceCompilationError(
|
|
460
|
+
f"{self.where}: filterable field {name!r} has a type a query value "
|
|
461
|
+
f"cannot be decoded into: {exc}"
|
|
462
|
+
) from exc
|
|
463
|
+
return tuple(columns.items())
|
|
464
|
+
|
|
465
|
+
def default_order(self) -> tuple[str, ...]:
|
|
466
|
+
"""Primary-key columns, the order the route applies when the client names none."""
|
|
467
|
+
if self.model is None or not self.takes_query_spec:
|
|
468
|
+
return ()
|
|
469
|
+
fields = get_column_fields(self.model)
|
|
470
|
+
return tuple(name for name, info in fields.items() if info.field.primary_key)
|
|
471
|
+
|
|
472
|
+
def _column_name(self, kind: str, entry: FieldRef | str) -> str:
|
|
473
|
+
if not isinstance(entry, FieldRef):
|
|
474
|
+
return entry
|
|
475
|
+
if entry.root is not self.model:
|
|
476
|
+
raise InterfaceCompilationError(
|
|
477
|
+
f"{self.where}: {kind} field {'.'.join(entry.path)!r} is rooted at "
|
|
478
|
+
f"{entry.root!r}, not at the route's model."
|
|
479
|
+
)
|
|
480
|
+
return ".".join(entry.path)
|
|
481
|
+
|
|
482
|
+
|
|
363
483
|
class RestInterfaceCompiler:
|
|
364
484
|
"""Compiles RestInterface declarations into CompiledRoute records.
|
|
365
485
|
|
|
@@ -509,6 +629,13 @@ class RestInterfaceCompiler:
|
|
|
509
629
|
seen[key] = route
|
|
510
630
|
|
|
511
631
|
full_path = f"{prefix}{route.path}" if route.path else prefix or "/"
|
|
632
|
+
where = f"{iface_name}: route ({route.method.upper()}, {route.path!r})"
|
|
633
|
+
takes_query_spec = any(names_query_spec(pb.annotation) for pb in plan.param_bindings)
|
|
634
|
+
columns = _ColumnPolicy(
|
|
635
|
+
where=where,
|
|
636
|
+
model=route.use_case.describe_main_repo()[0],
|
|
637
|
+
takes_query_spec=takes_query_spec,
|
|
638
|
+
)
|
|
512
639
|
|
|
513
640
|
compiled.append(
|
|
514
641
|
CompiledRoute(
|
|
@@ -527,7 +654,16 @@ class RestInterfaceCompiler:
|
|
|
527
654
|
execute_param_types=self._resolve_execute_param_types(route.use_case),
|
|
528
655
|
effective_requires_roles=self._resolve_requires_roles(route, interface),
|
|
529
656
|
effective_max_limit=self._defaults.max_limit,
|
|
530
|
-
query_fields=self._resolve_query_fields(
|
|
657
|
+
query_fields=self._resolve_query_fields(where, takes_query_spec, route, plan),
|
|
658
|
+
filter_fields=columns.filter_fields(route.filterable, interface.filterable),
|
|
659
|
+
sort_fields=tuple(
|
|
660
|
+
dict.fromkeys(
|
|
661
|
+
(
|
|
662
|
+
*columns.resolve("sortable", route.sortable, interface.sortable),
|
|
663
|
+
*columns.default_order(),
|
|
664
|
+
)
|
|
665
|
+
)
|
|
666
|
+
),
|
|
531
667
|
result_type=result_type,
|
|
532
668
|
created_type=created_type,
|
|
533
669
|
)
|
|
@@ -583,13 +719,12 @@ class RestInterfaceCompiler:
|
|
|
583
719
|
|
|
584
720
|
@staticmethod
|
|
585
721
|
def _resolve_query_fields(
|
|
586
|
-
|
|
722
|
+
where: str, takes_query_spec: bool, route: RestRoute, plan: ExecutionPlan
|
|
587
723
|
) -> tuple[QueryField, ...]:
|
|
588
724
|
binding = plan.query_binding
|
|
589
725
|
if binding is None:
|
|
590
726
|
return ()
|
|
591
|
-
|
|
592
|
-
if any(names_query_spec(pb.annotation) for pb in plan.param_bindings):
|
|
727
|
+
if takes_query_spec:
|
|
593
728
|
raise InterfaceCompilationError(
|
|
594
729
|
f"{where}: Query() cannot be combined with a QuerySpec parameter."
|
|
595
730
|
)
|