datacontract-cli 1.2.0__tar.gz → 1.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/MANIFEST.in +1 -1
- {datacontract_cli-1.2.0/datacontract_cli.egg-info → datacontract_cli-1.2.2}/PKG-INFO +45 -38
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/README.md +30 -30
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/api.py +59 -74
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/breaking/detector.py +7 -5
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/breaking/rules.py +47 -2
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/catalog/catalog.py +3 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/changelog/changelog.py +13 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/changelog/normalize.py +8 -7
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/cli.py +57 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/command_api.py +26 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/command_breaking.py +2 -8
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/command_changelog.py +2 -8
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/command_ci.py +2 -7
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/command_export.py +28 -10
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/command_import.py +49 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/command_init.py +1 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/command_lint.py +9 -8
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/command_test.py +3 -46
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/config/settings.py +59 -1
- datacontract_cli-1.2.2/datacontract/config/variables.py +256 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/data_contract.py +76 -5
- datacontract_cli-1.2.2/datacontract/editor_assets/VERSION +1 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/editor_assets/datacontract-editor.css +1 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/editor_assets/datacontract-editor.es.js +27133 -25620
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/editor_assets/index.html +9 -5
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/checks/check_spec.py +2 -2
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/checks/create_checks.py +258 -91
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/checks/dimensions.py +2 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/checks/physical_type_match.py +44 -4
- datacontract_cli-1.2.2/datacontract/engines/checks/severity.py +11 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/checks/sql_guard.py +43 -13
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/data_contract_test.py +48 -15
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/fastjsonschema/check_jsonschema.py +6 -4
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/fastjsonschema/s3/s3_read_files.py +3 -1
- datacontract_cli-1.2.2/datacontract/engines/hana/check_hana_execute.py +105 -0
- datacontract_cli-1.2.2/datacontract/engines/hana/hana_check_selection.py +76 -0
- datacontract_cli-1.2.2/datacontract/engines/hana/hana_connection.py +63 -0
- datacontract_cli-1.2.2/datacontract/engines/hana/hana_quality_check.py +742 -0
- datacontract_cli-1.2.2/datacontract/engines/hana/hana_schema_check.py +607 -0
- datacontract_cli-1.2.2/datacontract/engines/hana/hana_type_mapping.py +205 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/ibis/connections/connect.py +125 -18
- datacontract_cli-1.2.2/datacontract/engines/ibis/connections/exasol_patch.py +24 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/ibis/ibis_check_execute.py +272 -72
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/ibis/native_type.py +21 -0
- datacontract_cli-1.2.2/datacontract/export/excel_exporter.py +1119 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/great_expectations_exporter.py +58 -19
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/html_exporter.py +3 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/sodacl_check_builder.py +13 -2
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/sodacl_exporter.py +24 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/sql_type_converter.py +14 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/athena_importer.py +2 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/avro_importer.py +7 -7
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/bigquery_importer.py +1 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/csv_importer.py +20 -6
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/dbml_importer.py +3 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/dbt_importer.py +10 -8
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/dcs_importer.py +3 -1
- datacontract_cli-1.2.2/datacontract/imports/excel_importer.py +1070 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/glue_importer.py +10 -4
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/iceberg_importer.py +3 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/importer.py +1 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/importer_factory.py +5 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/jsonschema_importer.py +61 -14
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/mysql_importer.py +8 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/object_storage_importer.py +9 -2
- datacontract_cli-1.2.2/datacontract/imports/odata_importer.py +506 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/odcs_helper.py +66 -37
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/oracle_importer.py +8 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/postgres_importer.py +8 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/powerbi_importer.py +15 -6
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/protobuf_importer.py +2 -2
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/pydantic_importer.py +4 -4
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/redshift_importer.py +8 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/snowflake_importer.py +8 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/spark_importer.py +45 -40
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/spark_type_json.py +2 -2
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/sql_importer.py +62 -19
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/sqlserver_importer.py +8 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/trino_importer.py +8 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/unity_importer.py +6 -3
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/init/init_template.py +5 -3
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/integration/dbt_sync.py +54 -13
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/lint/files.py +1 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/lint/resolve.py +186 -62
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/lint/schema.py +7 -5
- datacontract_cli-1.2.2/datacontract/model/natural_keys.py +18 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/model/run.py +8 -3
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/model/server.py +0 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/model/vector_type.py +5 -1
- datacontract_cli-1.2.2/datacontract/model/workbook.py +260 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/output/test_results_writer.py +24 -20
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/output/text_breaking_results.py +9 -5
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/output/text_changelog_results.py +8 -4
- datacontract_cli-1.2.0/datacontract/templates/excel/odcs-template.xlsx → datacontract_cli-1.2.2/datacontract/templates/excel/odcs-template-v3.0.xlsx +0 -0
- datacontract_cli-1.2.2/datacontract/templates/excel/odcs-template-v3.1.xlsx +0 -0
- datacontract_cli-1.2.2/datacontract/templates/excel/odcs-template-v3.2.xlsx +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2/datacontract_cli.egg-info}/PKG-INFO +45 -38
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract_cli.egg-info/SOURCES.txt +34 -2
- datacontract_cli-1.2.2/datacontract_cli.egg-info/dependency_links.txt +1 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract_cli.egg-info/requires.txt +16 -7
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/pyproject.toml +28 -8
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_api.py +112 -17
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_breaking.py +153 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_changelog.py +53 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_changelog_normalize.py +7 -7
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_changelog_output_text.py +25 -6
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_cli.py +10 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_command_api.py +14 -0
- datacontract_cli-1.2.2/tests/test_command_api_options.py +49 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_config.py +1 -0
- datacontract_cli-1.2.2/tests/test_connect_exasol.py +117 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_connect_sqlserver.py +85 -9
- datacontract_cli-1.2.2/tests/test_create_checks_nested.py +204 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_create_checks_nested_type.py +28 -3
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_create_checks_physical_type.py +1 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_create_checks_servicelevel.py +60 -0
- datacontract_cli-1.2.2/tests/test_create_checks_sql_placeholders.py +160 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_dbt_sync.py +116 -4
- datacontract_cli-1.2.2/tests/test_export_excel.py +465 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_great_expectations.py +108 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_sodacl.py +37 -0
- datacontract_cli-1.2.2/tests/test_hana_connection.py +99 -0
- datacontract_cli-1.2.2/tests/test_hana_quality_check.py +464 -0
- datacontract_cli-1.2.2/tests/test_hana_schema_check.py +436 -0
- datacontract_cli-1.2.2/tests/test_hana_type_mapping.py +94 -0
- datacontract_cli-1.2.2/tests/test_ibis_check_execute.py +152 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_csv.py +9 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_dbt.py +10 -0
- datacontract_cli-1.2.2/tests/test_import_excel.py +124 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_iceberg.py +12 -0
- datacontract_cli-1.2.2/tests/test_import_jsonschema.py +151 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_object_storage.py +48 -1
- datacontract_cli-1.2.2/tests/test_import_odata.py +873 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_postgres.py +1 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_powerbi.py +0 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_pydantic_model.py +12 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_redshift.py +1 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_spark_type_json.py +2 -2
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_sql_oracle.py +5 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_sql_postgres.py +30 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_sql_snowflake.py +16 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_sql_sqlserver.py +2 -0
- datacontract_cli-1.2.2/tests/test_import_unmapped_types.py +94 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_install_extras.py +2 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_lint.py +54 -0
- datacontract_cli-1.2.2/tests/test_lint_files.py +10 -0
- datacontract_cli-1.2.2/tests/test_lint_schema.py +20 -0
- datacontract_cli-1.2.2/tests/test_nested_path_checks.py +102 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_physical_type_match.py +38 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_quality_sql_dialects.py +3 -3
- datacontract_cli-1.2.2/tests/test_quality_unrunnable_rules.py +240 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_resolve_definitions.py +18 -1
- datacontract_cli-1.2.2/tests/test_row_filter_duplicate_count.py +61 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_servers_3_2_0.py +3 -3
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_snowflake_structured_types.py +1 -3
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_checks_filter.py +2 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_dry_run.py +31 -0
- datacontract_cli-1.2.2/tests/test_test_hana.py +415 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_iceberg_rest.py +1 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_kafka.py +17 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_metadata_only.py +11 -11
- datacontract_cli-1.2.2/tests/test_test_nested_checks.py +154 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_parquet.py +22 -32
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_quality_percent_severity.py +12 -8
- datacontract_cli-1.2.2/tests/test_test_results_writer.py +44 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_s3_csv.py +1 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_s3_delta.py +1 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_s3_json.py +1 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_s3_json_complex.py +1 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_s3_json_multiple_models.py +1 -1
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_schema_evolution.py +6 -4
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_variables.py +60 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_untrusted_contract.py +80 -11
- datacontract_cli-1.2.2/tests/test_untrusted_contract_variables.py +209 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_vector_type.py +3 -0
- datacontract_cli-1.2.0/datacontract/config/variables.py +0 -133
- datacontract_cli-1.2.0/datacontract/editor_assets/VERSION +0 -1
- datacontract_cli-1.2.0/datacontract/export/excel_exporter.py +0 -993
- datacontract_cli-1.2.0/datacontract/imports/excel_importer.py +0 -1134
- datacontract_cli-1.2.0/datacontract/schemas/odcs-3.0.1.schema.json +0 -2634
- datacontract_cli-1.2.0/tests/test_create_checks_sql_placeholders.py +0 -44
- datacontract_cli-1.2.0/tests/test_export_excel.py +0 -164
- datacontract_cli-1.2.0/tests/test_import_excel.py +0 -49
- datacontract_cli-1.2.0/tests/test_import_jsonschema.py +0 -78
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/LICENSE +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/__init__.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/breaking/__init__.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/changelog/__init__.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/command_catalog.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/command_dbt.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/command_edit.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/command_publish.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/config/__init__.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/config/cli_context.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/editor_assets/assets/editor.worker-4.7.0.js +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/editor_assets/assets/yaml.worker-4.7.0.js +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/editor_assets/logo_fuchsia_v2.svg +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/editor_assets/monaco-4.7.0.js +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/editor_assets/odcs.svg +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/editor_assets/robots.txt +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/editor_assets/rolldown-runtime-DY7j01NX.js +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/editor_assets/sitemap.xml +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/__init__.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/checks/__init__.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/checks/check_filter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/checks/type_normalize.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/datacontract/check_azure_blob_file.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/datacontract/check_that_datacontract_contains_valid_servers_configuration.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/datacontract/check_that_datacontract_file_exists.py +0 -0
- /datacontract_cli-1.2.0/datacontract_cli.egg-info/dependency_links.txt → /datacontract_cli-1.2.2/datacontract/engines/hana/__init__.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/ibis/__init__.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/ibis/connections/__init__.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/ibis/connections/aws_credentials.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/ibis/connections/databricks_patch.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/ibis/connections/duckdb_connection.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/ibis/connections/iceberg.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/ibis/connections/kafka.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/ibis/connections/oracle_patch.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/ibis/connections/redshift_credentials.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/ibis/connections/redshift_patch.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/ibis/dtype_category.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/engines/ibis/snowflake_structured_types.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/__init__.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/avro_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/avro_idl_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/bigquery_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/custom_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/data_caterer_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/dbml_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/dbt_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/dcs_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/dqx_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/duckdb_type_converter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/exporter_factory.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/go_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/iceberg_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/jsonschema_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/markdown_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/mermaid_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/odcs_v3_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/pandas_type_converter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/protobuf_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/pydantic_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/rdf_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/spark_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/sql_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/export/sqlalchemy_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/json_importer.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/odcs_importer.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/imports/parquet_importer.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/integration/dbt_test_mapping.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/integration/entropy_data.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/lint/constraints.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/lint/resources.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/lint/s3.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/lint/urls.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/model/breaking.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/model/changelog.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/model/enum_values.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/model/exceptions.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/model/map_type.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/model/odcs.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/output/__init__.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/output/ci_output.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/output/json_test_results.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/output/junit_test_results.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/output/output_format.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/py.typed +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/schemas/datacontract-1.1.0.init.yaml +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/schemas/datacontract-1.1.0.schema.json +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/schemas/datacontract-1.2.0.init.yaml +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/schemas/datacontract-1.2.0.schema.json +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/schemas/datacontract-1.2.1.init.yaml +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/schemas/datacontract-1.2.1.schema.json +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/schemas/odcs-3.0.2.schema.json +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/schemas/odcs-3.1.0.schema.json +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/schemas/odcs-3.2.0.init.yaml +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/schemas/odcs-3.2.0.schema.json +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/datacontract.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/datacontract_odcs.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/index.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/macros/authoritative_definitions.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/macros/context.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/macros/schema.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/macros/server.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/macros/support.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials/datacontract_information.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials/datacontract_servicelevels.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials/datacontract_terms.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials/definition.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials/example.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials/model_field.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials/quality.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials/server.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials_odcs/context.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials_odcs/custom_properties.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials_odcs/diagram.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials_odcs/dialog_yaml.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials_odcs/footer.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials_odcs/fundamentals.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials_odcs/header.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials_odcs/pricing.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials_odcs/roles.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials_odcs/schema.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials_odcs/servers.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials_odcs/sla.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials_odcs/support.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials_odcs/team.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials_odcs/term_of_use.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/partials_odcs/title.html +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract/templates/style/output.css +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract_cli.egg-info/entry_points.txt +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/datacontract_cli.egg-info/top_level.txt +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/setup.cfg +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_api_openapi.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_breaking_odcs_3_2.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_catalog.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_changelog_engine.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_check_quality_provenance.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_ci_output.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_config_file.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_config_require.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_config_threading.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_connect_athena.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_connect_bigquery.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_connect_databricks.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_connect_impala.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_connect_mysql.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_connect_oracle.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_connect_postgres.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_connect_redshift.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_connect_s3_credentials.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_connect_snowflake.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_connect_trino.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_create_checks_array_items.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_create_checks_primary_key.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_create_checks_retention_period.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_data_contract.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_data_contract_checks.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_data_contract_specification.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_dbt_test_mapping.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_description_linter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_docs_commands.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_docs_config_options.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_docs_ordering.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_download_datacontract_file.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_dtype_category.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_duckdb_json.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_edit.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_enum_values.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_avro.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_avro_idl.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_bigquery.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_complex_data_contract.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_custom.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_custom_exporter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_custom_model.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_data_caterer.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_dbml.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_dbt_models.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_dbt_sources.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_dbt_staging_sql.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_dcs.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_dqx.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_go.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_html.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_iceberg.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_jsonschema.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_large_contract.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_markdown.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_mermaid.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_odcs_v3.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_protobuf.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_pydantic.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_rdf.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_spark.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_sql.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_sql_clickhouse.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_sql_query.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_export_sqlalchemy.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_ibis_mssql_pattern.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_ibis_mssql_schema.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_ibis_oracle_schema.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_athena.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_avro.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_bigquery.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_dbml.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_glue.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_json.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_mysql.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_odcs_v3.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_oracle.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_parquet.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_protobuf.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_snowflake.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_sqlserver.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_trino.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_import_unity_file.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_integration_entropydata.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_lint_odcs_3_2_constraints.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_lint_urls.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_map_type.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_metadata_fields.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_native_type_schema_scope.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_oracle_patch.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_publish_test_results.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_publish_test_results_payload.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_redshift_credentials.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_redshift_patch.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_resolve.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_resolve_local_definitions.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_roundtrip_jsonschema.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_roundtrip_pydantic_model.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_run_check_deprecated_fields.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_run_check_engine.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_server_overrides.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_server_type_mssql.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_server_type_synonyms.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_sql_type_converter_physicaltype.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_api.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_array_items.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_athena_iceberg.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_azure_blob_file.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_azure_remote.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_bigquery.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_databricks.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_delta.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_diagnostics.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_dimension_filter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_duckdb.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_failed_samples.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_gcs_csv_remote.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_gcs_json_remote.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_iceberg.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_iceberg_s3tables.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_kafka_decoding.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_kafka_remote.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_local_json.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_local_json_nd.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_mysql.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_oracle.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_oracle_xe.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_output_json.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_output_junit.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_postgres.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_quality.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_quality_id_and_tag_filter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_quality_local_fallback.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_redshift.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_row_filter.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_s3_json_remote.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_server_not_found.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_snowflake.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_soda_connection_error.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_sqlserver.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_test_trino.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_type_normalize.py +0 -0
- {datacontract_cli-1.2.0 → datacontract_cli-1.2.2}/tests/test_variables.py +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
include datacontract/templates/style/output.css
|
|
2
|
-
include datacontract/templates/excel
|
|
2
|
+
include datacontract/templates/excel/*.xlsx
|
|
3
3
|
recursive-include datacontract/templates/ **/*.html
|
|
4
4
|
recursive-include datacontract/schemas/ **/*.json **/*.yaml
|
|
5
5
|
recursive-include datacontract/editor_assets/ *
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: datacontract-cli
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.2
|
|
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
|
|
@@ -53,7 +53,7 @@ Requires-Dist: avro==1.12.2; extra == "avro"
|
|
|
53
53
|
Provides-Extra: bigquery
|
|
54
54
|
Requires-Dist: ibis-framework[bigquery]<13.0.0,>=10.0.0; extra == "bigquery"
|
|
55
55
|
Provides-Extra: csv
|
|
56
|
-
Requires-Dist:
|
|
56
|
+
Requires-Dist: datacontract-cli[duckdb]; extra == "csv"
|
|
57
57
|
Provides-Extra: excel
|
|
58
58
|
Requires-Dist: openpyxl<4.0.0,>=3.1.5; extra == "excel"
|
|
59
59
|
Provides-Extra: dataframe
|
|
@@ -66,8 +66,8 @@ Requires-Dist: pyarrow-hotfix>=0.4; extra == "dataframe"
|
|
|
66
66
|
Requires-Dist: rich>=12.4.4; extra == "dataframe"
|
|
67
67
|
Provides-Extra: databricks
|
|
68
68
|
Requires-Dist: ibis-framework[databricks]<13.0.0,>=10.0.0; extra == "databricks"
|
|
69
|
-
Requires-Dist: databricks-sql-connector<4.
|
|
70
|
-
Requires-Dist: databricks-sdk<0.
|
|
69
|
+
Requires-Dist: databricks-sql-connector<4.6.0,>=3.7.0; extra == "databricks"
|
|
70
|
+
Requires-Dist: databricks-sdk<0.140.0; extra == "databricks"
|
|
71
71
|
Requires-Dist: packaging<27.0,>=21.3; extra == "databricks"
|
|
72
72
|
Provides-Extra: databricks-runtime
|
|
73
73
|
Requires-Dist: datacontract-cli[databricks]; extra == "databricks-runtime"
|
|
@@ -112,6 +112,13 @@ Requires-Dist: packaging<27.0,>=21.3; extra == "oracle"
|
|
|
112
112
|
Provides-Extra: athena
|
|
113
113
|
Requires-Dist: ibis-framework[athena]<13.0.0,>=10.0.0; extra == "athena"
|
|
114
114
|
Requires-Dist: packaging<27.0,>=21.3; extra == "athena"
|
|
115
|
+
Provides-Extra: hana
|
|
116
|
+
Requires-Dist: hdbcli<3.0.0,>=2.20.0; extra == "hana"
|
|
117
|
+
Provides-Extra: exasol
|
|
118
|
+
Requires-Dist: ibis-framework[exasol]<13.0.0,>=10.0.0; extra == "exasol"
|
|
119
|
+
Requires-Dist: pyexasol>=1.1.0; extra == "exasol"
|
|
120
|
+
Requires-Dist: packaging<27.0,>=21.3; extra == "exasol"
|
|
121
|
+
Requires-Dist: sqlglot>=26.31.0; extra == "exasol"
|
|
115
122
|
Provides-Extra: trino
|
|
116
123
|
Requires-Dist: ibis-framework[trino]<13.0.0,>=10.0.0; extra == "trino"
|
|
117
124
|
Requires-Dist: packaging<27.0,>=21.3; extra == "trino"
|
|
@@ -129,11 +136,11 @@ Provides-Extra: rdf
|
|
|
129
136
|
Requires-Dist: rdflib==7.6.0; extra == "rdf"
|
|
130
137
|
Provides-Extra: api
|
|
131
138
|
Requires-Dist: fastapi<0.142.0,>=0.115.0; extra == "api"
|
|
132
|
-
Requires-Dist: uvicorn<0.
|
|
139
|
+
Requires-Dist: uvicorn<0.54.0,>=0.44.0; extra == "api"
|
|
133
140
|
Provides-Extra: protobuf
|
|
134
141
|
Requires-Dist: proto-schema-parser<3.0,>=1.0; extra == "protobuf"
|
|
135
142
|
Provides-Extra: all
|
|
136
|
-
Requires-Dist: datacontract-cli[api,athena,avro,azure,bigquery,csv,databricks,dataframe,dbml,duckdb,excel,gcs,iceberg,impala,kafka,mysql,oracle,parquet,postgres,protobuf,rdf,redshift,s3,snowflake,sqlserver,trino]; extra == "all"
|
|
143
|
+
Requires-Dist: datacontract-cli[api,athena,avro,azure,bigquery,csv,databricks,dataframe,dbml,duckdb,exasol,excel,gcs,iceberg,impala,kafka,mysql,oracle,parquet,postgres,protobuf,rdf,redshift,s3,snowflake,sqlserver,trino]; extra == "all"
|
|
137
144
|
Provides-Extra: dev
|
|
138
145
|
Requires-Dist: datacontract-cli[all]; extra == "dev"
|
|
139
146
|
Requires-Dist: httpx==0.28.1; extra == "dev"
|
|
@@ -146,10 +153,10 @@ Requires-Dist: pre-commit<4.7.0,>=3.7.1; extra == "dev"
|
|
|
146
153
|
Requires-Dist: pytest; extra == "dev"
|
|
147
154
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
148
155
|
Requires-Dist: pytest-xdist; extra == "dev"
|
|
149
|
-
Requires-Dist: pymssql==2.4.
|
|
156
|
+
Requires-Dist: pymssql==2.4.1; extra == "dev"
|
|
150
157
|
Requires-Dist: psycopg2-binary<3.0,>=2.9; extra == "dev"
|
|
151
158
|
Requires-Dist: mysql-connector-python<26.8.0,>=8.0.30; extra == "dev"
|
|
152
|
-
Requires-Dist: ruff==0.16.
|
|
159
|
+
Requires-Dist: ruff==0.16.8; extra == "dev"
|
|
153
160
|
Requires-Dist: testcontainers[kafka,minio,mssql,mysql,postgres]==4.15.0; extra == "dev"
|
|
154
161
|
Requires-Dist: trino==0.339.0; extra == "dev"
|
|
155
162
|
Dynamic: license-file
|
|
@@ -412,7 +419,7 @@ Released images are signed with [cosign](https://docs.sigstore.dev/cosign/signin
|
|
|
412
419
|
## Optional Dependencies (Extras)
|
|
413
420
|
|
|
414
421
|
The CLI tool defines several optional dependencies (also known as extras) that can be installed for using with specific servers types.
|
|
415
|
-
With _all_, all server dependencies are included.
|
|
422
|
+
With _all_, all server dependencies except `hana` are included.
|
|
416
423
|
|
|
417
424
|
```bash
|
|
418
425
|
uv tool install --python python3.11 --upgrade 'datacontract-cli[all]'
|
|
@@ -420,35 +427,35 @@ uv tool install --python python3.11 --upgrade 'datacontract-cli[all]'
|
|
|
420
427
|
|
|
421
428
|
A list of available extras:
|
|
422
429
|
|
|
423
|
-
| Dependency
|
|
424
|
-
|
|
425
|
-
|
|
|
426
|
-
|
|
|
427
|
-
|
|
|
428
|
-
|
|
|
429
|
-
|
|
|
430
|
-
| Databricks
|
|
431
|
-
|
|
|
432
|
-
|
|
|
433
|
-
|
|
|
434
|
-
|
|
|
435
|
-
| Excel
|
|
436
|
-
| GCS
|
|
437
|
-
|
|
|
438
|
-
|
|
|
439
|
-
|
|
|
440
|
-
|
|
|
441
|
-
|
|
|
442
|
-
|
|
|
443
|
-
|
|
|
444
|
-
|
|
|
445
|
-
|
|
|
446
|
-
|
|
|
447
|
-
|
|
|
448
|
-
|
|
|
449
|
-
|
|
|
450
|
-
|
|
|
451
|
-
|
|
|
430
|
+
| Dependency | Installation command |
|
|
431
|
+
|---|---|
|
|
432
|
+
| API (run as web server) | `pip install datacontract-cli[api]` |
|
|
433
|
+
| Amazon Athena | `pip install datacontract-cli[athena]` |
|
|
434
|
+
| Avro | `pip install datacontract-cli[avro]` |
|
|
435
|
+
| Azure | `pip install datacontract-cli[azure]` |
|
|
436
|
+
| Google BigQuery | `pip install datacontract-cli[bigquery]` |
|
|
437
|
+
| Databricks | `pip install datacontract-cli[databricks]` (also inside a Databricks Runtime, using the cluster's own Spark session) |
|
|
438
|
+
| DataFrame (Spark) | `pip install datacontract-cli[dataframe]` (PySpark not included — you supply the Spark session) |
|
|
439
|
+
| DBML | `pip install datacontract-cli[dbml]` |
|
|
440
|
+
| DuckDB (local file, CSV import and API response testing) | `pip install datacontract-cli[duckdb]` |
|
|
441
|
+
| Exasol | `pip install datacontract-cli[exasol]` |
|
|
442
|
+
| Excel | `pip install datacontract-cli[excel]` |
|
|
443
|
+
| GCS | `pip install datacontract-cli[gcs]` |
|
|
444
|
+
| SAP HANA / Datasphere | `pip install datacontract-cli[hana]` (not part of `all`: `hdbcli` is proprietary) |
|
|
445
|
+
| Apache Iceberg (schema import and export, REST catalog testing) | `pip install datacontract-cli[iceberg]` |
|
|
446
|
+
| Impala | `pip install datacontract-cli[impala]` |
|
|
447
|
+
| Kafka | `pip install datacontract-cli[kafka]` |
|
|
448
|
+
| MySQL | `pip install datacontract-cli[mysql]` |
|
|
449
|
+
| Oracle | `pip install datacontract-cli[oracle]` |
|
|
450
|
+
| Parquet | `pip install datacontract-cli[parquet]` |
|
|
451
|
+
| PostgreSQL | `pip install datacontract-cli[postgres]` |
|
|
452
|
+
| Protobuf | `pip install datacontract-cli[protobuf]` |
|
|
453
|
+
| RDF | `pip install datacontract-cli[rdf]` |
|
|
454
|
+
| Amazon Redshift | `pip install datacontract-cli[redshift]` |
|
|
455
|
+
| S3 | `pip install datacontract-cli[s3]` |
|
|
456
|
+
| Snowflake | `pip install datacontract-cli[snowflake]` |
|
|
457
|
+
| Microsoft SQL Server | `pip install datacontract-cli[sqlserver]` |
|
|
458
|
+
| Trino | `pip install datacontract-cli[trino]` |
|
|
452
459
|
|
|
453
460
|
|
|
454
461
|
## Documentation
|
|
@@ -256,7 +256,7 @@ Released images are signed with [cosign](https://docs.sigstore.dev/cosign/signin
|
|
|
256
256
|
## Optional Dependencies (Extras)
|
|
257
257
|
|
|
258
258
|
The CLI tool defines several optional dependencies (also known as extras) that can be installed for using with specific servers types.
|
|
259
|
-
With _all_, all server dependencies are included.
|
|
259
|
+
With _all_, all server dependencies except `hana` are included.
|
|
260
260
|
|
|
261
261
|
```bash
|
|
262
262
|
uv tool install --python python3.11 --upgrade 'datacontract-cli[all]'
|
|
@@ -264,35 +264,35 @@ uv tool install --python python3.11 --upgrade 'datacontract-cli[all]'
|
|
|
264
264
|
|
|
265
265
|
A list of available extras:
|
|
266
266
|
|
|
267
|
-
| Dependency
|
|
268
|
-
|
|
269
|
-
|
|
|
270
|
-
|
|
|
271
|
-
|
|
|
272
|
-
|
|
|
273
|
-
|
|
|
274
|
-
| Databricks
|
|
275
|
-
|
|
|
276
|
-
|
|
|
277
|
-
|
|
|
278
|
-
|
|
|
279
|
-
| Excel
|
|
280
|
-
| GCS
|
|
281
|
-
|
|
|
282
|
-
|
|
|
283
|
-
|
|
|
284
|
-
|
|
|
285
|
-
|
|
|
286
|
-
|
|
|
287
|
-
|
|
|
288
|
-
|
|
|
289
|
-
|
|
|
290
|
-
|
|
|
291
|
-
|
|
|
292
|
-
|
|
|
293
|
-
|
|
|
294
|
-
|
|
|
295
|
-
|
|
|
267
|
+
| Dependency | Installation command |
|
|
268
|
+
|---|---|
|
|
269
|
+
| API (run as web server) | `pip install datacontract-cli[api]` |
|
|
270
|
+
| Amazon Athena | `pip install datacontract-cli[athena]` |
|
|
271
|
+
| Avro | `pip install datacontract-cli[avro]` |
|
|
272
|
+
| Azure | `pip install datacontract-cli[azure]` |
|
|
273
|
+
| Google BigQuery | `pip install datacontract-cli[bigquery]` |
|
|
274
|
+
| Databricks | `pip install datacontract-cli[databricks]` (also inside a Databricks Runtime, using the cluster's own Spark session) |
|
|
275
|
+
| DataFrame (Spark) | `pip install datacontract-cli[dataframe]` (PySpark not included — you supply the Spark session) |
|
|
276
|
+
| DBML | `pip install datacontract-cli[dbml]` |
|
|
277
|
+
| DuckDB (local file, CSV import and API response testing) | `pip install datacontract-cli[duckdb]` |
|
|
278
|
+
| Exasol | `pip install datacontract-cli[exasol]` |
|
|
279
|
+
| Excel | `pip install datacontract-cli[excel]` |
|
|
280
|
+
| GCS | `pip install datacontract-cli[gcs]` |
|
|
281
|
+
| SAP HANA / Datasphere | `pip install datacontract-cli[hana]` (not part of `all`: `hdbcli` is proprietary) |
|
|
282
|
+
| Apache Iceberg (schema import and export, REST catalog testing) | `pip install datacontract-cli[iceberg]` |
|
|
283
|
+
| Impala | `pip install datacontract-cli[impala]` |
|
|
284
|
+
| Kafka | `pip install datacontract-cli[kafka]` |
|
|
285
|
+
| MySQL | `pip install datacontract-cli[mysql]` |
|
|
286
|
+
| Oracle | `pip install datacontract-cli[oracle]` |
|
|
287
|
+
| Parquet | `pip install datacontract-cli[parquet]` |
|
|
288
|
+
| PostgreSQL | `pip install datacontract-cli[postgres]` |
|
|
289
|
+
| Protobuf | `pip install datacontract-cli[protobuf]` |
|
|
290
|
+
| RDF | `pip install datacontract-cli[rdf]` |
|
|
291
|
+
| Amazon Redshift | `pip install datacontract-cli[redshift]` |
|
|
292
|
+
| S3 | `pip install datacontract-cli[s3]` |
|
|
293
|
+
| Snowflake | `pip install datacontract-cli[snowflake]` |
|
|
294
|
+
| Microsoft SQL Server | `pip install datacontract-cli[sqlserver]` |
|
|
295
|
+
| Trino | `pip install datacontract-cli[trino]` |
|
|
296
296
|
|
|
297
297
|
|
|
298
298
|
## Documentation
|
|
@@ -2,24 +2,25 @@ import json
|
|
|
2
2
|
import logging
|
|
3
3
|
import os
|
|
4
4
|
import secrets
|
|
5
|
-
import tempfile
|
|
6
5
|
from importlib import metadata
|
|
7
6
|
from typing import Annotated, Optional
|
|
8
7
|
|
|
9
8
|
import pydantic
|
|
10
|
-
import yaml
|
|
11
9
|
from fastapi import Body, Depends, FastAPI, HTTPException, Query, Request, status
|
|
12
|
-
from fastapi.responses import PlainTextResponse
|
|
10
|
+
from fastapi.responses import JSONResponse, PlainTextResponse
|
|
13
11
|
from fastapi.security.api_key import APIKeyHeader
|
|
14
12
|
from pydantic import BaseModel, Field, ValidationError
|
|
15
13
|
|
|
16
14
|
from datacontract.config import Config, known_env_names
|
|
15
|
+
from datacontract.config.variables import CONTRACT_VARIABLES_ENV, allowed_environment, resolve_variables
|
|
17
16
|
from datacontract.data_contract import DataContract, ExportFormat
|
|
18
17
|
from datacontract.model.breaking import BreakingChangeEntry
|
|
19
18
|
from datacontract.model.changelog import ChangelogEntry
|
|
20
19
|
from datacontract.model.exceptions import DataContractException, DefinitionResolutionError
|
|
21
20
|
from datacontract.model.run import Check, ResultEnum, Run
|
|
22
21
|
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
23
24
|
DATA_CONTRACT_EXAMPLE_PAYLOAD = """apiVersion: v3.2.0
|
|
24
25
|
kind: DataContract
|
|
25
26
|
id: orders
|
|
@@ -335,6 +336,25 @@ app = FastAPI(
|
|
|
335
336
|
],
|
|
336
337
|
)
|
|
337
338
|
|
|
339
|
+
|
|
340
|
+
@app.exception_handler(pydantic.ValidationError)
|
|
341
|
+
def _validation_error(request: Request, e: pydantic.ValidationError):
|
|
342
|
+
return JSONResponse(status_code=422, content={"detail": f"Invalid data contract: {e}"})
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
@app.exception_handler(DataContractException)
|
|
346
|
+
def _data_contract_exception(request: Request, e: DataContractException):
|
|
347
|
+
return JSONResponse(status_code=422, content={"detail": f"Data Contract Validation Failure: {e}"})
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
@app.exception_handler(DefinitionResolutionError)
|
|
351
|
+
def _definition_resolution_error(request: Request, e: DefinitionResolutionError):
|
|
352
|
+
# The reason names the host that was contacted and what it answered.
|
|
353
|
+
# Omit for security reasons.
|
|
354
|
+
logger.warning("Definition resolution failed: %s", e)
|
|
355
|
+
return JSONResponse(status_code=422, content={"detail": f"Could not resolve authoritative definition '{e.url}'."})
|
|
356
|
+
|
|
357
|
+
|
|
338
358
|
_fastapi_openapi = app.openapi
|
|
339
359
|
|
|
340
360
|
|
|
@@ -481,6 +501,7 @@ _ENVIRONMENT_CREDENTIAL_TARGETS: dict[str, tuple[str, str | None, tuple[str, ...
|
|
|
481
501
|
"oracle": ("host", "oracle_host", ("oracle_password",)),
|
|
482
502
|
"impala": ("host", "impala_host", ("impala_password",)),
|
|
483
503
|
"trino": ("host", "trino_host", ("trino_password",)),
|
|
504
|
+
"exasol": ("host", "exasol_host", ("exasol_password",)),
|
|
484
505
|
"redshift": ("host", "redshift_host", ("redshift_password",)),
|
|
485
506
|
"sqlserver": ("host", "sqlserver_host", ("sqlserver_password",)),
|
|
486
507
|
"snowflake": (
|
|
@@ -507,7 +528,10 @@ def _selected_server(body: str, server_name: str | None, config):
|
|
|
507
528
|
|
|
508
529
|
try:
|
|
509
530
|
data_contract = resolve.resolve_data_contract(data_contract_str=body, config=config)
|
|
510
|
-
|
|
531
|
+
server = get_server(data_contract, server_name)
|
|
532
|
+
# Guard the server type the test will run against, not a ${VAR:-local} reference to it.
|
|
533
|
+
variables = allowed_environment(_allowed_contract_variables())
|
|
534
|
+
return server and server.model_copy(update={"type": resolve_variables(server.type, variables=variables)})
|
|
511
535
|
except Exception:
|
|
512
536
|
return None
|
|
513
537
|
|
|
@@ -520,6 +544,11 @@ ALLOW_LOCAL_FILES_ENV = "DATACONTRACT_CLI_API_ALLOW_LOCAL_FILES"
|
|
|
520
544
|
_TRUTHY = frozenset({"1", "true", "yes", "on"})
|
|
521
545
|
|
|
522
546
|
|
|
547
|
+
def _allowed_contract_variables() -> list[str]:
|
|
548
|
+
"""The variable-name globs a posted contract may resolve; none by default."""
|
|
549
|
+
return (os.getenv(CONTRACT_VARIABLES_ENV) or "").split(",")
|
|
550
|
+
|
|
551
|
+
|
|
523
552
|
def _local_files_allowed() -> bool:
|
|
524
553
|
"""Whether the operator opted in to serving data from the server's own disk.
|
|
525
554
|
|
|
@@ -549,7 +578,7 @@ def _reject_local_server_type(body: str, server_name: str | None, config) -> Non
|
|
|
549
578
|
detail=(
|
|
550
579
|
f"Server type '{server.type}' reads from the file system of the server running this API, "
|
|
551
580
|
f"so it is refused. Use a server type that names a data source, such as s3, gcs, azure, "
|
|
552
|
-
f"postgres, or snowflake — or
|
|
581
|
+
f"postgres, or snowflake — or start the API server with --allow-local-files if this deployment serves "
|
|
553
582
|
f"its own files on purpose."
|
|
554
583
|
),
|
|
555
584
|
)
|
|
@@ -665,21 +694,21 @@ def _reject_request_platform_host_with_environment_key(config) -> None:
|
|
|
665
694
|
def check_api_key(api_key_header: str | None):
|
|
666
695
|
correct_api_key = os.getenv("DATACONTRACT_CLI_API_KEY")
|
|
667
696
|
if correct_api_key is None or correct_api_key == "":
|
|
668
|
-
|
|
697
|
+
logger.info("Environment variable DATACONTRACT_CLI_API_KEY is not set. Skip API key check.")
|
|
669
698
|
return
|
|
670
699
|
if api_key_header is None or api_key_header == "":
|
|
671
|
-
|
|
700
|
+
logger.warning("The API key is missing.")
|
|
672
701
|
raise HTTPException(
|
|
673
702
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
674
703
|
detail="Missing API key. Use Header 'x-api-key' to provide the API key.",
|
|
675
704
|
)
|
|
676
|
-
if not secrets.compare_digest(api_key_header, correct_api_key):
|
|
677
|
-
|
|
705
|
+
if not secrets.compare_digest(api_key_header.encode(), correct_api_key.encode()):
|
|
706
|
+
logger.warning("The provided API key is not correct.")
|
|
678
707
|
raise HTTPException(
|
|
679
708
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
680
709
|
detail="The provided API key is not correct.",
|
|
681
710
|
)
|
|
682
|
-
|
|
711
|
+
logger.info("Request authenticated with API key.")
|
|
683
712
|
pass
|
|
684
713
|
|
|
685
714
|
|
|
@@ -777,8 +806,7 @@ async def test(
|
|
|
777
806
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
778
807
|
detail="Use either the filter or the filters parameter, not both.",
|
|
779
808
|
)
|
|
780
|
-
|
|
781
|
-
logging.info(body)
|
|
809
|
+
logger.info("Testing data contract...")
|
|
782
810
|
config = config_from_headers(request.headers)
|
|
783
811
|
untrusted_contract = getattr(request.app.state, "untrusted_contracts", False)
|
|
784
812
|
if untrusted_contract:
|
|
@@ -795,6 +823,7 @@ async def test(
|
|
|
795
823
|
filter=filter,
|
|
796
824
|
filters=parsed_filters,
|
|
797
825
|
untrusted_contract=untrusted_contract,
|
|
826
|
+
allowed_variables=_allowed_contract_variables(),
|
|
798
827
|
).test()
|
|
799
828
|
|
|
800
829
|
|
|
@@ -857,7 +886,10 @@ async def lint(
|
|
|
857
886
|
) -> LintResponse:
|
|
858
887
|
check_api_key(api_key)
|
|
859
888
|
data_contract = DataContract(
|
|
860
|
-
data_contract_str=body,
|
|
889
|
+
data_contract_str=body,
|
|
890
|
+
schema_location=_require_schema_url(schema),
|
|
891
|
+
all_errors=all_errors,
|
|
892
|
+
untrusted_contract=True,
|
|
861
893
|
)
|
|
862
894
|
lint_result = data_contract.lint()
|
|
863
895
|
return LintResponse(result=lint_result.result, checks=lint_result.checks)
|
|
@@ -933,30 +965,10 @@ async def changelog_endpoint(
|
|
|
933
965
|
) -> ChangelogResponse:
|
|
934
966
|
check_api_key(api_key)
|
|
935
967
|
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
f2.write(body.v2)
|
|
941
|
-
v2_path = f2.name
|
|
942
|
-
|
|
943
|
-
try:
|
|
944
|
-
result = DataContract(data_contract_file=v1_path).changelog(DataContract(data_contract_file=v2_path))
|
|
945
|
-
return ChangelogResponse(summary=result.summary, entries=result.entries)
|
|
946
|
-
except yaml.YAMLError as e:
|
|
947
|
-
raise HTTPException(status_code=422, detail=f"Invalid YAML: {e}")
|
|
948
|
-
except pydantic.ValidationError as e:
|
|
949
|
-
raise HTTPException(status_code=422, detail=f"Invalid data contract: {e}")
|
|
950
|
-
except DefinitionResolutionError as e:
|
|
951
|
-
# The reason names the host that was contacted and what it answered.
|
|
952
|
-
# Omit for security reasons.
|
|
953
|
-
logging.warning("Definition resolution failed: %s", e)
|
|
954
|
-
raise HTTPException(status_code=422, detail=f"Could not resolve authoritative definition '{e.url}'.")
|
|
955
|
-
except DataContractException as e:
|
|
956
|
-
raise HTTPException(status_code=422, detail=f"Data Contract Validation Failure: {e}")
|
|
957
|
-
finally:
|
|
958
|
-
os.unlink(v1_path)
|
|
959
|
-
os.unlink(v2_path)
|
|
968
|
+
result = DataContract(data_contract_str=body.v1, untrusted_contract=True).changelog(
|
|
969
|
+
DataContract(data_contract_str=body.v2, untrusted_contract=True)
|
|
970
|
+
)
|
|
971
|
+
return ChangelogResponse(summary=result.summary, entries=result.entries)
|
|
960
972
|
|
|
961
973
|
|
|
962
974
|
@app.post(
|
|
@@ -986,25 +998,10 @@ def breaking_endpoint(
|
|
|
986
998
|
) -> BreakingChangesResponse:
|
|
987
999
|
check_api_key(api_key)
|
|
988
1000
|
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
f2.write(body.v2)
|
|
994
|
-
v2_path = f2.name
|
|
995
|
-
|
|
996
|
-
try:
|
|
997
|
-
result = DataContract(data_contract_file=v1_path).breaking(DataContract(data_contract_file=v2_path))
|
|
998
|
-
return BreakingChangesResponse(summary=result.summary, entries=result.entries, is_breaking=result.is_breaking)
|
|
999
|
-
except yaml.YAMLError as e:
|
|
1000
|
-
raise HTTPException(status_code=422, detail=f"Invalid YAML: {e}")
|
|
1001
|
-
except pydantic.ValidationError as e:
|
|
1002
|
-
raise HTTPException(status_code=422, detail=f"Invalid data contract: {e}")
|
|
1003
|
-
except DataContractException as e:
|
|
1004
|
-
raise HTTPException(status_code=422, detail=f"Data Contract Validation Failure: {e}")
|
|
1005
|
-
finally:
|
|
1006
|
-
os.unlink(v1_path)
|
|
1007
|
-
os.unlink(v2_path)
|
|
1001
|
+
result = DataContract(data_contract_str=body.v1, untrusted_contract=True).breaking(
|
|
1002
|
+
DataContract(data_contract_str=body.v2, untrusted_contract=True)
|
|
1003
|
+
)
|
|
1004
|
+
return BreakingChangesResponse(summary=result.summary, entries=result.entries, is_breaking=result.is_breaking)
|
|
1008
1005
|
|
|
1009
1006
|
|
|
1010
1007
|
@app.post(
|
|
@@ -1107,21 +1104,9 @@ def export(
|
|
|
1107
1104
|
] = None,
|
|
1108
1105
|
):
|
|
1109
1106
|
check_api_key(api_key)
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
)
|
|
1117
|
-
except yaml.YAMLError as e:
|
|
1118
|
-
raise HTTPException(status_code=422, detail=f"Invalid YAML: {e}")
|
|
1119
|
-
except pydantic.ValidationError as e:
|
|
1120
|
-
raise HTTPException(status_code=422, detail=f"Invalid data contract: {e}")
|
|
1121
|
-
except DefinitionResolutionError as e:
|
|
1122
|
-
# The reason names the host that was contacted and what it answered.
|
|
1123
|
-
# Omit for security reasons.
|
|
1124
|
-
logging.warning("Definition resolution failed: %s", e)
|
|
1125
|
-
raise HTTPException(status_code=422, detail=f"Could not resolve authoritative definition '{e.url}'.")
|
|
1126
|
-
except DataContractException as e:
|
|
1127
|
-
raise HTTPException(status_code=422, detail=f"Data Contract Validation Failure: {e}")
|
|
1107
|
+
return DataContract(data_contract_str=body, server=server, untrusted_contract=True).export(
|
|
1108
|
+
export_format=format,
|
|
1109
|
+
model=model,
|
|
1110
|
+
rdf_base=rdf_base,
|
|
1111
|
+
sql_server_type=sql_server_type,
|
|
1112
|
+
)
|
|
@@ -22,14 +22,16 @@ class BreakingChangeDetector:
|
|
|
22
22
|
|
|
23
23
|
def detect(self, changelog: ChangelogResult) -> BreakingChangeResult:
|
|
24
24
|
entries = [self._classify(entry) for entry in changelog.entries]
|
|
25
|
-
# Nothing inside
|
|
26
|
-
|
|
25
|
+
# Nothing inside an added element can break a consumer: it did not exist before.
|
|
26
|
+
# Inside a removed one, the element's own entry carries the grade; its former
|
|
27
|
+
# constraints are gone, which is a relaxation.
|
|
28
|
+
added_or_removed = {
|
|
27
29
|
entry.path
|
|
28
30
|
for entry in entries
|
|
29
|
-
if entry.change_type
|
|
31
|
+
if entry.change_type in (ChangelogType.added, ChangelogType.removed)
|
|
30
32
|
and (
|
|
31
33
|
entry.path.startswith("schema.")
|
|
32
|
-
and (len(entry.path.split(".")) == 2 or entry.path.split(".")[-2]
|
|
34
|
+
and (len(entry.path.split(".")) == 2 or entry.path.split(".")[-2] in ("properties", "quality"))
|
|
33
35
|
)
|
|
34
36
|
}
|
|
35
37
|
removed_enums = {
|
|
@@ -46,7 +48,7 @@ class BreakingChangeDetector:
|
|
|
46
48
|
added_values[entry.path.rsplit(".enum.", 1)[0]].add(entry.new_value)
|
|
47
49
|
for entry in entries:
|
|
48
50
|
segments = entry.path.split(".")
|
|
49
|
-
if any(".".join(segments[:i]) in
|
|
51
|
+
if any(".".join(segments[:i]) in added_or_removed for i in range(1, len(segments))):
|
|
50
52
|
entry.level = BreakingChangeLevel.INFO
|
|
51
53
|
if entry.rule_id == "enum-constraint-changed":
|
|
52
54
|
if any(entry.path.startswith(path + ".") for path in removed_enums):
|
|
@@ -160,6 +160,50 @@ class EnumConstraintRule(BreakingChangeRule):
|
|
|
160
160
|
return RuleEvaluation(self.rule_id, level, _change_message("allowed values", entry))
|
|
161
161
|
|
|
162
162
|
|
|
163
|
+
class QualityConstraintRule(BreakingChangeRule):
|
|
164
|
+
rule_id = "quality-constraint-changed"
|
|
165
|
+
_thresholds = (
|
|
166
|
+
".mustBeLessThan",
|
|
167
|
+
".mustBeLessOrEqualTo",
|
|
168
|
+
".mustBeGreaterThan",
|
|
169
|
+
".mustBeGreaterOrEqualTo",
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
def evaluate(self, entry: ChangelogEntry) -> RuleEvaluation | None:
|
|
173
|
+
if not entry.path.startswith("schema.") or ".quality." not in entry.path:
|
|
174
|
+
return None
|
|
175
|
+
rule_path = entry.path.rsplit(".quality.", 1)[1]
|
|
176
|
+
if rule_path.endswith(".arguments.validValues"):
|
|
177
|
+
# The diff emits one entry per list element.
|
|
178
|
+
level = BreakingChangeLevel.INFO if entry.type == ChangelogType.added else BreakingChangeLevel.ERROR
|
|
179
|
+
elif rule_path.endswith(".arguments.invalidValues"):
|
|
180
|
+
level = BreakingChangeLevel.INFO if entry.type == ChangelogType.removed else BreakingChangeLevel.ERROR
|
|
181
|
+
elif rule_path.endswith(self._thresholds):
|
|
182
|
+
old = _parse_number(entry.old_value)
|
|
183
|
+
new = _parse_number(entry.new_value)
|
|
184
|
+
if entry.type == ChangelogType.removed:
|
|
185
|
+
level = BreakingChangeLevel.INFO
|
|
186
|
+
elif old is None or new is None:
|
|
187
|
+
level = BreakingChangeLevel.WARNING
|
|
188
|
+
elif _is_tightening(entry.path, old, new):
|
|
189
|
+
level = BreakingChangeLevel.ERROR
|
|
190
|
+
else:
|
|
191
|
+
level = BreakingChangeLevel.INFO
|
|
192
|
+
elif "." not in rule_path:
|
|
193
|
+
# A new rule is a constraint existing data may not satisfy; a removed one is a relaxation.
|
|
194
|
+
level = BreakingChangeLevel.ERROR if entry.type == ChangelogType.added else BreakingChangeLevel.INFO
|
|
195
|
+
elif rule_path.endswith((".description", ".dimension", ".businessImpact", ".severity")):
|
|
196
|
+
level = BreakingChangeLevel.INFO
|
|
197
|
+
elif ".customProperties." in rule_path or ".authoritativeDefinitions." in rule_path or ".tags" in rule_path:
|
|
198
|
+
level = BreakingChangeLevel.INFO
|
|
199
|
+
else:
|
|
200
|
+
# What the rule checks changed (type, metric, query, other arguments, thresholds we cannot order).
|
|
201
|
+
level = BreakingChangeLevel.WARNING
|
|
202
|
+
name, _, field = rule_path.partition(".")
|
|
203
|
+
subject = f"{field} of quality rule '{name}'" if field else "quality rule"
|
|
204
|
+
return RuleEvaluation(self.rule_id, level, _change_message(subject, entry))
|
|
205
|
+
|
|
206
|
+
|
|
163
207
|
class VectorShapeRule(BreakingChangeRule):
|
|
164
208
|
rule_id = "vector-shape-changed"
|
|
165
209
|
|
|
@@ -206,9 +250,9 @@ def _parse_number(value: str | None) -> float | None:
|
|
|
206
250
|
|
|
207
251
|
|
|
208
252
|
def _is_tightening(path: str, old: float, new: float) -> bool:
|
|
209
|
-
if path.endswith((".minLength", ".minimum", ".exclusiveMinimum")):
|
|
253
|
+
if path.endswith((".minLength", ".minimum", ".exclusiveMinimum", ".mustBeGreaterThan", ".mustBeGreaterOrEqualTo")):
|
|
210
254
|
return new > old
|
|
211
|
-
if path.endswith((".maxLength", ".maximum", ".exclusiveMaximum")):
|
|
255
|
+
if path.endswith((".maxLength", ".maximum", ".exclusiveMaximum", ".mustBeLessThan", ".mustBeLessOrEqualTo")):
|
|
212
256
|
return new < old
|
|
213
257
|
return True
|
|
214
258
|
|
|
@@ -222,6 +266,7 @@ def _change_message(subject: str, entry: ChangelogEntry) -> str:
|
|
|
222
266
|
|
|
223
267
|
|
|
224
268
|
DEFAULT_RULES: tuple[BreakingChangeRule, ...] = (
|
|
269
|
+
QualityConstraintRule(),
|
|
225
270
|
RequiredChangedRule(),
|
|
226
271
|
SchemaRemovedRule(),
|
|
227
272
|
FieldRemovedRule(),
|
|
@@ -12,6 +12,8 @@ from datacontract.config import cli_config
|
|
|
12
12
|
from datacontract.data_contract import DataContract
|
|
13
13
|
from datacontract.export.html_exporter import get_version
|
|
14
14
|
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
15
17
|
|
|
16
18
|
def _get_owner(odcs: OpenDataContractStandard) -> Optional[str]:
|
|
17
19
|
"""Get the owner from ODCS customProperties or team."""
|
|
@@ -25,7 +27,7 @@ def _get_owner(odcs: OpenDataContractStandard) -> Optional[str]:
|
|
|
25
27
|
|
|
26
28
|
|
|
27
29
|
def create_data_contract_html(contracts, file: Path, path: Path, schema: str):
|
|
28
|
-
|
|
30
|
+
logger.debug(f"Creating data contract html for file {file} and schema {schema}")
|
|
29
31
|
data_contract = DataContract(
|
|
30
32
|
data_contract_file=f"{file.absolute()}", inline_references=True, schema_location=schema, config=cli_config()
|
|
31
33
|
)
|
|
@@ -26,7 +26,19 @@ def diff(v1: dict, v2: dict) -> dict:
|
|
|
26
26
|
n1 = normalize(v1)
|
|
27
27
|
n2 = normalize(v2)
|
|
28
28
|
result = DeepDiff(n1, n2, ignore_order=True, verbose_level=2)
|
|
29
|
-
|
|
29
|
+
result = json.loads(result.to_json())
|
|
30
|
+
# DeepDiff reports two dicts that share no key as one value change of the whole
|
|
31
|
+
# dict (e.g. the only schema renamed). Split it into per-key removals and additions.
|
|
32
|
+
for path, change in list(result.get("values_changed", {}).items()):
|
|
33
|
+
old, new = change.get("old_value"), change.get("new_value")
|
|
34
|
+
if not (isinstance(old, dict) and isinstance(new, dict)):
|
|
35
|
+
continue
|
|
36
|
+
del result["values_changed"][path]
|
|
37
|
+
for key, value in old.items():
|
|
38
|
+
result.setdefault("dictionary_item_removed", {})[f"{path}['{key}']"] = value
|
|
39
|
+
for key, value in new.items():
|
|
40
|
+
result.setdefault("dictionary_item_added", {})[f"{path}['{key}']"] = value
|
|
41
|
+
return result
|
|
30
42
|
|
|
31
43
|
|
|
32
44
|
_CHANGE_TYPE_MAP = {
|