datacontract-cli 0.10.24__tar.gz → 0.10.25__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.

Potentially problematic release.


This version of datacontract-cli might be problematic. Click here for more details.

Files changed (210) hide show
  1. {datacontract_cli-0.10.24/datacontract_cli.egg-info → datacontract_cli-0.10.25}/PKG-INFO +33 -5
  2. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/README.md +25 -1
  3. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/api.py +3 -3
  4. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/cli.py +1 -1
  5. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/great_expectations_converter.py +49 -2
  6. datacontract_cli-0.10.25/datacontract/export/odcs_v3_exporter.py +359 -0
  7. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/spark_converter.py +1 -1
  8. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/imports/avro_importer.py +23 -23
  9. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/imports/csv_importer.py +2 -2
  10. datacontract_cli-0.10.25/datacontract/imports/excel_importer.py +850 -0
  11. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/imports/importer.py +4 -2
  12. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/imports/importer_factory.py +5 -0
  13. datacontract_cli-0.10.25/datacontract/imports/odcs_v3_importer.py +415 -0
  14. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/imports/protobuf_importer.py +0 -2
  15. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/lint/linters/description_linter.py +1 -3
  16. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/lint/linters/field_reference_linter.py +1 -2
  17. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/lint/linters/notice_period_linter.py +2 -2
  18. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/lint/linters/valid_constraints_linter.py +3 -3
  19. datacontract_cli-0.10.25/datacontract/model/data_contract_specification/__init__.py +1 -0
  20. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25/datacontract_cli.egg-info}/PKG-INFO +33 -5
  21. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract_cli.egg-info/SOURCES.txt +3 -1
  22. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract_cli.egg-info/requires.txt +7 -2
  23. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/pyproject.toml +14 -4
  24. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_great_expectations.py +103 -0
  25. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_odcs_v3.py +11 -3
  26. datacontract_cli-0.10.25/tests/test_import_excel.py +40 -0
  27. datacontract_cli-0.10.24/datacontract/export/odcs_v3_exporter.py +0 -334
  28. datacontract_cli-0.10.24/datacontract/imports/odcs_v3_importer.py +0 -358
  29. datacontract_cli-0.10.24/datacontract/model/data_contract_specification.py +0 -327
  30. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/LICENSE +0 -0
  31. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/MANIFEST.in +0 -0
  32. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/__init__.py +0 -0
  33. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/breaking/breaking.py +0 -0
  34. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/breaking/breaking_change.py +0 -0
  35. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/breaking/breaking_rules.py +0 -0
  36. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/catalog/catalog.py +0 -0
  37. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/data_contract.py +0 -0
  38. {datacontract_cli-0.10.24/datacontract/output → datacontract_cli-0.10.25/datacontract/engines}/__init__.py +0 -0
  39. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/engines/data_contract_checks.py +0 -0
  40. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/engines/data_contract_test.py +0 -0
  41. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/engines/datacontract/check_that_datacontract_contains_valid_servers_configuration.py +0 -0
  42. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/engines/datacontract/check_that_datacontract_file_exists.py +0 -0
  43. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/engines/fastjsonschema/check_jsonschema.py +0 -0
  44. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/engines/fastjsonschema/s3/s3_read_files.py +0 -0
  45. {datacontract_cli-0.10.24/datacontract/lint/linters → datacontract_cli-0.10.25/datacontract/engines/soda}/__init__.py +0 -0
  46. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/engines/soda/check_soda_execute.py +0 -0
  47. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/engines/soda/connections/bigquery.py +0 -0
  48. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/engines/soda/connections/databricks.py +0 -0
  49. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/engines/soda/connections/duckdb_connection.py +0 -0
  50. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/engines/soda/connections/kafka.py +0 -0
  51. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/engines/soda/connections/postgres.py +0 -0
  52. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/engines/soda/connections/snowflake.py +0 -0
  53. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/engines/soda/connections/sqlserver.py +0 -0
  54. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/engines/soda/connections/trino.py +0 -0
  55. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/__init__.py +0 -0
  56. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/avro_converter.py +0 -0
  57. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/avro_idl_converter.py +0 -0
  58. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/bigquery_converter.py +0 -0
  59. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/custom_converter.py +0 -0
  60. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/data_caterer_converter.py +0 -0
  61. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/dbml_converter.py +0 -0
  62. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/dbt_converter.py +0 -0
  63. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/dcs_exporter.py +0 -0
  64. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/duckdb_type_converter.py +0 -0
  65. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/exporter.py +0 -0
  66. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/exporter_factory.py +0 -0
  67. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/go_converter.py +0 -0
  68. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/html_export.py +0 -0
  69. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/iceberg_converter.py +0 -0
  70. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/jsonschema_converter.py +0 -0
  71. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/markdown_converter.py +0 -0
  72. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/pandas_type_converter.py +0 -0
  73. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/protobuf_converter.py +0 -0
  74. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/pydantic_converter.py +0 -0
  75. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/rdf_converter.py +0 -0
  76. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/sodacl_converter.py +0 -0
  77. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/sql_converter.py +0 -0
  78. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/sql_type_converter.py +0 -0
  79. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/sqlalchemy_converter.py +0 -0
  80. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/export/terraform_converter.py +0 -0
  81. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/imports/bigquery_importer.py +0 -0
  82. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/imports/dbml_importer.py +0 -0
  83. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/imports/dbt_importer.py +0 -0
  84. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/imports/glue_importer.py +0 -0
  85. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/imports/iceberg_importer.py +0 -0
  86. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/imports/jsonschema_importer.py +0 -0
  87. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/imports/odcs_importer.py +0 -0
  88. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/imports/parquet_importer.py +0 -0
  89. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/imports/spark_importer.py +0 -0
  90. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/imports/sql_importer.py +0 -0
  91. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/imports/unity_importer.py +0 -0
  92. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/init/init_template.py +0 -0
  93. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/integration/datamesh_manager.py +0 -0
  94. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/lint/files.py +0 -0
  95. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/lint/lint.py +0 -0
  96. {datacontract_cli-0.10.24/datacontract/engines/soda → datacontract_cli-0.10.25/datacontract/lint/linters}/__init__.py +0 -0
  97. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/lint/linters/field_pattern_linter.py +0 -0
  98. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/lint/resolve.py +0 -0
  99. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/lint/resources.py +0 -0
  100. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/lint/schema.py +0 -0
  101. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/lint/urls.py +0 -0
  102. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/model/exceptions.py +0 -0
  103. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/model/odcs.py +0 -0
  104. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/model/run.py +0 -0
  105. {datacontract_cli-0.10.24/datacontract/engines → datacontract_cli-0.10.25/datacontract/output}/__init__.py +0 -0
  106. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/output/junit_test_results.py +0 -0
  107. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/output/output_format.py +0 -0
  108. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/output/test_results_writer.py +0 -0
  109. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/py.typed +0 -0
  110. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/schemas/datacontract-1.1.0.init.yaml +0 -0
  111. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/schemas/datacontract-1.1.0.schema.json +0 -0
  112. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/schemas/odcs-3.0.1.schema.json +0 -0
  113. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/templates/datacontract.html +0 -0
  114. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/templates/index.html +0 -0
  115. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/templates/partials/datacontract_information.html +0 -0
  116. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/templates/partials/datacontract_servicelevels.html +0 -0
  117. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/templates/partials/datacontract_terms.html +0 -0
  118. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/templates/partials/definition.html +0 -0
  119. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/templates/partials/example.html +0 -0
  120. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/templates/partials/model_field.html +0 -0
  121. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/templates/partials/quality.html +0 -0
  122. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/templates/partials/server.html +0 -0
  123. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract/templates/style/output.css +0 -0
  124. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract_cli.egg-info/dependency_links.txt +0 -0
  125. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract_cli.egg-info/entry_points.txt +0 -0
  126. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/datacontract_cli.egg-info/top_level.txt +0 -0
  127. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/setup.cfg +0 -0
  128. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_api.py +0 -0
  129. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_breaking.py +0 -0
  130. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_catalog.py +0 -0
  131. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_changelog.py +0 -0
  132. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_cli.py +0 -0
  133. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_data_contract_checks.py +0 -0
  134. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_data_contract_specification.py +0 -0
  135. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_description_linter.py +0 -0
  136. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_documentation_linter.py +0 -0
  137. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_download_datacontract_file.py +0 -0
  138. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_duckdb_json.py +0 -0
  139. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_avro.py +0 -0
  140. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_avro_idl.py +0 -0
  141. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_bigquery.py +0 -0
  142. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_complex_data_contract.py +0 -0
  143. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_custom.py +0 -0
  144. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_custom_exporter.py +0 -0
  145. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_data_caterer.py +0 -0
  146. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_dbml.py +0 -0
  147. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_dbt_models.py +0 -0
  148. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_dbt_sources.py +0 -0
  149. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_dbt_staging_sql.py +0 -0
  150. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_go.py +0 -0
  151. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_html.py +0 -0
  152. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_iceberg.py +0 -0
  153. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_jsonschema.py +0 -0
  154. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_markdown.py +0 -0
  155. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_protobuf.py +0 -0
  156. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_pydantic.py +0 -0
  157. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_rdf.py +0 -0
  158. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_sodacl.py +0 -0
  159. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_spark.py +0 -0
  160. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_sql.py +0 -0
  161. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_sql_query.py +0 -0
  162. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_sqlalchemy.py +0 -0
  163. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_export_terraform.py +0 -0
  164. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_field_constraint_linter.py +0 -0
  165. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_field_pattern_linter.py +0 -0
  166. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_field_reference_linter.py +0 -0
  167. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_import_avro.py +0 -0
  168. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_import_bigquery.py +0 -0
  169. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_import_csv.py +0 -0
  170. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_import_dbml.py +0 -0
  171. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_import_dbt.py +0 -0
  172. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_import_glue.py +0 -0
  173. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_import_iceberg.py +0 -0
  174. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_import_jsonschema.py +0 -0
  175. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_import_odcs_v3.py +0 -0
  176. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_import_parquet.py +0 -0
  177. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_import_protobuf.py +0 -0
  178. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_import_spark.py +0 -0
  179. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_import_sql_postgres.py +0 -0
  180. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_import_sql_sqlserver.py +0 -0
  181. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_import_unity_file.py +0 -0
  182. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_integration_datameshmanager.py +0 -0
  183. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_lint.py +0 -0
  184. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_notice_period_linter.py +0 -0
  185. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_resolve.py +0 -0
  186. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_roundtrip_jsonschema.py +0 -0
  187. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_spec_fields_field.py +0 -0
  188. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_spec_ref.py +0 -0
  189. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_azure_remote.py +0 -0
  190. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_bigquery.py +0 -0
  191. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_databricks.py +0 -0
  192. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_dataframe.py +0 -0
  193. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_delta.py +0 -0
  194. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_gcs_json_remote.py +0 -0
  195. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_kafka.py +0 -0
  196. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_kafka_remote.py +0 -0
  197. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_local_json.py +0 -0
  198. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_output_junit.py +0 -0
  199. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_parquet.py +0 -0
  200. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_postgres.py +0 -0
  201. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_quality.py +0 -0
  202. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_s3_csv.py +0 -0
  203. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_s3_delta.py +0 -0
  204. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_s3_json.py +0 -0
  205. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_s3_json_complex.py +0 -0
  206. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_s3_json_multiple_models.py +0 -0
  207. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_s3_json_remote.py +0 -0
  208. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_snowflake.py +0 -0
  209. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_sqlserver.py +0 -0
  210. {datacontract_cli-0.10.24 → datacontract_cli-0.10.25}/tests/test_test_trino.py +0 -0
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datacontract-cli
3
- Version: 0.10.24
3
+ Version: 0.10.25
4
4
  Summary: The datacontract CLI is an open source command-line tool for working with Data Contracts. It uses data contract YAML files to lint the data contract, connect to data sources and execute schema and quality tests, detect breaking changes, and export to different formats. The tool is written in Python. It can be used as a standalone CLI tool, in a CI/CD pipeline, or directly as a Python library.
