datacontract-cli 0.10.19__tar.gz → 0.10.21__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.19/datacontract_cli.egg-info → datacontract_cli-0.10.21}/PKG-INFO +103 -21
  2. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/README.md +94 -15
  3. datacontract_cli-0.10.21/datacontract/api.py +253 -0
  4. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/cli.py +28 -7
  5. datacontract_cli-0.10.21/datacontract/export/custom_converter.py +40 -0
  6. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/exporter.py +1 -0
  7. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/exporter_factory.py +4 -0
  8. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/lint/urls.py +13 -9
  9. datacontract_cli-0.10.21/datacontract/model/data_contract_specification.py +327 -0
  10. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/model/run.py +18 -18
  11. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/templates/datacontract.html +16 -2
  12. datacontract_cli-0.10.21/datacontract/templates/partials/definition.html +25 -0
  13. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/templates/partials/model_field.html +13 -0
  14. datacontract_cli-0.10.21/datacontract/templates/partials/quality.html +49 -0
  15. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/templates/style/output.css +151 -152
  16. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21/datacontract_cli.egg-info}/PKG-INFO +103 -21
  17. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract_cli.egg-info/SOURCES.txt +6 -3
  18. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract_cli.egg-info/requires.txt +10 -5
  19. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/pyproject.toml +13 -6
  20. datacontract_cli-0.10.19/tests/test_web.py → datacontract_cli-0.10.21/tests/test_api.py +6 -8
  21. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_catalog.py +1 -0
  22. datacontract_cli-0.10.21/tests/test_export_custom.py +34 -0
  23. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_custom_exporter.py +2 -2
  24. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_html.py +0 -11
  25. datacontract_cli-0.10.19/datacontract/model/data_contract_specification.py +0 -326
  26. datacontract_cli-0.10.19/datacontract/templates/partials/definition.html +0 -117
  27. datacontract_cli-0.10.19/datacontract/web.py +0 -67
  28. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/LICENSE +0 -0
  29. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/MANIFEST.in +0 -0
  30. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/__init__.py +0 -0
  31. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/breaking/breaking.py +0 -0
  32. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/breaking/breaking_rules.py +0 -0
  33. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/catalog/catalog.py +0 -0
  34. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/data_contract.py +0 -0
  35. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/engines/__init__.py +0 -0
  36. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/engines/datacontract/check_that_datacontract_contains_valid_servers_configuration.py +0 -0
  37. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/engines/datacontract/check_that_datacontract_file_exists.py +0 -0
  38. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/engines/fastjsonschema/check_jsonschema.py +0 -0
  39. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/engines/fastjsonschema/s3/s3_read_files.py +0 -0
  40. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/engines/soda/__init__.py +0 -0
  41. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/engines/soda/check_soda_execute.py +0 -0
  42. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/engines/soda/connections/bigquery.py +0 -0
  43. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/engines/soda/connections/dask.py +0 -0
  44. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/engines/soda/connections/databricks.py +0 -0
  45. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/engines/soda/connections/duckdb.py +0 -0
  46. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/engines/soda/connections/kafka.py +0 -0
  47. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/engines/soda/connections/postgres.py +0 -0
  48. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/engines/soda/connections/snowflake.py +0 -0
  49. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/engines/soda/connections/sqlserver.py +0 -0
  50. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/engines/soda/connections/trino.py +0 -0
  51. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/__init__.py +0 -0
  52. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/avro_converter.py +0 -0
  53. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/avro_idl_converter.py +0 -0
  54. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/bigquery_converter.py +0 -0
  55. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/csv_type_converter.py +0 -0
  56. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/data_caterer_converter.py +0 -0
  57. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/dbml_converter.py +0 -0
  58. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/dbt_converter.py +0 -0
  59. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/dcs_exporter.py +0 -0
  60. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/go_converter.py +0 -0
  61. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/great_expectations_converter.py +0 -0
  62. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/html_export.py +0 -0
  63. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/iceberg_converter.py +0 -0
  64. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/jsonschema_converter.py +0 -0
  65. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/markdown_converter.py +0 -0
  66. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/odcs_v2_exporter.py +0 -0
  67. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/odcs_v3_exporter.py +0 -0
  68. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/pandas_type_converter.py +0 -0
  69. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/protobuf_converter.py +0 -0
  70. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/pydantic_converter.py +0 -0
  71. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/rdf_converter.py +0 -0
  72. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/sodacl_converter.py +0 -0
  73. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/spark_converter.py +0 -0
  74. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/sql_converter.py +0 -0
  75. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/sql_type_converter.py +0 -0
  76. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/sqlalchemy_converter.py +0 -0
  77. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/export/terraform_converter.py +0 -0
  78. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/imports/avro_importer.py +0 -0
  79. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/imports/bigquery_importer.py +0 -0
  80. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/imports/csv_importer.py +0 -0
  81. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/imports/dbml_importer.py +0 -0
  82. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/imports/dbt_importer.py +0 -0
  83. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/imports/glue_importer.py +0 -0
  84. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/imports/iceberg_importer.py +0 -0
  85. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/imports/importer.py +0 -0
  86. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/imports/importer_factory.py +0 -0
  87. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/imports/jsonschema_importer.py +0 -0
  88. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/imports/odcs_importer.py +0 -0
  89. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/imports/odcs_v2_importer.py +0 -0
  90. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/imports/odcs_v3_importer.py +0 -0
  91. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/imports/parquet_importer.py +0 -0
  92. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/imports/spark_importer.py +0 -0
  93. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/imports/sql_importer.py +0 -0
  94. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/imports/unity_importer.py +0 -0
  95. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/init/init_template.py +0 -0
  96. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/integration/datamesh_manager.py +0 -0
  97. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/lint/files.py +0 -0
  98. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/lint/lint.py +0 -0
  99. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/lint/linters/__init__.py +0 -0
  100. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/lint/linters/description_linter.py +0 -0
  101. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/lint/linters/example_model_linter.py +0 -0
  102. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/lint/linters/field_pattern_linter.py +0 -0
  103. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/lint/linters/field_reference_linter.py +0 -0
  104. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/lint/linters/notice_period_linter.py +0 -0
  105. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/lint/linters/quality_schema_linter.py +0 -0
  106. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/lint/linters/valid_constraints_linter.py +0 -0
  107. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/lint/resolve.py +0 -0
  108. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/lint/resources.py +0 -0
  109. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/lint/schema.py +0 -0
  110. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/model/breaking_change.py +0 -0
  111. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/model/exceptions.py +0 -0
  112. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/model/odcs.py +0 -0
  113. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/py.typed +0 -0
  114. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/schemas/datacontract-1.1.0.init.yaml +0 -0
  115. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/schemas/datacontract-1.1.0.schema.json +0 -0
  116. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/schemas/odcs-3.0.1.schema.json +0 -0
  117. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/templates/index.html +0 -0
  118. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/templates/partials/datacontract_information.html +0 -0
  119. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/templates/partials/datacontract_servicelevels.html +0 -0
  120. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/templates/partials/datacontract_terms.html +0 -0
  121. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/templates/partials/example.html +0 -0
  122. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract/templates/partials/server.html +0 -0
  123. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract_cli.egg-info/dependency_links.txt +0 -0
  124. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract_cli.egg-info/entry_points.txt +0 -0
  125. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/datacontract_cli.egg-info/top_level.txt +0 -0
  126. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/setup.cfg +0 -0
  127. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_breaking.py +0 -0
  128. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_changelog.py +0 -0
  129. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_cli.py +0 -0
  130. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_data_contract_specification.py +0 -0
  131. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_description_linter.py +0 -0
  132. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_documentation_linter.py +0 -0
  133. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_download_datacontract_file.py +0 -0
  134. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_example_model_linter.py +0 -0
  135. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_avro.py +0 -0
  136. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_avro_idl.py +0 -0
  137. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_bigquery.py +0 -0
  138. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_complex_data_contract.py +0 -0
  139. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_data_caterer.py +0 -0
  140. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_dbml.py +0 -0
  141. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_dbt_models.py +0 -0
  142. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_dbt_sources.py +0 -0
  143. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_dbt_staging_sql.py +0 -0
  144. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_go.py +0 -0
  145. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_great_expectations.py +0 -0
  146. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_iceberg.py +0 -0
  147. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_jsonschema.py +0 -0
  148. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_markdown.py +0 -0
  149. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_odcs_v2.py +0 -0
  150. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_odcs_v3.py +0 -0
  151. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_protobuf.py +0 -0
  152. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_pydantic.py +0 -0
  153. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_rdf.py +0 -0
  154. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_sodacl.py +0 -0
  155. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_spark.py +0 -0
  156. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_sql.py +0 -0
  157. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_sql_query.py +0 -0
  158. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_sqlalchemy.py +0 -0
  159. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_export_terraform.py +0 -0
  160. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_field_constraint_linter.py +0 -0
  161. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_field_pattern_linter.py +0 -0
  162. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_field_reference_linter.py +0 -0
  163. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_import_avro.py +0 -0
  164. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_import_bigquery.py +0 -0
  165. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_import_csv.py +0 -0
  166. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_import_dbml.py +0 -0
  167. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_import_dbt.py +0 -0
  168. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_import_glue.py +0 -0
  169. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_import_iceberg.py +0 -0
  170. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_import_jsonschema.py +0 -0
  171. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_import_odcs_v2.py +0 -0
  172. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_import_odcs_v3.py +0 -0
  173. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_import_parquet.py +0 -0
  174. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_import_spark.py +0 -0
  175. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_import_sql.py +0 -0
  176. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_import_unity_file.py +0 -0
  177. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_integration_datameshmanager.py +0 -0
  178. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_lint.py +0 -0
  179. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_notice_period_linter.py +0 -0
  180. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_quality_schema_linter.py +0 -0
  181. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_resolve.py +0 -0
  182. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_roundtrip_jsonschema.py +0 -0
  183. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_spec_fields_field.py +0 -0
  184. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_spec_ref.py +0 -0
  185. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_azure_remote.py +0 -0
  186. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_bigquery.py +0 -0
  187. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_databricks.py +0 -0
  188. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_dataframe.py +0 -0
  189. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_delta.py +0 -0
  190. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_examples_csv.py +0 -0
  191. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_examples_formats_valid.py +0 -0
  192. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_examples_inline.py +0 -0
  193. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_examples_json.py +0 -0
  194. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_examples_missing.py +0 -0
  195. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_gcs_json_remote.py +0 -0
  196. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_kafka.py +0 -0
  197. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_kafka_remote.py +0 -0
  198. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_local_json.py +0 -0
  199. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_parquet.py +0 -0
  200. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_postgres.py +0 -0
  201. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_quality.py +0 -0
  202. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_s3_csv.py +0 -0
  203. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_s3_delta.py +0 -0
  204. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_s3_json.py +0 -0
  205. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_s3_json_complex.py +0 -0
  206. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_s3_json_multiple_models.py +0 -0
  207. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_s3_json_remote.py +0 -0
  208. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_snowflake.py +0 -0
  209. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_sqlserver.py +0 -0
  210. {datacontract_cli-0.10.19 → datacontract_cli-0.10.21}/tests/test_test_trino.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: datacontract-cli
