floe-python 0.6.7__tar.gz → 0.6.9__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.
- {floe_python-0.6.7 → floe_python-0.6.9}/Cargo.lock +13 -13
- {floe_python-0.6.7 → floe_python-0.6.9}/PKG-INFO +1 -1
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/Cargo.toml +1 -1
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/config/parse.rs +4 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/config/template.rs +14 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/config/types.rs +2 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/storage/providers/s3.rs +22 -1
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/lineage/mod.rs +20 -2
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/config/lineage_validation.rs +18 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/config/templating.rs +79 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/storage/s3.rs +22 -1
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/run/lineage.rs +63 -2
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-python/Cargo.toml +2 -2
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-python/pyproject.duckdb.toml +2 -2
- {floe_python-0.6.7 → floe_python-0.6.9}/pyproject.toml +1 -1
- {floe_python-0.6.7 → floe_python-0.6.9}/Cargo.toml +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/README.md +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/README.md +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/add_entity.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/checks/cast.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/checks/mismatch.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/checks/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/checks/normalize.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/checks/not_null.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/checks/unique.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/config/catalog.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/config/location.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/config/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/config/storage.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/config/validate.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/config/yaml_decode.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/errors.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/format.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/read/avro.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/read/csv.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/read/fixed_width.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/read/json.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/read/json_selector.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/read/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/read/orc.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/read/parquet.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/read/xlsx.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/read/xml.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/read/xml_selector.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/storage/core/extensions.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/storage/core/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/storage/core/paths.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/storage/core/placement.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/storage/core/planner.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/storage/core/uri.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/storage/core/validation.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/storage/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/storage/object_store.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/storage/ops/archive.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/storage/ops/inputs.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/storage/ops/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/storage/ops/output.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/storage/providers/adls.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/storage/providers/gcs.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/storage/providers/local.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/storage/providers/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/storage/target.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/unique_seed/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/accepted.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/arrow_convert.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/csv.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/delta/commit_metrics.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/delta/options.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/delta/record_batch.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/delta/unity.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/delta/unity_tests.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/delta.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/duckdb/conn.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/duckdb/merge.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/duckdb.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/iceberg/context.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/iceberg/data_files.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/iceberg/glue.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/iceberg/metadata.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/iceberg/rest.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/iceberg/schema.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/iceberg.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/metrics.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/parquet.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/parts.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/sink_format.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/strategy/append.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/strategy/merge/keys.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/strategy/merge/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/strategy/merge/scd1.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/strategy/merge/scd2.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/strategy/merge/shared.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/strategy/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/io/write/strategy/overwrite.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/lib.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/log.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/manifest/builder.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/manifest/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/manifest/model.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/manifest/reconstruct.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/manifest/runtime.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/profile/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/profile/parse.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/profile/types.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/profile/validate.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/report/build.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/report/entity.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/report/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/report/output.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/run/context.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/run/entity/accepted_buffer.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/run/entity/accepted_write.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/run/entity/incremental.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/run/entity/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/run/entity/pii.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/run/entity/precheck.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/run/entity/process.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/run/entity/resolve.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/run/entity/validate_split.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/run/events.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/run/file.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/run/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/run/output.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/run/perf.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/runner/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/runner/outcome.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/runtime.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/secret.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/state/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/vars/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/vars/resolve.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/src/warnings.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/integration/archive_run.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/integration/composite_unique.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/integration/delta_run.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/integration/dry_run.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/integration/duckdb_run.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/integration/fixed_width.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/integration/iceberg_gcs_run.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/integration/iceberg_glue_run.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/integration/iceberg_run.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/integration/iceberg_s3_run.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/integration/json_selectors.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/integration/local_run.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/integration/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/integration/path_normalization.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/integration/run_entities_filter.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/integration.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/common.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/config/add_entity.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/config/adls_storage.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/config/adls_validation.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/config/catalogs.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/config/config_validation.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/config/duckdb_validation.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/config/gcs_storage.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/config/gcs_validation.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/config/local_storage.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/config/location.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/config/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/config/parse.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/config/pii_validation.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/config/remote_base.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/config/storage_resolver_uri.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/format.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/read/avro_input.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/read/csv_nulls.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/read/json_array.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/read/json_ndjson.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/read/json_selector.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/read/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/read/orc_input.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/read/parquet_input.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/read/tsv.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/read/xlsx_input.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/read/xml.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/read/xml_selector.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/storage/adls.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/storage/adls_integration.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/storage/gcs.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/storage/inputs.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/storage/local.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/storage/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/storage/paths.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/storage/planner.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/storage/target.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/write/delta_merge.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/write/delta_write.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/write/iceberg_write.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/write/metrics.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/write/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/write/object_store.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/write/parquet_write.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/write/parts.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/io/write/rejected_csv.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/manifest/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/manifest/runtime.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/profile/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/profile/parse.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/profile/validate.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/report/accepted_output.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/report/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/report/storage.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/run/check_order.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/run/checks.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/run/entity/accepted_output.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/run/entity/incremental.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/run/entity/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/run/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/run/normalize.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/run/pii.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/run/replay_base.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/run/report.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/run/schema_mismatch.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/runner/adapter.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/runner/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/state/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/vars/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/vars/resolve.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-python/.gitignore +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-python/README.md +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-python/src/functions.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-python/src/lib.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-python/src/observer.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-python/src/types/config.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-python/src/types/errors.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-python/src/types/mod.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-python/src/types/outcome.rs +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-python/tests/fixtures/config.yml +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-python/tests/fixtures/in/customer/customers_valid.csv +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-python/tests/fixtures/invalid_config.yml +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-python/tests/fixtures/profile.yml +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-python/tests/test_floe.py +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/python/floe/__init__.py +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/python/floe/_floe.pyi +0 -0
- {floe_python-0.6.7 → floe_python-0.6.9}/python/floe/py.typed +0 -0
|
@@ -1805,7 +1805,7 @@ dependencies = [
|
|
|
1805
1805
|
"crc",
|
|
1806
1806
|
"digest",
|
|
1807
1807
|
"rustversion",
|
|
1808
|
-
"spin 0.10.
|
|
1808
|
+
"spin 0.10.1",
|
|
1809
1809
|
]
|
|
1810
1810
|
|
|
1811
1811
|
[[package]]
|
|
@@ -1847,9 +1847,9 @@ dependencies = [
|
|
|
1847
1847
|
|
|
1848
1848
|
[[package]]
|
|
1849
1849
|
name = "crossbeam-epoch"
|
|
1850
|
-
version = "0.9.
|
|
1850
|
+
version = "0.9.20"
|
|
1851
1851
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1852
|
-
checksum = "
|
|
1852
|
+
checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f"
|
|
1853
1853
|
dependencies = [
|
|
1854
1854
|
"crossbeam-utils",
|
|
1855
1855
|
]
|
|
@@ -3205,9 +3205,9 @@ dependencies = [
|
|
|
3205
3205
|
|
|
3206
3206
|
[[package]]
|
|
3207
3207
|
name = "ethnum"
|
|
3208
|
-
version = "1.5.
|
|
3208
|
+
version = "1.5.3"
|
|
3209
3209
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3210
|
-
checksum = "
|
|
3210
|
+
checksum = "40404c3f5f511ec4da6fe866ddf6a717c309fdbb69fbbad7b0f3edab8f2e835f"
|
|
3211
3211
|
|
|
3212
3212
|
[[package]]
|
|
3213
3213
|
name = "event-listener"
|
|
@@ -3340,7 +3340,7 @@ dependencies = [
|
|
|
3340
3340
|
|
|
3341
3341
|
[[package]]
|
|
3342
3342
|
name = "floe-cli"
|
|
3343
|
-
version = "0.6.
|
|
3343
|
+
version = "0.6.9"
|
|
3344
3344
|
dependencies = [
|
|
3345
3345
|
"assert_cmd",
|
|
3346
3346
|
"clap",
|
|
@@ -3353,7 +3353,7 @@ dependencies = [
|
|
|
3353
3353
|
|
|
3354
3354
|
[[package]]
|
|
3355
3355
|
name = "floe-core"
|
|
3356
|
-
version = "0.6.
|
|
3356
|
+
version = "0.6.9"
|
|
3357
3357
|
dependencies = [
|
|
3358
3358
|
"apache-avro",
|
|
3359
3359
|
"arrow",
|
|
@@ -3399,7 +3399,7 @@ dependencies = [
|
|
|
3399
3399
|
|
|
3400
3400
|
[[package]]
|
|
3401
3401
|
name = "floe-python"
|
|
3402
|
-
version = "0.6.
|
|
3402
|
+
version = "0.6.9"
|
|
3403
3403
|
dependencies = [
|
|
3404
3404
|
"floe-core",
|
|
3405
3405
|
"pyo3",
|
|
@@ -4535,7 +4535,7 @@ version = "1.5.0"
|
|
|
4535
4535
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
4536
4536
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|
4537
4537
|
dependencies = [
|
|
4538
|
-
"spin 0.9.
|
|
4538
|
+
"spin 0.9.9",
|
|
4539
4539
|
]
|
|
4540
4540
|
|
|
4541
4541
|
[[package]]
|
|
@@ -7535,15 +7535,15 @@ dependencies = [
|
|
|
7535
7535
|
|
|
7536
7536
|
[[package]]
|
|
7537
7537
|
name = "spin"
|
|
7538
|
-
version = "0.9.
|
|
7538
|
+
version = "0.9.9"
|
|
7539
7539
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
7540
|
-
checksum = "
|
|
7540
|
+
checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e"
|
|
7541
7541
|
|
|
7542
7542
|
[[package]]
|
|
7543
7543
|
name = "spin"
|
|
7544
|
-
version = "0.10.
|
|
7544
|
+
version = "0.10.1"
|
|
7545
7545
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
7546
|
-
checksum = "
|
|
7546
|
+
checksum = "023a211cb3138dbc438680b32560ad89f699977624c9f8dbb95a47d5b4c07dd3"
|
|
7547
7547
|
|
|
7548
7548
|
[[package]]
|
|
7549
7549
|
name = "spki"
|
|
@@ -1190,9 +1190,11 @@ pub(crate) fn parse_lineage_config(value: &Yaml) -> FloeResult<LineageConfig> {
|
|
|
1190
1190
|
"lineage",
|
|
1191
1191
|
&[
|
|
1192
1192
|
"url",
|
|
1193
|
+
"endpoint",
|
|
1193
1194
|
"api_key",
|
|
1194
1195
|
"timeout_secs",
|
|
1195
1196
|
"namespace",
|
|
1197
|
+
"dataset_namespace",
|
|
1196
1198
|
"producer",
|
|
1197
1199
|
"max_failures",
|
|
1198
1200
|
"job_name",
|
|
@@ -1200,9 +1202,11 @@ pub(crate) fn parse_lineage_config(value: &Yaml) -> FloeResult<LineageConfig> {
|
|
|
1200
1202
|
)?;
|
|
1201
1203
|
Ok(LineageConfig {
|
|
1202
1204
|
url: get_string(hash, "url", "lineage")?,
|
|
1205
|
+
endpoint: opt_string(hash, "endpoint", "lineage")?,
|
|
1203
1206
|
api_key: opt_string(hash, "api_key", "lineage")?,
|
|
1204
1207
|
timeout_secs: opt_u64(hash, "timeout_secs", "lineage")?,
|
|
1205
1208
|
namespace: get_string(hash, "namespace", "lineage")?,
|
|
1209
|
+
dataset_namespace: opt_string(hash, "dataset_namespace", "lineage")?,
|
|
1206
1210
|
producer: opt_string(hash, "producer", "lineage")?,
|
|
1207
1211
|
max_failures: opt_u32(hash, "max_failures", "lineage")?,
|
|
1208
1212
|
job_name: opt_string(hash, "job_name", "lineage")?,
|
|
@@ -34,9 +34,11 @@ pub fn apply_templates_with_vars(
|
|
|
34
34
|
|
|
35
35
|
if let Some(lineage) = config.lineage.as_mut() {
|
|
36
36
|
lineage.url = replace_placeholders(&lineage.url, &vars, "lineage.url", None)?;
|
|
37
|
+
replace_lineage_field(&mut lineage.endpoint, &vars, "endpoint")?;
|
|
37
38
|
if let Some(api_key) = lineage.api_key.as_mut() {
|
|
38
39
|
*api_key = replace_placeholders(api_key, &vars, "lineage.api_key", None)?;
|
|
39
40
|
}
|
|
41
|
+
replace_lineage_field(&mut lineage.dataset_namespace, &vars, "dataset_namespace")?;
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
if let Some(storages) = config.storages.as_mut() {
|
|
@@ -96,6 +98,18 @@ pub fn apply_templates_with_vars(
|
|
|
96
98
|
Ok(())
|
|
97
99
|
}
|
|
98
100
|
|
|
101
|
+
fn replace_lineage_field(
|
|
102
|
+
value: &mut Option<String>,
|
|
103
|
+
vars: &HashMap<String, String>,
|
|
104
|
+
field_name: &str,
|
|
105
|
+
) -> FloeResult<()> {
|
|
106
|
+
if let Some(current) = value.as_mut() {
|
|
107
|
+
let field = format!("lineage.{field_name}");
|
|
108
|
+
*current = replace_placeholders(current, vars, &field, None)?;
|
|
109
|
+
}
|
|
110
|
+
Ok(())
|
|
111
|
+
}
|
|
112
|
+
|
|
99
113
|
fn replace_storage_definition_field(
|
|
100
114
|
value: &mut Option<String>,
|
|
101
115
|
vars: &HashMap<String, String>,
|
|
@@ -28,9 +28,11 @@ pub struct RootConfig {
|
|
|
28
28
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
29
29
|
pub struct LineageConfig {
|
|
30
30
|
pub url: String,
|
|
31
|
+
pub endpoint: Option<String>,
|
|
31
32
|
pub api_key: Option<String>,
|
|
32
33
|
pub timeout_secs: Option<u64>,
|
|
33
34
|
pub namespace: String,
|
|
35
|
+
pub dataset_namespace: Option<String>,
|
|
34
36
|
pub producer: Option<String>,
|
|
35
37
|
pub max_failures: Option<u32>,
|
|
36
38
|
pub job_name: Option<String>,
|
|
@@ -12,6 +12,8 @@ use crate::io::storage::uri::{format_bucket_uri, parse_bucket_uri, BucketLocatio
|
|
|
12
12
|
use crate::io::storage::{planner, ConditionalWrite, ObjectRef, StorageClient, StoredObject};
|
|
13
13
|
use crate::FloeResult;
|
|
14
14
|
|
|
15
|
+
const AWS_S3_FORCE_PATH_STYLE: &str = "AWS_S3_FORCE_PATH_STYLE";
|
|
16
|
+
|
|
15
17
|
pub struct S3Client {
|
|
16
18
|
bucket: String,
|
|
17
19
|
client: Client,
|
|
@@ -44,7 +46,7 @@ impl S3Client {
|
|
|
44
46
|
builder.load().await
|
|
45
47
|
});
|
|
46
48
|
let mut s3_builder = aws_sdk_s3::config::Builder::from(&config);
|
|
47
|
-
if path_style_access
|
|
49
|
+
if resolve_path_style_access(path_style_access) {
|
|
48
50
|
s3_builder = s3_builder.force_path_style(true);
|
|
49
51
|
}
|
|
50
52
|
let client = Client::from_conf(s3_builder.build());
|
|
@@ -290,6 +292,25 @@ impl StorageClient for S3Client {
|
|
|
290
292
|
}
|
|
291
293
|
}
|
|
292
294
|
|
|
295
|
+
#[doc(hidden)]
|
|
296
|
+
pub fn resolve_path_style_access(configured: Option<bool>) -> bool {
|
|
297
|
+
let env_value = std::env::var(AWS_S3_FORCE_PATH_STYLE).ok();
|
|
298
|
+
resolve_path_style_access_from_env(configured, env_value.as_deref())
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
#[doc(hidden)]
|
|
302
|
+
pub fn resolve_path_style_access_from_env(
|
|
303
|
+
configured: Option<bool>,
|
|
304
|
+
env_value: Option<&str>,
|
|
305
|
+
) -> bool {
|
|
306
|
+
configured.unwrap_or_else(|| {
|
|
307
|
+
env_value.is_some_and(|value| {
|
|
308
|
+
let value = value.trim();
|
|
309
|
+
value == "1" || value.eq_ignore_ascii_case("true")
|
|
310
|
+
})
|
|
311
|
+
})
|
|
312
|
+
}
|
|
313
|
+
|
|
293
314
|
fn is_not_found<E: std::fmt::Display>(err: &E) -> bool {
|
|
294
315
|
let text = err.to_string();
|
|
295
316
|
text.contains("NoSuchKey") || text.contains("NotFound") || text.contains("404")
|
|
@@ -32,6 +32,18 @@ struct EntityUris {
|
|
|
32
32
|
rejected: Option<OlDataset>,
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
fn resolve_lineage_url(base: &str, endpoint: Option<&str>) -> String {
|
|
36
|
+
let path = endpoint
|
|
37
|
+
.map(str::trim)
|
|
38
|
+
.filter(|s| !s.is_empty())
|
|
39
|
+
.unwrap_or("api/v1/lineage");
|
|
40
|
+
format!(
|
|
41
|
+
"{}/{}",
|
|
42
|
+
base.trim_end_matches('/'),
|
|
43
|
+
path.trim_start_matches('/')
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
35
47
|
pub struct OpenLineageObserver {
|
|
36
48
|
client: reqwest::blocking::Client,
|
|
37
49
|
config: LineageConfig,
|
|
@@ -91,6 +103,12 @@ impl OpenLineageObserver {
|
|
|
91
103
|
})
|
|
92
104
|
.collect();
|
|
93
105
|
|
|
106
|
+
let dataset_namespace = config
|
|
107
|
+
.dataset_namespace
|
|
108
|
+
.clone()
|
|
109
|
+
.filter(|s| !s.trim().is_empty())
|
|
110
|
+
.unwrap_or_else(|| config.namespace.clone());
|
|
111
|
+
|
|
94
112
|
let entity_uris = entities
|
|
95
113
|
.iter()
|
|
96
114
|
.map(|e| {
|
|
@@ -105,7 +123,7 @@ impl OpenLineageObserver {
|
|
|
105
123
|
let ns = iceberg.namespace.as_deref().unwrap_or(e.name.as_str());
|
|
106
124
|
let tbl = iceberg.table.as_deref().unwrap_or(e.name.as_str());
|
|
107
125
|
OlDataset {
|
|
108
|
-
namespace:
|
|
126
|
+
namespace: dataset_namespace.clone(),
|
|
109
127
|
name: format!("{ns}.{tbl}"),
|
|
110
128
|
}
|
|
111
129
|
}
|
|
@@ -177,7 +195,7 @@ impl OpenLineageObserver {
|
|
|
177
195
|
return;
|
|
178
196
|
}
|
|
179
197
|
|
|
180
|
-
let url =
|
|
198
|
+
let url = resolve_lineage_url(&self.config.url, self.config.endpoint.as_deref());
|
|
181
199
|
let max_failures = self.config.max_failures.unwrap_or(3) as usize;
|
|
182
200
|
let retry_delays_ms: &[u64] = &[0, 100, 500];
|
|
183
201
|
|
{floe_python-0.6.7 → floe_python-0.6.9}/crates/floe-core/tests/unit/config/lineage_validation.rs
RENAMED
|
@@ -74,7 +74,9 @@ report:
|
|
|
74
74
|
path: "/tmp/reports"
|
|
75
75
|
lineage:
|
|
76
76
|
url: "http://marquez:5000"
|
|
77
|
+
endpoint: "/api/v1/openlineage/lineage"
|
|
77
78
|
namespace: "my-namespace"
|
|
79
|
+
dataset_namespace: "iceberg.prod"
|
|
78
80
|
timeout_secs: 10
|
|
79
81
|
producer: "https://github.com/myorg/floe"
|
|
80
82
|
entities:
|
|
@@ -95,6 +97,20 @@ entities:
|
|
|
95
97
|
"#;
|
|
96
98
|
let path = write_temp_config(config);
|
|
97
99
|
validate(&path, ValidateOptions::default()).expect("valid lineage config");
|
|
100
|
+
let parsed = load_config_with_profile_overrides(
|
|
101
|
+
&path,
|
|
102
|
+
&std::collections::HashMap::new(),
|
|
103
|
+
None,
|
|
104
|
+
None,
|
|
105
|
+
None,
|
|
106
|
+
)
|
|
107
|
+
.expect("lineage config should parse");
|
|
108
|
+
let lineage = parsed.lineage.expect("lineage should be present");
|
|
109
|
+
assert_eq!(
|
|
110
|
+
lineage.endpoint.as_deref(),
|
|
111
|
+
Some("/api/v1/openlineage/lineage")
|
|
112
|
+
);
|
|
113
|
+
assert_eq!(lineage.dataset_namespace.as_deref(), Some("iceberg.prod"));
|
|
98
114
|
}
|
|
99
115
|
|
|
100
116
|
#[test]
|
|
@@ -180,7 +196,9 @@ entities:
|
|
|
180
196
|
let path = write_temp_config(base);
|
|
181
197
|
let profile_lineage = LineageConfig {
|
|
182
198
|
url: "http://localhost:5000".to_string(),
|
|
199
|
+
endpoint: None,
|
|
183
200
|
namespace: "floe-demo-local".to_string(),
|
|
201
|
+
dataset_namespace: None,
|
|
184
202
|
api_key: None,
|
|
185
203
|
timeout_secs: Some(2),
|
|
186
204
|
producer: None,
|
|
@@ -88,6 +88,85 @@ entities:
|
|
|
88
88
|
);
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
#[test]
|
|
92
|
+
fn env_vars_apply_to_lineage_endpoint_and_dataset_namespace() {
|
|
93
|
+
let root = temp_dir("floe-lineage-vars");
|
|
94
|
+
let config_yaml = format!(
|
|
95
|
+
r#"version: "0.1"
|
|
96
|
+
env:
|
|
97
|
+
vars:
|
|
98
|
+
LINEAGE_ENDPOINT: "api/v1/openlineage/lineage"
|
|
99
|
+
DATASET_NAMESPACE: "iceberg.prod"
|
|
100
|
+
lineage:
|
|
101
|
+
url: "http://openmetadata:8585"
|
|
102
|
+
endpoint: "{{{{LINEAGE_ENDPOINT}}}}"
|
|
103
|
+
namespace: "dagster"
|
|
104
|
+
dataset_namespace: "{{{{DATASET_NAMESPACE}}}}"
|
|
105
|
+
entities:
|
|
106
|
+
- name: "orders"
|
|
107
|
+
source:
|
|
108
|
+
format: "csv"
|
|
109
|
+
path: "{root}/in/orders.csv"
|
|
110
|
+
sink:
|
|
111
|
+
accepted:
|
|
112
|
+
format: "parquet"
|
|
113
|
+
path: "{root}/out/orders"
|
|
114
|
+
policy:
|
|
115
|
+
severity: "warn"
|
|
116
|
+
schema:
|
|
117
|
+
columns:
|
|
118
|
+
- name: "id"
|
|
119
|
+
type: "string"
|
|
120
|
+
"#,
|
|
121
|
+
root = root.display(),
|
|
122
|
+
);
|
|
123
|
+
let config_path = write_config(&root, &config_yaml);
|
|
124
|
+
let parsed = load_config(&config_path).expect("parse config");
|
|
125
|
+
let lineage = parsed.lineage.expect("lineage");
|
|
126
|
+
|
|
127
|
+
assert_eq!(
|
|
128
|
+
lineage.endpoint.as_deref(),
|
|
129
|
+
Some("api/v1/openlineage/lineage")
|
|
130
|
+
);
|
|
131
|
+
assert_eq!(lineage.dataset_namespace.as_deref(), Some("iceberg.prod"));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
#[test]
|
|
135
|
+
fn unresolved_lineage_placeholder_errors() {
|
|
136
|
+
let root = temp_dir("floe-lineage-unresolved");
|
|
137
|
+
let config_yaml = format!(
|
|
138
|
+
r#"version: "0.1"
|
|
139
|
+
lineage:
|
|
140
|
+
url: "http://openmetadata:8585"
|
|
141
|
+
endpoint: "{{{{OPENLINEAGE_ENDPOINT}}}}"
|
|
142
|
+
namespace: "dagster"
|
|
143
|
+
entities:
|
|
144
|
+
- name: "orders"
|
|
145
|
+
source:
|
|
146
|
+
format: "csv"
|
|
147
|
+
path: "{root}/in/orders.csv"
|
|
148
|
+
sink:
|
|
149
|
+
accepted:
|
|
150
|
+
format: "parquet"
|
|
151
|
+
path: "{root}/out/orders"
|
|
152
|
+
policy:
|
|
153
|
+
severity: "warn"
|
|
154
|
+
schema:
|
|
155
|
+
columns:
|
|
156
|
+
- name: "id"
|
|
157
|
+
type: "string"
|
|
158
|
+
"#,
|
|
159
|
+
root = root.display(),
|
|
160
|
+
);
|
|
161
|
+
let config_path = write_config(&root, &config_yaml);
|
|
162
|
+
|
|
163
|
+
let err = load_config(&config_path).expect_err("placeholder error");
|
|
164
|
+
assert_eq!(
|
|
165
|
+
err.to_string(),
|
|
166
|
+
"lineage.endpoint references unknown variable OPENLINEAGE_ENDPOINT"
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
91
170
|
#[test]
|
|
92
171
|
fn env_file_vars_apply_to_source_path() {
|
|
93
172
|
let root = temp_dir("floe-env-file");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
use std::path::Path;
|
|
2
2
|
|
|
3
|
-
use floe_core::io::storage::s3::parse_s3_uri;
|
|
3
|
+
use floe_core::io::storage::s3::{parse_s3_uri, resolve_path_style_access_from_env};
|
|
4
4
|
use floe_core::io::storage::{filter_by_suffixes, stable_sort_refs, temp_path_for_key, ObjectRef};
|
|
5
5
|
|
|
6
6
|
#[test]
|
|
@@ -17,6 +17,27 @@ fn parse_s3_uri_allows_bucket_only() {
|
|
|
17
17
|
assert_eq!(loc.key, "");
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
#[test]
|
|
21
|
+
fn path_style_access_prefers_explicit_config() {
|
|
22
|
+
let resolve = resolve_path_style_access_from_env;
|
|
23
|
+
|
|
24
|
+
assert!(resolve(Some(true), None));
|
|
25
|
+
assert!(resolve(Some(true), Some("false")));
|
|
26
|
+
assert!(!resolve(Some(false), Some("true")));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
#[test]
|
|
30
|
+
fn path_style_access_falls_back_to_aws_env_convention() {
|
|
31
|
+
let resolve = resolve_path_style_access_from_env;
|
|
32
|
+
|
|
33
|
+
assert!(!resolve(None, None));
|
|
34
|
+
assert!(resolve(None, Some("true")));
|
|
35
|
+
assert!(resolve(None, Some("1")));
|
|
36
|
+
assert!(resolve(None, Some(" TRUE ")));
|
|
37
|
+
assert!(!resolve(None, Some("false")));
|
|
38
|
+
assert!(!resolve(None, Some("garbage")));
|
|
39
|
+
}
|
|
40
|
+
|
|
20
41
|
#[test]
|
|
21
42
|
fn filter_keys_by_suffix_sorts_and_filters() {
|
|
22
43
|
let refs = vec![
|
|
@@ -9,15 +9,34 @@ use serde_json::json;
|
|
|
9
9
|
fn make_config(server_url: &str, max_failures: Option<u32>) -> LineageConfig {
|
|
10
10
|
LineageConfig {
|
|
11
11
|
url: server_url.to_string(),
|
|
12
|
+
endpoint: None,
|
|
12
13
|
api_key: None,
|
|
13
14
|
timeout_secs: Some(2),
|
|
14
15
|
namespace: "test-ns".to_string(),
|
|
16
|
+
dataset_namespace: None,
|
|
15
17
|
producer: None,
|
|
16
18
|
max_failures,
|
|
17
19
|
job_name: None,
|
|
18
20
|
}
|
|
19
21
|
}
|
|
20
22
|
|
|
23
|
+
#[test]
|
|
24
|
+
fn custom_endpoint_is_used_for_posts() {
|
|
25
|
+
let mut server = mockito::Server::new();
|
|
26
|
+
let mock = server
|
|
27
|
+
.mock("POST", "/api/v1/openlineage/lineage")
|
|
28
|
+
.with_status(200)
|
|
29
|
+
.expect(1)
|
|
30
|
+
.create();
|
|
31
|
+
|
|
32
|
+
let mut config = make_config(&format!("{}/", server.url()), None);
|
|
33
|
+
config.endpoint = Some("/api/v1/openlineage/lineage".to_string());
|
|
34
|
+
let obs = OpenLineageObserver::new(&config, &[], "config.yml").unwrap();
|
|
35
|
+
|
|
36
|
+
obs.on_event(run_started_event());
|
|
37
|
+
mock.assert();
|
|
38
|
+
}
|
|
39
|
+
|
|
21
40
|
fn run_started_event() -> RunEvent {
|
|
22
41
|
RunEvent::RunStarted {
|
|
23
42
|
run_id: "test-run-1".to_string(),
|
|
@@ -987,7 +1006,8 @@ fn iceberg_accepted_uses_catalog_namespace_and_table_name() {
|
|
|
987
1006
|
.match_body(mockito::Matcher::PartialJson(json!({
|
|
988
1007
|
"eventType": "COMPLETE",
|
|
989
1008
|
"inputs": [{ "namespace": "s3://iceberg-data", "name": "bronze/sales/customers" }],
|
|
990
|
-
"
|
|
1009
|
+
"job": { "namespace": "test-ns" },
|
|
1010
|
+
"outputs": [{ "namespace": "iceberg.prod", "name": "sales_dev.customers" }]
|
|
991
1011
|
})))
|
|
992
1012
|
.with_status(200)
|
|
993
1013
|
.expect(1)
|
|
@@ -1006,7 +1026,8 @@ fn iceberg_accepted_uses_catalog_namespace_and_table_name() {
|
|
|
1006
1026
|
location: None,
|
|
1007
1027
|
});
|
|
1008
1028
|
|
|
1009
|
-
let config = make_config(&server.url(), None);
|
|
1029
|
+
let mut config = make_config(&server.url(), None);
|
|
1030
|
+
config.dataset_namespace = Some("iceberg.prod".to_string());
|
|
1010
1031
|
let obs = OpenLineageObserver::new(&config, &[entity], "config.yml").unwrap();
|
|
1011
1032
|
|
|
1012
1033
|
obs.on_event(RunEvent::EntityStarted {
|
|
@@ -1031,3 +1052,43 @@ fn iceberg_accepted_uses_catalog_namespace_and_table_name() {
|
|
|
1031
1052
|
_start_mock.assert();
|
|
1032
1053
|
_complete_mock.assert();
|
|
1033
1054
|
}
|
|
1055
|
+
|
|
1056
|
+
#[test]
|
|
1057
|
+
fn iceberg_accepted_dataset_namespace_defaults_to_job_namespace() {
|
|
1058
|
+
let mut server = mockito::Server::new();
|
|
1059
|
+
let _start_mock = server
|
|
1060
|
+
.mock("POST", "/api/v1/lineage")
|
|
1061
|
+
.with_status(200)
|
|
1062
|
+
.expect(1)
|
|
1063
|
+
.create();
|
|
1064
|
+
let _complete_mock = server
|
|
1065
|
+
.mock("POST", "/api/v1/lineage")
|
|
1066
|
+
.match_body(mockito::Matcher::PartialJson(json!({
|
|
1067
|
+
"eventType": "COMPLETE",
|
|
1068
|
+
"job": { "namespace": "test-ns" },
|
|
1069
|
+
"outputs": [{ "namespace": "test-ns", "name": "sales_dev.customers" }]
|
|
1070
|
+
})))
|
|
1071
|
+
.with_status(200)
|
|
1072
|
+
.expect(1)
|
|
1073
|
+
.create();
|
|
1074
|
+
|
|
1075
|
+
let mut entity = make_entity(
|
|
1076
|
+
"customers",
|
|
1077
|
+
"s3://iceberg-data/bronze/sales/customers",
|
|
1078
|
+
"s3://warehouse/silver/customers",
|
|
1079
|
+
None,
|
|
1080
|
+
);
|
|
1081
|
+
entity.sink.accepted.iceberg = Some(IcebergSinkTargetConfig {
|
|
1082
|
+
catalog: None,
|
|
1083
|
+
namespace: Some("sales_dev".to_string()),
|
|
1084
|
+
table: Some("customers".to_string()),
|
|
1085
|
+
location: None,
|
|
1086
|
+
});
|
|
1087
|
+
|
|
1088
|
+
let config = make_config(&server.url(), None);
|
|
1089
|
+
let obs = OpenLineageObserver::new(&config, &[entity], "config.yml").unwrap();
|
|
1090
|
+
obs.on_event(entity_started_event());
|
|
1091
|
+
obs.on_event(entity_finished_event("customers", "success"));
|
|
1092
|
+
_start_mock.assert();
|
|
1093
|
+
_complete_mock.assert();
|
|
1094
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "floe-python"
|
|
3
|
-
version = "0.6.
|
|
3
|
+
version = "0.6.9"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
description = "Python bindings for floe-core (PyO3-based)"
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -14,7 +14,7 @@ name = "_floe"
|
|
|
14
14
|
crate-type = ["cdylib"]
|
|
15
15
|
|
|
16
16
|
[dependencies]
|
|
17
|
-
floe-core = { path = "../floe-core", version = "0.6.
|
|
17
|
+
floe-core = { path = "../floe-core", version = "0.6.9", default-features = false }
|
|
18
18
|
pyo3 = { version = "0.29", features = ["extension-module", "abi3-py310"] }
|
|
19
19
|
serde_json = "1"
|
|
20
20
|
|
|
@@ -22,7 +22,7 @@ build-backend = "maturin"
|
|
|
22
22
|
|
|
23
23
|
[project]
|
|
24
24
|
name = "floe-duckdb"
|
|
25
|
-
version = "0.6.
|
|
25
|
+
version = "0.6.9"
|
|
26
26
|
description = "DuckDB companion extension for floe — adds the native DuckDB sink to the floe Python package"
|
|
27
27
|
readme = "README.md"
|
|
28
28
|
requires-python = ">=3.10"
|
|
@@ -46,7 +46,7 @@ classifiers = [
|
|
|
46
46
|
# only contributes the compiled DuckDB extension module into that package. Pin to
|
|
47
47
|
# the exact lean version so the companion's `_floe_duckdb` ABI always matches the
|
|
48
48
|
# `floe` package it plugs into.
|
|
49
|
-
dependencies = ["floe-python==0.6.
|
|
49
|
+
dependencies = ["floe-python==0.6.9"]
|
|
50
50
|
|
|
51
51
|
[project.urls]
|
|
52
52
|
Homepage = "https://github.com/malon64/floe"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|