5
5
  Author-email: Jochen Christ <jochen.christ@innoq.com>, Stefan Negele <stefan.negele@innoq.com>, Simon Harrer <simon.harrer@innoq.com>
6
+ License-Expression: MIT
6
7
  Project-URL: Homepage, https://cli.datacontract.com
7
8
  Project-URL: Issues, https://github.com/datacontract/datacontract-cli/issues
8
9
  Classifier: Programming Language :: Python :: 3
9
- Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
11
11
  Requires-Python: >=3.10
12
12
  Description-Content-Type: text/markdown
@@ -28,17 +28,21 @@ Requires-Dist: python-dotenv<2.0.0,>=1.0.0
28
28
  Requires-Dist: boto3<2.0.0,>=1.34.41
29
29
  Requires-Dist: Jinja2<4.0.0,>=3.1.5
30
30
  Requires-Dist: jinja_partials<1.0.0,>=0.2.1
31
+ Requires-Dist: datacontract-specification<2.0.0,>=1.1.1
32
+ Requires-Dist: open-data-contract-standard<4.0.0,>=3.0.4
31
33
  Provides-Extra: avro
32
34
  Requires-Dist: avro==1.12.0; extra == "avro"
33
35
  Provides-Extra: bigquery
34
36
  Requires-Dist: soda-core-bigquery<3.6.0,>=3.3.20; extra == "bigquery"