3
- Version: 0.10.19
3
+ Version: 0.10.21
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
6
  Project-URL: Homepage, https://cli.datacontract.com
@@ -15,8 +15,6 @@ Requires-Dist: typer<0.16,>=0.15.1
15
15
  Requires-Dist: pydantic<2.11.0,>=2.8.2
16
16
  Requires-Dist: pyyaml~=6.0.1
17
17
  Requires-Dist: requests<2.33,>=2.31
18
- Requires-Dist: fastapi==0.115.6
19
- Requires-Dist: uvicorn==0.34.0
20
18
  Requires-Dist: fastjsonschema<2.22.0,>=2.19.1
21
19
  Requires-Dist: fastparquet==2024.11.0
22
20
  Requires-Dist: numpy<2.0.0,>=1.26.4
@@ -51,7 +49,7 @@ Provides-Extra: postgres
51
49
  Requires-Dist: soda-core-postgres<3.4.0,>=3.3.20; extra == "postgres"
52
50
  Provides-Extra: s3
53
51
  Requires-Dist: s3fs==2024.12.0; extra == "s3"
54
- Requires-Dist: aiobotocore<2.18.0,>=2.17.0; extra == "s3"
52
+ Requires-Dist: aiobotocore<2.20.0,>=2.17.0; extra == "s3"
55
53
  Provides-Extra: snowflake
