datacontract-cli 1.2.8__tar.gz → 1.2.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.
Files changed (484) hide show
  1. {datacontract_cli-1.2.8/datacontract_cli.egg-info → datacontract_cli-1.2.9}/PKG-INFO +8 -7
  2. datacontract_cli-1.2.9/datacontract/__init__.py +30 -0
  3. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/api.py +57 -13
  4. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/cli.py +1 -2
  5. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/config/settings.py +16 -0
  6. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/checks/check_spec.py +2 -0
  7. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/checks/create_checks.py +14 -6
  8. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/checks/custom_quality_check.py +118 -36
  9. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/data_contract_test.py +4 -1
  10. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/hana/check_hana_execute.py +2 -1
  11. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/hana/hana_quality_check.py +4 -3
  12. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/ibis/connections/connect.py +23 -1
  13. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/ibis/ibis_check_execute.py +61 -21
  14. datacontract_cli-1.2.9/datacontract/engines/ibis/snowflake_nested_values.py +149 -0
  15. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/sql_exporter.py +82 -0
  16. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9/datacontract_cli.egg-info}/PKG-INFO +8 -7
  17. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract_cli.egg-info/SOURCES.txt +1 -0
  18. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract_cli.egg-info/requires.txt +7 -6
  19. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/pyproject.toml +10 -8
  20. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_api.py +213 -3
  21. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_connect_athena.py +1 -1
  22. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_connect_bigquery.py +54 -2
  23. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_connect_snowflake.py +71 -0
  24. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_create_checks_sql_placeholders.py +10 -0
  25. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_custom_quality_checks.py +160 -3
  26. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_docs_ordering.py +2 -2
  27. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_sql.py +147 -0
  28. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_hana_quality_check.py +15 -3
  29. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_snowflake.py +2 -1
  30. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_nested_path_checks.py +44 -2
  31. datacontract_cli-1.2.8/datacontract/__init__.py +0 -17
  32. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/LICENSE +0 -0
  33. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/MANIFEST.in +0 -0
  34. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/README.md +0 -0
  35. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/breaking/__init__.py +0 -0
  36. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/breaking/detector.py +0 -0
  37. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/breaking/rules.py +0 -0
  38. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/catalog/catalog.py +0 -0
  39. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/changelog/__init__.py +0 -0
  40. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/changelog/changelog.py +0 -0
  41. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/changelog/normalize.py +0 -0
  42. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/command_api.py +0 -0
  43. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/command_breaking.py +0 -0
  44. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/command_catalog.py +0 -0
  45. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/command_changelog.py +0 -0
  46. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/command_ci.py +0 -0
  47. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/command_dbt.py +0 -0
  48. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/command_edit.py +0 -0
  49. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/command_export.py +0 -0
  50. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/command_import.py +0 -0
  51. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/command_init.py +0 -0
  52. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/command_lint.py +0 -0
  53. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/command_publish.py +0 -0
  54. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/command_test.py +0 -0
  55. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/config/__init__.py +0 -0
  56. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/config/cli_context.py +0 -0
  57. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/config/variables.py +0 -0
  58. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/data_contract.py +0 -0
  59. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/editor_assets/VERSION +0 -0
  60. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/editor_assets/assets/editor.worker-4.7.0.js +0 -0
  61. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/editor_assets/assets/yaml.worker-4.7.0.js +0 -0
  62. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/editor_assets/datacontract-editor-version.json +0 -0
  63. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/editor_assets/datacontract-editor.css +0 -0
  64. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/editor_assets/datacontract-editor.es.js +0 -0
  65. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/editor_assets/index.html +0 -0
  66. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/editor_assets/logo_fuchsia_v2.svg +0 -0
  67. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/editor_assets/monaco-4.7.0.js +0 -0
  68. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/editor_assets/odcs.svg +0 -0
  69. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/editor_assets/robots.txt +0 -0
  70. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/editor_assets/rolldown-runtime-CEFd7nDs.js +0 -0
  71. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/editor_assets/sitemap.xml +0 -0
  72. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/__init__.py +0 -0
  73. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/checks/__init__.py +0 -0
  74. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/checks/check_filter.py +0 -0
  75. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/checks/dimensions.py +0 -0
  76. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/checks/physical_type_match.py +0 -0
  77. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/checks/severity.py +0 -0
  78. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/checks/sql_guard.py +0 -0
  79. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/checks/type_normalize.py +0 -0
  80. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/datacontract/check_azure_blob_file.py +0 -0
  81. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/datacontract/check_that_datacontract_contains_valid_servers_configuration.py +0 -0
  82. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/datacontract/check_that_datacontract_file_exists.py +0 -0
  83. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/fastjsonschema/check_jsonschema.py +0 -0
  84. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/fastjsonschema/s3/s3_read_files.py +0 -0
  85. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/hana/__init__.py +0 -0
  86. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/hana/hana_check_selection.py +0 -0
  87. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/hana/hana_connection.py +0 -0
  88. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/hana/hana_schema_check.py +0 -0
  89. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/hana/hana_type_mapping.py +0 -0
  90. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/http_api.py +0 -0
  91. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/ibis/__init__.py +0 -0
  92. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/ibis/connections/__init__.py +0 -0
  93. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/ibis/connections/athena_patch.py +0 -0
  94. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/ibis/connections/aws_credentials.py +0 -0
  95. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/ibis/connections/databricks_patch.py +0 -0
  96. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/ibis/connections/duckdb_connection.py +0 -0
  97. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/ibis/connections/exasol_patch.py +0 -0
  98. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/ibis/connections/hive_patch.py +0 -0
  99. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/ibis/connections/iceberg.py +0 -0
  100. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/ibis/connections/kafka.py +0 -0
  101. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/ibis/connections/oracle_patch.py +0 -0
  102. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/ibis/connections/redshift_credentials.py +0 -0
  103. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/ibis/connections/redshift_patch.py +0 -0
  104. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/ibis/dtype_category.py +0 -0
  105. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/ibis/native_type.py +0 -0
  106. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/engines/ibis/snowflake_structured_types.py +0 -0
  107. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/__init__.py +0 -0
  108. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/avro_exporter.py +0 -0
  109. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/avro_idl_exporter.py +0 -0
  110. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/bigquery_exporter.py +0 -0
  111. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/custom_exporter.py +0 -0
  112. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/data_caterer_exporter.py +0 -0
  113. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/dbml_exporter.py +0 -0
  114. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/dbt_exporter.py +0 -0
  115. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/dcs_exporter.py +0 -0
  116. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/dqx_exporter.py +0 -0
  117. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/duckdb_type_converter.py +0 -0
  118. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/excel_exporter.py +0 -0
  119. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/exporter.py +0 -0
  120. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/exporter_factory.py +0 -0
  121. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/go_exporter.py +0 -0
  122. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/great_expectations_exporter.py +0 -0
  123. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/html_exporter.py +0 -0
  124. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/iceberg_exporter.py +0 -0
  125. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/jsonschema_exporter.py +0 -0
  126. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/markdown_exporter.py +0 -0
  127. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/mermaid_exporter.py +0 -0
  128. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/odcs_v3_exporter.py +0 -0
  129. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/pandas_type_converter.py +0 -0
  130. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/protobuf_exporter.py +0 -0
  131. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/pydantic_exporter.py +0 -0
  132. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/rdf_exporter.py +0 -0
  133. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/sodacl_check_builder.py +0 -0
  134. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/sodacl_exporter.py +0 -0
  135. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/spark_exporter.py +0 -0
  136. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/sql_type_converter.py +0 -0
  137. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/sqlalchemy_exporter.py +0 -0
  138. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/export/xsd_exporter.py +0 -0
  139. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/athena_importer.py +0 -0
  140. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/avro_importer.py +0 -0
  141. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/bigquery_importer.py +0 -0
  142. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/clickhouse_importer.py +0 -0
  143. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/csv_importer.py +0 -0
  144. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/dbml_importer.py +0 -0
  145. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/dbt_importer.py +0 -0
  146. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/dcs_importer.py +0 -0
  147. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/excel_importer.py +0 -0
  148. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/glue_importer.py +0 -0
  149. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/hive_importer.py +0 -0
  150. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/iceberg_importer.py +0 -0
  151. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/importer.py +0 -0
  152. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/importer_factory.py +0 -0
  153. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/json_importer.py +0 -0
  154. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/jsonschema_importer.py +0 -0
  155. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/mysql_importer.py +0 -0
  156. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/object_storage_importer.py +0 -0
  157. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/odata_importer.py +0 -0
  158. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/odcs_helper.py +0 -0
  159. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/odcs_importer.py +0 -0
  160. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/openapi_importer.py +0 -0
  161. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/oracle_importer.py +0 -0
  162. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/parquet_importer.py +0 -0
  163. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/postgres_importer.py +0 -0
  164. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/powerbi_importer.py +0 -0
  165. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/protobuf_importer.py +0 -0
  166. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/pydantic_importer.py +0 -0
  167. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/redshift_importer.py +0 -0
  168. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/snowflake_importer.py +0 -0
  169. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/spark_importer.py +0 -0
  170. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/spark_type_json.py +0 -0
  171. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/sql_importer.py +0 -0
  172. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/sqlserver_importer.py +0 -0
  173. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/trino_importer.py +0 -0
  174. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/unity_importer.py +0 -0
  175. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/imports/xsd_importer.py +0 -0
  176. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/init/init_template.py +0 -0
  177. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/integration/dbt_sync.py +0 -0
  178. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/integration/dbt_test_mapping.py +0 -0
  179. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/integration/entropy_data.py +0 -0
  180. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/lint/constraints.py +0 -0
  181. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/lint/files.py +0 -0
  182. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/lint/resolve.py +0 -0
  183. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/lint/resources.py +0 -0
  184. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/lint/s3.py +0 -0
  185. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/lint/schema.py +0 -0
  186. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/lint/urls.py +0 -0
  187. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/model/breaking.py +0 -0
  188. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/model/changelog.py +0 -0
  189. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/model/enum_values.py +0 -0
  190. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/model/exceptions.py +0 -0
  191. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/model/map_type.py +0 -0
  192. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/model/natural_keys.py +0 -0
  193. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/model/odcs.py +0 -0
  194. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/model/run.py +0 -0
  195. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/model/server.py +0 -0
  196. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/model/vector_type.py +0 -0
  197. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/model/workbook.py +0 -0
  198. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/output/__init__.py +0 -0
  199. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/output/ci_output.py +0 -0
  200. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/output/json_test_results.py +0 -0
  201. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/output/junit_test_results.py +0 -0
  202. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/output/output_format.py +0 -0
  203. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/output/test_results_writer.py +0 -0
  204. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/output/text_breaking_results.py +0 -0
  205. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/output/text_changelog_results.py +0 -0
  206. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/py.typed +0 -0
  207. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/schemas/datacontract-1.1.0.init.yaml +0 -0
  208. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/schemas/datacontract-1.1.0.schema.json +0 -0
  209. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/schemas/datacontract-1.2.0.init.yaml +0 -0
  210. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/schemas/datacontract-1.2.0.schema.json +0 -0
  211. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/schemas/datacontract-1.2.1.init.yaml +0 -0
  212. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/schemas/datacontract-1.2.1.schema.json +0 -0
  213. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/schemas/odcs-3.0.2.schema.json +0 -0
  214. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/schemas/odcs-3.1.0.schema.json +0 -0
  215. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/schemas/odcs-3.2.0.init.yaml +0 -0
  216. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/schemas/odcs-3.2.0.schema.json +0 -0
  217. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/datacontract.html +0 -0
  218. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/datacontract_odcs.html +0 -0
  219. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/excel/odcs-template-v3.0.xlsx +0 -0
  220. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/excel/odcs-template-v3.1.xlsx +0 -0
  221. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/excel/odcs-template-v3.2.xlsx +0 -0
  222. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/index.html +0 -0
  223. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/macros/authoritative_definitions.html +0 -0
  224. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/macros/context.html +0 -0
  225. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/macros/schema.html +0 -0
  226. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/macros/server.html +0 -0
  227. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/macros/support.html +0 -0
  228. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials/datacontract_information.html +0 -0
  229. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials/datacontract_servicelevels.html +0 -0
  230. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials/datacontract_terms.html +0 -0
  231. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials/definition.html +0 -0
  232. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials/example.html +0 -0
  233. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials/model_field.html +0 -0
  234. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials/quality.html +0 -0
  235. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials/server.html +0 -0
  236. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials_odcs/context.html +0 -0
  237. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials_odcs/custom_properties.html +0 -0
  238. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials_odcs/diagram.html +0 -0
  239. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials_odcs/dialog_yaml.html +0 -0
  240. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials_odcs/footer.html +0 -0
  241. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials_odcs/fundamentals.html +0 -0
  242. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials_odcs/header.html +0 -0
  243. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials_odcs/pricing.html +0 -0
  244. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials_odcs/roles.html +0 -0
  245. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials_odcs/schema.html +0 -0
  246. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials_odcs/servers.html +0 -0
  247. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials_odcs/sla.html +0 -0
  248. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials_odcs/support.html +0 -0
  249. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials_odcs/team.html +0 -0
  250. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials_odcs/term_of_use.html +0 -0
  251. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/partials_odcs/title.html +0 -0
  252. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract/templates/style/output.css +0 -0
  253. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract_cli.egg-info/dependency_links.txt +0 -0
  254. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract_cli.egg-info/entry_points.txt +0 -0
  255. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/datacontract_cli.egg-info/top_level.txt +0 -0
  256. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/setup.cfg +0 -0
  257. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_api_concurrency.py +0 -0
  258. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_api_openapi.py +0 -0
  259. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_breaking.py +0 -0
  260. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_breaking_odcs_3_2.py +0 -0
  261. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_catalog.py +0 -0
  262. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_changelog.py +0 -0
  263. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_changelog_engine.py +0 -0
  264. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_changelog_normalize.py +0 -0
  265. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_changelog_output_text.py +0 -0
  266. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_check_quality_provenance.py +0 -0
  267. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_ci_output.py +0 -0
  268. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_cli.py +0 -0
  269. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_command_api.py +0 -0
  270. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_command_api_options.py +0 -0
  271. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_config.py +0 -0
  272. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_config_file.py +0 -0
  273. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_config_require.py +0 -0
  274. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_config_threading.py +0 -0
  275. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_connect_clickhouse.py +0 -0
  276. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_connect_databricks.py +0 -0
  277. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_connect_exasol.py +0 -0
  278. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_connect_hive.py +0 -0
  279. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_connect_impala.py +0 -0
  280. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_connect_mysql.py +0 -0
  281. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_connect_oracle.py +0 -0
  282. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_connect_postgres.py +0 -0
  283. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_connect_redshift.py +0 -0
  284. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_connect_s3_credentials.py +0 -0
  285. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_connect_sqlserver.py +0 -0
  286. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_connect_trino.py +0 -0
  287. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_create_checks_array_items.py +0 -0
  288. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_create_checks_nested.py +0 -0
  289. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_create_checks_nested_type.py +0 -0
  290. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_create_checks_physical_type.py +0 -0
  291. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_create_checks_primary_key.py +0 -0
  292. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_create_checks_retention_period.py +0 -0
  293. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_create_checks_servicelevel.py +0 -0
  294. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_data_contract.py +0 -0
  295. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_data_contract_checks.py +0 -0
  296. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_data_contract_specification.py +0 -0
  297. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_dbt_sync.py +0 -0
  298. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_dbt_test_mapping.py +0 -0
  299. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_description_linter.py +0 -0
  300. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_docs_commands.py +0 -0
  301. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_docs_config_options.py +0 -0
  302. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_download_datacontract_file.py +0 -0
  303. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_dtype_category.py +0 -0
  304. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_duckdb_json.py +0 -0
  305. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_edit.py +0 -0
  306. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_enum_values.py +0 -0
  307. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_avro.py +0 -0
  308. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_avro_idl.py +0 -0
  309. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_bigquery.py +0 -0
  310. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_complex_data_contract.py +0 -0
  311. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_custom.py +0 -0
  312. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_custom_exporter.py +0 -0
  313. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_custom_model.py +0 -0
  314. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_data_caterer.py +0 -0
  315. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_dbml.py +0 -0
  316. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_dbt_models.py +0 -0
  317. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_dbt_sources.py +0 -0
  318. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_dbt_staging_sql.py +0 -0
  319. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_dcs.py +0 -0
  320. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_dqx.py +0 -0
  321. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_excel.py +0 -0
  322. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_go.py +0 -0
  323. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_great_expectations.py +0 -0
  324. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_html.py +0 -0
  325. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_iceberg.py +0 -0
  326. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_jsonschema.py +0 -0
  327. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_large_contract.py +0 -0
  328. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_markdown.py +0 -0
  329. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_mermaid.py +0 -0
  330. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_odcs_v3.py +0 -0
  331. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_protobuf.py +0 -0
  332. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_pydantic.py +0 -0
  333. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_rdf.py +0 -0
  334. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_sodacl.py +0 -0
  335. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_spark.py +0 -0
  336. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_sql_clickhouse.py +0 -0
  337. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_sql_query.py +0 -0
  338. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_sqlalchemy.py +0 -0
  339. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_export_xsd.py +0 -0
  340. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_hana_connection.py +0 -0
  341. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_hana_schema_check.py +0 -0
  342. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_hana_type_mapping.py +0 -0
  343. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_ibis_check_execute.py +0 -0
  344. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_ibis_mssql_pattern.py +0 -0
  345. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_ibis_mssql_schema.py +0 -0
  346. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_ibis_oracle_schema.py +0 -0
  347. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_athena.py +0 -0
  348. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_avro.py +0 -0
  349. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_bigquery.py +0 -0
  350. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_clickhouse.py +0 -0
  351. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_csv.py +0 -0
  352. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_dbml.py +0 -0
  353. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_dbt.py +0 -0
  354. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_excel.py +0 -0
  355. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_glue.py +0 -0
  356. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_hive.py +0 -0
  357. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_iceberg.py +0 -0
  358. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_json.py +0 -0
  359. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_jsonschema.py +0 -0
  360. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_mysql.py +0 -0
  361. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_object_storage.py +0 -0
  362. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_odata.py +0 -0
  363. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_odcs_v3.py +0 -0
  364. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_openapi.py +0 -0
  365. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_oracle.py +0 -0
  366. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_parquet.py +0 -0
  367. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_postgres.py +0 -0
  368. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_powerbi.py +0 -0
  369. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_protobuf.py +0 -0
  370. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_pydantic_model.py +0 -0
  371. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_redshift.py +0 -0
  372. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_spark_type_json.py +0 -0
  373. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_sql_clickhouse.py +0 -0
  374. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_sql_hive.py +0 -0
  375. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_sql_oracle.py +0 -0
  376. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_sql_postgres.py +0 -0
  377. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_sql_snowflake.py +0 -0
  378. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_sql_sqlserver.py +0 -0
  379. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_sql_struct.py +0 -0
  380. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_sqlserver.py +0 -0
  381. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_trino.py +0 -0
  382. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_unity_file.py +0 -0
  383. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_unmapped_types.py +0 -0
  384. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_import_xsd.py +0 -0
  385. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_install_extras.py +0 -0
  386. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_integration_entropydata.py +0 -0
  387. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_lint.py +0 -0
  388. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_lint_files.py +0 -0
  389. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_lint_odcs_3_2_constraints.py +0 -0
  390. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_lint_schema.py +0 -0
  391. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_lint_urls.py +0 -0
  392. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_map_type.py +0 -0
  393. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_metadata_fields.py +0 -0
  394. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_native_type_schema_scope.py +0 -0
  395. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_oracle_patch.py +0 -0
  396. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_physical_type_match.py +0 -0
  397. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_publish_test_results.py +0 -0
  398. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_publish_test_results_payload.py +0 -0
  399. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_quality_sql_dialects.py +0 -0
  400. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_quality_unrunnable_rules.py +0 -0
  401. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_redshift_credentials.py +0 -0
  402. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_redshift_patch.py +0 -0
  403. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_resolve.py +0 -0
  404. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_resolve_definitions.py +0 -0
  405. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_resolve_local_definitions.py +0 -0
  406. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_roundtrip_jsonschema.py +0 -0
  407. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_roundtrip_pydantic_model.py +0 -0
  408. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_roundtrip_xsd.py +0 -0
  409. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_row_filter_duplicate_count.py +0 -0
  410. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_run_check_deprecated_fields.py +0 -0
  411. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_run_check_engine.py +0 -0
  412. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_server_overrides.py +0 -0
  413. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_server_type_mssql.py +0 -0
  414. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_server_type_synonyms.py +0 -0
  415. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_servers_3_2_0.py +0 -0
  416. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_snowflake_structured_types.py +0 -0
  417. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_sql_type_converter_physicaltype.py +0 -0
  418. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_api.py +0 -0
  419. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_api_endpoints.py +0 -0
  420. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_api_openapi_import.py +0 -0
  421. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_array_items.py +0 -0
  422. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_athena_iceberg.py +0 -0
  423. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_azure_blob_file.py +0 -0
  424. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_azure_remote.py +0 -0
  425. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_bigquery.py +0 -0
  426. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_checks_filter.py +0 -0
  427. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_clickhouse.py +0 -0
  428. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_databricks.py +0 -0
  429. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_delta.py +0 -0
  430. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_diagnostics.py +0 -0
  431. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_dimension_filter.py +0 -0
  432. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_dry_run.py +0 -0
  433. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_duckdb.py +0 -0
  434. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_failed_samples.py +0 -0
  435. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_gcs_csv_remote.py +0 -0
  436. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_gcs_json_remote.py +0 -0
  437. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_hana.py +0 -0
  438. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_hive.py +0 -0
  439. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_iceberg.py +0 -0
  440. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_iceberg_rest.py +0 -0
  441. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_iceberg_s3tables.py +0 -0
  442. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_kafka.py +0 -0
  443. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_kafka_decoding.py +0 -0
  444. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_kafka_remote.py +0 -0
  445. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_local_json.py +0 -0
  446. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_local_json_nd.py +0 -0
  447. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_local_xlsx.py +0 -0
  448. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_local_xml.py +0 -0
  449. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_metadata_only.py +0 -0
  450. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_mysql.py +0 -0
  451. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_nested_checks.py +0 -0
  452. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_oracle.py +0 -0
  453. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_oracle_xe.py +0 -0
  454. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_output_json.py +0 -0
  455. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_output_junit.py +0 -0
  456. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_parquet.py +0 -0
  457. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_postgres.py +0 -0
  458. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_quality.py +0 -0
  459. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_quality_id_and_tag_filter.py +0 -0
  460. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_quality_local_fallback.py +0 -0
  461. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_quality_percent_severity.py +0 -0
  462. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_redshift.py +0 -0
  463. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_relationships.py +0 -0
  464. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_results_writer.py +0 -0
  465. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_row_filter.py +0 -0
  466. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_s3_csv.py +0 -0
  467. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_s3_delta.py +0 -0
  468. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_s3_json.py +0 -0
  469. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_s3_json_complex.py +0 -0
  470. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_s3_json_multiple_files.py +0 -0
  471. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_s3_json_multiple_models.py +0 -0
  472. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_s3_xlsx.py +0 -0
  473. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_schema_evolution.py +0 -0
  474. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_server_not_found.py +0 -0
  475. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_snowflake.py +0 -0
  476. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_soda_connection_error.py +0 -0
  477. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_sqlserver.py +0 -0
  478. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_trino.py +0 -0
  479. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_test_variables.py +0 -0
  480. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_type_normalize.py +0 -0
  481. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_untrusted_contract.py +0 -0
  482. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_untrusted_contract_variables.py +0 -0
  483. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_variables.py +0 -0
  484. {datacontract_cli-1.2.8 → datacontract_cli-1.2.9}/tests/test_vector_type.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datacontract-cli