35
37
  Provides-Extra: csv
36
38
  Requires-Dist: pandas>=2.0.0; extra == "csv"
39
+ Provides-Extra: excel
40
+ Requires-Dist: openpyxl<4.0.0,>=3.1.5; extra == "excel"
37
41
  Provides-Extra: databricks
38
42
  Requires-Dist: soda-core-spark-df<3.6.0,>=3.3.20; extra == "databricks"
39
43
  Requires-Dist: soda-core-spark[databricks]<3.6.0,>=3.3.20; extra == "databricks"
40
44
  Requires-Dist: databricks-sql-connector<4.1.0,>=3.7.0; extra == "databricks"
41
- Requires-Dist: databricks-sdk<0.50.0; extra == "databricks"
45
+ Requires-Dist: databricks-sdk<0.51.0; extra == "databricks"
42
46
  Provides-Extra: iceberg
43
47
  Requires-Dist: pyiceberg==0.8.1; extra == "iceberg"
44
48
  Provides-Extra: kafka
@@ -70,7 +74,7 @@ Requires-Dist: uvicorn==0.34.0; extra == "api"
70
74
  Provides-Extra: protobuf
71
75
  Requires-Dist: grpcio-tools>=1.53; extra == "protobuf"
72
76
  Provides-Extra: all