56
54
  Requires-Dist: snowflake-connector-python[pandas]<3.13,>=3.6; extra == "snowflake"
57
55
  Requires-Dist: soda-core-snowflake<3.4.0,>=3.3.20; extra == "snowflake"
@@ -65,13 +63,18 @@ Provides-Extra: dbml
65
63
  Requires-Dist: pydbml>=1.1.1; extra == "dbml"
66
64
  Provides-Extra: parquet
67
65
  Requires-Dist: pyarrow>=18.1.0; extra == "parquet"
66
+ Provides-Extra: api
67
+ Requires-Dist: fastapi==0.115.6; extra == "api"
68
+ Requires-Dist: uvicorn==0.34.0; extra == "api"
69
+ Provides-Extra: custom
70
+ Requires-Dist: Jinja2>=3.1.5; extra == "custom"
68
71
  Provides-Extra: all
69
- Requires-Dist: datacontract-cli[bigquery,csv,databricks,dbml,dbt,iceberg,kafka,parquet,postgres,s3,snowflake,sqlserver,trino]; extra == "all"
72
+ Requires-Dist: datacontract-cli[api,bigquery,csv,custom,databricks,dbml,dbt,iceberg,kafka,parquet,postgres,s3,snowflake,sqlserver,trino]; extra == "all"
70
73
  Provides-Extra: dev
71
74
  Requires-Dist: datacontract-cli[all]; extra == "dev"
72
75
  Requires-Dist: httpx==0.28.1; extra == "dev"
73
76
  Requires-Dist: kafka-python; extra == "dev"