3
- Version: 1.2.8
3
+ Version: 1.2.9
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@entropy-data.com>, Stefan Negele <stefan.negele@innoq.com>, Simon Harrer <simon.harrer@entropy-data.com>
6
6
  License-Expression: MIT
@@ -73,7 +73,7 @@ Requires-Dist: rich>=12.4.4; extra == "dataframe"
73
73
  Provides-Extra: databricks
74
74
  Requires-Dist: ibis-framework[databricks]<13.0.0,>=10.0.0; extra == "databricks"
75
75
  Requires-Dist: databricks-sql-connector<4.7.0,>=3.7.0; extra == "databricks"
76
- Requires-Dist: databricks-sdk<0.154.0; extra == "databricks"
76
+ Requires-Dist: databricks-sdk<0.157.0; extra == "databricks"
77
77
  Requires-Dist: packaging<27.0,>=21.3; extra == "databricks"
78
78
  Provides-Extra: databricks-runtime
79
79
  Requires-Dist: datacontract-cli[databricks]; extra == "databricks-runtime"
@@ -107,8 +107,9 @@ Requires-Dist: duckdb-extension-azure<1.6.0,>=1.5.0; extra == "azure"
107
107
  Requires-Dist: azure-identity<1.27,>=1.17.1; extra == "azure"
