floe-python 0.4.1__tar.gz → 0.4.2__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.
Files changed (227) hide show
  1. {floe_python-0.4.1 → floe_python-0.4.2}/Cargo.lock +3 -3
  2. {floe_python-0.4.1 → floe_python-0.4.2}/PKG-INFO +1 -1
  3. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/Cargo.toml +1 -1
  4. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/README.md +1 -1
  5. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/config/types.rs +35 -26
  6. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/lib.rs +8 -3
  7. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/lineage/mod.rs +99 -46
  8. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/manifest/builder.rs +111 -19
  9. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/manifest/mod.rs +2 -0
  10. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/manifest/model.rs +62 -0
  11. floe_python-0.4.2/crates/floe-core/src/manifest/reconstruct.rs +319 -0
  12. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/report/mod.rs +5 -0
  13. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/run/context.rs +63 -0
  14. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/run/entity/incremental.rs +18 -4
  15. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/run/entity/mod.rs +18 -2
  16. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/run/entity/precheck.rs +6 -0
  17. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/run/entity/validate_split.rs +4 -0
  18. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/run/events.rs +4 -0
  19. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/run/mod.rs +41 -0
  20. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/state/mod.rs +13 -5
  21. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/config/lineage_validation.rs +48 -1
  22. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/run/entity/incremental.rs +55 -4
  23. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/run/lineage.rs +157 -1
  24. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/run/report.rs +4 -0
  25. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-python/Cargo.toml +2 -2
  26. {floe_python-0.4.1 → floe_python-0.4.2}/pyproject.toml +1 -1
  27. {floe_python-0.4.1 → floe_python-0.4.2}/Cargo.toml +0 -0
  28. {floe_python-0.4.1 → floe_python-0.4.2}/README.md +0 -0
  29. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/add_entity.rs +0 -0
  30. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/checks/cast.rs +0 -0
  31. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/checks/mismatch.rs +0 -0
  32. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/checks/mod.rs +0 -0
  33. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/checks/normalize.rs +0 -0
  34. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/checks/not_null.rs +0 -0
  35. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/checks/unique.rs +0 -0
  36. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/config/catalog.rs +0 -0
  37. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/config/location.rs +0 -0
  38. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/config/mod.rs +0 -0
  39. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/config/parse.rs +0 -0
  40. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/config/storage.rs +0 -0
  41. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/config/template.rs +0 -0
  42. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/config/validate.rs +0 -0
  43. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/config/yaml_decode.rs +0 -0
  44. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/errors.rs +0 -0
  45. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/format.rs +0 -0
  46. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/mod.rs +0 -0
  47. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/read/avro.rs +0 -0
  48. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/read/csv.rs +0 -0
  49. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/read/fixed_width.rs +0 -0
  50. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/read/json.rs +0 -0
  51. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/read/json_selector.rs +0 -0
  52. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/read/mod.rs +0 -0
  53. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/read/orc.rs +0 -0
  54. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/read/parquet.rs +0 -0
  55. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/read/xlsx.rs +0 -0
  56. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/read/xml.rs +0 -0
  57. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/read/xml_selector.rs +0 -0
  58. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/storage/core/extensions.rs +0 -0
  59. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/storage/core/mod.rs +0 -0
  60. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/storage/core/paths.rs +0 -0
  61. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/storage/core/placement.rs +0 -0
  62. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/storage/core/planner.rs +0 -0
  63. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/storage/core/uri.rs +0 -0
  64. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/storage/core/validation.rs +0 -0
  65. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/storage/mod.rs +0 -0
  66. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/storage/object_store.rs +0 -0
  67. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/storage/ops/archive.rs +0 -0
  68. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/storage/ops/inputs.rs +0 -0
  69. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/storage/ops/mod.rs +0 -0
  70. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/storage/ops/output.rs +0 -0
  71. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/storage/providers/adls.rs +0 -0
  72. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/storage/providers/gcs.rs +0 -0
  73. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/storage/providers/local.rs +0 -0
  74. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/storage/providers/mod.rs +0 -0
  75. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/storage/providers/s3.rs +0 -0
  76. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/storage/target.rs +0 -0
  77. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/unique_seed/mod.rs +0 -0
  78. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/accepted.rs +0 -0
  79. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/arrow_convert.rs +0 -0
  80. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/csv.rs +0 -0
  81. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/delta/commit_metrics.rs +0 -0
  82. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/delta/options.rs +0 -0
  83. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/delta/record_batch.rs +0 -0
  84. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/delta/unity.rs +0 -0
  85. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/delta/unity_tests.rs +0 -0
  86. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/delta.rs +0 -0
  87. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/iceberg/context.rs +0 -0
  88. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/iceberg/data_files.rs +0 -0
  89. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/iceberg/glue.rs +0 -0
  90. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/iceberg/metadata.rs +0 -0
  91. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/iceberg/rest.rs +0 -0
  92. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/iceberg/schema.rs +0 -0
  93. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/iceberg.rs +0 -0
  94. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/metrics.rs +0 -0
  95. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/mod.rs +0 -0
  96. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/parquet.rs +0 -0
  97. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/parts.rs +0 -0
  98. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/sink_format.rs +0 -0
  99. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/strategy/append.rs +0 -0
  100. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/strategy/merge/mod.rs +0 -0
  101. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/strategy/merge/scd1.rs +0 -0
  102. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/strategy/merge/scd2.rs +0 -0
  103. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/strategy/merge/shared.rs +0 -0
  104. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/strategy/mod.rs +0 -0
  105. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/io/write/strategy/overwrite.rs +0 -0
  106. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/log.rs +0 -0
  107. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/profile/mod.rs +0 -0
  108. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/profile/parse.rs +0 -0
  109. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/profile/types.rs +0 -0
  110. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/profile/validate.rs +0 -0
  111. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/report/build.rs +0 -0
  112. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/report/entity.rs +0 -0
  113. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/report/output.rs +0 -0
  114. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/run/entity/accepted_write.rs +0 -0
  115. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/run/entity/pii.rs +0 -0
  116. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/run/entity/process.rs +0 -0
  117. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/run/entity/resolve.rs +0 -0
  118. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/run/file.rs +0 -0
  119. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/run/output.rs +0 -0
  120. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/run/perf.rs +0 -0
  121. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/runner/mod.rs +0 -0
  122. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/runner/outcome.rs +0 -0
  123. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/runtime.rs +0 -0
  124. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/vars/mod.rs +0 -0
  125. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/vars/resolve.rs +0 -0
  126. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/src/warnings.rs +0 -0
  127. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/integration/archive_run.rs +0 -0
  128. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/integration/composite_unique.rs +0 -0
  129. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/integration/delta_run.rs +0 -0
  130. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/integration/dry_run.rs +0 -0
  131. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/integration/fixed_width.rs +0 -0
  132. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/integration/iceberg_gcs_run.rs +0 -0
  133. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/integration/iceberg_glue_run.rs +0 -0
  134. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/integration/iceberg_run.rs +0 -0
  135. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/integration/iceberg_s3_run.rs +0 -0
  136. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/integration/json_selectors.rs +0 -0
  137. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/integration/local_run.rs +0 -0
  138. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/integration/mod.rs +0 -0
  139. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/integration/path_normalization.rs +0 -0
  140. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/integration/run_entities_filter.rs +0 -0
  141. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/integration.rs +0 -0
  142. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/common.rs +0 -0
  143. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/config/add_entity.rs +0 -0
  144. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/config/adls_storage.rs +0 -0
  145. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/config/adls_validation.rs +0 -0
  146. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/config/catalogs.rs +0 -0
  147. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/config/config_validation.rs +0 -0
  148. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/config/gcs_storage.rs +0 -0
  149. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/config/gcs_validation.rs +0 -0
  150. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/config/local_storage.rs +0 -0
  151. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/config/mod.rs +0 -0
  152. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/config/parse.rs +0 -0
  153. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/config/pii_validation.rs +0 -0
  154. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/config/remote_base.rs +0 -0
  155. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/config/templating.rs +0 -0
  156. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/format.rs +0 -0
  157. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/mod.rs +0 -0
  158. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/read/avro_input.rs +0 -0
  159. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/read/csv_nulls.rs +0 -0
  160. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/read/json_array.rs +0 -0
  161. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/read/json_ndjson.rs +0 -0
  162. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/read/json_selector.rs +0 -0
  163. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/read/mod.rs +0 -0
  164. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/read/orc_input.rs +0 -0
  165. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/read/parquet_input.rs +0 -0
  166. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/read/tsv.rs +0 -0
  167. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/read/xlsx_input.rs +0 -0
  168. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/read/xml.rs +0 -0
  169. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/read/xml_selector.rs +0 -0
  170. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/storage/adls.rs +0 -0
  171. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/storage/adls_integration.rs +0 -0
  172. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/storage/gcs.rs +0 -0
  173. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/storage/inputs.rs +0 -0
  174. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/storage/local.rs +0 -0
  175. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/storage/mod.rs +0 -0
  176. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/storage/paths.rs +0 -0
  177. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/storage/planner.rs +0 -0
  178. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/storage/s3.rs +0 -0
  179. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/storage/target.rs +0 -0
  180. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/write/delta_merge.rs +0 -0
  181. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/write/delta_write.rs +0 -0
  182. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/write/iceberg_write.rs +0 -0
  183. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/write/metrics.rs +0 -0
  184. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/write/mod.rs +0 -0
  185. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/write/object_store.rs +0 -0
  186. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/write/parquet_write.rs +0 -0
  187. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/write/parts.rs +0 -0
  188. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/io/write/rejected_csv.rs +0 -0
  189. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/manifest/mod.rs +0 -0
  190. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/mod.rs +0 -0
  191. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/profile/mod.rs +0 -0
  192. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/profile/parse.rs +0 -0
  193. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/profile/validate.rs +0 -0
  194. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/report/accepted_output.rs +0 -0
  195. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/report/mod.rs +0 -0
  196. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/report/storage.rs +0 -0
  197. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/run/check_order.rs +0 -0
  198. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/run/checks.rs +0 -0
  199. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/run/entity/accepted_output.rs +0 -0
  200. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/run/entity/mod.rs +0 -0
  201. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/run/mod.rs +0 -0
  202. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/run/normalize.rs +0 -0
  203. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/run/pii.rs +0 -0
  204. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/run/schema_mismatch.rs +0 -0
  205. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/runner/adapter.rs +0 -0
  206. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/runner/mod.rs +0 -0
  207. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/state/mod.rs +0 -0
  208. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/vars/mod.rs +0 -0
  209. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit/vars/resolve.rs +0 -0
  210. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-core/tests/unit.rs +0 -0
  211. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-python/.gitignore +0 -0
  212. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-python/README.md +0 -0
  213. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-python/src/functions.rs +0 -0
  214. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-python/src/lib.rs +0 -0
  215. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-python/src/observer.rs +0 -0
  216. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-python/src/types/config.rs +0 -0
  217. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-python/src/types/errors.rs +0 -0
  218. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-python/src/types/mod.rs +0 -0
  219. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-python/src/types/outcome.rs +0 -0
  220. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-python/tests/fixtures/config.yml +0 -0
  221. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-python/tests/fixtures/in/customer/customers_valid.csv +0 -0
  222. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-python/tests/fixtures/invalid_config.yml +0 -0
  223. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-python/tests/fixtures/profile.yml +0 -0
  224. {floe_python-0.4.1 → floe_python-0.4.2}/crates/floe-python/tests/test_floe.py +0 -0
  225. {floe_python-0.4.1 → floe_python-0.4.2}/python/floe/__init__.py +0 -0
  226. {floe_python-0.4.1 → floe_python-0.4.2}/python/floe/_floe.pyi +0 -0
  227. {floe_python-0.4.1 → floe_python-0.4.2}/python/floe/py.typed +0 -0
