loom-kernel 9.1.0__tar.gz → 9.2.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-9.1.0 → loom_kernel-9.2.0}/CHANGELOG.md +52 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/PKG-INFO +1 -1
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/polars/_reader.py +37 -27
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/polars/_writer.py +33 -7
- loom_kernel-9.2.0/src/loom/etl/checkpoint/_backends/_memory.py +60 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/checkpoint/_backends/_polars.py +21 -8
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/testing/__init__.py +6 -3
- loom_kernel-9.2.0/src/loom/etl/testing/_delta.py +86 -0
- loom_kernel-9.2.0/src/loom/etl/testing/_result.py +173 -0
- loom_kernel-9.2.0/src/loom/etl/testing/_runners.py +393 -0
- loom_kernel-9.2.0/src/loom/etl/testing/_scenario.py +260 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/testing/spark.py +31 -1
- loom_kernel-9.1.0/src/loom/etl/testing/_result.py +0 -88
- loom_kernel-9.1.0/src/loom/etl/testing/_runners.py +0 -183
- loom_kernel-9.1.0/src/loom/etl/testing/_scenario.py +0 -79
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/.gitignore +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/LICENSE +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/README.md +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/pyproject.toml +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/_concurrency.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/_filters.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/_paths.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/_roles.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/_startup.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/_transport.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/_usecase.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/a2a/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/a2a/_binding.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/a2a/_handlers.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/a2a/_rpc.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/a2a/card.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/a2a/events.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/a2a/server.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/abc.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/bootstrap.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/compiler/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/compiler/_compiler.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/compiler/_fingerprint.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/compiler/_plan.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/compiler/phases/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/compiler/phases/_capabilities.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/compiler/phases/_conversation.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/compiler/phases/_feedable.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/compiler/phases/_hook.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/compiler/phases/_instructions.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/compiler/phases/_limits.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/compiler/phases/_model_role.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/compiler/phases/_output.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/compiler/phases/_state.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/declarative/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/declarative/_envelope.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/declarative/_schema.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/declarative/_v1.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/declarative/schemas/agent-spec-v1.schema.json +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/describe.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/_a2a.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/_capabilities.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/_engine.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/_errors.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/_escape.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/_events.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/_guards.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/_history.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/_instructions.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/_limits.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/_mcp.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/_models.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/_native.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/_output.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/_returns.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/_schemas.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/_spec.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/extras/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/extras/a2a.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/extras/handlebars.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/extras/mcp.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/extras/skills.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/provider.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/providers/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/providers/_shared.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/providers/anthropic.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/providers/bedrock.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/providers/gateway.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/providers/openai.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/engines/pydantic_ai/providers/typesafe.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/errors.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/etl/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/etl/_batch.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/etl/_columns.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/etl/_frames.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/etl/_ledger.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/etl/_runner.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/etl/_validation.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/fastapi/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/fastapi/endpoints.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/fastapi/response.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/fastapi/streaming.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/inference.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/pricing.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/registry.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/remote_auth.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/runtime/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/runtime/_bounded.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/runtime/_chain.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/runtime/_conversation.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/runtime/_grants.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/runtime/_handle.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/runtime/_health.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/runtime/_hooks.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/runtime/_lifecycle.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/runtime/_limits.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/runtime/_mcp.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/validate/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/ai/validate/__main__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/celery/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/celery/auto.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/celery/bootstrap.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/celery/config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/celery/constants.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/celery/runner.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/celery/service.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/cli/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/cli/app.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/cli/check.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/cli/schema.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/async_bridge.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/authz/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/authz/_decide.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/authz/_grants.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/authz/_roles.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/authz/_scope.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/authz/elevation.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/authz/product.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/backend/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/backend/core_model.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/backend/protocol.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/backend/scoped_ddl.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/backend/sqlalchemy.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/bootstrap/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/bootstrap/bootstrap.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/bootstrap/kernel.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/cache/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/cache/_batching.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/cache/_single_flight.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/cache/abc/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/cache/abc/backend.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/cache/abc/config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/cache/abc/dependency.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/cache/calls.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/cache/codec.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/cache/decorators.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/cache/dependency.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/cache/errors.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/cache/gateway.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/cache/keys.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/cache/memory.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/cache/repository.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/cache/result_codec.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/cache/serializer.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/cache/wiring.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/checks.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/command/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/command/adapter.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/command/base.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/command/field.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/command/introspection.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/compiler.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/config/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/config/_includes.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/config/_resolver_utils.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/config/binder.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/config/checks.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/config/configurable.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/config/context.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/config/convert.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/config/errors.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/config/keys.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/config/loader.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/config/model.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/config/observability.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/config/overrides.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/config/resolver.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/config/retired.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/config/secrets.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/config/ssm.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/connections/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/connections/_base.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/connections/aws/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/connections/aws/client.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/connections/aws/config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/connections/aws/loader.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/connections/clickhouse/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/connections/clickhouse/client.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/connections/clickhouse/config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/connections/clickhouse/loader.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/connections/mongo/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/connections/mongo/client.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/connections/mongo/config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/connections/mongo/loader.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/connections/relational.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/contracts/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/contracts/manifest.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/di/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/di/container.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/di/scope.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/discovery/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/discovery/_utils.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/discovery/base.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/discovery/interfaces.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/discovery/manifest.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/discovery/modules.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/engine/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/engine/compilable.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/engine/compiler.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/engine/events.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/engine/executor.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/engine/metrics.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/engine/plan.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/engine/post_commit.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/environment.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/errors/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/errors/codes.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/errors/errors.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/expr/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/expr/eval.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/expr/nodes.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/expr/refs.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/identity/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/identity/context.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/identity/identity.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/identity/issuer.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/identity/wire.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/introspection/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/introspection/base.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/introspection/describe.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/job/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/job/callback.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/job/context.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/job/handle.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/job/job.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/job/service.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/locator.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/logger/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/logger/abc.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/logger/checks.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/logger/config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/logger/context.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/logger/registry.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/logger/structlogger.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/model/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/model/_json_schema.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/model/_loom_type.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/model/base.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/model/convert.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/model/enums.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/model/field.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/model/introspection.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/model/partition.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/model/privilege.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/model/projection.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/model/redaction.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/model/relation.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/model/scoped.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/model/struct.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/model/timestamped.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/model/types.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/model/types_postgres.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/observability/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/observability/config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/observability/event.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/observability/observer/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/observability/observer/noop.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/observability/observer/otel.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/observability/observer/structlog.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/observability/otel_ids.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/observability/protocol.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/observability/runtime.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/observability/span.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/observability/topology.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/persistence/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/persistence/abc.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/persistence/database.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/persistence/none.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/persistence/profile.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/persistence/registry.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/plugins/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/plugins/entrypoints.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/plugins/optional.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/projection/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/projection/loaders.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/projection/runtime.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/abc/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/abc/checks.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/abc/cursor.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/abc/errors.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/abc/query.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/abc/query_compiler.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/abc/repo_for.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/abc/repository.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/abc/session_scope.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/dynamodb/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/dynamodb/backend.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/dynamodb/registry.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/dynamodb/repository.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/dynamodb/uow.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/mongo/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/mongo/backend.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/mongo/ids.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/mongo/query_compiler.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/mongo/registry.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/mongo/repository.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/mongo/uow.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/mongo/values.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/mutation.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/registration.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/registry.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/_pool_metrics.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/backend.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/integrity.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/loaders.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/migrations/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/migrations/env_template.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/migrations/hook.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/migrations/operations.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/migrations/runners.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/mixins.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/model.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/profile_loader.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/projection.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/query_compiler/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/query_compiler/compiler.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/query_compiler/cursor.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/query_compiler/errors.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/query_compiler/filters.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/query_compiler/ordering.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/query_compiler/paths.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/query_compiler/subquery.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/registry.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/repository.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/rls/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/rls/bootstrap.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/rls/config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/rls/elevate.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/rls/guard/0001.sql +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/rls/guard/0002.sql +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/rls/guard/preflight.sql +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/rls/guard_manifest.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/rls/integrity.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/rls/partitions.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/rls/provider.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/rls/schema.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/rls/sources.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/rls/verify.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/session_manager.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/session_settings.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/transactional.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/uow.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/repository/sqlalchemy/values.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/response/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/response/base.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/routing/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/routing/ref.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/routing/resolver.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/runner.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/schema/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/schema/schema_mode.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/schema_names.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/sql/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/sql/abc/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/sql/abc/contracts.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/sql/abc/errors.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/sql/caller_bound.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/sql/clickhouse/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/sql/clickhouse/_client.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/sql/clickhouse/executor.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/sql/clickhouse/registry.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/sql/config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/sql/roles.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/sql/service.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/symbols.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/tracing/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/tracing/context.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/transaction.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/transport/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/transport/adapter.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/uow/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/uow/abc.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/uow/context.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/use_case/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/use_case/_predicates.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/use_case/agent_markers.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/use_case/compute.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/use_case/constants.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/use_case/factory.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/use_case/field_ref.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/use_case/invoker.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/use_case/keys.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/use_case/markers.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/use_case/mcp_markers.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/use_case/outcome.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/use_case/registry.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/use_case/rule.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/core/use_case/use_case.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/_uri.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/_format_registry.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/_historify/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/_historify/_common.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/_historify/_log.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/_historify/_ops.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/_historify/_snapshot.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/_historify/_transform.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/_merge.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/_path_template.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/_predicate.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/_schema_aligner/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/_schema_aligner/_aligner.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/_schema_aligner/_policy.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/_write_policy.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/polars/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/polars/_dtype.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/polars/_file_writer.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/polars/_frame.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/polars/_historify.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/polars/_predicate.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/polars/_schema.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/polars/_schema_aligner.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/polars/_streaming.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/polars/provider.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/spark/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/spark/_dtype.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/spark/_historify.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/spark/_reader.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/spark/_schema.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/spark/_schema_aligner.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/spark/_writer.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/backends/spark/provider.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/checkpoint/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/checkpoint/_backends/_spark.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/checkpoint/_cleaners.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/checkpoint/_options.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/checkpoint/_paths.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/checkpoint/_scope.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/checkpoint/_store.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/compiler/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/compiler/_binding.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/compiler/_compiler.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/compiler/_errors.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/compiler/_filter.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/compiler/_plan.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/compiler/_validators.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/compiler/_validators_agents.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/compiler/_validators_config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/compiler/_validators_plan.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/compiler/_validators_step.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/_format.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/_read_options.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/_utils.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/_with_agent.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/_write_options.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/expr/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/expr/_params.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/expr/_predicate.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/expr/_predicate_dialect.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/expr/_refs.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/source/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/source/_from.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/source/_from_clickhouse.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/source/_from_config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/source/_from_dynamodb.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/source/_from_mongo.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/source/_specs.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/target/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/target/_client.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/target/_errors.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/target/_file.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/target/_history/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/target/_history/_builder.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/target/_history/_enums.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/target/_history/_errors.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/target/_history/_report.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/target/_history/_spec.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/target/_into.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/target/_table.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/declarative/target/_temp.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/executor/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/executor/_agents.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/executor/_dispatcher.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/executor/_executor.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/io/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/io/_clickhouse_connection.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/io/_registry.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/io/sources/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/io/sources/_clickhouse.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/io/sources/_dynamodb.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/io/sources/_dynamodb_items.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/io/sources/_dynamodb_predicate.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/io/sources/_mongo.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/io/sources/_mongo_batch.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/io/sources/_mongo_bson.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/io/sources/_mongo_predicate.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/io/sources/_serialization.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/io/targets/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/io/targets/_clickhouse.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/lineage/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/lineage/_config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/lineage/_observer.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/lineage/_records.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/lineage/sinks/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/lineage/sinks/_protocol.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/lineage/sinks/_table.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/lineage/sinks/_writer.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/maintenance/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/maintenance/_builder.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/maintenance/_ops.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/maintenance/_protocol.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/maintenance/_runner.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/maintenance/_step.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/maintenance/backends/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/maintenance/backends/_delta_rs.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/pipeline/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/pipeline/_generics.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/pipeline/_params.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/pipeline/_pipeline.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/pipeline/_process.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/pipeline/_sql.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/pipeline/_step.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/pipeline/_step_client.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/pipeline/_step_sql.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/runner/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/runner/_agents.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/runner/_providers.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/runner/_wiring.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/runner/config_loader.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/runner/core.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/runtime/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/runtime/_config_values.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/runtime/contracts.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/schema/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/schema/_contract.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/schema/_schema.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/storage/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/storage/_config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/storage/_file_locator.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/storage/_locator.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/storage/routing.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/etl/testing/_stubs.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/_async.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/_config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/_ctx.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/_flow_yaml.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/_meta.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/_placeholders.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/_summary.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/deploy/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/deploy/_discovery.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/deploy/_schedule.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/deploy/_yaml_etls.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/deploy/entrypoint.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/flow/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/flow/_assemble.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/flow/_backfill.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/flow/_backfill_body.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/flow/_body.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/flow/_common.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/flow/_factory.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/flow/_hooks.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/flow/_maintenance.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/flow/_params.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/flow/_run_name.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/flow/_runtime.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/flow/_signature.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/flow/_stages.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/manifest/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/manifest/_model.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/manifest/_s3.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/manifest/_store.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/notify/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/notify/_event.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/notify/_factory.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/notify/_format.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/notify/_port.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/notify/_slack.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/notify/_sns.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/observer/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/observer/_flow.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/observer/_logging_bridge.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/observer/_manifest.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prefect/observer/_task_run.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prometheus/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prometheus/_instruments.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prometheus/adapter.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prometheus/db_pool.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prometheus/kafka.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prometheus/lifecycle.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/prometheus/middleware.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/py.typed +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/_body.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/adapter.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/auth/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/auth/abc.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/auth/config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/auth/jwt.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/auth/middleware.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/autocrud.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/checks.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/compiler.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/constants.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/cors.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/errors.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/fastapi/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/fastapi/_auto_ai.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/fastapi/_auto_auth.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/fastapi/_auto_sql.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/fastapi/_errors.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/fastapi/_exclusions.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/fastapi/app.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/fastapi/auto.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/fastapi/health.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/fastapi/openapi.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/fastapi/response.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/fastapi/router_runtime.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/fastapi/sql.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/middleware.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/model.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/rest/rest_adapter.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/_adapter.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/_batch_spans.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/_commit_tracker.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/_error_boundary.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/_errors.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/_operators.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/_resource_manager.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/_runtime_io.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/_sink_registry.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/handlers/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/handlers/_shared.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/handlers/boundary.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/handlers/dispatcher.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/handlers/routing.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/handlers/scopes.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/handlers/shapes.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/handlers/steps.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/handlers/storage.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/bytewax/runner.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/compiler/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/compiler/_bindings.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/compiler/_compiler.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/compiler/_errors.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/compiler/_plan.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/compiler/phases/build_plan.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/compiler/phases/validate.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/core/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/core/_errors.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/core/_exceptions.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/core/_message.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/core/_tracing.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/core/_typing.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/graph/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/graph/_flow.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/kafka/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/kafka/_codec.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/kafka/_config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/kafka/_errors.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/kafka/_key_resolver.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/kafka/_message.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/kafka/_record.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/kafka/_wire.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/kafka/client/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/kafka/client/_consumer.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/kafka/client/_producer.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/kafka/client/_protocol.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/kafka/client/_retry.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/kafka/message/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/kafka/message/_consumer.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/kafka/message/_producer.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/kafka/message/_protocol.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/mongo/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/mongo/_bytewax_source.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/mongo/_config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/mongo/_event.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/mongo/_normalize.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_boundary.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_branches.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_broadcast.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_capabilities.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_decompose.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_expand_routes.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_expr_eval.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_fork.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_helpers.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_mongo.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_protocols.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_router.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_shape.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_sink.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_step.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_table/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_table/_clickhouse.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_table/_delta.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_table/_sqlalchemy.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_table/common.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_table/config.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/_with.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/nodes/refs.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/streaming/testing.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/testing/__init__.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/testing/agents.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/testing/golden.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/testing/http_harness.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/testing/in_memory.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/testing/repository_harness.py +0 -0
- {loom_kernel-9.1.0 → loom_kernel-9.2.0}/src/loom/testing/runner.py +0 -0
|
@@ -23,6 +23,58 @@
|
|
|
23
23
|
update and unmatched insert, with no delete clause. `UpsertSpec` gains
|
|
24
24
|
`delete_flag`; `UpsertDeleteFlagError` and
|
|
25
25
|
`UnsupportedUpsertDeleteFlagError` are exported from `loom.etl`.
|
|
26
|
+
- **etl:** `PolarsStepRunner` tests steps that use temps and real Delta
|
|
27
|
+
targets. `FromTemp`/`IntoTemp` work through an in-memory `CheckpointStore`
|
|
28
|
+
that keeps the production checks (an `IntoTemp` step returning a
|
|
29
|
+
`pl.DataFrame` raises `TypeError`, fan-in aligns to the first schema,
|
|
30
|
+
RUN then CORRELATION lookup); temps persist across `run()` calls of one
|
|
31
|
+
runner, which keeps a fixed run context. `seed_temp(name, data, columns,
|
|
32
|
+
*, schema=)` seeds a temp by `temp_name` from row tuples or a Polars frame;
|
|
33
|
+
`seed_temp(result)` seeds the `StepResult` of an `IntoTemp` step under the
|
|
34
|
+
name it wrote. A seeded temp lives in RUN scope, which `FromTemp` reads
|
|
35
|
+
before CORRELATION scope. A step whose target is `IntoTemp` returns, as its
|
|
36
|
+
`StepResult`, the temp read from the scope the step wrote (the accumulated
|
|
37
|
+
temp for fan-in) instead of raising "Step produced no output". `seed` and
|
|
38
|
+
`ETLScenario.with_table` accept `schema=` (loom types) so empty and all-null
|
|
39
|
+
columns keep their dtype. `PolarsStepRunner(*scenarios, delta_root=)`
|
|
40
|
+
applies scenarios at construction; with `delta_root` the real
|
|
41
|
+
`PolarsSourceReader`/`PolarsTargetWriter` run on that directory, seeds are
|
|
42
|
+
written as Delta tables (a column left without dtype raises `SchemaError`
|
|
43
|
+
asking for `schema=`), missing targets are created, and `table(ref)`
|
|
44
|
+
returns the final state. `StepResult` keeps the step's `target` spec and
|
|
45
|
+
derives `temp_name` and `delete_flag` from it. `StepResult.deletes` counts
|
|
46
|
+
the rows the step emitted with its upsert `delete_flag` set, and raises
|
|
47
|
+
`UpsertDeleteFlagError` when the output lacks the flag column or it is not
|
|
48
|
+
boolean; `StepResult.merged` returns the `MergeMetrics(inserted, updated,
|
|
49
|
+
deleted)` the Delta MERGE applied, only with `delta_root` and an upsert or
|
|
50
|
+
update that merged into an existing table. `ETLScenario` gains `with_temp`,
|
|
51
|
+
`after(step, params)` and `+`. `after()` runs the `IntoTemp` step once, on
|
|
52
|
+
a fresh in-memory runner seeded only with the scenario entries before it
|
|
53
|
+
(not the runner's config or other seeds), and seeds the memoized output on
|
|
54
|
+
every application. The scenario `repr` lists `tables`, `temps` and
|
|
55
|
+
`after` separately.
|
|
56
|
+
`SparkStepRunner.seed_temp` and `SparkStepRunner.seed(..., schema=...)`
|
|
57
|
+
raise `NotImplementedError`. Cache scenarios and frames, not runners: tests
|
|
58
|
+
that mutate state need a function-scoped runner on their own `tmp_path`.
|
|
59
|
+
|
|
60
|
+
## ⚠ Behaviour changes
|
|
61
|
+
|
|
62
|
+
### etl
|
|
63
|
+
|
|
64
|
+
- **etl:** the `PolarsStepRunner` reader applies what a `FromTable` or
|
|
65
|
+
`FromFile` declares, as `PolarsSourceReader` does: `.where()` filters,
|
|
66
|
+
`.columns()` projects (an unknown column raises
|
|
67
|
+
`polars.exceptions.ColumnNotFoundError`), `with_schema` casts and
|
|
68
|
+
`parse_json` decodes. Before, the seeded frame reached the step unchanged;
|
|
69
|
+
a seed that was already decoded for a `parse_json` column must now hold the
|
|
70
|
+
JSON text.
|
|
71
|
+
- **etl:** `ETLScenario` is immutable: `with_table` returns a new scenario
|
|
72
|
+
and no longer changes the one it is called on. Chained calls work as before;
|
|
73
|
+
code that called `scenario.with_table(...)` without using the result must
|
|
74
|
+
use it.
|
|
75
|
+
- **etl:** `StepRunnerProto` requires `seed(..., *, schema=None)`,
|
|
76
|
+
`seed_temp` and `run`. `ETLScenario.apply` still calls `seed(ref, data,
|
|
77
|
+
columns)` positionally when no schema is declared.
|
|
26
78
|
|
|
27
79
|
# 🚀 Releases 2.1.3 to 9.0.0
|
|
28
80
|
|
|
@@ -296,17 +296,13 @@ class PolarsSourceReader(SourceReader):
|
|
|
296
296
|
target.location.uri,
|
|
297
297
|
storage_options=target.location.storage_options or None,
|
|
298
298
|
)
|
|
299
|
-
|
|
300
|
-
for predicate in spec.predicates:
|
|
301
|
-
frame = frame.filter(predicate_to_polars(predicate, params))
|
|
302
|
-
|
|
303
|
-
return self._finalize_source_frame(frame, spec)
|
|
299
|
+
return _finalize_source_frame(frame, spec, params)
|
|
304
300
|
|
|
305
301
|
def _read_file(self, spec: FileSourceSpec, params_instance: Any) -> pl.LazyFrame:
|
|
306
302
|
"""Read file (CSV, JSON, XLSX, Parquet), resolving alias if needed."""
|
|
307
303
|
path = self._resolve_file_path(spec, params_instance)
|
|
308
304
|
frame = self._read_file_by_format(path, spec.format, spec.read_options)
|
|
309
|
-
return
|
|
305
|
+
return _finalize_source_frame(frame, spec, params_instance)
|
|
310
306
|
|
|
311
307
|
def _resolve_file_path(self, spec: FileSourceSpec, params_instance: Any) -> str:
|
|
312
308
|
"""Return the physical URI for *spec*, resolving alias and template."""
|
|
@@ -318,20 +314,6 @@ class PolarsSourceReader(SourceReader):
|
|
|
318
314
|
role="FromFile",
|
|
319
315
|
)
|
|
320
316
|
|
|
321
|
-
def _finalize_source_frame(
|
|
322
|
-
self,
|
|
323
|
-
frame: pl.LazyFrame,
|
|
324
|
-
spec: TableSourceSpec | FileSourceSpec,
|
|
325
|
-
) -> pl.LazyFrame:
|
|
326
|
-
"""Apply post-read transformations: columns, schema, json decode."""
|
|
327
|
-
if spec.columns:
|
|
328
|
-
frame = frame.select(list(spec.columns))
|
|
329
|
-
if spec.schema:
|
|
330
|
-
frame = self._apply_source_schema(frame, spec.schema)
|
|
331
|
-
if spec.json_columns:
|
|
332
|
-
frame = decode_json_columns(frame, spec.json_columns)
|
|
333
|
-
return frame
|
|
334
|
-
|
|
335
317
|
@staticmethod
|
|
336
318
|
def _read_file_by_format(path: str, format: Any, options: Any) -> pl.LazyFrame:
|
|
337
319
|
"""Dispatch to format-specific reader."""
|
|
@@ -380,14 +362,42 @@ class PolarsSourceReader(SourceReader):
|
|
|
380
362
|
def _read_parquet(path: str, _options: Any) -> pl.LazyFrame:
|
|
381
363
|
return pl.scan_parquet(path)
|
|
382
364
|
|
|
383
|
-
@staticmethod
|
|
384
|
-
def _apply_source_schema(frame: pl.LazyFrame, schema: tuple[ColumnSchema, ...]) -> pl.LazyFrame:
|
|
385
|
-
"""Cast declared columns to their Loom type."""
|
|
386
|
-
if not schema:
|
|
387
|
-
return frame
|
|
388
365
|
|
|
389
|
-
|
|
390
|
-
|
|
366
|
+
def _finalize_source_frame(
|
|
367
|
+
frame: pl.LazyFrame,
|
|
368
|
+
spec: TableSourceSpec | FileSourceSpec,
|
|
369
|
+
params_instance: Any,
|
|
370
|
+
) -> pl.LazyFrame:
|
|
371
|
+
"""Apply what *spec* declares on top of a raw scan, as :class:`PolarsSourceReader` does.
|
|
372
|
+
|
|
373
|
+
Filters by the table predicates first, then projects ``columns``, casts the
|
|
374
|
+
declared ``schema`` and decodes ``json_columns``. Returns *frame* itself
|
|
375
|
+
when the spec declares none of them.
|
|
376
|
+
|
|
377
|
+
Args:
|
|
378
|
+
frame: Raw frame scanned or seeded for the source.
|
|
379
|
+
spec: Compiled table or file source spec.
|
|
380
|
+
params_instance: Concrete params the predicates resolve against.
|
|
381
|
+
|
|
382
|
+
Returns:
|
|
383
|
+
The lazy frame the step receives.
|
|
384
|
+
"""
|
|
385
|
+
if isinstance(spec, TableSourceSpec):
|
|
386
|
+
for predicate in spec.predicates:
|
|
387
|
+
frame = frame.filter(predicate_to_polars(predicate, params_instance))
|
|
388
|
+
if spec.columns:
|
|
389
|
+
frame = frame.select(list(spec.columns))
|
|
390
|
+
if spec.schema:
|
|
391
|
+
frame = _apply_source_schema(frame, spec.schema)
|
|
392
|
+
if spec.json_columns:
|
|
393
|
+
frame = decode_json_columns(frame, spec.json_columns)
|
|
394
|
+
return frame
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def _apply_source_schema(frame: pl.LazyFrame, schema: tuple[ColumnSchema, ...]) -> pl.LazyFrame:
|
|
398
|
+
"""Cast declared columns to their Loom type."""
|
|
399
|
+
cast_exprs = [pl.col(col.name).cast(loom_type_to_polars(col.dtype)) for col in schema]
|
|
400
|
+
return frame.with_columns(cast_exprs)
|
|
391
401
|
|
|
392
402
|
|
|
393
403
|
def execute_sql(frames: dict[str, pl.LazyFrame], query: str) -> pl.LazyFrame:
|
|
@@ -7,6 +7,7 @@ from typing import Any, Literal
|
|
|
7
7
|
|
|
8
8
|
import polars as pl
|
|
9
9
|
from deltalake import CommitProperties, DeltaTable, WriterProperties, write_deltalake
|
|
10
|
+
from deltalake.exceptions import TableNotFoundError
|
|
10
11
|
from deltalake.table import TableMerger
|
|
11
12
|
|
|
12
13
|
from loom.core.logger import get_logger
|
|
@@ -57,6 +58,7 @@ from ._file_writer import PolarsFileWriter
|
|
|
57
58
|
from ._streaming import partition_rows_from_spool, spool_lazy_to_arrow_reader
|
|
58
59
|
|
|
59
60
|
_log = get_logger(__name__)
|
|
61
|
+
_COMMIT_EVENT = "delta write commit"
|
|
60
62
|
|
|
61
63
|
|
|
62
64
|
def _log_write_start(
|
|
@@ -78,23 +80,39 @@ def _log_write_start(
|
|
|
78
80
|
)
|
|
79
81
|
|
|
80
82
|
|
|
83
|
+
def _open_delta_table(location: TableLocation) -> DeltaTable | None:
|
|
84
|
+
"""Open the Delta table at *location*, or return ``None`` when it does not exist."""
|
|
85
|
+
try:
|
|
86
|
+
return DeltaTable(location.uri, storage_options=location.storage_options or None)
|
|
87
|
+
except TableNotFoundError:
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _last_commit(table: DeltaTable) -> tuple[int, dict[str, Any]]:
|
|
92
|
+
"""Return the version of *table* and its latest commit entry (empty without history)."""
|
|
93
|
+
history = table.history(1)
|
|
94
|
+
return table.version(), (history[0] if history else {})
|
|
95
|
+
|
|
96
|
+
|
|
81
97
|
def _log_write_commit(mode: str, location: TableLocation) -> None:
|
|
82
98
|
try:
|
|
83
|
-
dt =
|
|
84
|
-
|
|
85
|
-
|
|
99
|
+
dt = _open_delta_table(location)
|
|
100
|
+
if dt is None:
|
|
101
|
+
_log.info(_COMMIT_EVENT, mode=mode, uri=location.uri, metrics="unavailable")
|
|
102
|
+
return
|
|
103
|
+
version, entry = _last_commit(dt)
|
|
86
104
|
metrics = entry.get("operationMetrics") or {}
|
|
87
105
|
_log.info(
|
|
88
|
-
|
|
106
|
+
_COMMIT_EVENT,
|
|
89
107
|
mode=mode,
|
|
90
108
|
uri=location.uri,
|
|
91
|
-
version=
|
|
109
|
+
version=version,
|
|
92
110
|
rows=int(metrics.get("numOutputRows", 0)) or None,
|
|
93
111
|
bytes=int(metrics.get("numOutputBytes", 0)) or None,
|
|
94
112
|
files=int(metrics.get("numAddedFiles", 0)) or None,
|
|
95
113
|
)
|
|
96
114
|
except Exception: # noqa: BLE001
|
|
97
|
-
_log.info(
|
|
115
|
+
_log.info(_COMMIT_EVENT, mode=mode, uri=location.uri, metrics="unavailable")
|
|
98
116
|
|
|
99
117
|
|
|
100
118
|
def _check_null_dtype_columns_lazy(frame: pl.LazyFrame) -> None:
|
|
@@ -133,7 +151,15 @@ def _require_delete_flag(frame: pl.LazyFrame, spec: UpsertSpec, flag: str) -> No
|
|
|
133
151
|
flag,
|
|
134
152
|
f"conflicts with {conflict}; the flag column is not written to the target",
|
|
135
153
|
)
|
|
136
|
-
|
|
154
|
+
_require_boolean_flag_column(frame.collect_schema(), flag)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _require_boolean_flag_column(schema: pl.Schema, flag: str) -> None:
|
|
158
|
+
"""Check that *schema* has *flag* as a boolean column.
|
|
159
|
+
|
|
160
|
+
Raises:
|
|
161
|
+
UpsertDeleteFlagError: *flag* is missing from *schema*, or is not boolean.
|
|
162
|
+
"""
|
|
137
163
|
if flag not in schema:
|
|
138
164
|
raise UpsertDeleteFlagError(flag, "is missing from the source frame")
|
|
139
165
|
dtype = schema[flag]
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""In-memory Polars backend for CheckpointStore, used by the step test runners."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import polars as pl
|
|
8
|
+
|
|
9
|
+
from loom.etl.checkpoint._backends._polars import (
|
|
10
|
+
_align_lazy_to_schema,
|
|
11
|
+
_checkpoint_key,
|
|
12
|
+
_require_polars_lazy_frame,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class _InMemoryCheckpointBackend:
|
|
17
|
+
"""Polars checkpoint backend holding collected frames in a dict.
|
|
18
|
+
|
|
19
|
+
Keeps the checks of the Arrow IPC backend: only a ``LazyFrame`` is accepted,
|
|
20
|
+
and a fan-in write is aligned to the schema of the first write for that name.
|
|
21
|
+
Frames are collected at write time, so errors surface at the write like the
|
|
22
|
+
real materialisation does. It remembers the last intermediate written, so a
|
|
23
|
+
runner can return what a step wrote without rebuilding scope paths. Not
|
|
24
|
+
thread-safe: one instance serves one runner.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self) -> None:
|
|
28
|
+
self._parts: dict[str, list[pl.DataFrame]] = {}
|
|
29
|
+
self._schemas: dict[str, pl.Schema] = {}
|
|
30
|
+
self._last_key: str | None = None
|
|
31
|
+
|
|
32
|
+
def probe(self, name: str, base: str) -> pl.LazyFrame | None:
|
|
33
|
+
"""Return the concatenated parts stored for *name* under *base*, or ``None``."""
|
|
34
|
+
return self._probe_key(_checkpoint_key(name, base))
|
|
35
|
+
|
|
36
|
+
def probe_last(self) -> pl.LazyFrame | None:
|
|
37
|
+
"""Return the intermediate of the last :meth:`write`, or ``None`` before any."""
|
|
38
|
+
return None if self._last_key is None else self._probe_key(self._last_key)
|
|
39
|
+
|
|
40
|
+
def write(self, name: str, base: str, data: Any, *, append: bool) -> None:
|
|
41
|
+
"""Store *data* for *name* under *base*, appending a part in fan-in mode."""
|
|
42
|
+
frame = _require_polars_lazy_frame(data)
|
|
43
|
+
key = _checkpoint_key(name, base)
|
|
44
|
+
existing = self._schemas.get(key)
|
|
45
|
+
if existing is None:
|
|
46
|
+
self._schemas[key] = frame.collect_schema()
|
|
47
|
+
elif append:
|
|
48
|
+
frame = _align_lazy_to_schema(frame, existing)
|
|
49
|
+
collected = frame.collect()
|
|
50
|
+
if append:
|
|
51
|
+
self._parts.setdefault(key, []).append(collected)
|
|
52
|
+
else:
|
|
53
|
+
self._parts[key] = [collected]
|
|
54
|
+
self._last_key = key
|
|
55
|
+
|
|
56
|
+
def _probe_key(self, key: str) -> pl.LazyFrame | None:
|
|
57
|
+
parts = self._parts.get(key)
|
|
58
|
+
if not parts:
|
|
59
|
+
return None
|
|
60
|
+
return pl.concat(parts, how="vertical").lazy()
|
|
@@ -23,6 +23,20 @@ def _is_polars_lazy_frame(value: Any) -> TypeGuard[pl.LazyFrame]:
|
|
|
23
23
|
return isinstance(value, pl.LazyFrame)
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
def _require_polars_lazy_frame(data: Any) -> pl.LazyFrame:
|
|
27
|
+
"""Return *data* as a LazyFrame, or raise the error every Polars backend raises.
|
|
28
|
+
|
|
29
|
+
Raises:
|
|
30
|
+
TypeError: When *data* is not a :class:`polars.LazyFrame`.
|
|
31
|
+
"""
|
|
32
|
+
if not _is_polars_lazy_frame(data):
|
|
33
|
+
raise TypeError(
|
|
34
|
+
f"Polars backend expects polars.LazyFrame, got {type(data).__qualname__!r}. "
|
|
35
|
+
"Verify that CheckpointStore was constructed without a SparkSession."
|
|
36
|
+
)
|
|
37
|
+
return data
|
|
38
|
+
|
|
39
|
+
|
|
26
40
|
class _PolarsCheckpointBackend:
|
|
27
41
|
"""Polars Arrow IPC backend with atomic write-then-rename."""
|
|
28
42
|
|
|
@@ -47,14 +61,8 @@ class _PolarsCheckpointBackend:
|
|
|
47
61
|
|
|
48
62
|
def write(self, name: str, base: str, data: Any, *, append: bool) -> None:
|
|
49
63
|
"""Sink *data* as Arrow IPC atomically (write-then-rename)."""
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
f"Polars backend expects polars.LazyFrame, got {type(data).__qualname__!r}. "
|
|
53
|
-
"Verify that CheckpointStore was constructed without a SparkSession."
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
frame = data
|
|
57
|
-
key = f"{base}/{name}"
|
|
64
|
+
frame = _require_polars_lazy_frame(data)
|
|
65
|
+
key = _checkpoint_key(name, base)
|
|
58
66
|
|
|
59
67
|
with self._lock:
|
|
60
68
|
existing = self._schemas.get(key)
|
|
@@ -82,6 +90,11 @@ class _PolarsCheckpointBackend:
|
|
|
82
90
|
return None
|
|
83
91
|
|
|
84
92
|
|
|
93
|
+
def _checkpoint_key(name: str, base: str) -> str:
|
|
94
|
+
"""Return the key identifying the intermediate *name* under *base*."""
|
|
95
|
+
return f"{base}/{name}"
|
|
96
|
+
|
|
97
|
+
|
|
85
98
|
def _arrow_path(name: str, base: str) -> str:
|
|
86
99
|
return _join_path(base, f"{name}.arrow")
|
|
87
100
|
|
|
@@ -6,9 +6,11 @@ Public API
|
|
|
6
6
|
* :class:`StubSourceReader` — in-memory reader, keyed by table reference.
|
|
7
7
|
* :class:`StubTargetWriter` — in-memory writer that captures written frames.
|
|
8
8
|
* :class:`StubRunObserver` — in-memory observer that records lifecycle events.
|
|
9
|
-
* :class:`PolarsStepRunner` — Polars
|
|
9
|
+
* :class:`PolarsStepRunner` — Polars step harness, in memory or on a local
|
|
10
|
+
Delta root (``delta_root=``).
|
|
10
11
|
* :class:`StepResult` — unified assertion surface for step output.
|
|
11
|
-
* :class:`
|
|
12
|
+
* :class:`MergeMetrics` — rows a Delta MERGE applied (``StepResult.merged``).
|
|
13
|
+
* :class:`ETLScenario` — backend-agnostic, immutable, composable seed dataset.
|
|
12
14
|
* :class:`StepRunnerProto` — protocol satisfied by both runner types.
|
|
13
15
|
|
|
14
16
|
Pytest fixtures
|
|
@@ -36,7 +38,7 @@ except ModuleNotFoundError as exc: # pragma: no cover - packaging guard
|
|
|
36
38
|
"loom.etl.testing defines pytest fixtures: install loom-kernel[testing]"
|
|
37
39
|
) from exc
|
|
38
40
|
|
|
39
|
-
from loom.etl.testing._result import StepResult
|
|
41
|
+
from loom.etl.testing._result import MergeMetrics, StepResult
|
|
40
42
|
from loom.etl.testing._runners import PolarsStepRunner
|
|
41
43
|
from loom.etl.testing._scenario import ETLScenario, StepRunnerProto
|
|
42
44
|
from loom.etl.testing._stubs import (
|
|
@@ -53,6 +55,7 @@ __all__ = [
|
|
|
53
55
|
"StubRunObserver",
|
|
54
56
|
"PolarsStepRunner",
|
|
55
57
|
"StepResult",
|
|
58
|
+
"MergeMetrics",
|
|
56
59
|
"ETLScenario",
|
|
57
60
|
"StepRunnerProto",
|
|
58
61
|
]
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""Delta root of a ``PolarsStepRunner(delta_root=...)``: real reader and writer on one root."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
import polars as pl
|
|
9
|
+
|
|
10
|
+
from loom.etl.backends.polars import PolarsSourceReader, PolarsTargetWriter
|
|
11
|
+
from loom.etl.backends.polars._writer import _last_commit, _open_delta_table
|
|
12
|
+
from loom.etl.declarative.expr._refs import TableRef
|
|
13
|
+
from loom.etl.declarative.source import TableSourceSpec
|
|
14
|
+
from loom.etl.declarative.target import SchemaMode, TargetSpec
|
|
15
|
+
from loom.etl.declarative.target._table import ReplaceSpec, UpdateSpec, UpsertSpec
|
|
16
|
+
from loom.etl.storage import MissingTablePolicy, PrefixLocator
|
|
17
|
+
from loom.etl.testing._result import MergeMetrics
|
|
18
|
+
|
|
19
|
+
_MERGE = "MERGE"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class _DeltaRoot:
|
|
23
|
+
"""One local Delta root whose tables are read and written as production does.
|
|
24
|
+
|
|
25
|
+
:meth:`write` is a target writer: it delegates to the real
|
|
26
|
+
:class:`PolarsTargetWriter` and keeps, in :attr:`last_merge`, what the
|
|
27
|
+
MERGE of an upsert or update applied.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
root: Local directory holding the tables, e.g. pytest's ``tmp_path``.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, root: str | Path) -> None:
|
|
34
|
+
self._root = str(root)
|
|
35
|
+
self._locator = PrefixLocator(self._root)
|
|
36
|
+
self.reader = PolarsSourceReader(self._root)
|
|
37
|
+
self.writer = PolarsTargetWriter(self._root, missing_table_policy=MissingTablePolicy.CREATE)
|
|
38
|
+
self.last_merge: MergeMetrics | None = None
|
|
39
|
+
|
|
40
|
+
def seed(self, ref: str, frame: pl.LazyFrame) -> None:
|
|
41
|
+
"""Write *frame* as the whole content of table *ref*, creating it if missing."""
|
|
42
|
+
spec = ReplaceSpec(table_ref=TableRef(ref), schema_mode=SchemaMode.OVERWRITE)
|
|
43
|
+
self.writer.write(frame, spec, None)
|
|
44
|
+
|
|
45
|
+
def read(self, ref: str) -> pl.DataFrame:
|
|
46
|
+
"""Return the current content of table *ref*."""
|
|
47
|
+
spec = TableSourceSpec(alias=ref, table_ref=TableRef(ref))
|
|
48
|
+
return self.reader.read(spec, None).collect()
|
|
49
|
+
|
|
50
|
+
def write(
|
|
51
|
+
self,
|
|
52
|
+
frame: Any,
|
|
53
|
+
spec: TargetSpec,
|
|
54
|
+
params_instance: Any,
|
|
55
|
+
*,
|
|
56
|
+
streaming: bool = False,
|
|
57
|
+
write_ctx: Any = None,
|
|
58
|
+
) -> None:
|
|
59
|
+
"""Write with the real writer, recording the MERGE metrics of an upsert or update.
|
|
60
|
+
|
|
61
|
+
:attr:`last_merge` is ``None`` when the target is not an upsert or
|
|
62
|
+
update, or when the table did not exist and this write created it.
|
|
63
|
+
"""
|
|
64
|
+
self.last_merge = None
|
|
65
|
+
table = None
|
|
66
|
+
if isinstance(spec, (UpsertSpec, UpdateSpec)):
|
|
67
|
+
table = _open_delta_table(self._locator.locate(spec.table_ref))
|
|
68
|
+
version_before = None if table is None else table.version()
|
|
69
|
+
self.writer.write(frame, spec, params_instance, streaming=streaming, write_ctx=write_ctx)
|
|
70
|
+
if table is None:
|
|
71
|
+
return
|
|
72
|
+
table.update_incremental()
|
|
73
|
+
version, commit = _last_commit(table)
|
|
74
|
+
if version == version_before:
|
|
75
|
+
self.last_merge = MergeMetrics(inserted=0, updated=0, deleted=0)
|
|
76
|
+
elif commit.get("operation") == _MERGE:
|
|
77
|
+
self.last_merge = _merge_metrics(commit.get("operationMetrics") or {})
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _merge_metrics(metrics: dict[str, Any]) -> MergeMetrics:
|
|
81
|
+
"""Read delta-rs MERGE ``operationMetrics`` (snake_case keys)."""
|
|
82
|
+
return MergeMetrics(
|
|
83
|
+
inserted=int(metrics.get("num_target_rows_inserted", 0)),
|
|
84
|
+
updated=int(metrics.get("num_target_rows_updated", 0)),
|
|
85
|
+
deleted=int(metrics.get("num_target_rows_deleted", 0)),
|
|
86
|
+
)
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"""StepResult — unified assertion interface for step test output."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
import polars as pl
|
|
8
|
+
|
|
9
|
+
from loom.etl.backends.polars._writer import _require_boolean_flag_column
|
|
10
|
+
from loom.etl.declarative.target import TargetSpec
|
|
11
|
+
from loom.etl.declarative.target._table import UpsertSpec
|
|
12
|
+
from loom.etl.declarative.target._temp import TempFanInSpec, TempSpec
|
|
13
|
+
from loom.etl.schema._schema import LoomDtype
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True)
|
|
17
|
+
class MergeMetrics:
|
|
18
|
+
"""Rows a Delta MERGE applied to the target table.
|
|
19
|
+
|
|
20
|
+
Read from ``operationMetrics`` of the commit the step wrote.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
inserted: Target rows inserted.
|
|
24
|
+
updated: Target rows updated.
|
|
25
|
+
deleted: Target rows deleted.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
inserted: int
|
|
29
|
+
updated: int
|
|
30
|
+
deleted: int
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass(frozen=True)
|
|
34
|
+
class StepResult:
|
|
35
|
+
"""Output of a :class:`PolarsStepRunner` or :class:`SparkStepRunner` run.
|
|
36
|
+
|
|
37
|
+
Provides a backend-agnostic assertion surface. The internal frame is
|
|
38
|
+
always a materialised ``polars.DataFrame`` — Spark results are converted
|
|
39
|
+
before constructing this object.
|
|
40
|
+
|
|
41
|
+
Two counts answer different questions about an upsert with ``delete_flag``:
|
|
42
|
+
|
|
43
|
+
* :attr:`deletes` — rows the step *emitted* with the flag set, before any
|
|
44
|
+
MERGE. Available with or without ``delta_root``.
|
|
45
|
+
* :attr:`merged` — rows the MERGE *applied* to the table. Only with
|
|
46
|
+
``delta_root`` and an upsert or update target.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
_frame: Materialised output frame.
|
|
50
|
+
target: Target spec of the step that produced the frame, if known.
|
|
51
|
+
merge_metrics: Metrics of the MERGE commit, set by a ``delta_root``
|
|
52
|
+
runner for upsert and update targets.
|
|
53
|
+
|
|
54
|
+
Example::
|
|
55
|
+
|
|
56
|
+
result = runner.run(MyStep, params)
|
|
57
|
+
result.assert_count(10)
|
|
58
|
+
result.assert_schema({"id": LoomDtype.INT64, "amount": LoomDtype.FLOAT64})
|
|
59
|
+
result.show()
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
_frame: pl.DataFrame
|
|
63
|
+
target: TargetSpec | None = None
|
|
64
|
+
merge_metrics: MergeMetrics | None = None
|
|
65
|
+
|
|
66
|
+
def to_polars(self) -> pl.DataFrame:
|
|
67
|
+
"""Return the materialised output as a ``polars.DataFrame``."""
|
|
68
|
+
return self._frame
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def temp_name(self) -> str | None:
|
|
72
|
+
"""Temp name when the step's target is ``IntoTemp``, else ``None``."""
|
|
73
|
+
if isinstance(self.target, (TempSpec, TempFanInSpec)):
|
|
74
|
+
return self.target.temp_name
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def delete_flag(self) -> str | None:
|
|
79
|
+
"""``delete_flag`` of the step's upsert target, else ``None``."""
|
|
80
|
+
if isinstance(self.target, UpsertSpec):
|
|
81
|
+
return self.target.delete_flag
|
|
82
|
+
return None
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def deletes(self) -> int:
|
|
86
|
+
"""Rows the step emitted with the target's ``delete_flag`` set to true.
|
|
87
|
+
|
|
88
|
+
Counts the step output, not what the MERGE did: use :attr:`merged`
|
|
89
|
+
for that.
|
|
90
|
+
|
|
91
|
+
Raises:
|
|
92
|
+
RuntimeError: When the target is not an upsert with ``delete_flag``.
|
|
93
|
+
UpsertDeleteFlagError: When the output has no flag column, or it
|
|
94
|
+
is not boolean.
|
|
95
|
+
"""
|
|
96
|
+
flag = self.delete_flag
|
|
97
|
+
if flag is None:
|
|
98
|
+
raise RuntimeError(
|
|
99
|
+
"deletes needs a step whose target is IntoTable(...).upsert(delete_flag=...)."
|
|
100
|
+
)
|
|
101
|
+
_require_boolean_flag_column(self._frame.schema, flag)
|
|
102
|
+
return int(self._frame.select(pl.col(flag).fill_null(False).sum()).item())
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def merged(self) -> MergeMetrics:
|
|
106
|
+
"""Rows the MERGE applied to the target table.
|
|
107
|
+
|
|
108
|
+
Raises:
|
|
109
|
+
RuntimeError: When the runner has no ``delta_root``, the target is
|
|
110
|
+
not an upsert or update, or the target table did not exist and
|
|
111
|
+
was created by this write instead of merged.
|
|
112
|
+
"""
|
|
113
|
+
if self.merge_metrics is None:
|
|
114
|
+
raise RuntimeError(
|
|
115
|
+
"merged is unavailable: no MERGE ran because the runner has no "
|
|
116
|
+
"delta_root, the target is not an upsert or update, "
|
|
117
|
+
"or the target table did not exist and was created by this write. "
|
|
118
|
+
"Check the final table with runner.table(ref).assert_count(n) instead."
|
|
119
|
+
)
|
|
120
|
+
return self.merge_metrics
|
|
121
|
+
|
|
122
|
+
def assert_schema(self, expected: dict[str, LoomDtype]) -> None:
|
|
123
|
+
"""Assert that the output columns match the expected Loom schema.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
expected: Mapping of column name → :class:`~loom.etl._schema.LoomDtype`.
|
|
127
|
+
|
|
128
|
+
Raises:
|
|
129
|
+
AssertionError: When a column is missing or has a different dtype.
|
|
130
|
+
"""
|
|
131
|
+
from loom.etl.backends.polars._dtype import loom_type_to_polars
|
|
132
|
+
|
|
133
|
+
for col_name, loom_dtype in expected.items():
|
|
134
|
+
actual = self._frame.schema.get(col_name)
|
|
135
|
+
if actual is None:
|
|
136
|
+
raise AssertionError(f"Column '{col_name}' not found in result schema")
|
|
137
|
+
expected_polars = loom_type_to_polars(loom_dtype)
|
|
138
|
+
if actual != expected_polars:
|
|
139
|
+
raise AssertionError(
|
|
140
|
+
f"Column '{col_name}': expected {expected_polars}, got {actual}"
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
def assert_count(self, n: int) -> None:
|
|
144
|
+
"""Assert the result contains exactly *n* rows.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
n: Expected row count.
|
|
148
|
+
|
|
149
|
+
Raises:
|
|
150
|
+
AssertionError: When the row count differs.
|
|
151
|
+
"""
|
|
152
|
+
actual = len(self._frame)
|
|
153
|
+
if actual != n:
|
|
154
|
+
raise AssertionError(f"Expected {n} rows, got {actual}")
|
|
155
|
+
|
|
156
|
+
def assert_not_empty(self) -> None:
|
|
157
|
+
"""Assert the result contains at least one row.
|
|
158
|
+
|
|
159
|
+
Raises:
|
|
160
|
+
AssertionError: When the result is empty.
|
|
161
|
+
"""
|
|
162
|
+
if len(self._frame) <= 0:
|
|
163
|
+
raise AssertionError("Expected non-empty result, got 0 rows")
|
|
164
|
+
|
|
165
|
+
def show(self, n: int = 10) -> None:
|
|
166
|
+
"""Print the first *n* rows to stdout.
|
|
167
|
+
|
|
168
|
+
Useful for visual inspection during ``pytest -s`` runs.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
n: Number of rows to display. Defaults to 10.
|
|
172
|
+
"""
|
|
173
|
+
print(self._frame.head(n))
|