74
- Requires-Dist: moto==5.0.26; extra == "dev"
77
+ Requires-Dist: moto==5.0.27; extra == "dev"
75
78
  Requires-Dist: pandas>=2.1.0; extra == "dev"
76
79
  Requires-Dist: pre-commit<4.1.0,>=3.7.1; extra == "dev"
77
80
  Requires-Dist: pytest; extra == "dev"
@@ -304,7 +307,7 @@ Commands
304
307
  - [diff](#diff)
305
308
  - [catalog](#catalog)
306
309
  - [publish](#publish)
307
- - [serve](#serve)
310
+ - [api](#api)
308
311
 
309
312
  ### init
310
313
  ```
@@ -880,7 +883,7 @@ models:
880
883
  │ vro-idl|sql|sql-query|html| │
881
884
  │ go|bigquery|dbml|spark|sqla │
882
885
  │ lchemy|data-caterer|dcs|mar │
883
- │ kdown|iceberg]
886
+ │ kdown|iceberg|custom]
884
887
  │ --output PATH Specify the file path where │
885
888
  │ the exported data will be │
886
889
  │ saved. If no path is │
@@ -903,6 +906,9 @@ models:
903
906
  │ --engine TEXT [engine] The engine used for │
904
907
  │ great expection run. │
905
908
  │ [default: None] │
909
+ │ --template PATH [custom] The file path of │
910
+ │ Jinja template. │
911
+ │ [default: None] │
906
912
  │ --help Show this message and exit. │
907
913
  ╰──────────────────────────────────────────────────────────────────────────────╯
908
914
  ╭─ RDF Options ────────────────────────────────────────────────────────────────╮
@@ -954,6 +960,7 @@ Available export options:
954
960
  | `dcs` | Export to Data Contract Specification in YAML format | ✅ |
955
961
  | `markdown` | Export to Markdown | ✅ |
956
962
  | `iceberg` | Export to an Iceberg JSON Schema Definition | partial |
963
+ | `custom` | Export to Custom format with Jinja | ✅ |
957
964
  | Missing something? | Please create an issue on GitHub | TBD |
958
965
 
959
966
 
@@ -1135,6 +1142,76 @@ to limit your contract export to a single model.
1135
1142
  }
1136
1143
  ```
1137
1144
 
1145
+ #### Custom
1146
+
1147
+ The export function converts the data contract specification into the custom format with Jinja. You can specify the path to a Jinja template with the `--template` argument, allowing you to output files in any format.
1148
+
1149
+ ```shell
1150
+ datacontract export --format custom --template template.txt datacontract.yaml
1151
+ ```
1152
+
1153
+ ##### Jinja variables
1154
+
1155
+ You can directly use the Data Contract Specification as template variables.
1156
+
1157
+ ```shell
1158
+ $ cat template.txt
1159
+ title: {{ data_contract.info.title }}
1160
+
1161
+ $ datacontract export --format custom --template template.txt datacontract.yaml
1162
+ title: Orders Latest
1163
+ ```
1164
+
1165
+ ##### Example Jinja Templates
1166
+
1167
+ ###### Customized dbt model
1168
+
1169
+ You can export the dbt models containing any logic.
1170
+
1171
+ Below is an example of a dbt staging layer that converts a field of `type: timestamp` to a `DATETIME` type with time zone conversion.
1172
+
1173
+ template.sql
1174
+
1175
+ {% raw %}
1176
+ ```sql
1177
+ {%- for model_name, model in data_contract.models.items() %}
1178
+ {#- Export only the first model #}
1179
+ {%- if loop.first -%}
1180
+ SELECT
1181
+ {%- for field_name, field in model.fields.items() %}
1182
+ {%- if field.type == "timestamp" %}
1183
+ DATETIME({{ field_name }}, "Asia/Tokyo") AS {{ field_name }},
1184
+ {%- else %}
1185
+ {{ field_name }} AS {{ field_name }},
1186
+ {%- endif %}
1187
+ {%- endfor %}
1188
+ FROM
1189
+ {{ "{{" }} ref('{{ model_name }}') {{ "}}" }}
1190
+ {%- endif %}
1191
+ {%- endfor %}
1192
+ ```
1193
+ {% endraw %}
1194
+
1195
+ command
1196
+
1197
+ ```shell
1198
+ datacontract export --format custom --template template.sql --output output.sql datacontract.yaml
1199
+ ```
1200
+
1201
+ output.sql
1202
+
1203
+ ```sql
1204
+ SELECT
1205
+ order_id AS order_id,
1206
+ DATETIME(order_timestamp, "Asia/Tokyo") AS order_timestamp,
1207
+ order_total AS order_total,
1208
+ customer_id AS customer_id,
1209
+ customer_email_address AS customer_email_address,
1210
+ DATETIME(processed_timestamp, "Asia/Tokyo") AS processed_timestamp,
1211
+ FROM
1212
+ {{ ref('orders') }}
1213
+ ```
1214
+
1138
1215
  ### import
1139
1216
  ```
1140
1217
 
@@ -1539,18 +1616,23 @@ datacontract catalog --files "*.odcs.yaml"
1539
1616
 
1540
1617
  ```
1541
1618
 
1542
- ### serve
1619
+ ### api
1543
1620
  ```
1544
-
1545
- Usage: datacontract serve [OPTIONS]
1546
-
1547
- Start the datacontract web server.
1548
-
1549
- ╭─ Options ────────────────────────────────────────────────────────────────────╮
1550
- --port INTEGER Bind socket to this port. [default: 4242] │
1551
- --host TEXT Bind socket to this host. [default: 127.0.0.1] │
1552
- │ --help Show this message and exit. │
1553
- ╰──────────────────────────────────────────────────────────────────────────────╯
1621
+
1622
+ Usage: datacontract api [OPTIONS]
1623
+
1624
+ Start the datacontract CLI as server application with REST API.
1625
+ The OpenAPI documentation as Swagger UI is available on http://localhost:4242. You can execute the commands directly from the Swagger UI.
1626
+ To protect the API, you can set the environment variable DATACONTRACT_CLI_API_KEY to a secret API key. To authenticate, requests must include the header 'x-api-key' with the
1627
+ correct API key. This is highly recommended, as data contract tests may be subject to SQL injections or leak sensitive information.
1628
+ To connect to servers (such as a Snowflake data source), set the credentials as environment variables as documented in https://cli.datacontract.com/#test
1629
+
1630
+ ╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
1631
+ │ --port INTEGER Bind socket to this port. [default: 4242] │
1632
+ │ --host TEXT Bind socket to this host. Hint: For running in docker, set it to 0.0.0.0 [default: 127.0.0.1] │
1633
+ │ --help Show this message and exit. │
1634
+ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
1635
+
1554
1636
 
1555
1637
  ```
1556
1638
 
@@ -1708,7 +1790,7 @@ class CustomExporter(Exporter):
1708
1790
 
1709
1791
 
1710
1792
  # Register the new custom class into factory
1711
- exporter_factory.register_exporter("custom", CustomExporter)
1793
+ exporter_factory.register_exporter("custom_exporter", CustomExporter)
1712
1794
 
1713
1795
 
1714
1796
  if __name__ == "__main__":
@@ -1718,7 +1800,7 @@ if __name__ == "__main__":
1718
1800
  )
1719
1801
  # Call export
1720
1802
  result = data_contract.export(
1721
- export_format="custom", model="orders", server="production", custom_arg="my_custom_arg"
1803
+ export_format="custom_exporter", model="orders", server="production", custom_arg="my_custom_arg"
1722
1804
  )
1723
1805
  print(result)
1724
1806
 
@@ -221,7 +221,7 @@ Commands
221
221
  - [diff](#diff)
222
222
  - [catalog](#catalog)
223
223
  - [publish](#publish)
224
- - [serve](#serve)
224
+ - [api](#api)
225
225
 
226
226
  ### init
227
227
  ```
@@ -797,7 +797,7 @@ models:
797
797
  │ vro-idl|sql|sql-query|html| │
798
798
  │ go|bigquery|dbml|spark|sqla │
799
799
  │ lchemy|data-caterer|dcs|mar │
800
- │ kdown|iceberg]
800
+ │ kdown|iceberg|custom]
801
801
  │ --output PATH Specify the file path where │
802
802
  │ the exported data will be │
803
803
  │ saved. If no path is │
@@ -820,6 +820,9 @@ models:
820
820
  │ --engine TEXT [engine] The engine used for │
821
821
  │ great expection run. │
822
822
  │ [default: None] │
823
+ │ --template PATH [custom] The file path of │
824
+ │ Jinja template. │
825
+ │ [default: None] │
823
826
  │ --help Show this message and exit. │
824
827
  ╰──────────────────────────────────────────────────────────────────────────────╯
825
828
  ╭─ RDF Options ────────────────────────────────────────────────────────────────╮
@@ -871,6 +874,7 @@ Available export options:
871
874
  | `dcs` | Export to Data Contract Specification in YAML format | ✅ |
872
875
  | `markdown` | Export to Markdown | ✅ |
873
876
  | `iceberg` | Export to an Iceberg JSON Schema Definition | partial |
877
+ | `custom` | Export to Custom format with Jinja | ✅ |
874
878
  | Missing something? | Please create an issue on GitHub | TBD |
875
879
 
876
880
 
@@ -1052,6 +1056,76 @@ to limit your contract export to a single model.
1052
1056
  }
1053
1057
  ```
1054
1058
 
1059
+ #### Custom
1060
+
1061
+ The export function converts the data contract specification into the custom format with Jinja. You can specify the path to a Jinja template with the `--template` argument, allowing you to output files in any format.
1062
+
1063
+ ```shell
1064
+ datacontract export --format custom --template template.txt datacontract.yaml
1065
+ ```
1066
+
1067
+ ##### Jinja variables
1068
+
1069
+ You can directly use the Data Contract Specification as template variables.
1070
+
1071
+ ```shell
1072
+ $ cat template.txt
1073
+ title: {{ data_contract.info.title }}
1074
+
1075
+ $ datacontract export --format custom --template template.txt datacontract.yaml
1076
+ title: Orders Latest
1077
+ ```
1078
+
1079
+ ##### Example Jinja Templates
1080
+
1081
+ ###### Customized dbt model
1082
+
1083
+ You can export the dbt models containing any logic.
1084
+
1085
+ Below is an example of a dbt staging layer that converts a field of `type: timestamp` to a `DATETIME` type with time zone conversion.
1086
+
1087
+ template.sql
1088
+
1089
+ {% raw %}
1090
+ ```sql
1091
+ {%- for model_name, model in data_contract.models.items() %}
1092
+ {#- Export only the first model #}
1093
+ {%- if loop.first -%}
1094
+ SELECT
1095
+ {%- for field_name, field in model.fields.items() %}
1096
+ {%- if field.type == "timestamp" %}
1097
+ DATETIME({{ field_name }}, "Asia/Tokyo") AS {{ field_name }},
1098
+ {%- else %}
1099
+ {{ field_name }} AS {{ field_name }},
1100
+ {%- endif %}
1101
+ {%- endfor %}
1102
+ FROM
1103
+ {{ "{{" }} ref('{{ model_name }}') {{ "}}" }}
1104
+ {%- endif %}
1105
+ {%- endfor %}
1106
+ ```
1107
+ {% endraw %}
1108
+
1109
+ command
1110
+
1111
+ ```shell
1112
+ datacontract export --format custom --template template.sql --output output.sql datacontract.yaml
1113
+ ```
1114
+
1115
+ output.sql
1116
+
1117
+ ```sql
1118
+ SELECT
1119
+ order_id AS order_id,
1120
+ DATETIME(order_timestamp, "Asia/Tokyo") AS order_timestamp,
1121
+ order_total AS order_total,
1122
+ customer_id AS customer_id,
1123
+ customer_email_address AS customer_email_address,
1124
+ DATETIME(processed_timestamp, "Asia/Tokyo") AS processed_timestamp,
1125
+ FROM
1126
+ {{ ref('orders') }}
1127
+ ```
1128
+
1055
1129
  ### import
1056
1130
  ```
1057
1131
 
@@ -1456,18 +1530,23 @@ datacontract catalog --files "*.odcs.yaml"
1456
1530
 
1457
1531
  ```
1458
1532
 
1459
- ### serve
1533
+ ### api
1460
1534
  ```
1461
-
1462
- Usage: datacontract serve [OPTIONS]
1463
-
1464
- Start the datacontract web server.
1465
-
1466
- ╭─ Options ────────────────────────────────────────────────────────────────────╮
1467
- --port INTEGER Bind socket to this port. [default: 4242] │
1468
- --host TEXT Bind socket to this host. [default: 127.0.0.1] │
1469
- │ --help Show this message and exit. │
1470
- ╰──────────────────────────────────────────────────────────────────────────────╯
1535
+
1536
+ Usage: datacontract api [OPTIONS]
1537
+
1538
+ Start the datacontract CLI as server application with REST API.
1539
+ The OpenAPI documentation as Swagger UI is available on http://localhost:4242. You can execute the commands directly from the Swagger UI.
1540
+ To protect the API, you can set the environment variable DATACONTRACT_CLI_API_KEY to a secret API key. To authenticate, requests must include the header 'x-api-key' with the
1541
+ correct API key. This is highly recommended, as data contract tests may be subject to SQL injections or leak sensitive information.
1542
+ To connect to servers (such as a Snowflake data source), set the credentials as environment variables as documented in https://cli.datacontract.com/#test
1543
+
1544
+ ╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
1545
+ │ --port INTEGER Bind socket to this port. [default: 4242] │
1546
+ │ --host TEXT Bind socket to this host. Hint: For running in docker, set it to 0.0.0.0 [default: 127.0.0.1] │
1547
+ │ --help Show this message and exit. │
1548
+ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
1549
+
1471
1550
 
1472
1551
  ```
1473
1552
 
@@ -1625,7 +1704,7 @@ class CustomExporter(Exporter):
1625
1704
 
1626
1705
 
1627
1706
  # Register the new custom class into factory
1628
- exporter_factory.register_exporter("custom", CustomExporter)
1707
+ exporter_factory.register_exporter("custom_exporter", CustomExporter)
1629
1708
 
1630
1709
 
1631
1710
  if __name__ == "__main__":
@@ -1635,7 +1714,7 @@ if __name__ == "__main__":
1635
1714
  )
1636
1715
  # Call export
1637
1716
  result = data_contract.export(
1638
- export_format="custom", model="orders", server="production", custom_arg="my_custom_arg"
1717
+ export_format="custom_exporter", model="orders", server="production", custom_arg="my_custom_arg"
1639
1718
  )
1640
1719
  print(result)
1641
1720
 
@@ -0,0 +1,253 @@
1
+ import logging
2
+ import os
3
+ from typing import Annotated, Optional
4
+
5
+ import typer
6
+ from fastapi import Body, Depends, FastAPI, HTTPException, Query, status
7
+ from fastapi.responses import PlainTextResponse
8
+ from fastapi.security.api_key import APIKeyHeader
9
+
10
+ from datacontract.data_contract import DataContract, ExportFormat
11
+ from datacontract.model.run import Run
12
+
13
+ DATA_CONTRACT_EXAMPLE_PAYLOAD = """dataContractSpecification: 1.1.0
14
+ id: urn:datacontract:checkout:orders-latest
15
+ info:
16
+ title: Orders Latest
17
+ version: 2.0.0
18
+ owner: Sales Team
19
+ servers:
20
+ production:
21
+ type: s3
22
+ location: s3://datacontract-example-orders-latest/v2/{model}/*.json
23
+ format: json
24
+ delimiter: new_line
25
+ models:
26
+ orders:
27
+ description: One record per order. Includes cancelled and deleted orders.
28
+ type: table
29
+ fields:
30
+ order_id:
31
+ type: string
32
+ primaryKey: true
33
+ order_timestamp:
34
+ description: The business timestamp in UTC when the order was successfully registered in the source system and the payment was successful.
35
+ type: timestamp
36
+ required: true
37
+ examples:
38
+ - "2024-09-09T08:30:00Z"
39
+ order_total:
40
+ description: Total amount the smallest monetary unit (e.g., cents).
41
+ type: long
42
+ required: true
43
+ examples:
44
+ - 9999
45
+ quality:
46
+ - type: sql
47
+ description: 95% of all order total values are expected to be between 10 and 499 EUR.
48
+ query: |
49
+ SELECT quantile_cont(order_total, 0.95) AS percentile_95
50
+ FROM orders
51
+ mustBeBetween: [1000, 99900]
52
+ customer_id:
53
+ description: Unique identifier for the customer.
54
+ type: text
55
+ minLength: 10
56
+ maxLength: 20
57
+ """
58
+
59
+ app = FastAPI(
60
+ docs_url="/",
61
+ title="Data Contract CLI API",
62
+ summary="You can use the API to test, export, and lint your data contracts.",
63
+ license_info={
64
+ "name": "MIT License",
65
+ "identifier": "MIT",
66
+ },
67
+ contact={"name": "Data Contract CLI", "url": "https://cli.datacontract.com/"},
68
+ openapi_tags=[
69
+ {
70
+ "name": "test",
71
+ "externalDocs": {
72
+ "description": "Documentation",
73
+ "url": "https://cli.datacontract.com/#test",
74
+ },
75
+ },
76
+ {
77
+ "name": "lint",
78
+ "externalDocs": {
79
+ "description": "Documentation",
80
+ "url": "https://cli.datacontract.com/#lint",
81
+ },
82
+ },
83
+ {
84
+ "name": "export",
85
+ "externalDocs": {
86
+ "description": "Documentation",
87
+ "url": "https://cli.datacontract.com/#export",
88
+ },
89
+ },
90
+ ],
91
+ )
92
+
93
+ api_key_header = APIKeyHeader(
94
+ name="x-api-key",
95
+ auto_error=False, # this makes authentication optional
96
+ )
97
+
98
+
99
+ def check_api_key(api_key_header: str | None):
100
+ correct_api_key = os.getenv("DATACONTRACT_CLI_API_KEY")
101
+ if correct_api_key is None or correct_api_key == "":
102
+ logging.info("Environment variable DATACONTRACT_CLI_API_KEY is not set. Skip API key check.")
103
+ return
104
+ if api_key_header is None or api_key_header == "":
105
+ logging.info("The API key is missing.")
106
+ raise HTTPException(
107
+ status_code=status.HTTP_401_UNAUTHORIZED,
108
+ detail="Missing API key. Use Header 'x-api-key' to provide the API key.",
109
+ )
110
+ if api_key_header != correct_api_key:
111
+ logging.info("The provided API key is not correct.")
112
+ raise HTTPException(
113
+ status_code=status.HTTP_403_FORBIDDEN,
114
+ detail="The provided API key is not correct.",
115
+ )
116
+ logging.info("Request authenticated with API key.")
117
+ pass
118
+
119
+
120
+ @app.post(
121
+ "/test",
122
+ tags=["test"],
123
+ summary="Run data contract tests",
124
+ description="""
125
+ Run schema and quality tests. Data Contract CLI connects to the data sources configured in the server section.
126
+ This usually requires credentials to access the data sources.
127
+ Credentials must be provided via environment variables when running the web server.
128
+ POST the data contract YAML as payload.
129
+ """,
130
+ responses={
131
+ 401: {
132
+ "description": "Unauthorized (when an environment variable DATACONTRACT_CLI_API_KEY is configured).",
133
+ "content": {
134
+ "application/json": {
135
+ "examples": {
136
+ "api_key_missing": {
137
+ "summary": "API key Missing",
138
+ "value": {"detail": "Missing API key. Use Header 'x-api-key' to provide the API key."},
139
+ },
140
+ "api_key_wrong": {
141
+ "summary": "API key Wrong",
142
+ "value": {"detail": "The provided API key is not correct."},
143
+ },
144
+ }
145
+ }
146
+ },
147
+ },
148
+ },
149
+ response_model_exclude_none=True,
150
+ response_model_exclude_unset=True,
151
+ )
152
+ async def test(
153
+ body: Annotated[
154
+ str,
155
+ Body(
156
+ title="Data Contract YAML",
157
+ media_type="application/yaml",
158
+ examples=[DATA_CONTRACT_EXAMPLE_PAYLOAD],
159
+ ),
160
+ ],
161
+ api_key: Annotated[str | None, Depends(api_key_header)] = None,
162
+ server: Annotated[
163
+ str | None,
164
+ Query(
165
+ example="production",
166
+ description="The server name to test. Optional, if there is only one server.",
167
+ ),
168
+ ] = None,
169
+ ) -> Run:
170
+ check_api_key(api_key)
171
+ logging.info("Testing data contract...")
172
+ logging.info(body)
173
+ return DataContract(data_contract_str=body, server=server).test()
174
+
175
+
176
+ @app.post(
177
+ "/lint",
178
+ tags=["lint"],
179
+ summary="Validate that the datacontract.yaml is correctly formatted.",
180
+ description="""Validate that the datacontract.yaml is correctly formatted.""",
181
+ )
182
+ async def lint(
183
+ body: Annotated[
184
+ str,
185
+ Body(
186
+ title="Data Contract YAML",
187
+ media_type="application/yaml",
188
+ examples=[DATA_CONTRACT_EXAMPLE_PAYLOAD],
189
+ ),
190
+ ],
191
+ schema: Annotated[
192
+ str | None,
193
+ Query(
194
+ example="https://datacontract.com/datacontract.schema.json",
195
+ description="The schema to use for validation. This must be a URL.",
196
+ ),
197
+ ] = None,
198
+ ):
199
+ data_contract = DataContract(data_contract_str=body, schema_location=schema)
200
+ lint_result = data_contract.lint()
201
+ return {"result": lint_result.result, "checks": lint_result.checks}
202
+
203
+
204
+ @app.post(
205
+ "/export",
206
+ tags=["export"],
207
+ summary="Convert data contract to a specific format.",
208
+ response_class=PlainTextResponse,
209
+ )
210
+ def export(
211
+ body: Annotated[
212
+ str,
213
+ Body(
214
+ title="Data Contract YAML",
215
+ media_type="application/yaml",
216
+ examples=[DATA_CONTRACT_EXAMPLE_PAYLOAD],
217
+ ),
218
+ ],
219
+ format: Annotated[ExportFormat, typer.Option(help="The export format.")],
220
+ server: Annotated[
221
+ str | None,
222
+ Query(
223
+ example="production",
224
+ description="The server name to export. Optional, if there is only one server.",
225
+ ),
226
+ ] = None,
227
+ model: Annotated[
228
+ str | None,
229
+ Query(
230
+ description="Use the key of the model in the data contract yaml file "
231
+ "to refer to a model, e.g., `orders`, or `all` for all "
232
+ "models (default).",
233
+ ),
234
+ ] = "all",
235
+ rdf_base: Annotated[
236
+ Optional[str],
237
+ typer.Option(help="[rdf] The base URI used to generate the RDF graph.", rich_help_panel="RDF Options"),
238
+ ] = None,
239
+ sql_server_type: Annotated[
240
+ Optional[str],
241
+ Query(
242
+ description="[sql] The server type to determine the sql dialect. By default, it uses 'auto' to automatically detect the sql dialect via the specified servers in the data contract.",
243
+ ),
244
+ ] = None,
245
+ ):
246
+ result = DataContract(data_contract_str=body, server=server).export(
247
+ export_format=format,
248
+ model=model,
249
+ rdf_base=rdf_base,
250
+ sql_server_type=sql_server_type,
251
+ )
252
+
253
+ return result