@@ -3399,7 +3399,7 @@ dependencies = [
3399
3399
 
3400
3400
  [[package]]
3401
3401
  name = "floe-cli"
3402
- version = "0.4.1"
3402
+ version = "0.4.2"
3403
3403
  dependencies = [
3404
3404
  "assert_cmd",
3405
3405
  "clap",
@@ -3412,7 +3412,7 @@ dependencies = [
3412
3412
 
3413
3413
  [[package]]
3414
3414
  name = "floe-core"
3415
- version = "0.4.1"
3415
+ version = "0.4.2"
3416
3416
  dependencies = [
3417
3417
  "apache-avro 0.16.0",
3418
3418
  "arrow",
@@ -3455,7 +3455,7 @@ dependencies = [
3455
3455
 
3456
3456
  [[package]]
3457
3457
  name = "floe-python"
3458
- version = "0.4.1"
3458
+ version = "0.4.2"
3459
3459
  dependencies = [
3460
3460
  "floe-core",
3461
3461
  "pyo3",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: floe-python
3
- Version: 0.4.1
3
+ Version: 0.4.2
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: Intended Audience :: Science/Research
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "floe-core"
3
- version = "0.4.1"
3
+ version = "0.4.2"
4
4
  edition = "2021"
5
5
  description = "Core library for Floe, a YAML-driven technical ingestion tool."
6
6
  license = "MIT"
@@ -73,7 +73,7 @@ floe run -c config.yml # run the pipeline
73
73
  | S3 storage | [docs/storages/s3.md](docs/storages/s3.md) |
74
74
  | ADLS storage | [docs/storages/adls.md](docs/storages/adls.md) |
75
75
  | GCS storage | [docs/storages/gcs.md](docs/storages/gcs.md) |
76
- | Incremental ingestion | [docs/profiles.md](docs/profiles.md) |
76
+ | Environement specific profile config | [docs/profiles.md](docs/profiles.md) [docs/variables.md](docs/variables.md) |
77
77
  | Run reports | [docs/report.md](docs/report.md) |
78
78
  | CLI reference | [docs/cli.md](docs/cli.md) |
79
79
  | Orchestration (Dagster / Airflow) | [docs/summary.md](docs/summary.md) |
@@ -1,6 +1,8 @@
1
1
  use std::collections::HashMap;
2
2
  use std::path::Path;
3
3
 
4
+ use serde::{Deserialize, Serialize};
5
+
4
6
  use polars::polars_utils::pl_str::PlSmallStr;
5
7
  use polars::prelude::{
6
8
  CsvEncoding, CsvParseOptions, CsvReadOptions, DataType, NullValues, TimeUnit,
@@ -21,7 +23,7 @@ pub struct RootConfig {
21
23
  pub entities: Vec<EntityConfig>,
22
24
  }
23
25
 
24
- #[derive(Debug, Clone)]
26
+ #[derive(Debug, Clone, Serialize, Deserialize)]
25
27
  pub struct LineageConfig {
26
28
  pub url: String,
27
29
  pub api_key: Option<String>,
@@ -66,12 +68,12 @@ pub struct EntityConfig {
66
68
  pub pii: Option<PiiConfig>,
67
69
  }
68
70
 
69
- #[derive(Debug)]
71
+ #[derive(Debug, Serialize, Deserialize)]
70
72
  pub struct PiiConfig {
71
73
  pub columns: Vec<PiiColumnConfig>,
72
74
  }
73
75
 
74
- #[derive(Debug)]
76
+ #[derive(Debug, Serialize, Deserialize)]
75
77
  pub struct PiiColumnConfig {
76
78
  pub name: String,
77
79
  pub strategy: PiiStrategy,
@@ -79,7 +81,8 @@ pub struct PiiColumnConfig {
79
81
  pub redact_value: Option<String>,
80
82
  }
81
83
 
82
- #[derive(Debug, Clone, Copy, PartialEq, Eq)]
84
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
85
+ #[serde(rename_all = "lowercase")]
83
86
  pub enum PiiStrategy {
84
87
  Hash,
85
88
  Drop,
@@ -103,7 +106,8 @@ impl EntityConfig {
103
106
  }
104
107
  }
105
108
 
106
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
109
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
110
+ #[serde(rename_all = "lowercase")]
107
111
  pub enum IncrementalMode {
108
112
  #[default]
109
113
  None,
@@ -146,7 +150,7 @@ pub struct SourceConfig {
146
150
  pub cast_mode: Option<String>,
147
151
  }
148
152
 
149
- #[derive(Debug, Clone)]
153
+ #[derive(Debug, Clone, Deserialize)]
150
154
  pub struct SourceOptions {
151
155
  pub header: Option<bool>,
152
156
  pub separator: Option<String>,
@@ -262,7 +266,8 @@ pub struct SinkConfig {
262
266
  pub archive: Option<ArchiveTarget>,
263
267
  }
264
268
 
265
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
269
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
270
+ #[serde(rename_all = "snake_case")]
266
271
  pub enum WriteMode {
267
272
  #[default]
268
273
  Overwrite,
@@ -300,34 +305,34 @@ pub const DEFAULT_SCD2_CURRENT_FLAG_COLUMN: &str = "__floe_is_current";
300
305
  pub const DEFAULT_SCD2_VALID_FROM_COLUMN: &str = "__floe_valid_from";
301
306
  pub const DEFAULT_SCD2_VALID_TO_COLUMN: &str = "__floe_valid_to";
302
307
 
303
- #[derive(Debug, Clone)]
308
+ #[derive(Debug, Clone, Serialize, Deserialize)]
304
309
  pub struct MergeOptionsConfig {
305
310
  pub ignore_columns: Option<Vec<String>>,
306
311
  pub compare_columns: Option<Vec<String>>,
307
312
  pub scd2: Option<MergeScd2OptionsConfig>,
308
313
  }
309
314
 
310
- #[derive(Debug, Clone)]
315
+ #[derive(Debug, Clone, Serialize, Deserialize)]
311
316
  pub struct MergeScd2OptionsConfig {
312
317
  pub current_flag_column: Option<String>,
313
318
  pub valid_from_column: Option<String>,
314
319
  pub valid_to_column: Option<String>,
315
320
  }
316
321
 
317
- #[derive(Debug)]
322
+ #[derive(Debug, Serialize, Deserialize)]
318
323
  pub struct SinkOptions {
319
324
  pub compression: Option<String>,
320
325
  pub row_group_size: Option<u64>,
321
326
  pub max_size_per_file: Option<u64>,
322
327
  }
323
328
 
324
- #[derive(Debug, Clone)]
329
+ #[derive(Debug, Clone, Serialize, Deserialize)]
325
330
  pub struct IcebergPartitionFieldConfig {
326
331
  pub column: String,
327
332
  pub transform: String,
328
333
  }
329
334
 
330
- #[derive(Debug, Clone)]
335
+ #[derive(Debug, Clone, Serialize, Deserialize)]
331
336
  pub struct IcebergSinkTargetConfig {
332
337
  pub catalog: Option<String>,
333
338
  pub namespace: Option<String>,
@@ -335,7 +340,7 @@ pub struct IcebergSinkTargetConfig {
335
340
  pub location: Option<String>,
336
341
  }
337
342
 
338
- #[derive(Debug, Clone)]
343
+ #[derive(Debug, Clone, Serialize, Deserialize)]
339
344
  pub struct DeltaSinkTargetConfig {
340
345
  /// Name of the catalog definition to use (falls back to `catalogs.default`).
341
346
  pub catalog: Option<String>,
@@ -345,13 +350,13 @@ pub struct DeltaSinkTargetConfig {
345
350
  pub table: Option<String>,
346
351
  }
347
352
 
348
- #[derive(Debug, Clone)]
353
+ #[derive(Debug, Clone, Serialize, Deserialize)]
349
354
  pub struct StoragesConfig {
350
355
  pub default: Option<String>,
351
356
  pub definitions: Vec<StorageDefinition>,
352
357
  }
353
358
 
354
- #[derive(Debug, Clone)]
359
+ #[derive(Debug, Clone, Serialize, Deserialize)]
355
360
  pub struct StorageDefinition {
356
361
  pub name: String,
357
362
  pub fs_type: String,
@@ -362,7 +367,7 @@ pub struct StorageDefinition {
362
367
  pub prefix: Option<String>,
363
368
  }
364
369
 
365
- #[derive(Debug, Clone)]
370
+ #[derive(Debug, Clone, Serialize, Deserialize)]
366
371
  pub struct CatalogsConfig {
367
372
  pub default: Option<String>,
368
373
  pub definitions: Vec<CatalogDefinition>,
@@ -371,7 +376,8 @@ pub struct CatalogsConfig {
371
376
  /// Type-specific configuration for a catalog definition.
372
377
  /// Each variant carries only the fields relevant to that catalog type.
373
378
  /// Add a new variant here when supporting a new catalog type.
374
- #[derive(Debug, Clone)]
379
+ #[derive(Debug, Clone, Serialize, Deserialize)]
380
+ #[serde(tag = "type", rename_all = "lowercase")]
375
381
  pub enum CatalogTypeConfig {
376
382
  Glue {
377
383
  region: String,
@@ -419,7 +425,7 @@ impl CatalogTypeConfig {
419
425
  }
420
426
  }
421
427
 
422
- #[derive(Debug, Clone)]
428
+ #[derive(Debug, Clone, Serialize, Deserialize)]
423
429
  pub struct CatalogDefinition {
424
430
  pub name: String,
425
431
  pub type_config: CatalogTypeConfig,
@@ -440,7 +446,8 @@ pub struct ArchiveTarget {
440
446
  pub storage: Option<String>,
441
447
  }
442
448
 
443
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
449
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
450
+ #[serde(rename_all = "lowercase")]
444
451
  pub enum PolicySeverity {
445
452
  #[default]
446
453
  Warn,
@@ -469,7 +476,7 @@ pub struct PolicyConfig {
469
476
  pub severity: PolicySeverity,
470
477
  }
471
478
 
472
- #[derive(Debug)]
479
+ #[derive(Debug, Serialize)]
473
480
  pub struct SchemaConfig {
474
481
  pub normalize_columns: Option<NormalizeColumnsConfig>,
475
482
  pub mismatch: Option<SchemaMismatchConfig>,
@@ -485,19 +492,20 @@ impl SchemaConfig {
485
492
  }
486
493
  }
487
494
 
488
- #[derive(Debug)]
495
+ #[derive(Debug, Serialize, Deserialize)]
489
496
  pub struct NormalizeColumnsConfig {
490
497
  pub enabled: Option<bool>,
491
498
  pub strategy: Option<String>,
492
499
  }
493
500
 
494
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
501
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
495
502
  pub struct SchemaEvolutionConfig {
496
503
  pub mode: SchemaEvolutionMode,
497
504
  pub on_incompatible: SchemaEvolutionIncompatibleAction,
498
505
  }
499
506
 
500
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
507
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
508
+ #[serde(rename_all = "snake_case")]
501
509
  pub enum SchemaEvolutionMode {
502
510
  #[default]
503
511
  Strict,
@@ -513,7 +521,8 @@ impl SchemaEvolutionMode {
513
521
  }
514
522
  }
515
523
 
516
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
524
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
525
+ #[serde(rename_all = "lowercase")]
517
526
  pub enum SchemaEvolutionIncompatibleAction {
518
527
  #[default]
519
528
  Fail,
@@ -527,13 +536,13 @@ impl SchemaEvolutionIncompatibleAction {
527
536
  }
528
537
  }
529
538
 
530
- #[derive(Debug)]
539
+ #[derive(Debug, Serialize, Deserialize)]
531
540
  pub struct SchemaMismatchConfig {
532
541
  pub missing_columns: Option<String>,
533
542
  pub extra_columns: Option<String>,
534
543
  }
535
544
 
536
- #[derive(Debug, Clone)]
545
+ #[derive(Debug, Clone, Serialize)]
537
546
  pub struct ColumnConfig {
538
547
  pub name: String,
539
548
  pub source: Option<String>,
@@ -17,18 +17,23 @@ pub mod state;
17
17
  pub mod vars;
18
18
  pub mod warnings;
19
19
 
20
- pub use crate::state::{inspect_entity_state_with_base, reset_entity_state_with_base};
20
+ pub use crate::state::{
21
+ inspect_entity_state, inspect_entity_state_with_base, reset_entity_state,
22
+ reset_entity_state_with_base,
23
+ };
21
24
  pub use add_entity::{add_entity_to_config, AddEntityOptions, AddEntityOutcome};
22
25
  pub use checks as check;
23
26
  pub use config::{resolve_config_location, ConfigLocation};
24
27
  pub use errors::ConfigError;
25
- pub use manifest::build_common_manifest_json;
28
+ pub use manifest::{build_common_manifest_json, config_from_manifest_json};
26
29
  pub use profile::{
27
30
  detect_malformed_placeholder, detect_unresolved_placeholders, parse_profile,
28
31
  parse_profile_from_str, validate_merged_vars, validate_profile, ProfileConfig,
29
32
  };
30
33
  pub use run::events::{set_observer, MultiObserver, RunEvent, RunObserver};
31
- pub use run::{run, run_with_base, DryRunEntityPreview, EntityOutcome, RunOutcome};
34
+ pub use run::{
35
+ run, run_with_base, run_with_manifest_path, DryRunEntityPreview, EntityOutcome, RunOutcome,
36
+ };
32
37
  pub use runner::{parse_run_status_from_logs, ConnectorRunStatus};
33
38
  pub use runtime::{DefaultRuntime, Runtime};
34
39
  pub use vars::{resolve_vars, VarSources};
@@ -8,6 +8,12 @@ use serde_json::{json, Value};
8
8
  use crate::config::{EntityConfig, LineageConfig};
9
9
  use crate::run::events::{RunEvent, RunObserver};
10
10
 
11
+ struct EntityUris {
12
+ source: String,
13
+ accepted: String,
14
+ rejected: Option<String>,
15
+ }
16
+
11
17
  pub struct OpenLineageObserver {
12
18
  client: reqwest::blocking::Client,
13
19
  config: LineageConfig,
@@ -15,6 +21,7 @@ pub struct OpenLineageObserver {
15
21
  entity_run_ids: Mutex<HashMap<String, String>>,
16
22
  run_start_ms: Mutex<Option<u128>>,
17
23
  entity_schemas: HashMap<String, Vec<(String, String)>>,
24
+ entity_uris: HashMap<String, EntityUris>,
18
25
  consecutive_failures: AtomicUsize,
19
26
  circuit_open: AtomicBool,
20
27
  }
@@ -44,6 +51,20 @@ impl OpenLineageObserver {
44
51
  })
45
52
  .collect();
46
53
 
54
+ let entity_uris = entities
55
+ .iter()
56
+ .map(|e| {
57
+ (
58
+ e.name.clone(),
59
+ EntityUris {
60
+ source: e.source.path.clone(),
61
+ accepted: e.sink.accepted.path.clone(),
62
+ rejected: e.sink.rejected.as_ref().map(|r| r.path.clone()),
63
+ },
64
+ )
65
+ })
66
+ .collect();
67
+
47
68
  Ok(Self {
48
69
  client,
49
70
  config: config.clone(),
@@ -51,6 +72,7 @@ impl OpenLineageObserver {
51
72
  entity_run_ids: Mutex::new(HashMap::new()),
52
73
  run_start_ms: Mutex::new(None),
53
74
  entity_schemas,
75
+ entity_uris,
54
76
  consecutive_failures: AtomicUsize::new(0),
55
77
  circuit_open: AtomicBool::new(false),
56
78
  })
@@ -180,6 +202,7 @@ impl OpenLineageObserver {
180
202
  event_type: &str,
181
203
  ts_ms: u128,
182
204
  stats: Option<EntityStats>,
205
+ uris: Option<&EntityUris>,
183
206
  ) {
184
207
  let event_time = ms_to_iso8601(ts_ms);
185
208
  let job_name = format!("{}.{name}", self.config.namespace);
@@ -189,50 +212,71 @@ impl OpenLineageObserver {
189
212
  run_facets["parent"] = parent;
190
213
  }
191
214
 
192
- // Build inputs with all facets for COMPLETE events; empty for START.
193
- let inputs = if let Some(ref s) = stats {
194
- let rejection_rate = if s.rows > 0 {
195
- s.rejected as f64 / s.rows as f64
196
- } else {
197
- 0.0
198
- };
199
- let schema_facet = json!({
200
- "fields": s.schema_fields.iter().map(|(col_name, col_type)| {
201
- json!({ "name": col_name, "type": col_type })
202
- }).collect::<Vec<_>>(),
203
- "_producer": self.producer(),
204
- "_schemaURL": "https://openlineage.io/spec/facets/1-1-1/SchemaDatasetFacet.json"
205
- });
206
- let dq_facet = json!({
207
- "rowCount": s.rows,
208
- "validCount": s.accepted,
209
- "invalidCount": s.rejected,
210
- "_producer": self.producer(),
211
- "_schemaURL": "https://openlineage.io/spec/facets/1-0-2/DataQualityMetricsInputDatasetFacet.json"
212
- });
213
- let floe_facet = json!({
214
- "entity": name,
215
- "rejectionRate": rejection_rate,
216
- "files": s.files,
217
- "rows": s.rows,
218
- "accepted": s.accepted,
219
- "rejected": s.rejected,
220
- "warnings": s.warnings,
221
- "errors": s.errors,
222
- "_producer": self.producer(),
223
- "_schemaURL": "https://github.com/malon64/floe/schemas/FloeQualityRunFacet.json"
224
- });
225
- json!([{
226
- "namespace": self.config.namespace,
227
- "name": name,
228
- "facets": {
229
- "schema": schema_facet,
230
- "dataQualityMetrics": dq_facet,
231
- "floeQualityRun": floe_facet
215
+ // Build inputs: source dataset with schema and quality facets on COMPLETE/FAIL.
216
+ let inputs = match (stats.as_ref(), uris) {
217
+ (Some(s), Some(u)) => {
218
+ let rejection_rate = if s.rows > 0 {
219
+ s.rejected as f64 / s.rows as f64
220
+ } else {
221
+ 0.0
222
+ };
223
+ let schema_facet = json!({
224
+ "fields": s.schema_fields.iter().map(|(col_name, col_type)| {
225
+ json!({ "name": col_name, "type": col_type })
226
+ }).collect::<Vec<_>>(),
227
+ "_producer": self.producer(),
228
+ "_schemaURL": "https://openlineage.io/spec/facets/1-1-1/SchemaDatasetFacet.json"
229
+ });
230
+ let dq_facet = json!({
231
+ "rowCount": s.rows,
232
+ "validCount": s.accepted,
233
+ "invalidCount": s.rejected,
234
+ "_producer": self.producer(),
235
+ "_schemaURL": "https://openlineage.io/spec/facets/1-0-2/DataQualityMetricsInputDatasetFacet.json"
236
+ });
237
+ let floe_facet = json!({
238
+ "entity": name,
239
+ "rejectionRate": rejection_rate,
240
+ "files": s.files,
241
+ "rows": s.rows,
242
+ "accepted": s.accepted,
243
+ "rejected": s.rejected,
244
+ "warnings": s.warnings,
245
+ "errors": s.errors,
246
+ "_producer": self.producer(),
247
+ "_schemaURL": "https://github.com/malon64/floe/schemas/FloeQualityRunFacet.json"
248
+ });
249
+ json!([{
250
+ "namespace": self.config.namespace,
251
+ "name": u.source,
252
+ "facets": {
253
+ "schema": schema_facet,
254
+ "dataQualityMetrics": dq_facet,
255
+ "floeQualityRun": floe_facet
256
+ }
257
+ }])
258
+ }
259
+ _ => json!([]),
260
+ };
261
+
262
+ // Build outputs: accepted sink always present; rejected sink when configured.
263
+ let outputs = match uris {
264
+ Some(u) => {
265
+ let mut out = vec![json!({
266
+ "namespace": self.config.namespace,
267
+ "name": u.accepted,
268
+ "facets": {}
269
+ })];
270
+ if let Some(ref rej) = u.rejected {
271
+ out.push(json!({
272
+ "namespace": self.config.namespace,
273
+ "name": rej,
274
+ "facets": {}
275
+ }));
232
276
  }
233
- }])
234
- } else {
235
- json!([])
277
+ json!(out)
278
+ }
279
+ None => json!([]),
236
280
  };
237
281
 
238
282
  let body = json!({
@@ -248,7 +292,7 @@ impl OpenLineageObserver {
248
292
  "facets": {}
249
293
  },
250
294
  "inputs": inputs,
251
- "outputs": [],
295
+ "outputs": outputs,
252
296
  "producer": self.producer(),
253
297
  "schemaURL": "https://openlineage.io/spec/1-0-5/OpenLineage.json#/$defs/RunEvent"
254
298
  });
@@ -329,13 +373,14 @@ impl RunObserver for OpenLineageObserver {
329
373
  if let Ok(mut guard) = self.entity_run_ids.lock() {
330
374
  guard.insert(name.clone(), entity_run_id.clone());
331
375
  }
332
- self.emit_entity_run_event(&entity_run_id, &name, "START", ts_ms, None);
376
+ self.emit_entity_run_event(&entity_run_id, &name, "START", ts_ms, None, None);
333
377
  }
334
378
  RunEvent::EntityFinished {
335
379
  run_id,
336
380
  name,
337
381
  status,
338
382
  files,
383
+ files_skipped: _,
339
384
  rows,
340
385
  accepted,
341
386
  rejected,
@@ -364,7 +409,15 @@ impl RunObserver for OpenLineageObserver {
364
409
  errors,
365
410
  schema_fields,
366
411
  };
367
- self.emit_entity_run_event(&entity_run_id, &name, event_type, ts_ms, Some(stats));
412
+ let uris = self.entity_uris.get(&name);
413
+ self.emit_entity_run_event(
414
+ &entity_run_id,
415
+ &name,
416
+ event_type,
417
+ ts_ms,
418
+ Some(stats),
419
+ uris,
420
+ );
368
421
  }
369
422
  RunEvent::RunFinished {
370
423
  run_id,