108
108
  Requires-Dist: azure-storage-blob<12.32,>=12.24; extra == "azure"
109
109
  Provides-Extra: snowflake
110
- Requires-Dist: snowflake-connector-python[pandas]<4.9,>=3.6; extra == "snowflake"
110
+ Requires-Dist: snowflake-connector-python[pandas]<5.2,>=3.17; extra == "snowflake"
111
111
  Requires-Dist: ibis-framework[snowflake]<13.0.0,>=10.0.0; extra == "snowflake"
112
+ Requires-Dist: packaging<27.0,>=21.3; extra == "snowflake"
112
113
  Provides-Extra: sqlserver
113
114
  Requires-Dist: ibis-framework[mssql]<13.0.0,>=10.0.0; extra == "sqlserver"
114
115
  Requires-Dist: packaging<27.0,>=21.3; extra == "sqlserver"
@@ -144,7 +145,7 @@ Requires-Dist: pyarrow>=18.1.0; extra == "parquet"
144
145
  Provides-Extra: rdf
145
146
  Requires-Dist: rdflib==7.6.0; extra == "rdf"
146
147
  Provides-Extra: api
147
- Requires-Dist: fastapi<0.144.0,>=0.115.0; extra == "api"
148
+ Requires-Dist: fastapi<0.162.0,>=0.115.0; extra == "api"
148
149
  Requires-Dist: uvicorn<0.55.0,>=0.44.0; extra == "api"