73
- Requires-Dist: datacontract-cli[api,bigquery,csv,databricks,dbml,dbt,iceberg,kafka,parquet,postgres,protobuf,rdf,s3,snowflake,sqlserver,trino]; extra == "all"
77
+ Requires-Dist: datacontract-cli[api,bigquery,csv,databricks,dbml,dbt,excel,iceberg,kafka,parquet,postgres,protobuf,rdf,s3,snowflake,sqlserver,trino]; extra == "all"
74
78
  Provides-Extra: dev
75
79
  Requires-Dist: datacontract-cli[all]; extra == "dev"
76
80
  Requires-Dist: httpx==0.28.1; extra == "dev"
@@ -900,6 +904,29 @@ models:
900
904
  | `DATACONTRACT_TRINO_PASSWORD` | `mysecretpassword` | Password |
901
905
 
902
906
 
907
+ #### Local
908
+
909
+ Data Contract CLI can test local files in parquet, json, csv, or delta format.
910
+
911
+ ##### Example
912
+
913
+ datacontract.yaml
914
+ ```yaml
915
+ servers:
916
+ local:
917
+ type: local
918
+ path: ./*.parquet
919
+ format: parquet
920
+ models:
921
+ my_table_1: # corresponds to a table
922
+ type: table
923
+ fields:
924
+ my_column_1: # corresponds to a column
925
+ type: varchar
926
+ my_column_2: # corresponds to a column
927
+ type: string
928
+ ```
929
+
903
930
 
904
931
  ### export
905
932
  ```
@@ -1994,7 +2021,8 @@ pytest
1994
2021
  ```bash
1995
2022
  # make sure uv is installed
1996
2023
  uv python pin 3.11
1997
- uv sync --all-extras
2024
+ uv pip install -e '.[dev]'
2025
+ uv run ruff check
1998
2026
  uv run pytest
