loom-kernel 8.0.1__tar.gz → 9.1.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-8.0.1 → loom_kernel-9.1.0}/CHANGELOG.md +441 -29
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/PKG-INFO +5 -1
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/README.md +4 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/a2a/card.py +1 -1
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/a2a/server.py +4 -1
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/_plan.py +12 -7
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/_capabilities.py +17 -6
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/config.py +38 -23
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_capabilities.py +6 -4
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_mcp.py +13 -13
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_schemas.py +11 -6
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/providers/_shared.py +14 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/providers/anthropic.py +2 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/providers/bedrock.py +2 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/providers/openai.py +2 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/providers/typesafe.py +2 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/errors.py +48 -10
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/inference.py +2 -1
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/remote_auth.py +9 -3
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_lifecycle.py +5 -6
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/celery/bootstrap.py +53 -38
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/celery/config.py +6 -5
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/cli/check.py +1 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/backend/sqlalchemy.py +24 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/abc/config.py +5 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/decorators.py +4 -5
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/gateway.py +3 -1
- loom_kernel-9.1.0/src/loom/core/cache/keys.py +186 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/repository.py +263 -148
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/result_codec.py +5 -29
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/checks.py +21 -4
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/__init__.py +2 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/_resolver_utils.py +10 -12
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/binder.py +4 -3
- loom_kernel-9.1.0/src/loom/core/config/checks.py +64 -0
- loom_kernel-9.1.0/src/loom/core/config/convert.py +206 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/keys.py +2 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/loader.py +2 -1
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/observability.py +13 -7
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/overrides.py +31 -9
- loom_kernel-9.1.0/src/loom/core/config/retired.py +35 -0
- loom_kernel-9.1.0/src/loom/core/connections/__init__.py +40 -0
- loom_kernel-9.1.0/src/loom/core/connections/_base.py +134 -0
- loom_kernel-9.1.0/src/loom/core/connections/aws/__init__.py +12 -0
- loom_kernel-9.1.0/src/loom/core/connections/aws/client.py +51 -0
- loom_kernel-9.1.0/src/loom/core/connections/aws/config.py +91 -0
- loom_kernel-9.1.0/src/loom/core/connections/aws/loader.py +35 -0
- loom_kernel-9.1.0/src/loom/core/connections/clickhouse/__init__.py +12 -0
- loom_kernel-9.1.0/src/loom/core/connections/clickhouse/client.py +83 -0
- loom_kernel-9.1.0/src/loom/core/connections/clickhouse/config.py +77 -0
- loom_kernel-9.1.0/src/loom/core/connections/clickhouse/loader.py +44 -0
- loom_kernel-9.1.0/src/loom/core/connections/mongo/__init__.py +12 -0
- loom_kernel-9.1.0/src/loom/core/connections/mongo/client.py +64 -0
- loom_kernel-9.1.0/src/loom/core/connections/mongo/config.py +112 -0
- loom_kernel-9.1.0/src/loom/core/connections/mongo/loader.py +41 -0
- loom_kernel-9.1.0/src/loom/core/connections/relational.py +27 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/engine/executor.py +1 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/environment.py +21 -4
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/errors/__init__.py +2 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/errors/errors.py +4 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/locator.py +10 -54
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/logger/__init__.py +2 -0
- loom_kernel-9.1.0/src/loom/core/logger/context.py +43 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/__init__.py +2 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/_loom_type.py +5 -4
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/convert.py +31 -1
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/field.py +9 -4
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/introspection.py +50 -8
- loom_kernel-9.1.0/src/loom/core/model/redaction.py +508 -0
- loom_kernel-9.1.0/src/loom/core/model/struct.py +112 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/timestamped.py +0 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/types.py +4 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/types_postgres.py +1 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/config.py +2 -1
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/observer/otel.py +15 -7
- loom_kernel-9.1.0/src/loom/core/persistence/__init__.py +46 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/persistence/abc.py +31 -11
- loom_kernel-9.1.0/src/loom/core/persistence/database.py +265 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/persistence/none.py +14 -7
- loom_kernel-9.1.0/src/loom/core/persistence/profile.py +119 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/plugins/entrypoints.py +5 -13
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/abc/__init__.py +21 -4
- loom_kernel-9.1.0/src/loom/core/repository/abc/checks.py +60 -0
- loom_kernel-9.1.0/src/loom/core/repository/abc/cursor.py +682 -0
- loom_kernel-9.1.0/src/loom/core/repository/abc/session_scope.py +60 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/dynamodb/backend.py +50 -47
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/dynamodb/registry.py +8 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/dynamodb/repository.py +58 -15
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/mongo/backend.py +44 -34
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/mongo/ids.py +6 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/mongo/registry.py +19 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/mongo/repository.py +57 -27
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/__init__.py +2 -1
- loom_kernel-9.1.0/src/loom/core/repository/sqlalchemy/_pool_metrics.py +42 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/backend.py +86 -76
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/migrations/runners.py +2 -1
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/mixins.py +39 -6
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/query_compiler/compiler.py +56 -15
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/query_compiler/cursor.py +34 -12
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/registry.py +25 -8
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/repository.py +17 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/__init__.py +1 -1
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/session_manager.py +89 -54
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/values.py +47 -31
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/clickhouse/_client.py +8 -31
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/clickhouse/registry.py +10 -18
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/config.py +62 -30
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/__init__.py +1 -3
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/compute.py +2 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/invoker.py +1 -1
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/rule.py +6 -11
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/__init__.py +8 -3
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_merge.py +43 -3
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_schema_aligner/_policy.py +2 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_write_policy.py +78 -21
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_reader.py +0 -6
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_schema.py +1 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_writer.py +94 -4
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/provider.py +32 -41
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/spark/_schema.py +1 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/spark/_writer.py +4 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/spark/provider.py +3 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/checkpoint/__init__.py +0 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/checkpoint/_cleaners.py +3 -7
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/checkpoint/_store.py +2 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_compiler.py +11 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_errors.py +8 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_filter.py +2 -30
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_validators.py +1 -15
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_validators_plan.py +6 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_validators_step.py +21 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/__init__.py +4 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/_with_agent.py +5 -16
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/source/_from_clickhouse.py +0 -4
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/source/_specs.py +0 -5
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/__init__.py +10 -2
- loom_kernel-9.1.0/src/loom/etl/declarative/target/_errors.py +68 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_history/_builder.py +1 -1
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_history/_spec.py +1 -1
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_into.py +37 -3
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_table.py +33 -1
- loom_kernel-9.1.0/src/loom/etl/io/_clickhouse_connection.py +44 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/_clickhouse.py +20 -21
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/targets/_clickhouse.py +35 -31
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/lineage/_config.py +4 -3
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/runner/__init__.py +1 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/runner/config_loader.py +2 -1
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/runner/core.py +3 -5
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/schema/_schema.py +11 -5
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/storage/__init__.py +0 -4
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/storage/_config.py +63 -69
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/storage/routing.py +3 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/_flow_yaml.py +6 -1
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/deploy/_discovery.py +4 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/notify/_factory.py +4 -3
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/notify/_slack.py +5 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/notify/_sns.py +3 -2
- loom_kernel-9.1.0/src/loom/prometheus/db_pool.py +135 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prometheus/lifecycle.py +6 -3
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/_body.py +25 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/compiler.py +161 -50
- loom_kernel-9.1.0/src/loom/rest/fastapi/_auto_ai.py +524 -0
- loom_kernel-9.1.0/src/loom/rest/fastapi/_auto_auth.py +145 -0
- loom_kernel-9.1.0/src/loom/rest/fastapi/_auto_sql.py +221 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/_errors.py +30 -3
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/app.py +15 -49
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/auto.py +105 -875
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/openapi.py +8 -18
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/router_runtime.py +53 -44
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/sql.py +12 -25
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/middleware.py +6 -8
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/model.py +8 -5
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/__init__.py +0 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/_adapter.py +35 -9
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/_resource_manager.py +34 -54
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/_runtime_io.py +19 -11
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/handlers/_shared.py +6 -17
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/runner.py +6 -5
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/compiler/_errors.py +6 -17
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/compiler/_plan.py +20 -17
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/compiler/phases/build_plan.py +6 -3
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/compiler/phases/validate.py +10 -31
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/_config.py +28 -34
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/mongo/_bytewax_source.py +13 -24
- loom_kernel-9.1.0/src/loom/streaming/mongo/_config.py +68 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/__init__.py +0 -2
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_table/__init__.py +3 -4
- loom_kernel-9.1.0/src/loom/streaming/nodes/_table/_clickhouse.py +206 -0
- loom_kernel-9.1.0/src/loom/streaming/nodes/_table/_delta.py +255 -0
- loom_kernel-9.1.0/src/loom/streaming/nodes/_table/_sqlalchemy.py +163 -0
- loom_kernel-9.1.0/src/loom/streaming/nodes/_table/common.py +595 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_table/config.py +70 -10
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/testing/repository_harness.py +7 -1
- loom_kernel-8.0.1/src/loom/core/cache/keys.py +0 -96
- loom_kernel-8.0.1/src/loom/core/config/_boto3.py +0 -22
- loom_kernel-8.0.1/src/loom/core/model/struct.py +0 -38
- loom_kernel-8.0.1/src/loom/core/persistence/__init__.py +0 -18
- loom_kernel-8.0.1/src/loom/core/repository/abc/cursor.py +0 -157
- loom_kernel-8.0.1/src/loom/core/repository/abc/session_scope.py +0 -37
- loom_kernel-8.0.1/src/loom/etl/declarative/target/_errors.py +0 -30
- loom_kernel-8.0.1/src/loom/etl/declarative/target/_schema_mode.py +0 -5
- loom_kernel-8.0.1/src/loom/etl/runner/errors.py +0 -7
- loom_kernel-8.0.1/src/loom/etl/runner/filtering.py +0 -41
- loom_kernel-8.0.1/src/loom/streaming/mongo/_config.py +0 -55
- loom_kernel-8.0.1/src/loom/streaming/nodes/_table/common.py +0 -1221
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/.gitignore +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/LICENSE +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/pyproject.toml +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/_concurrency.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/_filters.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/_paths.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/_roles.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/_startup.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/_transport.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/_usecase.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/a2a/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/a2a/_binding.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/a2a/_handlers.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/a2a/_rpc.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/a2a/events.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/abc.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/bootstrap.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/_compiler.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/_fingerprint.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/_conversation.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/_feedable.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/_hook.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/_instructions.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/_limits.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/_model_role.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/_output.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/_state.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/declarative/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/declarative/_envelope.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/declarative/_schema.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/declarative/_v1.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/declarative/schemas/agent-spec-v1.schema.json +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/describe.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_a2a.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_engine.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_escape.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_events.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_guards.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_history.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_instructions.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_limits.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_models.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_native.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_output.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_returns.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_spec.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/extras/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/extras/a2a.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/extras/handlebars.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/extras/mcp.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/extras/skills.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/provider.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/providers/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/providers/gateway.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/etl/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/etl/_batch.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/etl/_columns.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/etl/_frames.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/etl/_ledger.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/etl/_runner.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/etl/_validation.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/fastapi/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/fastapi/endpoints.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/fastapi/response.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/fastapi/streaming.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/pricing.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/registry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_bounded.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_chain.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_conversation.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_grants.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_handle.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_health.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_hooks.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_limits.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_mcp.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/validate/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/validate/__main__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/celery/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/celery/auto.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/celery/constants.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/celery/runner.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/celery/service.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/cli/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/cli/app.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/cli/schema.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/async_bridge.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/authz/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/authz/_decide.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/authz/_grants.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/authz/_roles.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/authz/_scope.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/authz/elevation.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/authz/product.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/backend/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/backend/core_model.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/backend/protocol.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/backend/scoped_ddl.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/bootstrap/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/bootstrap/bootstrap.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/bootstrap/kernel.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/_batching.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/_single_flight.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/abc/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/abc/backend.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/abc/dependency.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/calls.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/codec.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/dependency.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/memory.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/serializer.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/wiring.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/command/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/command/adapter.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/command/base.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/command/field.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/command/introspection.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/compiler.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/_includes.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/configurable.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/context.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/model.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/resolver.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/secrets.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/ssm.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/contracts/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/contracts/manifest.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/di/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/di/container.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/di/scope.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/discovery/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/discovery/_utils.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/discovery/base.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/discovery/interfaces.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/discovery/manifest.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/discovery/modules.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/engine/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/engine/compilable.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/engine/compiler.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/engine/events.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/engine/metrics.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/engine/plan.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/engine/post_commit.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/errors/codes.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/expr/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/expr/eval.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/expr/nodes.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/expr/refs.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/identity/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/identity/context.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/identity/identity.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/identity/issuer.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/identity/wire.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/introspection/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/introspection/base.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/introspection/describe.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/job/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/job/callback.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/job/context.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/job/handle.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/job/job.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/job/service.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/logger/abc.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/logger/checks.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/logger/config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/logger/registry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/logger/structlogger.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/_json_schema.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/base.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/enums.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/partition.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/privilege.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/projection.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/relation.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/scoped.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/event.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/observer/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/observer/noop.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/observer/structlog.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/otel_ids.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/protocol.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/runtime.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/span.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/topology.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/persistence/registry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/plugins/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/plugins/optional.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/projection/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/projection/loaders.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/projection/runtime.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/abc/errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/abc/query.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/abc/query_compiler.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/abc/repo_for.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/abc/repository.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/dynamodb/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/dynamodb/uow.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/mongo/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/mongo/query_compiler.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/mongo/uow.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/mongo/values.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/mutation.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/registration.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/registry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/integrity.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/loaders.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/migrations/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/migrations/env_template.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/migrations/hook.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/migrations/operations.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/model.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/profile_loader.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/projection.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/query_compiler/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/query_compiler/errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/query_compiler/filters.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/query_compiler/ordering.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/query_compiler/paths.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/query_compiler/subquery.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/bootstrap.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/elevate.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/guard/0001.sql +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/guard/0002.sql +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/guard/preflight.sql +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/guard_manifest.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/integrity.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/partitions.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/provider.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/schema.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/sources.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/verify.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/session_settings.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/transactional.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/uow.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/response/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/response/base.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/routing/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/routing/ref.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/routing/resolver.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/runner.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/schema/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/schema/schema_mode.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/schema_names.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/abc/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/abc/contracts.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/abc/errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/caller_bound.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/clickhouse/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/clickhouse/executor.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/roles.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/service.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/symbols.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/tracing/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/tracing/context.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/transaction.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/transport/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/transport/adapter.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/uow/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/uow/abc.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/uow/context.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/_predicates.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/agent_markers.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/constants.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/factory.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/field_ref.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/keys.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/markers.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/mcp_markers.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/outcome.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/registry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/use_case.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/_uri.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_format_registry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_historify/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_historify/_common.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_historify/_log.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_historify/_ops.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_historify/_snapshot.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_historify/_transform.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_path_template.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_predicate.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_schema_aligner/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_schema_aligner/_aligner.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_dtype.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_file_writer.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_frame.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_historify.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_predicate.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_schema_aligner.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_streaming.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/spark/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/spark/_dtype.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/spark/_historify.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/spark/_reader.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/spark/_schema_aligner.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/checkpoint/_backends/_polars.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/checkpoint/_backends/_spark.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/checkpoint/_options.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/checkpoint/_paths.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/checkpoint/_scope.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_binding.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_plan.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_validators_agents.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_validators_config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/_format.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/_read_options.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/_utils.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/_write_options.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/expr/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/expr/_params.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/expr/_predicate.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/expr/_predicate_dialect.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/expr/_refs.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/source/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/source/_from.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/source/_from_config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/source/_from_dynamodb.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/source/_from_mongo.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_client.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_file.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_history/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_history/_enums.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_history/_errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_history/_report.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_temp.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/executor/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/executor/_agents.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/executor/_dispatcher.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/executor/_executor.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/_registry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/_dynamodb.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/_dynamodb_items.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/_dynamodb_predicate.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/_mongo.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/_mongo_batch.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/_mongo_bson.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/_mongo_predicate.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/_serialization.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/targets/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/lineage/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/lineage/_observer.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/lineage/_records.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/lineage/sinks/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/lineage/sinks/_protocol.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/lineage/sinks/_table.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/lineage/sinks/_writer.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/maintenance/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/maintenance/_builder.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/maintenance/_ops.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/maintenance/_protocol.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/maintenance/_runner.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/maintenance/_step.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/maintenance/backends/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/maintenance/backends/_delta_rs.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/pipeline/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/pipeline/_generics.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/pipeline/_params.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/pipeline/_pipeline.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/pipeline/_process.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/pipeline/_sql.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/pipeline/_step.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/pipeline/_step_client.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/pipeline/_step_sql.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/runner/_agents.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/runner/_providers.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/runner/_wiring.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/runtime/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/runtime/_config_values.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/runtime/contracts.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/schema/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/schema/_contract.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/storage/_file_locator.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/storage/_locator.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/testing/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/testing/_result.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/testing/_runners.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/testing/_scenario.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/testing/_stubs.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/testing/spark.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/_async.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/_config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/_ctx.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/_meta.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/_placeholders.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/_summary.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/deploy/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/deploy/_schedule.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/deploy/_yaml_etls.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/deploy/entrypoint.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_assemble.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_backfill.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_backfill_body.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_body.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_common.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_factory.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_hooks.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_maintenance.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_params.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_run_name.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_runtime.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_signature.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_stages.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/manifest/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/manifest/_model.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/manifest/_s3.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/manifest/_store.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/notify/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/notify/_event.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/notify/_format.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/notify/_port.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/observer/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/observer/_flow.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/observer/_logging_bridge.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/observer/_manifest.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/observer/_task_run.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prometheus/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prometheus/_instruments.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prometheus/adapter.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prometheus/kafka.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prometheus/middleware.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/py.typed +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/adapter.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/auth/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/auth/abc.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/auth/config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/auth/jwt.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/auth/middleware.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/autocrud.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/checks.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/constants.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/cors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/_exclusions.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/health.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/response.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/rest_adapter.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/_batch_spans.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/_commit_tracker.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/_error_boundary.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/_errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/_operators.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/_sink_registry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/handlers/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/handlers/boundary.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/handlers/dispatcher.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/handlers/routing.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/handlers/scopes.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/handlers/shapes.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/handlers/steps.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/handlers/storage.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/compiler/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/compiler/_bindings.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/compiler/_compiler.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/core/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/core/_errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/core/_exceptions.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/core/_message.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/core/_tracing.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/core/_typing.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/graph/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/graph/_flow.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/_codec.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/_errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/_key_resolver.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/_message.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/_record.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/_wire.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/client/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/client/_consumer.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/client/_producer.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/client/_protocol.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/client/_retry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/message/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/message/_consumer.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/message/_producer.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/message/_protocol.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/mongo/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/mongo/_event.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/mongo/_normalize.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_boundary.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_branches.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_broadcast.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_capabilities.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_decompose.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_expand_routes.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_expr_eval.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_fork.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_helpers.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_mongo.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_protocols.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_router.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_shape.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_sink.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_step.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_with.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/refs.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/testing.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/testing/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/testing/agents.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/testing/golden.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/testing/http_harness.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/testing/in_memory.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/testing/runner.py +0 -0
|
@@ -2,6 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
## ✨ Features
|
|
4
4
|
|
|
5
|
+
### etl
|
|
6
|
+
|
|
7
|
+
- **etl:** `IntoTable(...).upsert(..., delete_flag=...)` deletes matched rows
|
|
8
|
+
whose boolean source column is true and does not insert unmatched rows with
|
|
9
|
+
that flag. A false or null flag keeps the normal update or insert; null is
|
|
10
|
+
read as false (`coalesce(s.<flag>, false)`). The column is removed before
|
|
11
|
+
schema alignment, including `SchemaMode.STRICT`, so it is never written and
|
|
12
|
+
never appears in the update or insert maps. It must exist on the source
|
|
13
|
+
frame, be boolean, must not be a key, a partition column, or listed in
|
|
14
|
+
`exclude` or `include`, and must not name a column of the target table;
|
|
15
|
+
otherwise `UpsertDeleteFlagError` is raised before anything is written. The
|
|
16
|
+
Polars writer applies it. Any other writer, including Spark, raises
|
|
17
|
+
`UnsupportedUpsertDeleteFlagError` and does not write. On first write the
|
|
18
|
+
table is created from the unflagged rows, so a batch where every row is
|
|
19
|
+
flagged creates an empty table. A key repeated in the source batch (for
|
|
20
|
+
example a tombstone and a live row) fails the MERGE. With
|
|
21
|
+
`SchemaMode.EVOLVE` the MERGE does not add new source columns, as before.
|
|
22
|
+
Omitting `delete_flag` leaves the MERGE byte-for-byte as it was: matched
|
|
23
|
+
update and unmatched insert, with no delete clause. `UpsertSpec` gains
|
|
24
|
+
`delete_flag`; `UpsertDeleteFlagError` and
|
|
25
|
+
`UnsupportedUpsertDeleteFlagError` are exported from `loom.etl`.
|
|
26
|
+
|
|
27
|
+
# 🚀 Releases 2.1.3 to 9.0.0
|
|
28
|
+
|
|
29
|
+
Entries from 2.1.3 to 9.0.0 were kept under one heading and are not split
|
|
30
|
+
by version; each release's own list is in its GitHub Release notes.
|
|
31
|
+
|
|
32
|
+
## ✨ Features
|
|
33
|
+
|
|
5
34
|
### core
|
|
6
35
|
|
|
7
36
|
- **core:** range-partitioned row-scoped tables.
|
|
@@ -99,6 +128,13 @@
|
|
|
99
128
|
parameter raises a `TypeError` naming the code. `AgentErrorCode`,
|
|
100
129
|
`StreamingErrorCode` and `ETLErrorCode` are such catalogues, and
|
|
101
130
|
`ETLCompilationError.from_issue(issue)` raises the ETL error for an issue.
|
|
131
|
+
- **core:** `loom.core.logger.log_context(**values)` adds fields to every log
|
|
132
|
+
record emitted inside the block through `get_logger` with its default
|
|
133
|
+
factory, and to plain stdlib records once `configure_logging` has installed
|
|
134
|
+
loom's formatter, so an application can bind, say, an audit `request_id`
|
|
135
|
+
without importing structlog. The values follow the current thread or
|
|
136
|
+
asyncio task, and each key regains its previous value on exit, even by
|
|
137
|
+
exception. The block must be entered and exited in the same context.
|
|
102
138
|
|
|
103
139
|
### ai
|
|
104
140
|
|
|
@@ -412,7 +448,7 @@
|
|
|
412
448
|
selection can be checked without running it. A bare string as `include`
|
|
413
449
|
raises `TypeError`. The runner now filters through it. `InvalidStageError`
|
|
414
450
|
is exported from `loom.etl.compiler` as well; it is the same class as
|
|
415
|
-
`loom.etl.
|
|
451
|
+
`loom.etl.InvalidStageError`.
|
|
416
452
|
- **etl:** `iter_processes`, `iter_steps_in_process` and `iter_all_steps` are
|
|
417
453
|
exported from `loom.etl.compiler`. They flatten a compiled plan in
|
|
418
454
|
execution order, parallel groups in declaration order, so code that walks
|
|
@@ -459,6 +495,68 @@
|
|
|
459
495
|
|
|
460
496
|
### core
|
|
461
497
|
|
|
498
|
+
- **core:** `RuleViolation` and `RuleViolations` are no longer exported by
|
|
499
|
+
`loom.core.use_case` or `loom.core.use_case.rule`. Import them from
|
|
500
|
+
`loom.core.errors`, their only public home.
|
|
501
|
+
- **core:** wrapping a repository in `CachedRepository` raises `RuntimeError`
|
|
502
|
+
when one of its `@cache_query` reads has a missing return annotation, one
|
|
503
|
+
the defining module cannot resolve, or one outside the supported grammar,
|
|
504
|
+
naming the repository and the method; a `@cached` repository therefore fails
|
|
505
|
+
when it is built. Before, wrapping emitted a `DeprecationWarning` and logged
|
|
506
|
+
`CacheQueryReturnTypeUnusable`, and the cached call returned the decoded
|
|
507
|
+
payload instead of the declared type. Annotate the read's return type with a
|
|
508
|
+
struct, a scalar, or a `list`, `tuple` or optional of those. A
|
|
509
|
+
`@cache_query` coroutine that is not defined on the repository class, such
|
|
510
|
+
as one set on the instance, raises `RuntimeError` when it is looked up on
|
|
511
|
+
the wrapper, since no codec was built for it; define it as a method of the
|
|
512
|
+
class.
|
|
513
|
+
- **core:** a field annotated `X | UnsetType` infers `X`'s column type.
|
|
514
|
+
`UNSET` means "not provided", not another type, so `str | UnsetType` now
|
|
515
|
+
compiles to `String` and `int | UnsetType` to `Integer` instead of `JSON`,
|
|
516
|
+
and `Annotated[str, String(20)] | UnsetType` reads its declared type. Such
|
|
517
|
+
a column is scalar: a REST route may declare it filterable, `like` and
|
|
518
|
+
`ilike` included for text, and sortable by offset; a cursor sort on it is
|
|
519
|
+
still refused, since a cursor key must be a bare type. Nullability is
|
|
520
|
+
unchanged: `str | None | UnsetType` admits `None` and is nullable,
|
|
521
|
+
`UnsetType` alone keeps the column `NOT NULL`. An undeclared
|
|
522
|
+
`Decimal | UnsetType`, plain `Enum | UnsetType` or `Literal[...] | UnsetType`
|
|
523
|
+
now needs a declared column type, as it does without `UnsetType`. On Mongo,
|
|
524
|
+
a `str | UnsetType` or `UUID | UnsetType` primary key is now accepted, and
|
|
525
|
+
a range filter or sort on a `Decimal | UnsetType` field is refused, as on a
|
|
526
|
+
`Decimal` field. Alembic autogenerate will show the type change from `JSON`
|
|
527
|
+
for existing tables with such columns.
|
|
528
|
+
- **core:** a column's nullability follows its field's annotation. A field
|
|
529
|
+
whose annotation admits `None` (`x: int | None = None`, also inside
|
|
530
|
+
`Annotated`) compiles to a nullable column; any other field compiles to
|
|
531
|
+
`NOT NULL`, and a primary key column is `NOT NULL` whatever its annotation.
|
|
532
|
+
Before, every column was `NOT NULL` unless declared otherwise, so the model
|
|
533
|
+
accepted `None` and the database refused it on insert. `nullable=` on
|
|
534
|
+
`ColumnField`, `ScopedField` or `Field` now defaults to `None` (follow the
|
|
535
|
+
annotation) and a declared `True` or `False` still wins. Alembic
|
|
536
|
+
autogenerate will propose `nullable` changes for existing tables whose
|
|
537
|
+
Optional fields were created `NOT NULL`; to keep such a column `NOT NULL`,
|
|
538
|
+
declare `nullable=False`. ETL schema contracts keep their own rule (a
|
|
539
|
+
column is nullable unless declared otherwise), which this change does not
|
|
540
|
+
touch.
|
|
541
|
+
- **core:** a `uuid.UUID` field without a declared column type is now a
|
|
542
|
+
`Uuid` column (`loom.core.model.Uuid`, SQLAlchemy `Uuid`) instead of
|
|
543
|
+
`JSON`: `UUID` on Postgres, `CHAR(32)` holding the hex form on dialects
|
|
544
|
+
without a native UUID type, such as SQLite. Such a field is now a scalar
|
|
545
|
+
column, so REST `filterable`, `sortable` and `ALL` accept it on every
|
|
546
|
+
backend, `mongo` included; on SQLite a cursor walk sorted by it pages in
|
|
547
|
+
UUID order and an equality filter on it matches. Streaming `IntoTable` with the
|
|
548
|
+
SQLAlchemy backend binds a `UUID` field the same way instead of failing to
|
|
549
|
+
serialise it as JSON. Migration: an existing table with such a column needs
|
|
550
|
+
a revision changing its type; Alembic autogenerate reports it as a type
|
|
551
|
+
change from `JSON` to `Uuid`. Postgres does not cast `json` to `uuid`, so
|
|
552
|
+
the revision needs `postgresql_using="(<column> #>> '{}')::uuid"`. On a
|
|
553
|
+
dialect without a native UUID type the old rows hold JSON text (the quoted
|
|
554
|
+
UUID with dashes), which the `Uuid` column cannot read, so after the type
|
|
555
|
+
change the revision rewrites each value to its 32-character hex. On
|
|
556
|
+
SQLite: `op.batch_alter_table` for the type change, then
|
|
557
|
+
`UPDATE <table> SET <column> = replace(json_extract(<column>, '$'), '-', '')`.
|
|
558
|
+
Rewriting before the type change loses values on SQLite: a hex form made
|
|
559
|
+
only of digits is stored as a number in the `JSON` column.
|
|
462
560
|
- **core:** a `Decimal` field, plain or optional, declares its column type: a
|
|
463
561
|
SQLAlchemy model with an undeclared one is refused when it is compiled,
|
|
464
562
|
naming the field. loom inferred `NUMERIC(10, 2)`, and Postgres silently
|
|
@@ -560,6 +658,81 @@
|
|
|
560
658
|
or `RuleViolation` it returns no longer fails the rule. Migrate
|
|
561
659
|
`Rule.check(F(Order).total, via=lambda v: v <= 0, message="total must be > 0")`
|
|
562
660
|
to `Rule.check(F(Order).total, via=lambda v: "total must be > 0" if v <= 0 else None)`.
|
|
661
|
+
- **core:** cursor signing keys are required (ADR 0004). An application whose
|
|
662
|
+
persistence backend serves repositories (`sqlalchemy`, `mongo`), and a
|
|
663
|
+
Celery worker that registers repositories, read `persistence.cursors` at
|
|
664
|
+
startup and fail with a `ConfigError` without a key:
|
|
665
|
+
|
|
666
|
+
```yaml
|
|
667
|
+
persistence:
|
|
668
|
+
cursors:
|
|
669
|
+
current_key_id: "2026-10"
|
|
670
|
+
keys:
|
|
671
|
+
"2026-10": {env: CURSOR_KEY_2026_10} # or {path: /run/secrets/...}
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
Keys are read from a file or an environment variable, never written in the
|
|
675
|
+
configuration, as standard base64 decoding to at least 32 random bytes
|
|
676
|
+
(`openssl rand -base64 32`); a passphrase is refused. Older key ids stay in
|
|
677
|
+
`keys` to verify the tokens they signed during a rotation.
|
|
678
|
+
The default is `signed` in every environment; `signing: ephemeral` (a
|
|
679
|
+
random per-process key, for `development.yaml`) and `signing: unsigned`
|
|
680
|
+
(for `test.yaml`) are explicit opt-outs, and both log a WARNING at
|
|
681
|
+
startup. In production and staging the deploy check `loom.cursors.E001`
|
|
682
|
+
fails startup, and `loom check --deploy` fails, when a `database` or
|
|
683
|
+
`persistence.mongo` section is set and `signing` is not `signed` or
|
|
684
|
+
`current_key_id` names no entry of `keys`. No `config.overridable` entry
|
|
685
|
+
may open a key under `persistence.cursors`. A key's `env` source must not
|
|
686
|
+
name a `LOOM_*` variable. Tokens issued before this release are refused:
|
|
687
|
+
clients restart from the first page.
|
|
688
|
+
- **core:** a cursor page orders only by non-null columns of a type a token
|
|
689
|
+
carries; a dotted path, a JSON, `bytes` or optional column answers
|
|
690
|
+
`400 unsupported_query` before the query runs (`require_cursor_sort`), and
|
|
691
|
+
a page whose last row holds a non-finite number or a value the token
|
|
692
|
+
cannot carry answers 400 instead of 500. An empty cursor is an invalid
|
|
693
|
+
token on SQLAlchemy as on Mongo. Tokens bind the model as
|
|
694
|
+
`module.qualname`; `UnsupportedQuery` and the client's 400 name it by its
|
|
695
|
+
qualified name alone. `CursorCodec.encode`/`decode`, `require_cursor_sort`
|
|
696
|
+
and `QuerySpecCompiler(model=...)` take the model class (or a name). Mongo
|
|
697
|
+
issues the next token in the model's types, so a page sorted by a date or
|
|
698
|
+
UUID column, or keyed by a UUID, reaches the next page.
|
|
699
|
+
- **core:** one `CursorCodec` per process: the registration modules register
|
|
700
|
+
it with `register_cursor_codec`, which raises `ConfigError` when a
|
|
701
|
+
different codec is already registered, and, in a deployed environment,
|
|
702
|
+
for an `ephemeral` or `unsigned` codec unless `CursorCodec.from_context`
|
|
703
|
+
built it from a configuration silencing `loom.cursors.E001`. Without a
|
|
704
|
+
registered `Environment` the process environment decides (`LOOM_ENV`, else
|
|
705
|
+
production).
|
|
706
|
+
- **core:** `loom.core.checks.silenced_checks(config)` returns the ids
|
|
707
|
+
`checks.silenced` lists, as the deploy-check runner reads them.
|
|
708
|
+
- **core:** the unsigned module functions `encode_cursor` and
|
|
709
|
+
`decode_cursor` are gone. `CursorCodec` (with `CursorConfig` and
|
|
710
|
+
`CursorKeySource`, exported from `loom.core.repository.abc`) issues and
|
|
711
|
+
verifies tokens: `encode(cursor, *, model, query, scope)` and
|
|
712
|
+
`decode(token, *, backend, model, query, scope, columns, primary_key)`,
|
|
713
|
+
where `scope` is required and `""` binds a token to no tenant, `columns`
|
|
714
|
+
maps each column name to its annotation and `primary_key` names the key
|
|
715
|
+
columns in order. A sort key or primary-key value whose type is not its
|
|
716
|
+
column's is refused (`400 unsupported_query`), as is a sort field missing
|
|
717
|
+
from `columns`. The backends
|
|
718
|
+
register the codec they build in DI, so a service paginating by hand
|
|
719
|
+
resolves it with `container.resolve(CursorCodec)`. A decoded datetime key
|
|
720
|
+
is always aware. A `time` sort key is carried too, with the offset it was
|
|
721
|
+
issued with; before, a page sorted by a column holding `time` values
|
|
722
|
+
raised `TypeError` when it issued the next cursor.
|
|
723
|
+
- **core:** `RepositorySQLAlchemy`, `RepositoryMongo`, `QuerySpecCompiler`
|
|
724
|
+
(with a required `scope` and `columns` too), `SQLAlchemyDefaultRepositoryBuilder`,
|
|
725
|
+
`MongoDefaultRepositoryBuilder`, `build_sqlalchemy_repository_registration_module`,
|
|
726
|
+
`build_mongo_repository_registration_module` and
|
|
727
|
+
`loom.testing.build_repository_harness` take a required keyword-only
|
|
728
|
+
`cursor_codec`. A custom repository `builder` passes
|
|
729
|
+
`context.container.resolve(CursorCodec)`. `extract_next_cursor` returns the
|
|
730
|
+
next `Cursor` position instead of a token, and `SessionManager` gains
|
|
731
|
+
`current_settings()`. SQLAlchemy repositories bind cursors to the caller's
|
|
732
|
+
`loom.scope.*` session values. `loom.core.environment` gains
|
|
733
|
+
`configured_variable(name)`, which reads a variable a configuration names
|
|
734
|
+
and refuses a `LOOM_*` name.
|
|
735
|
+
|
|
563
736
|
- **core:** the `LoomType` protocol gains `from_query(params)`, which
|
|
564
737
|
validates query-string values strictly. A number takes the JSON number
|
|
565
738
|
grammar and must be finite, an integer its integer subset within
|
|
@@ -577,8 +750,7 @@
|
|
|
577
750
|
takes the tuple as its first argument and raises `TypeError` for anything
|
|
578
751
|
else. A cursor token issued for such a model before this release is refused with
|
|
579
752
|
`UnsupportedQuery`, `400 unsupported_query`; clients restart from the first
|
|
580
|
-
page. `
|
|
581
|
-
`get_id_attributes` returns every key column name.
|
|
753
|
+
page. `get_id_attributes` returns every key column name.
|
|
582
754
|
|
|
583
755
|
- **core:** `compile_all` raises `ValueError` for a model with a composite
|
|
584
756
|
primary key that declares a relation or a projection whose loader runs
|
|
@@ -673,6 +845,8 @@
|
|
|
673
845
|
present convert those rows deliberately (for example to UTC with
|
|
674
846
|
`(c::timetz AT TIME ZONE 'UTC')::time`) before changing the type. MongoDB is
|
|
675
847
|
unaffected: it stores `date` and `time` values as ISO 8601 strings.
|
|
848
|
+
- **core:** `to_column_value` is imported from `loom.core.model.convert`; it is
|
|
849
|
+
no longer exported by `loom.core.repository.sqlalchemy.values`.
|
|
676
850
|
|
|
677
851
|
### ai
|
|
678
852
|
|
|
@@ -681,9 +855,15 @@
|
|
|
681
855
|
example `spec_malformed`, `engine_not_found` and `mcp_server_unreachable`.
|
|
682
856
|
Build an issue with `AgentErrorCode.X.issue(...)` and keyword arguments,
|
|
683
857
|
such as `AgentErrorCode.ENGINE_NOT_FOUND.issue(component="openai-agents",
|
|
684
|
-
available=["pydantic-ai"])`. `loom.ai.errors.from_message` is removed too
|
|
685
|
-
|
|
686
|
-
|
|
858
|
+
available=["pydantic-ai"])`. `loom.ai.errors.from_message` is removed too.
|
|
859
|
+
Messages keep their text; a list that is empty renders `none`.
|
|
860
|
+
- **ai:** `AgentCompilationError` takes `AgentCompilationIssue` values only;
|
|
861
|
+
bare strings and the `AgentErrorCode.UNSPECIFIED` code they became are
|
|
862
|
+
removed. Build an issue from an `AgentErrorCode` member with `.issue()`.
|
|
863
|
+
The five pydantic-ai engine failures that raised bare strings now carry
|
|
864
|
+
their own codes, with the same messages: `TOOL_NAME_COLLISION`,
|
|
865
|
+
`TOOL_NAME_TOO_LONG`, `USECASE_NOT_COMPILED`, `CAPABILITY_KIND_NO_BUILDER`
|
|
866
|
+
and `MCP_CONNECTION_NOT_OPENED`.
|
|
687
867
|
- **ai:** `AgentCompilationIssue` is a type alias of
|
|
688
868
|
`CompileIssue[AgentErrorCode]` from `loom.core.errors.codes`, not a class.
|
|
689
869
|
It has the same fields, but `isinstance` against it raises `TypeError`
|
|
@@ -762,6 +942,9 @@
|
|
|
762
942
|
declares both a pydantic `type_ref` output and `output_check` serialises
|
|
763
943
|
an accepted answer twice per attempt — once for the check's own builtins
|
|
764
944
|
projection, once for the wire — accepted rather than optimised away.
|
|
945
|
+
- **ai:** a provider's `credentials_ref` is read through
|
|
946
|
+
`loom.core.environment.configured_variable` and may not name a `LOOM_*`
|
|
947
|
+
variable.
|
|
765
948
|
|
|
766
949
|
### rest
|
|
767
950
|
|
|
@@ -818,12 +1001,56 @@
|
|
|
818
1001
|
- **rest:** a JSON object body that fails `Command` validation now answers
|
|
819
1002
|
`422 boundary_validation` with a `violations` list (`{field, message}`
|
|
820
1003
|
pairs, `field` being the wire name the client sent, the same shape
|
|
821
|
-
`rule_violations` already uses) instead of a generic `500
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
1004
|
+
`rule_violations` already uses) instead of a generic `500`.
|
|
1005
|
+
`Command.from_payload` now raises `BoundaryValidationError` — a
|
|
1006
|
+
`ValueError` — instead of `msgspec.ValidationError`. The root `title` is
|
|
1007
|
+
dropped on pydantic OpenAPI schemas for request bodies and responses alike,
|
|
1008
|
+
matching the untitled document a Struct always produced.
|
|
1009
|
+
- **rest:** a `sortable` column must be a field of the items the route
|
|
1010
|
+
answers with (`PageResult[T]`, `CursorResult[T]` or `list[T]`); a column
|
|
1011
|
+
the response does not show, or a result type that does not say, fails
|
|
1012
|
+
compilation naming the route and the field, since ordering by it reveals
|
|
1013
|
+
its values. `sortable=ALL` opens every scalar column, hidden ones included,
|
|
1014
|
+
and its startup warning says so. `filterable` follows the same rule, with
|
|
1015
|
+
`filterable=ALL` as its escape hatch. "Shown" is decided by field name; a
|
|
1016
|
+
pydantic field declared `exclude=True` is not shown.
|
|
1017
|
+
- **rest:** breaking: a `QuerySpec` route that can serve cursor pages (cursor
|
|
1018
|
+
mode, or the default `allow_pagination_override=True`) must answer with
|
|
1019
|
+
items that show its primary key, which every cursor token carries. A route
|
|
1020
|
+
whose response hides the key, or whose result type is untyped (`str`,
|
|
1021
|
+
`dict[str, Any]`, ...), now fails compilation naming the route and the key.
|
|
1022
|
+
`sortable=ALL` opens it with a warning; a route that must hide its keys
|
|
1023
|
+
serves offset pages only (`pagination_mode` offset and
|
|
1024
|
+
`allow_pagination_override=False`). On such a route the key must also be of
|
|
1025
|
+
a type a token carries, in a scalar column: a key declared in a JSON or
|
|
1026
|
+
array column, which a SQL keyset cannot order, fails compilation instead
|
|
1027
|
+
of on the first cursor request. A bare `UUID` key, a scalar `Uuid` column,
|
|
1028
|
+
compiles and pages on SQLAlchemy and Mongo alike.
|
|
1029
|
+
- **rest:** `create_fastapi_app(interfaces=...)` is removed and `routes` is
|
|
1030
|
+
required; use `create_fastapi_app(result, RouteSources(python=[...]))`.
|
|
1031
|
+
- **rest:** the `QUERY_PARAM_PAGE`, `QUERY_PARAM_LIMIT`,
|
|
1032
|
+
`QUERY_PARAM_PAGINATION`, `QUERY_PARAM_AFTER`, `QUERY_PARAM_CURSOR`,
|
|
1033
|
+
`QUERY_PARAM_SORT`, `QUERY_PARAM_DIRECTION` and `QUERY_PARAM_PROFILE`
|
|
1034
|
+
re-exports of `loom.rest.fastapi.openapi` are removed; use the matching
|
|
1035
|
+
`loom.rest.constants.QueryParam` member (`QueryParam.PAGE`, ...).
|
|
1036
|
+
- **rest:** a request body that is not well-formed JSON — a syntax error,
|
|
1037
|
+
bytes that are not UTF-8, nesting too deep to decode, or an empty body on a
|
|
1038
|
+
route that takes input — now answers `400` with the standard error body
|
|
1039
|
+
(`code: bad_request`, the fixed message `Request body is not valid JSON`,
|
|
1040
|
+
`trace_id`) instead of a generic `500 internal_error` without the `detail`
|
|
1041
|
+
envelope. Well-formed JSON that is not an object (an array, a string, a
|
|
1042
|
+
number, `null`) answers `422 boundary_validation` with the fixed message
|
|
1043
|
+
`Request body must be a JSON object` and one `body` violation, instead of
|
|
1044
|
+
that same `500`. Neither echoes the body. A JSON object that fails
|
|
1045
|
+
validation still answers `422` as before, and the `Content-Type` header is
|
|
1046
|
+
still not checked.
|
|
1047
|
+
- **rest:** the SQL endpoint answers a body that is not well-formed JSON the
|
|
1048
|
+
same way: `400` with `code: bad_request` and the fixed message
|
|
1049
|
+
`Request body is not valid JSON`, instead of a `422 rule_violation` that
|
|
1050
|
+
carried the decoder's message. Bytes that are not UTF-8 inside a JSON
|
|
1051
|
+
string and nesting too deep to decode, which answered a generic
|
|
1052
|
+
`500 internal_error`, are now that `400` too. A well-formed body
|
|
1053
|
+
that does not fit the schema still answers `422 rule_violation`.
|
|
827
1054
|
|
|
828
1055
|
### prefect
|
|
829
1056
|
|
|
@@ -914,11 +1141,8 @@
|
|
|
914
1141
|
- **etl:** a `WithAgent` compiled by a runner whose config has no `ai:`
|
|
915
1142
|
section fails with the new code `AGENT_RUNNER_NOT_CONFIGURED` instead of
|
|
916
1143
|
`AGENT_NOT_FOUND`, which now means only that no artifact declares the name.
|
|
917
|
-
- **etl:**
|
|
918
|
-
`
|
|
919
|
-
`_map_process_nodes`) are deprecated and removed in loom 3.0; each emits a
|
|
920
|
-
`DeprecationWarning` naming its replacement, `loom.etl.compiler.filter_plan`
|
|
921
|
-
or, for `_collect_all_names`, `iter_processes` and `iter_all_steps`.
|
|
1144
|
+
- **etl:** `loom.etl.runner.filtering` is removed; use
|
|
1145
|
+
`loom.etl.compiler.filter_plan`.
|
|
922
1146
|
- **etl:** the Polars writer refuses, under `SchemaMode.STRICT` and
|
|
923
1147
|
`EVOLVE`, a frame column that is a `Struct` or `List` where the Delta table
|
|
924
1148
|
has `String`, or `String` where the table has a `Struct` or `List`, at any
|
|
@@ -937,8 +1161,7 @@
|
|
|
937
1161
|
`Unknown step or process names: [...]` instead of `No steps or processes
|
|
938
1162
|
match include=[...]`, the constructor's parameter is `unknown`, and the
|
|
939
1163
|
names are kept on the new `unknown` attribute. Positional construction is
|
|
940
|
-
unchanged
|
|
941
|
-
`DeprecationWarning` and is removed in loom 3.0. The error survives pickle
|
|
1164
|
+
unchanged. The error survives pickle
|
|
942
1165
|
with its `unknown` names, so it crosses process boundaries intact.
|
|
943
1166
|
- **etl:** `ThreadDispatcher` runs each task in a copy of the caller's
|
|
944
1167
|
context, as `asyncio.to_thread` does, so a step of a parallel group sees
|
|
@@ -949,16 +1172,75 @@
|
|
|
949
1172
|
caller's context among the requirements on an implementation.
|
|
950
1173
|
- **etl:** `WithAgent(max_usd=...)` keeps the budget as a `Decimal`. An
|
|
951
1174
|
`int`, or another `numbers.Integral` such as `numpy.int64`, is converted
|
|
952
|
-
exactly. A `
|
|
953
|
-
`
|
|
954
|
-
|
|
955
|
-
`
|
|
956
|
-
|
|
957
|
-
`
|
|
958
|
-
|
|
1175
|
+
exactly. A `bool`, accepted before, and any other type, such as `str`,
|
|
1176
|
+
raise `TypeError`. `NaN`, `sNaN` and `Infinity` raise `ValueError`, like
|
|
1177
|
+
zero and a negative amount; a `Decimal` `NaN` or `sNaN` used to raise
|
|
1178
|
+
`decimal.InvalidOperation`, and a `Decimal` `Infinity` was accepted.
|
|
1179
|
+
- **etl:** `InvalidStageError(include=...)` is removed; use
|
|
1180
|
+
`InvalidStageError(unknown=...)` or pass the names positionally.
|
|
1181
|
+
- **etl:** `WithAgent(max_usd=<float>)` is removed and raises `TypeError`;
|
|
1182
|
+
pass a `Decimal`, such as `Decimal("2.50")`, or an `int`.
|
|
1183
|
+
- **etl:** `loom.etl.CheckpointCleaner` and
|
|
1184
|
+
`loom.etl.checkpoint.CheckpointCleaner` are removed; use
|
|
1185
|
+
`FsspecTempCleaner`, now exported from `loom.etl` as well.
|
|
1186
|
+
- **etl:** the module `loom.etl.declarative.target._schema_mode` is removed;
|
|
1187
|
+
import `SchemaMode` from `loom.core.schema` (or `loom.etl`).
|
|
1188
|
+
- **etl:** `FromClickHouse.select(columns)` is removed; use
|
|
1189
|
+
`FromClickHouse.columns(*columns)`.
|
|
1190
|
+
- **etl:** `ClickHouseSourceSpec.table` is removed; use
|
|
1191
|
+
`ClickHouseSourceSpec.table_ref.ref`.
|
|
1192
|
+
- **etl:** `loom.etl.backends.polars._reader._apply_source_schema` is
|
|
1193
|
+
removed. It was a test helper and has no public replacement.
|
|
1194
|
+
- **etl:** the module `loom.etl.runner.errors` is removed, and neither
|
|
1195
|
+
`loom.etl.runner` nor `loom.etl.runner.core` exports `InvalidStageError`;
|
|
1196
|
+
import it from `loom.etl.compiler` (or `loom.etl`).
|
|
1197
|
+
- **etl:** `loom.etl.io.sources._clickhouse` no longer re-exports
|
|
1198
|
+
`FromClickHouse` and `ClickHouseSourceSpec`; import them from
|
|
1199
|
+
`loom.etl.declarative.source` (`FromClickHouse` also from `loom.etl`).
|
|
959
1200
|
|
|
960
1201
|
### streaming
|
|
961
1202
|
|
|
1203
|
+
- **streaming:** `ConsumerSettings.delivery` is required. A Kafka consumer
|
|
1204
|
+
config without `delivery` fails to decode, so compiling a flow that reads
|
|
1205
|
+
from Kafka raises `CompilationError` with `KAFKA_CONFIG_INVALID` naming the
|
|
1206
|
+
missing field. Before, a missing `delivery` resolved to `at_most_once`.
|
|
1207
|
+
Declare `delivery: at_most_once` to keep that behaviour, or
|
|
1208
|
+
`delivery: at_least_once`. `ConsumerSettings.effective_delivery()` is
|
|
1209
|
+
removed; read `ConsumerSettings.delivery`.
|
|
1210
|
+
- **streaming:** `ConsumerSettings.enable_auto_commit` is removed, together
|
|
1211
|
+
with the `DELIVERY_CONFLICT` compile code. The consumer settings forbid
|
|
1212
|
+
unknown fields, so a config that sets `enable_auto_commit` fails to decode
|
|
1213
|
+
(`KAFKA_CONFIG_INVALID`). Declare `delivery` instead: `enable_auto_commit:
|
|
1214
|
+
false` was `delivery: at_least_once`, and `true` was `delivery:
|
|
1215
|
+
at_most_once`.
|
|
1216
|
+
- **streaming:** `ConsumerSettings.poll_timeout_ms` is removed. The
|
|
1217
|
+
partitioned source ignored it and logged a deprecation warning; a config
|
|
1218
|
+
that sets it now fails to decode (`KAFKA_CONFIG_INVALID`). Remove the key;
|
|
1219
|
+
the partitioned source is tuned with `batch_size` and `poll_backoff_ms`.
|
|
1220
|
+
- **streaming:** `CompilationError` takes `CompilationIssue` values only;
|
|
1221
|
+
bare strings and the `StreamingErrorCode.UNSPECIFIED` code they became are
|
|
1222
|
+
removed. Build an issue from a `StreamingErrorCode` member with `.issue()`.
|
|
1223
|
+
- **streaming:** `CompilationError.errors` is removed. Read the messages from
|
|
1224
|
+
`CompilationError.issues` (`[issue.message for issue in error.issues]`).
|
|
1225
|
+
- **streaming:** an `IntoTable` sink section (`streaming.sinks.<name>`) with a
|
|
1226
|
+
key its backend does not read fails at compile with `SINK_CONFIG_INVALID`,
|
|
1227
|
+
naming every unknown key; on Delta this covers the keys under `staging`
|
|
1228
|
+
too, and a `staging` or `writer_properties` that is not a mapping is
|
|
1229
|
+
refused. Before, such a key was ignored. A SQLAlchemy sink that references a
|
|
1230
|
+
shared `database` reads no pool keys (`pool_size`, `echo`, ...) from its own
|
|
1231
|
+
section, so they are refused there; set them under `database.<name>`.
|
|
1232
|
+
A SQLAlchemy or ClickHouse sink section that sets both `url` and `database`
|
|
1233
|
+
is refused too, instead of one silently winning: a SQLAlchemy sink sets one
|
|
1234
|
+
or the other, and a ClickHouse sink takes its url from `database.<name>`, so
|
|
1235
|
+
it sets `database` only.
|
|
1236
|
+
Delta's `part_max_records` is removed and therefore refused: it was an alias
|
|
1237
|
+
of `writer_properties.max_row_group_size`, which is the key to set. Without
|
|
1238
|
+
`writer_properties` the row groups still hold at most 10 000 rows.
|
|
1239
|
+
`DeltaSinkConfig` has no `part_max_records` attribute.
|
|
1240
|
+
- **streaming:** `CompiledSingleSource` and `CompiledMultiSource` take a
|
|
1241
|
+
required `settings_key`, the config key their consumer settings were
|
|
1242
|
+
resolved from (`kafka.consumer` or `kafka.consumers.<ref>`);
|
|
1243
|
+
`KafkaSettings.consumer_key_for(ref)` names it.
|
|
962
1244
|
- **streaming:** `FromTopic`, `FromMultiTypeTopic`, `FromMongoCDC` and
|
|
963
1245
|
`IntoTopic` take no `shape`, `CompiledSingleSource`, `CompiledMultiSource`
|
|
964
1246
|
and `CompiledMongoCDCSource` have no `shape` field, and `StreamShape.MANY`
|
|
@@ -1088,11 +1370,71 @@
|
|
|
1088
1370
|
- **streaming:** a sync `With(process=...)` hands on one message at a time, as
|
|
1089
1371
|
`WithAsync` does. After a `CollectBatch` it handed on whole batches, so as
|
|
1090
1372
|
the last node of a flow without `output` its messages never completed.
|
|
1373
|
+
- **streaming:** `IntoTable` with `Backend.SQLALCHEMY` binds each column with
|
|
1374
|
+
the type core compiles for the field instead of its own map:
|
|
1375
|
+
- a `StrEnum` or `IntEnum` field is written as its scalar (`String`,
|
|
1376
|
+
`Integer`) instead of as JSON;
|
|
1377
|
+
- a column type declared with `ColumnField` (on a `BaseModel`) or
|
|
1378
|
+
`Annotated[T, <ColumnType>]` is used;
|
|
1379
|
+
- a `Decimal`, plain `Enum` or `Literal` field without a declared column
|
|
1380
|
+
type is refused when the partition is built, with core's message, instead
|
|
1381
|
+
of being written as `Numeric()` (a `Decimal`) or as JSON. Declare it, e.g.
|
|
1382
|
+
`Annotated[Decimal, Numeric(precision=12, scale=2)]`, or
|
|
1383
|
+
`Annotated[Decimal, Numeric()]` for an unbounded `NUMERIC`.
|
|
1384
|
+
- **streaming:** `IntoTable` with `Backend.CLICKHOUSE` hands a `date` field to
|
|
1385
|
+
clickhouse-connect as a `date`, as core keeps it for a column, instead of as
|
|
1386
|
+
its ISO-8601 text. clickhouse-connect writes a `Date` column only from a
|
|
1387
|
+
`date` and refused the text ("unsupported operand type(s) for -: 'str' and
|
|
1388
|
+
'datetime.date'"); a `String` column now refuses the `date` ("object of type
|
|
1389
|
+
'datetime.date' has no len()"). A `dict` value is written as compact JSON
|
|
1390
|
+
text from `msgspec.json`, keys still sorted (`{"a":1}`, was `{"a": 1}`).
|
|
1091
1391
|
|
|
1092
1392
|
## 🐛 Fixes
|
|
1093
1393
|
|
|
1094
1394
|
### core
|
|
1095
1395
|
|
|
1396
|
+
- **core:** `RepositoryDynamoDB` reads, updates and deletes by a `UUID`
|
|
1397
|
+
primary key. `get_by_id`, `get_by`, `exists_by`, `update` and `delete`
|
|
1398
|
+
handed the raw key to boto3's `TypeSerializer`, which raised
|
|
1399
|
+
`TypeError: Unsupported type "<class 'uuid.UUID'>"`; `create` already stored
|
|
1400
|
+
the key as a string through `msgspec.to_builtins`. The key is now encoded
|
|
1401
|
+
with that same conversion, so it matches its stored form and round-trips.
|
|
1402
|
+
`update` keeps the key as stored instead of rewriting it from the argument.
|
|
1403
|
+
Attribute values are encoded as before.
|
|
1404
|
+
- **cache:** security: the repository cache keeps each caller's entries apart.
|
|
1405
|
+
The entity key (`get_by_id`, and the rows behind a cached page), the
|
|
1406
|
+
`list_paginated` index key, the `list_with_query` key and the key of a
|
|
1407
|
+
`@cache_query` read (`scope="entity"` and `scope="list"`) now carry the
|
|
1408
|
+
caller's cache scope, so a row, a page of ids, a first page with its next
|
|
1409
|
+
cursor or a custom read's result cached for one caller is no longer served
|
|
1410
|
+
to another that row-level security hides it from. The scope comes from the
|
|
1411
|
+
new, provisional `SupportsCacheScope.cache_scope()` (`""` for a repository
|
|
1412
|
+
without it): `RepositorySQLAlchemy` builds it from every setting the
|
|
1413
|
+
session-settings provider returns, so a policy reading a product setting
|
|
1414
|
+
such as `app.tenant_id` is kept apart too, while cursor tokens stay bound to
|
|
1415
|
+
the `loom.scope.*` settings only. Inside a caller-owned transaction (the
|
|
1416
|
+
unit of work a use case runs in, or a `@transactional` scope) every cached
|
|
1417
|
+
read goes straight to the repository, with no lookup and no store, and so
|
|
1418
|
+
does a call to a `@cache_query` method whose `session` parameter, passed by
|
|
1419
|
+
position or by name, is not `None`. This holds where the backend reports
|
|
1420
|
+
such a transaction, SQLAlchemy and Mongo with transactions; DynamoDB and
|
|
1421
|
+
Mongo with `transactions: false` keep caching, and a read-only use case run
|
|
1422
|
+
outside another unit of work opens none and keeps using the cache. Writes
|
|
1423
|
+
still evict every scope's entries: the scope is not part of the dependency
|
|
1424
|
+
tags, and a write bumps the same generation counters whatever its scope. The
|
|
1425
|
+
scope is read once per cache operation and read again before its writes,
|
|
1426
|
+
which are skipped if it changed. `CachedRepository` implements
|
|
1427
|
+
`cache_scope()` and `has_caller_scoped_session()` by forwarding the wrapped
|
|
1428
|
+
repository's, so a wrapper around it keys by the same scope and stays out of
|
|
1429
|
+
the same transactions, and refuses at construction, with a `RuntimeError`, a
|
|
1430
|
+
repository whose `session_manager` has session settings but which does not
|
|
1431
|
+
implement `cache_scope()`. The list filter, query and `@cache_query`
|
|
1432
|
+
arguments fingerprints in cache keys are now the full SHA-256 instead of its
|
|
1433
|
+
first 64 bits. `entity_key` and `list_index_key` take a required
|
|
1434
|
+
keyword-only `scope`, and the new `query_index_key` and `custom_query_key`
|
|
1435
|
+
build the `list_with_query` and `@cache_query` keys. Existing entity, list,
|
|
1436
|
+
query and `@cache_query` entries are no longer read after the upgrade and
|
|
1437
|
+
expire by their TTL.
|
|
1096
1438
|
- **core:** one environment selector and deploy checks (ADR 0005). loom had
|
|
1097
1439
|
two unconnected notions of environment (the logger's `dev`/`prod`, where an
|
|
1098
1440
|
unknown value meant `dev`, and `FlowCtx.environment`) and nothing checked a
|
|
@@ -1143,10 +1485,25 @@
|
|
|
1143
1485
|
startup. `parse_environment` validates a value naming an environment.
|
|
1144
1486
|
- **core:** the SQLAlchemy query compiler converts a filter value, and each
|
|
1145
1487
|
`in` item, as the repository converts a value it writes
|
|
1146
|
-
(`loom.core.
|
|
1488
|
+
(`loom.core.model.convert.to_column_value`, now shared by
|
|
1147
1489
|
both): an `Enum` member is bound as its value, a JSON column's value is
|
|
1148
1490
|
reduced to builtins. A plain `Enum` member as the value of a filter on a
|
|
1149
1491
|
string column failed to bind.
|
|
1492
|
+
- **core:** pagination cursors are signed and decoded strictly (ADR 0004).
|
|
1493
|
+
A cursor token was base64url JSON with no integrity, and a datetime key
|
|
1494
|
+
decoded without a time zone, so a client could forge a position and a
|
|
1495
|
+
consumer comparing it with aware datetimes raised `TypeError` (a 500). A
|
|
1496
|
+
token is now `base64url(payload).base64url(tag)`, the tag an HMAC-SHA256
|
|
1497
|
+
over a domain-separated input bound to the model, the normalised filters,
|
|
1498
|
+
the sort and the caller's scope, verified with `hmac.compare_digest` before
|
|
1499
|
+
the payload is parsed. A malformed, unsigned, forged or rebound token, a
|
|
1500
|
+
key signed by an unknown key id, a datetime key without a time zone, a key
|
|
1501
|
+
of an unknown type, the wrong number of keys or the wrong backend is
|
|
1502
|
+
`UnsupportedQuery` (`400 unsupported_query`), and the message never echoes
|
|
1503
|
+
the token. A naive datetime key, such as a `DateTime(tz=False)` column, is
|
|
1504
|
+
issued as UTC with an explicit offset and compared as naive UTC against
|
|
1505
|
+
that column, on SQLite and Postgres alike.
|
|
1506
|
+
|
|
1150
1507
|
- **core:** a `BoundaryValidationError` no longer echoes the rejected value
|
|
1151
1508
|
(#347). msgspec's `Invalid enum value 'x'` (an `Enum`, `IntEnum` or `Literal`
|
|
1152
1509
|
field or dict key) and `Invalid value 'x'` (a tagged-union tag) become
|
|
@@ -1175,8 +1532,9 @@
|
|
|
1175
1532
|
column only. The cursor now orders and compares on
|
|
1176
1533
|
every key column after the sort keys and carries every key value in the
|
|
1177
1534
|
token; offset pages and `list_paginated` order by every key column too.
|
|
1178
|
-
|
|
1179
|
-
model keyed its entries by the first key column
|
|
1535
|
+
That fix leaves tokens of single-column keys as they were. A cached
|
|
1536
|
+
repository over such a model keyed its entries by the first key column
|
|
1537
|
+
too, so a warm
|
|
1180
1538
|
`list_paginated` or first cursor page served the rows sharing a first key
|
|
1181
1539
|
value as copies of one of them; it now caches and reloads every row by its
|
|
1182
1540
|
full key, one `get_by_id` per missing row.
|
|
@@ -1212,6 +1570,12 @@
|
|
|
1212
1570
|
|
|
1213
1571
|
### etl
|
|
1214
1572
|
|
|
1573
|
+
- **etl:** the error for a missing destination table names only advice that
|
|
1574
|
+
works under the policy in force. Under `missing_table_policy='error'` it
|
|
1575
|
+
used to suggest `SchemaMode.OVERWRITE`, which that policy ignores; it now
|
|
1576
|
+
suggests `missing_table_policy='create'`, `'schema_mode'` with
|
|
1577
|
+
`SchemaMode.OVERWRITE`, or creating the table first.
|
|
1578
|
+
|
|
1215
1579
|
- **etl:** `replace(allow_empty=False)` on Spark writes the rows it checked.
|
|
1216
1580
|
The writer ran `DataFrame.isEmpty()` and then let the write compute the
|
|
1217
1581
|
frame again, so a source that changed in between, or a nondeterministic
|
|
@@ -1392,6 +1756,11 @@
|
|
|
1392
1756
|
|
|
1393
1757
|
### streaming
|
|
1394
1758
|
|
|
1759
|
+
- **streaming:** `SINK_CANNOT_TRACK_COMMITS` and
|
|
1760
|
+
`INLINE_SINK_CANNOT_SKIP_COMMITS` point their `field` at the `delivery` of
|
|
1761
|
+
the consumer the source was bound through, `kafka.consumer.delivery` or
|
|
1762
|
+
`kafka.consumers.<ref>.delivery`, instead of `streaming.delivery`, which no
|
|
1763
|
+
config reads.
|
|
1395
1764
|
- **streaming:** `ForEach` accepts the batch a `BatchStep` produces, so
|
|
1396
1765
|
`CollectBatch → BatchStep → ForEach → IntoTopic` compiles; it failed with
|
|
1397
1766
|
`shape mismatch: expected many but got batch before ForEach`. Under
|
|
@@ -1482,6 +1851,49 @@
|
|
|
1482
1851
|
offset at the step, also when the batch holds several messages of one
|
|
1483
1852
|
offset that an earlier expanding node produced. The new return type is under
|
|
1484
1853
|
Behaviour changes.
|
|
1854
|
+
- **streaming:** `IntoTable` with `Backend.SQLALCHEMY` binds a `bytes` field as
|
|
1855
|
+
`LargeBinary` (`bytea` on Postgres). It bound it as text, which Postgres
|
|
1856
|
+
refused for a `bytea` column ("column is of type bytea but expression is of
|
|
1857
|
+
type character varying"). IntoTable now takes each column's type from core's
|
|
1858
|
+
model introspection (`loom.core.backend.sqlalchemy.sa_table_for`), the type
|
|
1859
|
+
a compiled model declares, and builds each row with core's new
|
|
1860
|
+
`loom.core.repository.sqlalchemy.values.to_column_row`, which converts and
|
|
1861
|
+
checks values as the repository does when it writes them: a plain `Enum` as
|
|
1862
|
+
its value, a struct in a JSON column as a dict, an `UNSET` value left out so
|
|
1863
|
+
the column's database default applies, also when other rows of the batch
|
|
1864
|
+
set it, and a `time` whose UTC offset its column cannot take refused with
|
|
1865
|
+
`BoundaryValidationError` (`boundary_validation`) instead of being written
|
|
1866
|
+
without the offset. Relation and projection fields are no longer columns
|
|
1867
|
+
for any backend: the SQLAlchemy and Delta rows included them and failed on
|
|
1868
|
+
their `UNSET` value, and the ClickHouse insert named them. A `date` or
|
|
1869
|
+
`time` field is bound as `Date` or `Time`, as core infers it, so it is
|
|
1870
|
+
written into a Postgres `date` or `time` column; it was bound as `String`
|
|
1871
|
+
and Postgres refused it ("column is of type date but expression is of type
|
|
1872
|
+
character varying").
|
|
1873
|
+
- **streaming:** `IntoTable` with `Backend.DELTA` or `Backend.CLICKHOUSE`
|
|
1874
|
+
refuses an `UNSET` column value when the item is written, with
|
|
1875
|
+
`BoundaryValidationError` (`boundary_validation`) naming the field and the
|
|
1876
|
+
table. Delta failed later, at a mini-batch or flush, with pyarrow's
|
|
1877
|
+
`ArrowInvalid`, and ClickHouse passed the `UNSET` object to
|
|
1878
|
+
clickhouse-connect's `insert`. Neither can leave a column out for one row as
|
|
1879
|
+
`Backend.SQLALCHEMY` does.
|
|
1880
|
+
- **streaming:** `IntoTable` with `Backend.DELTA` or `Backend.CLICKHOUSE`
|
|
1881
|
+
converts each column value as `Backend.SQLALCHEMY` and core's repository
|
|
1882
|
+
do, with `loom.core.model.convert.to_column_value`: a plain `Enum` becomes
|
|
1883
|
+
its value and a nested `msgspec.Struct` or `LoomStruct` a dict, also inside a
|
|
1884
|
+
list or a dict, while `bytes`, `datetime`, `date`, `time`, `Decimal` and
|
|
1885
|
+
`UUID` are kept. Delta refused an `Enum` or a struct with pyarrow's
|
|
1886
|
+
`ArrowInvalid` ("did not recognize Python value type when inferring an
|
|
1887
|
+
Arrow data type"); a nested struct is now a Delta struct column, as a `dict`
|
|
1888
|
+
field already was, and keeps its `datetime` and `Decimal` types.
|
|
1889
|
+
clickhouse-connect refused an `Enum` or a struct ("object of type ... has no
|
|
1890
|
+
len()") and `json.dumps` a `dict` holding a `Decimal` or `datetime` ("Object
|
|
1891
|
+
of type Decimal is not JSON serializable"); an `Enum` is now inserted as its
|
|
1892
|
+
value and a struct or `dict` as JSON text from `msgspec.json`, a `datetime`
|
|
1893
|
+
inside it as ISO-8601 text and a `Decimal` as decimal text.
|
|
1894
|
+
`to_column_value` moved to `loom.core.model.convert` (under Behaviour
|
|
1895
|
+
changes), so the Delta and ClickHouse writers use it without SQLAlchemy
|
|
1896
|
+
installed.
|
|
1485
1897
|
|
|
1486
1898
|
### prefect
|
|
1487
1899
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: loom-kernel
|
|
3
|
-
Version:
|
|
3
|
+
Version: 9.1.0
|
|
4
4
|
Summary: Loom Python project
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -457,6 +457,10 @@ app:
|
|
|
457
457
|
title: My Store API
|
|
458
458
|
version: 0.1.0
|
|
459
459
|
|
|
460
|
+
persistence:
|
|
461
|
+
cursors:
|
|
462
|
+
signing: ephemeral # development.yaml only; production.yaml configures keys
|
|
463
|
+
|
|
460
464
|
database:
|
|
461
465
|
url: ${oc.env:DATABASE_URL,sqlite+aiosqlite:///store.db}
|
|
462
466
|
|
|
@@ -136,7 +136,7 @@ def build_agent_card(
|
|
|
136
136
|
"protocolVersion": PROTOCOL_VERSION,
|
|
137
137
|
"name": plan.name,
|
|
138
138
|
"description": plan.description,
|
|
139
|
-
"url": agent_url(config.base_url, plan.name, prefix=prefix),
|
|
139
|
+
"url": agent_url(config.base_url.reveal(), plan.name, prefix=prefix),
|
|
140
140
|
"version": str(plan.spec_version),
|
|
141
141
|
"capabilities": dict(_TRANSPORT_CAPABILITIES),
|
|
142
142
|
"defaultInputModes": list(_INPUT_MODES),
|