149
150
  Provides-Extra: protobuf
150
151
  Requires-Dist: proto-schema-parser<3.0,>=1.0; extra == "protobuf"
@@ -164,10 +165,10 @@ Requires-Dist: pre-commit<4.7.0,>=3.7.1; extra == "dev"
164
165
  Requires-Dist: pytest; extra == "dev"
165
166
  Requires-Dist: pytest-cov; extra == "dev"
166
167
  Requires-Dist: pytest-xdist; extra == "dev"
167
- Requires-Dist: pymssql==2.4.4; extra == "dev"
168
+ Requires-Dist: pymssql==2.4.5; extra == "dev"
168
169
  Requires-Dist: psycopg2-binary<3.0,>=2.9; extra == "dev"
169
- Requires-Dist: mysql-connector-python<26.8.0,>=8.0.30; extra == "dev"
170
- Requires-Dist: ruff==0.17.1; extra == "dev"
170
+ Requires-Dist: mysql-connector-python<26.11.0,>=8.0.30; extra == "dev"
171
+ Requires-Dist: ruff==0.17.2; extra == "dev"
171
172
  Requires-Dist: testcontainers[kafka,minio,mssql,mysql,postgres]==4.15.0; extra == "dev"
172
173
  Requires-Dist: trino==0.340.0; extra == "dev"
173
174
  Dynamic: license-file
@@ -0,0 +1,30 @@
1
+ # Configuration so that yaml.safe_dump dumps strings with line breaks with yaml literal |
2
+ import warnings
3
+
4
+ import yaml
5
+
6
+ yaml.SafeDumper.org_represent_str = yaml.SafeDumper.represent_str
7
+
8
+
9
+ def repr_str(dumper, data):
10
+ if "\n" in data:
11
+ return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="|")
12
+ return dumper.org_represent_str(data)
13
+
14
+
15
+ yaml.add_representer(str, repr_str, Dumper=yaml.SafeDumper)
16
+
17
+ # snowflake-connector-python 5.x warns on every connection about a changing logout default, and about the 4.x
18
+ # parameter names we keep passing because Python 3.10 installs still get 4.x.
19
+ warnings.filterwarnings(
20
+ "ignore", message="enable_server_session_keep_alive_auto_detection was not set", category=FutureWarning
21
+ )
22
+ warnings.filterwarnings(
23
+ "ignore",
24
+ message="'(private_key_file_pwd|network_timeout|socket_timeout)' is deprecated",
25
+ category=DeprecationWarning,
26
+ )
27
+
28
+ from datacontract.config import Config # noqa: E402
29
+
30
+ __all__ = ["Config"]
@@ -12,7 +12,7 @@ from fastapi.security.api_key import APIKeyHeader
12
12
  from pydantic import BaseModel, Field, ValidationError
13
13
 
14
14
  from datacontract.config import Config, known_env_names
15
- from datacontract.config.variables import CONTRACT_VARIABLES_ENV, allowed_environment, resolve_variables
15
+ from datacontract.config.variables import CONTRACT_VARIABLES_ENV, allowed_environment, resolve_server_variables
16
16
  from datacontract.data_contract import DataContract, ExportFormat
17
17
  from datacontract.model.breaking import BreakingChangeEntry, Perspective
18
18
  from datacontract.model.changelog import ChangelogEntry