1999
2027
  ```
2000
2028
 
@@ -812,6 +812,29 @@ models:
812
812
  | `DATACONTRACT_TRINO_PASSWORD` | `mysecretpassword` | Password |
813
813
 
814
814
 
815
+ #### Local
816
+
817
+ Data Contract CLI can test local files in parquet, json, csv, or delta format.
818
+
819
+ ##### Example
820
+
821
+ datacontract.yaml
822
+ ```yaml
823
+ servers:
824
+ local:
825
+ type: local
826
+ path: ./*.parquet
827
+ format: parquet
828
+ models:
829
+ my_table_1: # corresponds to a table
830
+ type: table
831
+ fields:
832
+ my_column_1: # corresponds to a column
833
+ type: varchar
834
+ my_column_2: # corresponds to a column
835
+ type: string
836
+ ```
837
+
815
838
 
816
839
  ### export
817
840
  ```
@@ -1906,7 +1929,8 @@ pytest
1906
1929
  ```bash
1907
1930
  # make sure uv is installed
1908
1931
  uv python pin 3.11
1909
- uv sync --all-extras
1932
+ uv pip install -e '.[dev]'
1933
+ uv run ruff check
1910
1934
  uv run pytest
1911
1935
  ```
1912
1936
 
@@ -162,7 +162,7 @@ async def test(
162
162
  server: Annotated[
163
163
  str | None,
164
164
  Query(
165
- example="production",
165
+ examples=["production"],
166
166
  description="The server name to test. Optional, if there is only one server.",
167
167
  ),
168
168
  ] = None,
@@ -191,7 +191,7 @@ async def lint(
191
191
  schema: Annotated[
192
192
  str | None,
193
193
  Query(
194
- example="https://datacontract.com/datacontract.schema.json",
194
+ examples=["https://datacontract.com/datacontract.schema.json"],
195
195
  description="The schema to use for validation. This must be a URL.",
196
196
  ),
197
197
  ] = None,
@@ -220,7 +220,7 @@ def export(
220
220
  server: Annotated[
221
221
  str | None,
222
222
  Query(
223
- example="production",
223
+ examples=["production"],
224
224
  description="The server name to export. Optional, if there is only one server.",
225
225
  ),
226
226
  ] = None,
@@ -244,7 +244,7 @@ def import_(
244
244
  ] = None,
245
245
  source: Annotated[
246
246
  Optional[str],
247
- typer.Option(help="The path to the file or Glue Database that should be imported."),
247
+ typer.Option(help="The path to the file that should be imported."),
248
248
  ] = None,
249
249
  dialect: Annotated[
250
250
  Optional[str],
@@ -19,6 +19,7 @@ from datacontract.export.spark_converter import to_spark_data_type
19
19
  from datacontract.export.sql_type_converter import convert_to_sql_type
20
20
  from datacontract.model.data_contract_specification import (
21
21
  DataContractSpecification,
22
+ DeprecatedQuality,
22
23
  Field,
23
24
  Quality,
24
25
  )
@@ -91,8 +92,14 @@ def to_great_expectations(
91
92
  model_key=model_key, contract_version=data_contract_spec.info.version
92
93
  )
93
94
  model_value = data_contract_spec.models.get(model_key)
94
- quality_checks = get_quality_checks(data_contract_spec.quality)
95
+
96
+ # Support for Deprecated Quality
97
+ quality_checks = get_deprecated_quality_checks(data_contract_spec.quality)
98
+
99
+ expectations.extend(get_quality_checks(model_value.quality))
100
+
95
101
  expectations.extend(model_to_expectations(model_value.fields, engine, sql_server_type))
102
+
96
103
  expectations.extend(checks_to_expectations(quality_checks, model_key))
97
104
  model_expectation_suite = to_suite(expectations, expectation_suite_name)
98
105
 
@@ -135,6 +142,7 @@ def model_to_expectations(fields: Dict[str, Field], engine: str | None, sql_serv
135
142
  add_column_order_exp(fields, expectations)
136
143
  for field_name, field in fields.items():
137
144
  add_field_expectations(field_name, field, expectations, engine, sql_server_type)
145
+ expectations.extend(get_quality_checks(field.quality, field_name))
138
146
  return expectations
139
147
 
140
148
 
@@ -173,6 +181,8 @@ def add_field_expectations(
173
181
  expectations.append(to_column_length_exp(field_name, field.minLength, field.maxLength))
174
182
  if field.minimum is not None or field.maximum is not None:
175
183
  expectations.append(to_column_min_max_exp(field_name, field.minimum, field.maximum))
184
+ if field.enum is not None and len(field.enum) != 0:
185
+ expectations.append(to_column_enum_exp(field_name, field.enum))
176
186
 
177
187
  return expectations
178
188
 
@@ -266,7 +276,24 @@ def to_column_min_max_exp(field_name, minimum, maximum) -> Dict[str, Any]:
266
276
  }
267
277
 
268
278
 
269
- def get_quality_checks(quality: Quality) -> Dict[str, Any]:
279
+ def to_column_enum_exp(field_name, enum_list: List[str]) -> Dict[str, Any]:
280
+ """Creates a expect_column_values_to_be_in_set expectation.
281
+
282
+ Args:
283
+ field_name (str): The name of the field.
284
+ enum_list (Set[str]): enum list of value.
285
+
286
+ Returns:
287
+ Dict[str, Any]: Column value in set expectation.
288
+ """
289
+ return {
290
+ "expectation_type": "expect_column_values_to_be_in_set",
291
+ "kwargs": {"column": field_name, "value_set": enum_list},
292
+ "meta": {},
293
+ }
294
+
295
+
296
+ def get_deprecated_quality_checks(quality: DeprecatedQuality) -> Dict[str, Any]:
270
297
  """Retrieves quality checks defined in a data contract.
271
298
 
272
299
  Args:
@@ -288,6 +315,26 @@ def get_quality_checks(quality: Quality) -> Dict[str, Any]:
288
315
  return quality_specification
289
316
 
290
317
 
318
+ def get_quality_checks(qualities: List[Quality], field_name: str | None = None) -> List[Dict[str, Any]]:
319
+ """Retrieves quality checks defined in a data contract.
320
+
321
+ Args:
322
+ qualities (List[Quality]): List of quality object from the model specification.
323
+ field_name (str | None): field name if the quality list is attached to a specific field
324
+
325
+ Returns:
326
+ Dict[str, Any]: Dictionary of quality checks.
327
+ """
328
+ quality_specification = []
329
+ for quality in qualities:
330
+ if quality is not None and quality.engine is not None and quality.engine.lower() == "great-expectations":
331
+ ge_expectation = quality.implementation
332
+ if field_name is not None:
333
+ ge_expectation["column"] = field_name
334
+ quality_specification.append(ge_expectation)
335
+ return quality_specification
336
+
337
+
291
338
  def checks_to_expectations(quality_checks: Dict[str, Any], model_key: str) -> List[Dict[str, Any]]:
292
339
  """Converts quality checks to a list of expectations.
293
340
 
@@ -0,0 +1,359 @@
1
+ from typing import Dict
2
+
3
+ from open_data_contract_standard.model import (
4
+ CustomProperty,
5
+ DataQuality,
6
+ Description,
7
+ OpenDataContractStandard,
8
+ Role,
9
+ SchemaObject,
10
+ SchemaProperty,
11
+ Server,
12
+ ServiceLevelAgreementProperty,
13
+ Support,
14
+ )
15
+
16
+ from datacontract.export.exporter import Exporter
17
+ from datacontract.model.data_contract_specification import DataContractSpecification, Field, Model
18
+
19
+
20
+ class OdcsV3Exporter(Exporter):
21
+ def export(self, data_contract, model, server, sql_server_type, export_args) -> dict:
22
+ return to_odcs_v3_yaml(data_contract)
23
+
24
+
25
+ def to_odcs_v3_yaml(data_contract_spec: DataContractSpecification) -> str:
26
+ result = OpenDataContractStandard(
27
+ apiVersion="v3.0.1",
28
+ kind="DataContract",
29
+ id=data_contract_spec.id,
30
+ name=data_contract_spec.info.title,
31
+ version=data_contract_spec.info.version,
32
+ status=to_status(data_contract_spec.info.status),
33
+ )
34
+
35
+ if data_contract_spec.terms is not None:
36
+ result.description = Description(
37
+ purpose=data_contract_spec.terms.description.strip()
38
+ if data_contract_spec.terms.description is not None
39
+ else None,
40
+ usage=data_contract_spec.terms.usage.strip() if data_contract_spec.terms.usage is not None else None,
41
+ limitations=data_contract_spec.terms.limitations.strip()
42
+ if data_contract_spec.terms.limitations is not None
43
+ else None,
44
+ )
45
+
46
+ result.schema_ = []
47
+ for model_key, model_value in data_contract_spec.models.items():
48
+ odcs_schema = to_odcs_schema(model_key, model_value)
49
+ result.schema_.append(odcs_schema)
50
+
51
+ if data_contract_spec.servicelevels is not None:
52
+ slas = []
53
+ if data_contract_spec.servicelevels.availability is not None:
54
+ slas.append(
55
+ ServiceLevelAgreementProperty(
56
+ property="generalAvailability", value=data_contract_spec.servicelevels.availability.description
57
+ )
58
+ )
59
+ if data_contract_spec.servicelevels.retention is not None:
60
+ slas.append(
61
+ ServiceLevelAgreementProperty(
62
+ property="retention", value=data_contract_spec.servicelevels.retention.period
63
+ )
64
+ )
65
+
66
+ if len(slas) > 0:
67
+ result.slaProperties = slas
68
+
69
+ if data_contract_spec.info.contact is not None:
70
+ support = []
71
+ if data_contract_spec.info.contact.email is not None:
72
+ support.append(Support(channel="email", url="mailto:" + data_contract_spec.info.contact.email))
73
+ if data_contract_spec.info.contact.url is not None:
74
+ support.append(Support(channel="other", url=data_contract_spec.info.contact.url))
75
+ if len(support) > 0:
76
+ result.support = support
77
+
78
+ if data_contract_spec.servers is not None and len(data_contract_spec.servers) > 0:
79
+ servers = []
80
+
81
+ for server_key, server_value in data_contract_spec.servers.items():
82
+ server = Server(server=server_key, type=server_value.type or "")
83
+
84
+ # Set all the attributes that are not None
85
+ if server_value.environment is not None:
86
+ server.environment = server_value.environment
87
+ if server_value.account is not None:
88
+ server.account = server_value.account
89
+ if server_value.database is not None:
90
+ server.database = server_value.database
91
+ if server_value.schema_ is not None:
92
+ server.schema_ = server_value.schema_
93
+ if server_value.format is not None:
94
+ server.format = server_value.format
95
+ if server_value.project is not None:
96
+ server.project = server_value.project
97
+ if server_value.dataset is not None:
98
+ server.dataset = server_value.dataset
99
+ if server_value.path is not None:
100
+ server.path = server_value.path
101
+ if server_value.delimiter is not None:
102
+ server.delimiter = server_value.delimiter
103
+ if server_value.endpointUrl is not None:
104
+ server.endpointUrl = server_value.endpointUrl
105
+ if server_value.location is not None:
106
+ server.location = server_value.location
107
+ if server_value.host is not None:
108
+ server.host = server_value.host
109
+ if server_value.port is not None:
110
+ server.port = server_value.port
111
+ if server_value.catalog is not None:
112
+ server.catalog = server_value.catalog
113
+ if server_value.topic is not None:
114
+ server.topic = server_value.topic
115
+ if server_value.http_path is not None:
116
+ server.http_path = server_value.http_path
117
+ if server_value.token is not None:
118
+ server.token = server_value.token
119
+ if server_value.driver is not None:
120
+ server.driver = server_value.driver
121
+
122
+ if server_value.roles is not None:
123
+ server.roles = [Role(role=role.name, description=role.description) for role in server_value.roles]
124
+
125
+ servers.append(server)
126
+
127
+ if len(servers) > 0:
128
+ result.servers = servers
129
+
130
+ custom_properties = []
131
+ if data_contract_spec.info.owner is not None:
132
+ custom_properties.append(CustomProperty(property="owner", value=data_contract_spec.info.owner))
133
+ if data_contract_spec.info.model_extra is not None:
134
+ for key, value in data_contract_spec.info.model_extra.items():
135
+ custom_properties.append(CustomProperty(property=key, value=value))
136
+
137
+ if len(custom_properties) > 0:
138
+ result.customProperties = custom_properties
139
+
140
+ return result.to_yaml()
141
+
142
+
143
+ def to_odcs_schema(model_key, model_value: Model) -> SchemaObject:
144
+ schema_obj = SchemaObject(
145
+ name=model_key, physicalName=model_key, logicalType="object", physicalType=model_value.type
146
+ )
147
+
148
+ if model_value.description is not None:
149
+ schema_obj.description = model_value.description
150
+
151
+ properties = to_properties(model_value.fields)
152
+ if properties:
153
+ schema_obj.properties = properties
154
+
155
+ model_quality = to_odcs_quality_list(model_value.quality)
156
+ if len(model_quality) > 0:
157
+ schema_obj.quality = model_quality
158
+
159
+ custom_properties = []
160
+ if model_value.model_extra is not None:
161
+ for key, value in model_value.model_extra.items():
162
+ custom_properties.append(CustomProperty(property=key, value=value))
163
+
164
+ if len(custom_properties) > 0:
165
+ schema_obj.customProperties = custom_properties
166
+
167
+ return schema_obj
168
+
169
+
170
+ def to_properties(fields: Dict[str, Field]) -> list:
171
+ properties = []
172
+ for field_name, field in fields.items():
173
+ property = to_property(field_name, field)
174
+ properties.append(property)
175
+ return properties
176
+
177
+
178
+ def to_logical_type(type: str) -> str | None:
179
+ if type is None:
180
+ return None
181
+ if type.lower() in ["string", "varchar", "text"]:
182
+ return "string"
183
+ if type.lower() in ["timestamp", "timestamp_tz"]:
184
+ return "date"
185
+ if type.lower() in ["timestamp_ntz"]:
186
+ return "date"
187
+ if type.lower() in ["date"]:
188
+ return "date"
189
+ if type.lower() in ["time"]:
190
+ return "string"
191
+ if type.lower() in ["number", "decimal", "numeric"]:
192
+ return "number"
193
+ if type.lower() in ["float", "double"]:
194
+ return "number"
195
+ if type.lower() in ["integer", "int", "long", "bigint"]:
196
+ return "integer"
197
+ if type.lower() in ["boolean"]:
198
+ return "boolean"
199
+ if type.lower() in ["object", "record", "struct"]:
200
+ return "object"
201
+ if type.lower() in ["bytes"]:
202
+ return "array"
203
+ if type.lower() in ["array"]:
204
+ return "array"
205
+ if type.lower() in ["null"]:
206
+ return None
207
+ return None
208
+
209
+
210
+ def to_physical_type(type: str) -> str | None:
211
+ return type
212
+
213
+
214
+ def to_property(field_name: str, field: Field) -> SchemaProperty:
215
+ property = SchemaProperty(name=field_name)
216
+
217
+ if field.fields:
218
+ properties = []
219
+ for field_name_, field_ in field.fields.items():
220
+ property_ = to_property(field_name_, field_)
221
+ properties.append(property_)
222
+ property.properties = properties
223
+
224
+ if field.items:
225
+ items = to_property(field_name, field.items)
226
+ items.name = None # Clear the name for items
227
+ property.items = items
228
+
229
+ if field.title is not None:
230
+ property.businessName = field.title
231
+
232
+ if field.type is not None:
233
+ property.logicalType = to_logical_type(field.type)
234
+ property.physicalType = to_physical_type(field.type)
235
+
236
+ if field.description is not None:
237
+ property.description = field.description
238
+
239
+ if field.required is not None:
240
+ property.required = field.required
241
+
242
+ if field.unique is not None:
243
+ property.unique = field.unique
244
+
245
+ if field.classification is not None:
246
+ property.classification = field.classification
247
+
248
+ if field.examples is not None:
249
+ property.examples = field.examples.copy()
250
+
251
+ if field.example is not None:
252
+ property.examples = [field.example]
253
+
254
+ if field.primaryKey is not None and field.primaryKey:
255
+ property.primaryKey = field.primaryKey
256
+ property.primaryKeyPosition = 1
257
+
258
+ if field.primary is not None and field.primary:
259
+ property.primaryKey = field.primary
260
+ property.primaryKeyPosition = 1
261
+
262
+ custom_properties = []
263
+ if field.model_extra is not None:
264
+ for key, value in field.model_extra.items():
265
+ custom_properties.append(CustomProperty(property=key, value=value))
266
+
267
+ if field.pii is not None:
268
+ custom_properties.append(CustomProperty(property="pii", value=field.pii))
269
+
270
+ if len(custom_properties) > 0:
271
+ property.customProperties = custom_properties
272
+
273
+ if field.tags is not None and len(field.tags) > 0:
274
+ property.tags = field.tags
275
+
276
+ logical_type_options = {}
277
+ if field.minLength is not None:
278
+ logical_type_options["minLength"] = field.minLength
279
+ if field.maxLength is not None:
280
+ logical_type_options["maxLength"] = field.maxLength
281
+ if field.pattern is not None:
282
+ logical_type_options["pattern"] = field.pattern
283
+ if field.minimum is not None:
284
+ logical_type_options["minimum"] = field.minimum
285
+ if field.maximum is not None:
286
+ logical_type_options["maximum"] = field.maximum
287
+ if field.exclusiveMinimum is not None:
288
+ logical_type_options["exclusiveMinimum"] = field.exclusiveMinimum
289
+ if field.exclusiveMaximum is not None:
290
+ logical_type_options["exclusiveMaximum"] = field.exclusiveMaximum
291
+
292
+ if logical_type_options:
293
+ property.logicalTypeOptions = logical_type_options
294
+
295
+ if field.quality is not None:
296
+ quality_list = field.quality
297
+ quality_property = to_odcs_quality_list(quality_list)
298
+ if len(quality_property) > 0:
299
+ property.quality = quality_property
300
+
301
+ return property
302
+
303
+
304
+ def to_odcs_quality_list(quality_list):
305
+ quality_property = []
306
+ for quality in quality_list:
307
+ quality_property.append(to_odcs_quality(quality))
308
+ return quality_property
309
+
310
+
311
+ def to_odcs_quality(quality):
312
+ quality_obj = DataQuality(type=quality.type)
313
+
314
+ if quality.description is not None:
315
+ quality_obj.description = quality.description
316
+ if quality.query is not None:
317
+ quality_obj.query = quality.query
318
+ # dialect is not supported in v3.0.0
319
+ if quality.mustBe is not None:
320
+ quality_obj.mustBe = quality.mustBe
321
+ if quality.mustNotBe is not None:
322
+ quality_obj.mustNotBe = quality.mustNotBe
323
+ if quality.mustBeGreaterThan is not None:
324
+ quality_obj.mustBeGreaterThan = quality.mustBeGreaterThan
325
+ if quality.mustBeGreaterThanOrEqualTo is not None:
326
+ quality_obj.mustBeGreaterOrEqualTo = quality.mustBeGreaterThanOrEqualTo
327
+ if quality.mustBeLessThan is not None:
328
+ quality_obj.mustBeLessThan = quality.mustBeLessThan
329
+ if quality.mustBeLessThanOrEqualTo is not None:
330
+ quality_obj.mustBeLessOrEqualTo = quality.mustBeLessThanOrEqualTo
331
+ if quality.mustBeBetween is not None:
332
+ quality_obj.mustBeBetween = quality.mustBeBetween
333
+ if quality.mustNotBeBetween is not None:
334
+ quality_obj.mustNotBeBetween = quality.mustNotBeBetween
335
+ if quality.engine is not None:
336
+ quality_obj.engine = quality.engine
337
+ if quality.implementation is not None:
338
+ quality_obj.implementation = quality.implementation
339
+
340
+ return quality_obj
341
+
342
+
343
+ def to_status(status):
344
+ """Convert the data contract status to ODCS v3 format."""
345
+ if status is None:
346
+ return "draft" # Default to draft if no status is provided
347
+
348
+ # Valid status values according to ODCS v3.0.1 spec
349
+ valid_statuses = ["proposed", "draft", "active", "deprecated", "retired"]
350
+
351
+ # Convert to lowercase for comparison
352
+ status_lower = status.lower()
353
+
354
+ # If status is already valid, return it as is
355
+ if status_lower in valid_statuses:
356
+ return status_lower
357
+
358
+ # Default to "draft" for any non-standard status
359
+ return "draft"
@@ -175,7 +175,7 @@ def print_schema(dtype: types.DataType) -> str:
175
175
  Returns:
176
176
  str: The indented text.
177
177
  """
178
- return "\n".join([f'{" " * level}{line}' for line in text.split("\n")])
178
+ return "\n".join([f"{' ' * level}{line}" for line in text.split("\n")])
179
179
 
180
180
  def repr_column(column: types.StructField) -> str:
181
181
  """