@@ -443,6 +443,22 @@ AUTHENTICATION_RESPONSES: dict[int | str, dict] = {
443
443
 
444
444
  _CONFIG_HEADER_PREFIX = "datacontract-"
445
445
 
446
+ # Options naming a file or folder on the server's disk, or the server's own workload identity: the operator's
447
+ # to choose, never the caller's, or a caller could have the server log in as the operator to a host of their choosing.
448
+ _SERVER_ONLY_OPTIONS = frozenset(
449
+ {
450
+ "DATACONTRACT_CUSTOM_QUALITY_CHECKS",
451
+ "DATACONTRACT_SNOWFLAKE_PRIVATE_KEY_FILE",
452
+ "DATACONTRACT_SNOWFLAKE_PRIVATE_KEY_PATH",
453
+ "DATACONTRACT_SNOWFLAKE_TOKEN_FILE_PATH",
454
+ "DATACONTRACT_SNOWFLAKE_WORKLOAD_IDENTITY_PROVIDER",
455
+ "DATACONTRACT_BIGQUERY_ACCOUNT_INFO_JSON_PATH",
456
+ "DATACONTRACT_DATABRICKS_PROFILE",
457
+ "DATACONTRACT_ORACLE_CLIENT_DIR",
458
+ "DATACONTRACT_DUCKDB_DATABASE",
459
+ }
460
+ )
461
+
446
462
 
447
463
  def config_from_headers(headers) -> "Config | None":
448
464
  """Build a per-request Config from configuration option headers.
@@ -452,8 +468,8 @@ def config_from_headers(headers) -> "Config | None":
452
468
  → ``DATACONTRACT_SNOWFLAKE_PASSWORD``, ``entropy-data-api-key`` →
453
469
  ``ENTROPY_DATA_API_KEY``. Returns None when no config headers are present,
454
470
  so env-var-configured deployments behave exactly as before. Unknown
455
- ``datacontract-*`` option names are rejected with a 400, and so is the
456
- custom quality checks folder.
471
+ ``datacontract-*`` option names are rejected with a 400, and so are options
472
+ only the operator may set.
457
473
  """
458
474
  known = known_env_names()
459
475
  values = {}
@@ -461,11 +477,10 @@ def config_from_headers(headers) -> "Config | None":
461
477
  lowered = name.lower()
462
478
  env = lowered.upper().replace("-", "_")
463
479
  if lowered.startswith(_CONFIG_HEADER_PREFIX) or env in known:
464
- if env == "DATACONTRACT_CUSTOM_QUALITY_CHECKS":
465
- # A folder on the server's disk is the operator's to choose, never the caller's.
480
+ if env in _SERVER_ONLY_OPTIONS:
466
481
  raise HTTPException(
467
482
  status_code=status.HTTP_400_BAD_REQUEST,
468
- detail="The custom quality checks folder is configured by the API server, not per request.",
483
+ detail=f"{env} is set on the API server. It is not possible to override it per request.",
469
484
  )
470
485
  values[env] = value
471
486
  if not values:
@@ -516,12 +531,25 @@ _ENVIRONMENT_CREDENTIAL_TARGETS: dict[str, tuple[str, str | None, tuple[str, ...
516
531
  "hive": ("host", "hive_host", ("hive_password",)),
517
532
  "redshift": ("host", "redshift_host", ("redshift_password",)),
518
533
  "sqlserver": ("host", "sqlserver_host", ("sqlserver_password",)),
534
+ "mssql": ("host", "sqlserver_host", ("sqlserver_password",)),
519
535
  "snowflake": (
520
536
  "account",
521
537
  "snowflake_account",
522
- ("snowflake_password", "snowflake_token", "snowflake_private_key"),
538
+ (
539
+ "snowflake_password",
540
+ "snowflake_token",
541
+ "snowflake_private_key",
542
+ "snowflake_private_key_file",
543
+ "snowflake_private_key_path",
544
+ "snowflake_token_file_path",
545
+ "snowflake_workload_identity_provider",
546
+ ),
547
+ ),
548
+ "databricks": (
549
+ "host",
550
+ "databricks_server_hostname",
551
+ ("databricks_token", "databricks_client_secret", "databricks_profile"),
523
552
  ),
524
- "databricks": ("host", "databricks_server_hostname", ("databricks_token", "databricks_client_secret")),
525
553
  # Kafka's broker host is always the contract's `server.host` (no environment
526
554
  # option pins it), so an environment-held SASL password can never be paired
527
555
  # with a posted contract safely -- host_field is None, so it is always rejected.
@@ -539,13 +567,17 @@ def _selected_server(body: str, server_name: str | None, config):
539
567
  """
540
568
  from datacontract.engines.data_contract_test import get_server
541
569
  from datacontract.lint import resolve
570
+ from datacontract.model.server import get_server_type
542
571
 
543
572
  try:
544
573
  data_contract = resolve.resolve_data_contract(data_contract_str=body, config=config)
545
574
  server = get_server(data_contract, server_name)
546
- # Guard the server type the test will run against, not a ${VAR:-local} reference to it.
547
- variables = allowed_environment(_allowed_contract_variables())
548
- return server and server.model_copy(update={"type": resolve_variables(server.type, variables=variables)})
575
+ if server is None:
576
+ return None
577
+ # Guard the server type the test will connect to: references like ${VAR:-local} resolved, and
578
+ # `custom` + customType or an ODCS synonym such as `postgresql` mapped to the type the CLI dispatches on.
579
+ server = resolve_server_variables(server, allowed_environment(_allowed_contract_variables()))
580
+ return server.model_copy(update={"type": get_server_type(server)})
549
581
  except Exception:
550
582
  return None
551
583
 
@@ -630,11 +662,23 @@ def _reject_environment_credentials_to_untrusted_host(body: str, server_name: st
630
662
  target_attr, host_field, secret_fields = guard
631
663
  if not any(resolved.option_source(field) == "env" for field in secret_fields):
632
664
  return # no environment-held secret for this server type; nothing to protect
633
- if host_field is not None and resolved.option_source(host_field) == "env":
634
- return # the operator pinned the target host; the contract's host is ignored
635
665
  held = [
636
666
  env_name(field, Config.model_fields[field]) for field in secret_fields if resolved.option_source(field) == "env"
637
667
  ]
668
+ if host_field is not None and resolved.option_source(host_field) == "env":
669
+ # Snowflake's host and port override the address the pinned account resolves to.
670
+ redirects = [
671
+ env_name(field, Config.model_fields[field])
672
+ for field in ("snowflake_host", "snowflake_port")
673
+ if server.type == "snowflake" and resolved.option_source(field) == "request"
674
+ ]
675
+ if not redirects:
676
+ return # the operator pinned the target host; the contract's host is ignored
677
+ raise HTTPException(
678
+ status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
679
+ detail=f"{', '.join(redirects)} cannot be set per request while the API server uses its own Snowflake "
680
+ f"credential ({', '.join(held)}). Remove it, or send all credentials with the request.",
681
+ )
638
682
  if host_field is not None:
639
683
  env_var = env_name(host_field, Config.model_fields[host_field])
640
684
  detail = (
@@ -35,8 +35,7 @@ custom_quality_checks_option = Annotated[
35
35
  Optional[Path],
36
36
  typer.Option(
37
37
  metavar="DIR",
38
- help="Folder with the custom quality checks the contract's quality rules use, one YAML file per check. "
39
- "Defaults to DATACONTRACT_CUSTOM_QUALITY_CHECKS.",
38
+ help="Folder with custom quality checks. Defaults to DATACONTRACT_CUSTOM_QUALITY_CHECKS.",
40
39
  ),
41
40
  ]
42
41
 
@@ -136,6 +136,8 @@ class Config(BaseSettings):
136
136
  bigquery_account_info_json_path: str | None = None
137
137
  bigquery_billing_project: str | None = None
138
138
  bigquery_impersonation_account: str | None = None
139
+ bigquery_location: str | None = None
140
+ bigquery_kms_key_name: str | None = None
139
141
  # overrides for the contract's servers block
140
142
  bigquery_project: str | None = None
141
143
  bigquery_dataset: str | None = None
@@ -279,8 +281,10 @@ class Config(BaseSettings):
279
281
  snowflake_username: str | None = None
280
282
  snowflake_password: SecretStr | None = None
281
283
  snowflake_authenticator: str | None = None
284
+ snowflake_workload_identity_provider: str | None = None
282
285
  snowflake_role: str | None = None
283
286
  snowflake_token: SecretStr | None = None
287
+ snowflake_token_file_path: str | None = None
284
288
  snowflake_passcode: SecretStr | None = None
285
289
  snowflake_private_key: SecretStr | None = None
286
290
  snowflake_private_key_file: str | None = None
@@ -582,6 +586,12 @@ class Config(BaseSettings):
582
586
  def get_bigquery_impersonation_account(self, required: bool = False) -> str | None:
583
587
  return self._str_option("bigquery_impersonation_account", required)
584
588
 
589
+ def get_bigquery_location(self, required: bool = False) -> str | None:
590
+ return self._str_option("bigquery_location", required)
591
+
592
+ def get_bigquery_kms_key_name(self, required: bool = False) -> str | None:
593
+ return self._str_option("bigquery_kms_key_name", required)
594
+
585
595
  def get_bigquery_project(self, required: bool = False) -> str | None:
586
596
  return self._str_option("bigquery_project", required)
587
597
 
@@ -902,12 +912,18 @@ class Config(BaseSettings):
902
912
  def get_snowflake_authenticator(self, required: bool = False) -> str | None:
903
913
  return self._str_option("snowflake_authenticator", required)
904
914
 
915
+ def get_snowflake_workload_identity_provider(self, required: bool = False) -> str | None:
916
+ return self._str_option("snowflake_workload_identity_provider", required)
917
+
905
918
  def get_snowflake_role(self, required: bool = False) -> str | None:
906
919
  return self._str_option("snowflake_role", required)
907
920
 
908
921
  def get_snowflake_token(self, required: bool = False) -> str | None:
909
922
  return self._str_option("snowflake_token", required)
910
923
 
924
+ def get_snowflake_token_file_path(self, required: bool = False) -> str | None:
925
+ return self._str_option("snowflake_token_file_path", required)
926
+
911
927
  def get_snowflake_passcode(self, required: bool = False) -> str | None:
912
928
  return self._str_option("snowflake_passcode", required)
913
929
 
@@ -151,6 +151,7 @@ class CheckSpec:
151
151
  valid_min_items: Optional[int] = None # INVALID_COUNT, array columns
152
152
  valid_max_items: Optional[int] = None # INVALID_COUNT, array columns
153
153
  valid_unique_items: Optional[bool] = None # INVALID_COUNT, array columns
154
+ value_type: Optional[str] = None # the declared type a value stored untyped is cast to
154
155
 
155
156
  expected_category: Optional[str] = None # FIELD_TYPE: human-readable label (display only)
156
157
  expected_type_label: Optional[str] = None # FIELD_TYPE: human-readable expected type
@@ -166,6 +167,7 @@ class CheckSpec:
166
167
  query: Optional[str] = None # CUSTOM_SQL (placeholders already substituted)
167
168
  dialect: Optional[str] = None # CUSTOM_SQL input SQL dialect
168
169
  diagnostics: Optional[dict] = None # CUSTOM_SQL: reported alongside the measured value
170
+ custom_quality_check: Optional[str] = None # CUSTOM_SQL: the check's ID and arguments, as between(min=1, max=100)
169
171
  warnings: Optional[List[str]] = None # for the run's log
170
172
 
171
173
  seconds: Optional[int] = None # FRESHNESS / RETENTION threshold in seconds
@@ -28,6 +28,7 @@ from datacontract.engines.checks.check_spec import METADATA_METRICS, CheckSpec,
28
28
  from datacontract.engines.checks.custom_quality_check import (
29
29
  COLUMN_PLACEHOLDERS,
30
30
  ENGINE,
31
+ CustomQualityChecks,
31
32
  CustomQualityCheckUnusable,
32
33
  Instance,
33
34
  instantiate,
@@ -54,6 +55,7 @@ _NESTED_CHECK_SERVER_TYPES = {
54
55
  "kafka",
55
56
  "trino",
56
57
  "athena",
58
+ "snowflake",
57
59
  } | _FILE_SERVER_TYPES
58
60
 
59
61
 
@@ -212,10 +214,14 @@ def prepare_query(
212
214
  names |= dict.fromkeys(COLUMN_PLACEHOLDERS, field_name)
213
215
 
214
216
  def identifier(name: str, forced: bool) -> str:
215
- return ".".join(
217
+ parts = [
216
218
  exp.to_identifier(part, quoted=forced or not bare.fullmatch(part)).sql(dialect=dialect)
217
219
  for part in name.split(".")
218
- )
220
+ ]
221
+ if dialect == "snowflake" and name == field_name:
222
+ # Snowflake reaches into a column's value with `:`; a dot would name a table's column
223
+ return parts[0] + "".join(f":{part}" for part in parts[1:])
224
+ return ".".join(parts)
219
225
 
220
226
  if instance is not None:
221
227
  return instance.render(dialect, names, identifier)
@@ -234,7 +240,7 @@ def create_checks(
234
240
  server: Optional[Server],
235
241
  schema_name: str = "all",
236
242
  variables: Optional[Mapping[str, str]] = None,
237
- custom_quality_checks: Optional[str] = None,
243
+ custom_quality_checks: Optional[CustomQualityChecks] = None,
238
244
  ) -> List[CheckSpec]:
239
245
  checks: List[CheckSpec] = []
240
246
  if data_contract.schema_ is None:
@@ -265,7 +271,7 @@ def _to_schema_checks(
265
271
  schema_object: SchemaObject,
266
272
  server: Optional[Server],
267
273
  variables: Optional[Mapping[str, str]] = None,
268
- custom_quality_checks: Optional[str] = None,
274
+ custom_quality_checks: Optional[CustomQualityChecks] = None,
269
275
  ) -> List[CheckSpec]:
270
276
  checks: List[CheckSpec] = []
271
277
  server_type = get_server_type(server) if server is not None else None
@@ -598,6 +604,7 @@ def _to_schema_checks(
598
604
 
599
605
  # A check the server cannot run is reported, not dropped.
600
606
  for check in checks[first_check:]:
607
+ check.value_type = prop_type
601
608
  if check.preset_result == "warning":
602
609
  # An unrunnable rule keeps its own, more specific reason.
603
610
  continue
@@ -831,7 +838,7 @@ def _quality_checks(
831
838
  quality_list: List[DataQuality],
832
839
  server: Optional[Server],
833
840
  variables: Optional[Mapping[str, str]] = None,
834
- custom_quality_checks: Optional[str] = None,
841
+ custom_quality_checks: Optional[CustomQualityChecks] = None,
835
842
  ) -> List[CheckSpec]:
836
843
  checks: List[CheckSpec] = []
837
844
  for count, quality in enumerate(quality_list):
@@ -933,7 +940,7 @@ def _quality_rule_checks(
933
940
  count: int,
934
941
  server: Optional[Server],
935
942
  variables: Optional[Mapping[str, str]] = None,
936
- custom_quality_checks: Optional[str] = None,
943
+ custom_quality_checks: Optional[CustomQualityChecks] = None,
937
944
  ) -> List[CheckSpec]:
938
945
  """The checks of a single ODCS quality rule (``count`` is its index in the list)."""
939
946
  if quality.type == "custom" and quality.engine == "soda" and quality.implementation:
@@ -1000,6 +1007,7 @@ def _quality_rule_checks(
1000
1007
  severity=rule.severity,
1001
1008
  dimension=rule.dimension,
1002
1009
  diagnostics=instance.diagnostics,
1010
+ custom_quality_check=instance.call,
1003
1011
  warnings=instance.warnings,
1004
1012
  )
1005
1013
  ]
@@ -8,7 +8,9 @@ import re
8
8
  from dataclasses import dataclass, field
9
9
  from pathlib import Path
10
10
  from typing import Any, Callable, Mapping, Optional
11
+ from urllib.parse import quote, urlparse
11
12
 
13
+ import requests
12
14
  import sqlglot
13
15
  import yaml
14
16
  from open_data_contract_standard.model import DataQuality
@@ -17,9 +19,11 @@ from sqlglot import exp
17
19
  from sqlglot.dialects.dialect import Dialect
18
20
  from sqlglot.tokens import TokenType
19
21
 
22
+ from datacontract.config import Config
20
23
  from datacontract.config.variables import _ENUM_VALUES
21
24
  from datacontract.engines.checks.sql_guard import _DIALECT_BY_SERVER_TYPE
22
- from datacontract.lint.resolve import _SafeLoaderNoTimestamp
25
+ from datacontract.integration.entropy_data import _get_api_key_or_none, _get_host
26
+ from datacontract.lint.resolve import _api_key_for, _SafeLoaderNoTimestamp
23
27
 
24
28
  ENGINE = "datacontract-cli"
25
29
 
@@ -91,41 +95,104 @@ class CustomQualityCheck:
91
95
  warnings: list[str] = field(default_factory=list)
92
96
 
93
97
 
94
- def load(directory: str, check_id: str) -> CustomQualityCheck:
95
- folder = Path(directory)
96
- if not folder.is_dir():
97
- problem = "is a file, not a folder" if folder.exists() else "does not exist"
98
- raise CustomQualityCheckError(f"The custom quality checks folder {directory} {problem}.")
99
- # The ID comes from the contract, so it is looked up among the files, never joined into a path.
100
- # IDs are unique ignoring case.
101
- files: dict[str, list[Path]] = {}
102
- for path in sorted(folder.iterdir()):
103
- if path.is_file() and path.suffix in (".yaml", ".yml"):
104
- files.setdefault(path.stem.lower(), []).append(path)
105
- paths = files.get(check_id.lower(), [])
106
- if len(paths) > 1:
107
- raise CustomQualityCheckError(
108
- f"The custom quality check '{check_id}' is defined twice: {', '.join(path.name for path in paths)}."
98
+ class CustomQualityChecks:
99
+ """Where a test run finds its custom quality checks: the folder first, then Entropy Data."""
100
+
101
+ def __init__(self, config: Config, untrusted_contract: bool = False):
102
+ self.directory = config.get_custom_quality_checks()
103
+ # An untrusted caller may set the host per request (API header); checks still come from the platform
104
+ # as the environment sees it, or the request would choose where the server sends its GET.
105
+ self.host = _get_host(None if untrusted_contract else config).rstrip("/")
106
+ self.api_key = _api_key_for(self.host, config, untrusted_contract)
107
+ # A key the request brought for its own host is not sent to the environment's host.
108
+ self.ignored_request_host = (
109
+ _get_host(config)
110
+ if untrusted_contract and self.api_key is None and _get_api_key_or_none(config) is not None
111
+ else None
109
112
  )
110
- if not paths or paths[0].stem != check_id:
111
- ids = sorted(path.stem for group in files.values() for path in group)
112
- if len(ids) <= 7:
113
- hint = f" Available: {', '.join(ids) or 'none'}."
114
- else:
115
- similar = difflib.get_close_matches(check_id, ids, n=3)
116
- hint = f" Did you mean {', '.join(similar)}?" if similar else ""
117
- raise CustomQualityCheckError(f"There is no custom quality check with the ID '{check_id}'.{hint}")
118
- try:
119
- document = yaml.load(paths[0].read_text(encoding="utf-8"), Loader=_SafeLoaderNoTimestamp)
120
- except yaml.YAMLError as e:
121
- raise CustomQualityCheckError(f"The custom quality check '{check_id}' is not valid YAML: {e}")
122
- return _parse(check_id, document)
113
+ # lowercased ID -> the check's YAML, or why Entropy Data could not provide it
114
+ self._fetched: dict[str, str | CustomQualityCheckError] = {}
115
+
116
+ def load(self, check_id: str) -> CustomQualityCheck:
117
+ """The check with ``check_id``, regardless of case."""
118
+ if self.directory is not None:
119
+ folder = Path(self.directory)
120
+ if not folder.is_dir():
121
+ problem = "is a file, not a folder" if folder.exists() else "does not exist"
122
+ raise CustomQualityCheckError(f"The custom quality checks folder {self.directory} {problem}.")
123
+ # The ID comes from the contract, so it is looked up among the files, never joined into a path.
124
+ files: dict[str, list[Path]] = {}
125
+ for path in sorted(folder.iterdir()):
126
+ if path.is_file() and path.suffix in (".yaml", ".yml"):
127
+ files.setdefault(path.stem.lower(), []).append(path)
128
+ paths = files.get(check_id.lower(), [])
129
+ if len(paths) > 1:
130
+ raise CustomQualityCheckError(
131
+ f"The custom quality check '{check_id}' is defined twice: {', '.join(path.name for path in paths)}."
132
+ )
133
+ if paths:
134
+ return _parse(check_id, paths[0].read_text(encoding="utf-8"))
135
+ if self.api_key is None:
136
+ ids = sorted(path.stem for group in files.values() for path in group)
137
+ if len(ids) <= 7:
138
+ hint = f" Available: {', '.join(ids) or 'none'}."
139
+ else:
140
+ similar = difflib.get_close_matches(check_id, ids, n=3)
141
+ hint = f" Did you mean {', '.join(similar)}?" if similar else ""
142
+ raise CustomQualityCheckError(f"There is no custom quality check with the ID '{check_id}'.{hint}")
143
+
144
+ key = check_id.lower()
145
+ if key not in self._fetched:
146
+ reason = None
147
+ try:
148
+ # Not following redirects keeps the API key from travelling to another host.
149
+ response = requests.get(
150
+ f"{self.host}/api/custom-quality-checks/{quote(check_id, safe='')}/check.yaml",
151
+ headers={"x-api-key": self.api_key, "Accept": "application/yaml"},
152
+ timeout=10,
153
+ allow_redirects=False,
154
+ )
155
+ except requests.RequestException as e:
156
+ reason = str(e)
157
+ else:
158
+ if response.status_code == 200:
159
+ self._fetched[key] = response.content.decode("utf-8")
160
+ elif response.status_code == 404:
161
+ self._fetched[key] = CustomQualityCheckError(
162
+ f"Neither '{self.directory}' nor Entropy Data has the custom quality check '{check_id}'."
163
+ if self.directory is not None
164
+ else f"Entropy Data has no custom quality check '{check_id}'."
165
+ )
166
+ elif response.is_redirect:
167
+ reason = (
168
+ f"HTTP {response.status_code} redirect to '{response.headers.get('Location')}' is not followed"
169
+ )
170
+ elif response.status_code in (401, 403):
171
+ reason = f"the API key was rejected (HTTP {response.status_code})"
172
+ else:
173
+ reason = f"HTTP {response.status_code} {response.reason}"
174
+ if reason is not None:
175
+ source = urlparse(self.host).netloc or self.host
176
+ self._fetched[key] = CustomQualityCheckError(
177
+ f"The custom quality check '{check_id}' is not in '{self.directory}' and could not be loaded "
178
+ f"from {source}: {reason}."
179
+ if self.directory is not None
180
+ else f"Could not load the custom quality check '{check_id}' from {source}: {reason}."
181
+ )
182
+ fetched = self._fetched[key]
183
+ if isinstance(fetched, CustomQualityCheckError):
184
+ raise fetched
185
+ return _parse(check_id, fetched)
123
186
 
124
187
 
125
- def _parse(check_id: str, document) -> CustomQualityCheck:
188
+ def _parse(check_id: str, text: str) -> CustomQualityCheck:
126
189
  def invalid(detail: str) -> CustomQualityCheckError:
127
190
  return CustomQualityCheckError(f"The custom quality check '{check_id}' is invalid: {detail}")
128
191
 
192
+ try:
193
+ document = yaml.load(text, Loader=_SafeLoaderNoTimestamp)
194
+ except yaml.YAMLError as e:
195
+ raise CustomQualityCheckError(f"The custom quality check '{check_id}' is not valid YAML: {e}")
129
196
  if not isinstance(document, dict):
130
197
  raise invalid("it must be a YAML mapping.")
131
198
  # Unknown keys only warn, so a file written for a newer version still runs.
@@ -232,6 +299,8 @@ class Instance:
232
299
  # The rule with the check's defaults filled in: expected result and dimension.
233
300
  quality: DataQuality
234
301
  name: str
302
+ # The check's ID with the rule's arguments, as between(min=1, max=100)
303
+ call: str
235
304
  diagnostics: dict
236
305
  warnings: list[str]
237
306
 
@@ -365,7 +434,7 @@ def instantiate(
365
434
  model: str,
366
435
  field_name: Optional[str],
367
436
  dialect: Optional[str],
368
- directory: Optional[str],
437
+ custom_quality_checks: Optional[CustomQualityChecks],
369
438
  ) -> Instance:
370
439
  """The rule's custom quality check for a server whose rules are written in ``dialect``."""
371
440
  implementation = quality.implementation if isinstance(quality.implementation, dict) else {}
@@ -386,6 +455,8 @@ def instantiate(
386
455
  f"The custom quality check ID '{check_id}' must not contain spaces, slashes, "
387
456
  "or any of the characters \\ % ; # ?"
388
457
  )
458
+ if check_id in (".", ".."):
459
+ raise unusable(f"'{check_id}' is no valid custom quality check ID.")
389
460
  location = model if field_name is None else f"{model}.{field_name}"
390
461
  rule_warnings += [
391
462
  f"Custom quality check '{check_id}' on {location}: Unknown key 'implementation.{key}' is ignored."
@@ -414,13 +485,22 @@ def instantiate(
414
485
  or f"{check_id}({', '.join(f'{argument}={value_text(value)}' for argument, value in given.items())})"
415
486
  )
416
487
 
417
- if directory is None:
488
+ if custom_quality_checks is None or (
489
+ custom_quality_checks.directory is None and custom_quality_checks.api_key is None
490
+ ):
491
+ if custom_quality_checks is not None and custom_quality_checks.ignored_request_host is not None:
492
+ raise unusable(
493
+ f"The rule uses the custom quality check '{check_id}', but the request's API key belongs to its "
494
+ f"entropy-data-host '{custom_quality_checks.ignored_request_host}', so set ENTROPY_DATA_HOST to that "
495
+ "host on the server running the API."
496
+ )
418
497
  raise unusable(
419
- f"The rule uses the custom quality check '{check_id}', but no custom quality checks folder is "
420
- f"configured. Pass --custom-quality-checks or set DATACONTRACT_CUSTOM_QUALITY_CHECKS.",
498
+ f"The rule uses the custom quality check '{check_id}', but neither a custom quality checks folder nor "
499
+ f"an Entropy Data API key is configured. Pass --custom-quality-checks, or set "
500
+ f"DATACONTRACT_CUSTOM_QUALITY_CHECKS or ENTROPY_DATA_API_KEY.",
421
501
  )
422
502
  try:
423
- check = load(directory, check_id)
503
+ check = custom_quality_checks.load(check_id)
424
504
  except CustomQualityCheckError as e:
425
505
  raise unusable(str(e))
426
506
 
@@ -453,6 +533,7 @@ def instantiate(
453
533
  for item in (value if isinstance(value, list) else [value])
454
534
  ]
455
535
  arguments[argument] = (False, numbers if isinstance(value, list) else numbers[0])
536
+ call = f"{check.id}({', '.join(f'{name}={value_text(value)}' for name, (_, value) in arguments.items())})"
456
537
  if quality.description:
457
538
  name = quality.description
458
539
  elif check.description:
@@ -472,7 +553,7 @@ def instantiate(
472
553
 
473
554
  name = reference_pattern(TABLE_PLACEHOLDERS + COLUMN_PLACEHOLDERS).sub(fill, check.description)
474
555
  else:
475
- name = f"{check.id}({', '.join(f'{name}={value_text(value)}' for name, (_, value) in arguments.items())})"
556
+ name = call
476
557
 
477
558
  for argument, (identifier, value) in arguments.items():
478
559
  if identifier and (not isinstance(value, str) or not value):
@@ -534,6 +615,7 @@ def instantiate(
534
615
  arguments=arguments,
535
616
  quality=quality.model_copy(update=updates),
536
617
  name=name,
618
+ call=call,
537
619
  diagnostics={
538
620
  "custom_quality_check": check.id,
539
621
  "query": query_dialect,
@@ -12,6 +12,7 @@ from open_data_contract_standard.model import OpenDataContractStandard, Server
12
12
  from datacontract.config import Config
13
13
  from datacontract.engines.checks.check_spec import MetricType
14
14
  from datacontract.engines.checks.create_checks import create_checks, to_schema_name
15
+ from datacontract.engines.checks.custom_quality_check import CustomQualityChecks
15
16
  from datacontract.engines.checks.dimensions import default_dimension
16
17
 
17
18
  if typing.TYPE_CHECKING:
@@ -123,6 +124,7 @@ def execute_data_contract_test(
123
124
  )
124
125
 
125
126
  model_filters = resolve_row_filters(data_contract, server, run, filter, filters, schema_name)
127
+ custom_quality_checks = CustomQualityChecks(config, untrusted_contract)
126
128
 
127
129
  if server.type == "hana":
128
130
  from datacontract.engines.hana.check_hana_execute import check_hana_execute
@@ -140,6 +142,7 @@ def execute_data_contract_test(
140
142
  quality_ids=quality_ids,
141
143
  tags=tags,
142
144
  config=config,
145
+ custom_quality_checks=custom_quality_checks,
143
146
  )
144
147
  return
145
148
 
@@ -148,7 +151,7 @@ def execute_data_contract_test(
148
151
  server,
149
152
  schema_name=schema_name,
150
153
  variables=variables,
151
- custom_quality_checks=config.get_custom_quality_checks(),
154
+ custom_quality_checks=custom_quality_checks,
152
155
  )
153
156
  if check_categories is not None:
154
157
  specs = [s for s in specs if s.category in check_categories]