datacontract-cli 1.1.2__tar.gz → 1.1.3__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.1.2/datacontract_cli.egg-info → datacontract_cli-1.1.3}/PKG-INFO +7 -4
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/README.md +3 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/api.py +72 -0
- datacontract_cli-1.1.3/datacontract/breaking/detector.py +74 -0
- datacontract_cli-1.1.3/datacontract/breaking/rules.py +196 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/cli.py +13 -3
- datacontract_cli-1.1.3/datacontract/command_breaking.py +39 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/command_ci.py +1 -1
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/command_dbt.py +2 -2
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/command_export.py +7 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/command_test.py +9 -1
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/config/settings.py +4 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/data_contract.py +16 -3
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/checks/check_spec.py +6 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/checks/create_checks.py +59 -15
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/checks/dimensions.py +3 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/data_contract_test.py +96 -12
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/fastjsonschema/check_jsonschema.py +16 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/ibis/connections/duckdb_connection.py +7 -6
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/ibis/connections/kafka.py +2 -1
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/ibis/ibis_check_execute.py +32 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/avro_exporter.py +1 -1
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/duckdb_type_converter.py +1 -1
- datacontract_cli-1.1.3/datacontract/export/great_expectations_exporter.py +732 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/jsonschema_exporter.py +3 -3
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/sodacl_check_builder.py +2 -2
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/dcs_importer.py +2 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/sql_importer.py +79 -19
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/lint/resolve.py +273 -22
- datacontract_cli-1.1.3/datacontract/model/breaking.py +33 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/model/run.py +15 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/output/test_results_writer.py +5 -0
- datacontract_cli-1.1.3/datacontract/output/text_breaking_results.py +81 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3/datacontract_cli.egg-info}/PKG-INFO +7 -4
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract_cli.egg-info/SOURCES.txt +12 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract_cli.egg-info/requires.txt +3 -3
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/pyproject.toml +4 -4
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_api.py +22 -0
- datacontract_cli-1.1.3/tests/test_breaking.py +337 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_cli.py +30 -0
- datacontract_cli-1.1.3/tests/test_create_checks_array_items.py +71 -0
- datacontract_cli-1.1.3/tests/test_create_checks_retention_period.py +57 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_create_checks_servicelevel.py +25 -0
- datacontract_cli-1.1.3/tests/test_description_linter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_duckdb_json.py +48 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_avro.py +17 -0
- datacontract_cli-1.1.3/tests/test_export_great_expectations.py +1508 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_jsonschema.py +19 -1
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_sodacl.py +41 -3
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_sql_oracle.py +1 -1
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_sql_postgres.py +24 -1
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_sql_snowflake.py +42 -1
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_sql_sqlserver.py +1 -1
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_resolve.py +37 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_resolve_definitions.py +45 -5
- datacontract_cli-1.1.3/tests/test_resolve_local_definitions.py +615 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_roundtrip_pydantic_model.py +33 -5
- datacontract_cli-1.1.3/tests/test_test_array_items.py +109 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_dimension_filter.py +3 -0
- datacontract_cli-1.1.3/tests/test_test_dry_run.py +175 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_kafka_decoding.py +20 -0
- datacontract_cli-1.1.2/datacontract/export/great_expectations_exporter.py +0 -357
- datacontract_cli-1.1.2/tests/test_export_great_expectations.py +0 -621
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/LICENSE +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/MANIFEST.in +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/__init__.py +0 -0
- {datacontract_cli-1.1.2/datacontract/engines → datacontract_cli-1.1.3/datacontract/breaking}/__init__.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/catalog/catalog.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/changelog/__init__.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/changelog/changelog.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/changelog/normalize.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/command_api.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/command_catalog.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/command_changelog.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/command_edit.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/command_import.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/command_init.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/command_lint.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/command_publish.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/config/__init__.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/config/cli_context.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/VERSION +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/abap-Bs8kvjsq.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/apex-Dspwrl5m.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/assets/editor.worker-4.7.0.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/assets/yaml.worker-4.7.0.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/azcli-k1BiOau1.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/bat-BIP72KWc.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/bicep-VhQeYhS3.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/cameligo-DnuAXtHg.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/clojure-BAuDPsal.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/coffee-BV06qSnj.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/cpp-Cz8Jeyrf.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/csharp-F6hhlXFb.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/csp-KzlEHCyI.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/css-e4FKntZ3.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/cssMode-BNkTa2xp.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/cypher-CpvDGKRr.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/dart-DdHeFWR0.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/datacontract-editor.css +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/datacontract-editor.es.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/dockerfile-aoNXDcio.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/ecl-C4Q0DYuA.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/elixir-C9X42b0T.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/flow9-Bff42pfB.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/freemarker2-Dyfzmb5A.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/fsharp-C6vPAsHG.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/go-DEr8zx9f.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/graphql-BiNBBRFh.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/handlebars-BtDNI-uC.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/hcl-2T9lKuFg.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/html-Cn4TGw_o.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/htmlMode-Bf84vbo2.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/index.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/ini-CZGtssYM.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/java-B260NeH3.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/javascript-B86Kac07.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/jsonMode-Ckgg5lAE.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/julia-kuNLM9c5.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/kotlin-Bz6kAefA.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/less-AZUtS89I.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/lexon-BcmgnyRb.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/liquid-D0NPwuu_.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/logo_fuchsia_v2.svg +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/lua-Dz1RbATg.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/m3-CIMooLFn.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/markdown-C1BsCK9P.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/mdx-QFRSBtVQ.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/mips-BovsnfLQ.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/monaco-4.7.0.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/msdax-CiRB2ZB-.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/mysql-BwdpPE19.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/objective-c-D4nfHfso.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/odcs.svg +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/pascal--j5-PYtz.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/pascaligo-C7TcJxNL.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/perl-BzEWqUb5.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/pgsql-B_KZ0mGX.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/php-A19QHzQV.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/pla-COeKY1hA.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/postiats-BfMp7zJL.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/powerquery-B0TS_5Gb.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/powershell-5jSbKdYB.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/protobuf-YgnOutn3.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/pug-DLej6kn5.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/python-C8RW9B6A.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/qsharp-AhjqtSHB.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/r-D-F4P80w.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/razor-CLZqdY_r.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/redis-hwwIlMnV.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/redshift-Bcm_kjEG.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/restructuredtext-CrdzfPP-.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/ruby-QC2UNm1s.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/rust-5aqiQ3L5.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/sb-B1g1ZfLJ.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/scala-C2U4R5Gb.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/scheme-DeFRbslr.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/scss-RSTCiCmI.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/shell-BpF-iNu8.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/solidity-C00r2mbQ.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/sophia-DVW5ZKDB.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/sparql-B0nmpxeX.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/sql-CJwKPERn.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/st-DPlKG5DT.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/swift-YZBAbVHV.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/systemverilog-CDQSaH63.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/tcl-Dlu8sp6Q.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/tsMode-yleMwhPq.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/twig-C5TO7-kw.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/typescript-CJBeebKU.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/typespec-BsmjDEu7.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/vb-ChHvIDrk.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/wgsl-XEp1ju8c.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/xml-vC-NMVX1.js +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/editor_assets/yaml-Dlf2VF-T.js +0 -0
- {datacontract_cli-1.1.2/datacontract/engines/checks → datacontract_cli-1.1.3/datacontract/engines}/__init__.py +0 -0
- {datacontract_cli-1.1.2/datacontract/engines/ibis → datacontract_cli-1.1.3/datacontract/engines/checks}/__init__.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/checks/check_filter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/checks/physical_type_match.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/checks/sql_guard.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/checks/type_normalize.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/datacontract/check_azure_blob_file.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/datacontract/check_that_datacontract_contains_valid_servers_configuration.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/datacontract/check_that_datacontract_file_exists.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/fastjsonschema/s3/s3_read_files.py +0 -0
- {datacontract_cli-1.1.2/datacontract/engines/ibis/connections → datacontract_cli-1.1.3/datacontract/engines/ibis}/__init__.py +0 -0
- {datacontract_cli-1.1.2/datacontract/export → datacontract_cli-1.1.3/datacontract/engines/ibis/connections}/__init__.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/ibis/connections/aws_credentials.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/ibis/connections/connect.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/ibis/connections/databricks_patch.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/ibis/connections/oracle_patch.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/ibis/connections/redshift_credentials.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/ibis/connections/redshift_patch.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/ibis/dtype_category.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/ibis/native_type.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/engines/ibis/snowflake_structured_types.py +0 -0
- {datacontract_cli-1.1.2/datacontract/output → datacontract_cli-1.1.3/datacontract/export}/__init__.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/avro_idl_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/bigquery_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/custom_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/data_caterer_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/dbml_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/dbt_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/dcs_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/dqx_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/excel_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/exporter_factory.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/go_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/html_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/iceberg_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/markdown_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/mermaid_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/odcs_v3_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/pandas_type_converter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/protobuf_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/pydantic_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/rdf_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/sodacl_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/spark_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/sql_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/sql_type_converter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/export/sqlalchemy_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/athena_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/avro_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/bigquery_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/csv_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/dbml_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/dbt_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/excel_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/glue_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/iceberg_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/importer_factory.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/json_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/jsonschema_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/mysql_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/object_storage_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/odcs_helper.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/odcs_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/oracle_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/parquet_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/postgres_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/powerbi_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/protobuf_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/pydantic_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/redshift_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/snowflake_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/spark_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/spark_type_json.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/sqlserver_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/trino_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/imports/unity_importer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/init/init_template.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/integration/dbt_sync.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/integration/dbt_test_mapping.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/integration/entropy_data.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/lint/files.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/lint/resources.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/lint/s3.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/lint/schema.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/lint/urls.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/model/changelog.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/model/exceptions.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/model/odcs.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/model/server.py +0 -0
- /datacontract_cli-1.1.2/datacontract/py.typed → /datacontract_cli-1.1.3/datacontract/output/__init__.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/output/ci_output.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/output/json_test_results.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/output/junit_test_results.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/output/output_format.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/output/text_changelog_results.py +0 -0
- /datacontract_cli-1.1.2/tests/test_description_linter.py → /datacontract_cli-1.1.3/datacontract/py.typed +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/schemas/datacontract-1.1.0.init.yaml +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/schemas/datacontract-1.1.0.schema.json +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/schemas/datacontract-1.2.0.init.yaml +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/schemas/datacontract-1.2.0.schema.json +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/schemas/datacontract-1.2.1.init.yaml +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/schemas/datacontract-1.2.1.schema.json +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/schemas/odcs-3.0.1.schema.json +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/schemas/odcs-3.0.2.schema.json +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/schemas/odcs-3.1.0.init.yaml +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/schemas/odcs-3.1.0.schema.json +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/datacontract.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/datacontract_odcs.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/excel/odcs-template.xlsx +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/index.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/macros/authoritative_definitions.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/macros/schema.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/macros/server.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/macros/support.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials/datacontract_information.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials/datacontract_servicelevels.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials/datacontract_terms.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials/definition.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials/example.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials/model_field.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials/quality.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials/server.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials_odcs/custom_properties.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials_odcs/diagram.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials_odcs/dialog_yaml.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials_odcs/footer.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials_odcs/fundamentals.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials_odcs/header.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials_odcs/pricing.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials_odcs/roles.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials_odcs/schema.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials_odcs/servers.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials_odcs/sla.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials_odcs/support.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials_odcs/team.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials_odcs/term_of_use.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/partials_odcs/title.html +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract/templates/style/output.css +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract_cli.egg-info/dependency_links.txt +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract_cli.egg-info/entry_points.txt +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/datacontract_cli.egg-info/top_level.txt +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/setup.cfg +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_api_openapi.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_catalog.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_changelog.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_changelog_engine.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_changelog_normalize.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_changelog_output_text.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_check_quality_provenance.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_ci_output.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_command_api.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_config.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_config_file.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_config_require.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_config_threading.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_connect_athena.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_connect_bigquery.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_connect_databricks.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_connect_impala.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_connect_mysql.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_connect_oracle.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_connect_postgres.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_connect_redshift.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_connect_s3_credentials.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_connect_snowflake.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_connect_sqlserver.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_connect_trino.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_create_checks_nested_type.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_create_checks_physical_type.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_create_checks_primary_key.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_create_checks_sql_placeholders.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_data_contract.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_data_contract_checks.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_data_contract_specification.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_dbt_sync.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_dbt_test_mapping.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_docs_commands.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_docs_config_options.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_docs_ordering.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_download_datacontract_file.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_dtype_category.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_edit.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_avro_idl.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_bigquery.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_complex_data_contract.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_custom.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_custom_exporter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_custom_model.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_data_caterer.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_dbml.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_dbt_models.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_dbt_sources.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_dbt_staging_sql.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_dcs.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_dqx.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_excel.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_go.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_html.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_iceberg.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_large_contract.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_markdown.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_mermaid.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_odcs_v3.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_protobuf.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_pydantic.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_rdf.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_spark.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_sql.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_sql_clickhouse.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_sql_query.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_export_sqlalchemy.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_ibis_mssql_pattern.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_ibis_mssql_schema.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_ibis_oracle_schema.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_athena.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_avro.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_bigquery.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_csv.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_dbml.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_dbt.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_excel.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_glue.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_iceberg.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_json.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_jsonschema.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_mysql.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_object_storage.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_odcs_v3.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_oracle.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_parquet.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_postgres.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_powerbi.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_protobuf.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_pydantic_model.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_redshift.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_snowflake.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_spark_type_json.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_sqlserver.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_trino.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_import_unity_file.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_install_extras.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_integration_entropydata.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_lint.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_lint_urls.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_native_type_schema_scope.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_oracle_patch.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_physical_type_match.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_publish_test_results.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_publish_test_results_payload.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_quality_sql_dialects.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_redshift_credentials.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_redshift_patch.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_roundtrip_jsonschema.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_run_check_deprecated_fields.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_run_check_engine.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_server_overrides.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_server_type_mssql.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_server_type_synonyms.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_snowflake_structured_types.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_sql_type_converter_physicaltype.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_api.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_athena_iceberg.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_azure_blob_file.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_azure_remote.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_bigquery.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_checks_filter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_databricks.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_delta.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_diagnostics.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_duckdb.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_failed_samples.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_gcs_csv_remote.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_gcs_json_remote.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_kafka.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_kafka_remote.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_local_json.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_local_json_nd.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_metadata_only.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_mysql.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_oracle.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_oracle_xe.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_output_json.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_output_junit.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_parquet.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_postgres.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_quality.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_quality_id_and_tag_filter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_quality_local_fallback.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_quality_percent_severity.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_redshift.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_row_filter.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_s3_csv.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_s3_delta.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_s3_json.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_s3_json_complex.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_s3_json_multiple_models.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_s3_json_remote.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_schema_evolution.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_server_not_found.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_snowflake.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_soda_connection_error.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_sqlserver.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_test_trino.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_type_normalize.py +0 -0
- {datacontract_cli-1.1.2 → datacontract_cli-1.1.3}/tests/test_untrusted_contract.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: datacontract-cli
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.3
|
|
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
|
|
@@ -46,7 +46,7 @@ Requires-Dist: boto3<2.0.0,>=1.34.41
|
|
|
46
46
|
Requires-Dist: Jinja2<4.0.0,>=3.1.5
|
|
47
47
|
Requires-Dist: jinja_partials<1.0.0,>=0.2.1
|
|
48
48
|
Requires-Dist: datacontract-specification<2.0.0,>=1.2.3
|
|
49
|
-
Requires-Dist: open-data-contract-standard<
|
|
49
|
+
Requires-Dist: open-data-contract-standard<3.2.0,>=3.1.2
|
|
50
50
|
Requires-Dist: deepdiff<10.0.0,>=6.0.0
|
|
51
51
|
Provides-Extra: avro
|
|
52
52
|
Requires-Dist: avro==1.12.2; extra == "avro"
|
|
@@ -138,7 +138,7 @@ Requires-Dist: datacontract-cli[all]; extra == "dev"
|
|
|
138
138
|
Requires-Dist: httpx==0.28.1; extra == "dev"
|
|
139
139
|
Requires-Dist: kafka-python; extra == "dev"
|
|
140
140
|
Requires-Dist: minio==7.2.20; extra == "dev"
|
|
141
|
-
Requires-Dist: moto==5.2.
|
|
141
|
+
Requires-Dist: moto==5.2.3; extra == "dev"
|
|
142
142
|
Requires-Dist: openapi-spec-validator<0.10,>=0.7; extra == "dev"
|
|
143
143
|
Requires-Dist: pandas>=2.1.0; extra == "dev"
|
|
144
144
|
Requires-Dist: pre-commit<4.7.0,>=3.7.1; extra == "dev"
|
|
@@ -148,7 +148,7 @@ Requires-Dist: pytest-xdist; extra == "dev"
|
|
|
148
148
|
Requires-Dist: pymssql==2.3.13; extra == "dev"
|
|
149
149
|
Requires-Dist: psycopg2-binary<3.0,>=2.9; extra == "dev"
|
|
150
150
|
Requires-Dist: mysql-connector-python<26.8.0,>=8.0.30; extra == "dev"
|
|
151
|
-
Requires-Dist: ruff==0.16.
|
|
151
|
+
Requires-Dist: ruff==0.16.5; extra == "dev"
|
|
152
152
|
Requires-Dist: testcontainers[kafka,minio,mssql,mysql,postgres]==4.15.0; extra == "dev"
|
|
153
153
|
Requires-Dist: trino==0.339.0; extra == "dev"
|
|
154
154
|
Dynamic: license-file
|
|
@@ -296,6 +296,9 @@ $ datacontract lint odcs.yaml
|
|
|
296
296
|
# show a changelog between two data contracts
|
|
297
297
|
$ datacontract changelog v1.odcs.yaml v2.odcs.yaml
|
|
298
298
|
|
|
299
|
+
# fail when a contract change is backward-incompatible
|
|
300
|
+
$ datacontract breaking v1.odcs.yaml v2.odcs.yaml
|
|
301
|
+
|
|
299
302
|
# execute schema and quality checks (define credentials as environment variables)
|
|
300
303
|
$ datacontract test odcs.yaml
|
|
301
304
|
|
|
@@ -141,6 +141,9 @@ $ datacontract lint odcs.yaml
|
|
|
141
141
|
# show a changelog between two data contracts
|
|
142
142
|
$ datacontract changelog v1.odcs.yaml v2.odcs.yaml
|
|
143
143
|
|
|
144
|
+
# fail when a contract change is backward-incompatible
|
|
145
|
+
$ datacontract breaking v1.odcs.yaml v2.odcs.yaml
|
|
146
|
+
|
|
144
147
|
# execute schema and quality checks (define credentials as environment variables)
|
|
145
148
|
$ datacontract test odcs.yaml
|
|
146
149
|
|
|
@@ -15,6 +15,7 @@ from pydantic import BaseModel, Field, ValidationError
|
|
|
15
15
|
|
|
16
16
|
from datacontract.config import Config, known_env_names
|
|
17
17
|
from datacontract.data_contract import DataContract, ExportFormat
|
|
18
|
+
from datacontract.model.breaking import BreakingChangeEntry
|
|
18
19
|
from datacontract.model.changelog import ChangelogEntry
|
|
19
20
|
from datacontract.model.exceptions import DataContractException, DefinitionResolutionError
|
|
20
21
|
from datacontract.model.run import Check, ResultEnum, Run
|
|
@@ -323,6 +324,14 @@ app = FastAPI(
|
|
|
323
324
|
"url": "https://docs.datacontract.com/commands/changelog",
|
|
324
325
|
},
|
|
325
326
|
},
|
|
327
|
+
{
|
|
328
|
+
"name": "breaking",
|
|
329
|
+
"description": "Compare two versions of a data contract and grade each change by compatibility impact.",
|
|
330
|
+
"externalDocs": {
|
|
331
|
+
"description": "Documentation",
|
|
332
|
+
"url": "https://docs.datacontract.com/commands/breaking",
|
|
333
|
+
},
|
|
334
|
+
},
|
|
326
335
|
],
|
|
327
336
|
)
|
|
328
337
|
|
|
@@ -881,6 +890,21 @@ class ChangelogResponse(BaseModel):
|
|
|
881
890
|
)
|
|
882
891
|
|
|
883
892
|
|
|
893
|
+
class BreakingChangesResponse(BaseModel):
|
|
894
|
+
"""Every change between two versions of a data contract, each graded `info`, `warning` or `error`."""
|
|
895
|
+
|
|
896
|
+
summary: list[BreakingChangeEntry] = Field(
|
|
897
|
+
description="One entry per changed element, graded by the most severe change. A property whose type and requiredness "
|
|
898
|
+
"both changed appears once.",
|
|
899
|
+
)
|
|
900
|
+
entries: list[BreakingChangeEntry] = Field(
|
|
901
|
+
description="Every single change with its grade and the old and new value.",
|
|
902
|
+
)
|
|
903
|
+
is_breaking: bool = Field(
|
|
904
|
+
description="Whether any detected change is classified as an error-level breaking change.",
|
|
905
|
+
)
|
|
906
|
+
|
|
907
|
+
|
|
884
908
|
@app.post(
|
|
885
909
|
"/changelog",
|
|
886
910
|
tags=["changelog"],
|
|
@@ -935,6 +959,54 @@ async def changelog_endpoint(
|
|
|
935
959
|
os.unlink(v2_path)
|
|
936
960
|
|
|
937
961
|
|
|
962
|
+
@app.post(
|
|
963
|
+
"/breaking",
|
|
964
|
+
tags=["breaking"],
|
|
965
|
+
operation_id="breakingChangesDataContracts",
|
|
966
|
+
summary="Show compatibility impact between two data contracts.",
|
|
967
|
+
description="""
|
|
968
|
+
Compare two versions of an ODCS data contract and detect backward-incompatible changes.
|
|
969
|
+
|
|
970
|
+
`POST` a JSON body with `v1` (before) and `v2` (after) as YAML strings. A contract that cannot be
|
|
971
|
+
parsed is answered with `422`.
|
|
972
|
+
""",
|
|
973
|
+
response_description="The breaking changes detected between the two data contracts.",
|
|
974
|
+
responses={
|
|
975
|
+
**AUTHENTICATION_RESPONSES,
|
|
976
|
+
422: {
|
|
977
|
+
"description": "One of the two data contracts is not valid YAML or not a valid data contract.",
|
|
978
|
+
"model": UnprocessableEntityResponse,
|
|
979
|
+
"content": {"application/json": {"example": {"detail": "Invalid YAML: while parsing a block mapping"}}},
|
|
980
|
+
},
|
|
981
|
+
},
|
|
982
|
+
)
|
|
983
|
+
def breaking_endpoint(
|
|
984
|
+
body: ChangelogRequest,
|
|
985
|
+
api_key: Annotated[str | None, Depends(api_key_header)] = None,
|
|
986
|
+
) -> BreakingChangesResponse:
|
|
987
|
+
check_api_key(api_key)
|
|
988
|
+
|
|
989
|
+
with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f1:
|
|
990
|
+
f1.write(body.v1)
|
|
991
|
+
v1_path = f1.name
|
|
992
|
+
with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f2:
|
|
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)
|
|
1008
|
+
|
|
1009
|
+
|
|
938
1010
|
@app.post(
|
|
939
1011
|
"/export",
|
|
940
1012
|
tags=["export"],
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from collections import defaultdict
|
|
2
|
+
from collections.abc import Iterable
|
|
3
|
+
|
|
4
|
+
from datacontract.breaking.rules import DEFAULT_RULES, BreakingChangeRule
|
|
5
|
+
from datacontract.model.breaking import BreakingChangeEntry, BreakingChangeLevel, BreakingChangeResult
|
|
6
|
+
from datacontract.model.changelog import ChangelogEntry, ChangelogResult, ChangelogType
|
|
7
|
+
|
|
8
|
+
_LEVEL_ORDER = {
|
|
9
|
+
BreakingChangeLevel.INFO: 0,
|
|
10
|
+
BreakingChangeLevel.WARNING: 1,
|
|
11
|
+
BreakingChangeLevel.ERROR: 2,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class BreakingChangeDetector:
|
|
16
|
+
"""Classify detailed changelog entries using an ordered rule set."""
|
|
17
|
+
|
|
18
|
+
def __init__(self, rules: Iterable[BreakingChangeRule] = DEFAULT_RULES):
|
|
19
|
+
self._rules = tuple(rules)
|
|
20
|
+
if not self._rules:
|
|
21
|
+
raise ValueError("At least one breaking-change rule is required")
|
|
22
|
+
|
|
23
|
+
def detect(self, changelog: ChangelogResult) -> BreakingChangeResult:
|
|
24
|
+
entries = [self._classify(entry) for entry in changelog.entries]
|
|
25
|
+
# Nothing inside a newly added element can break a consumer: it did not exist before.
|
|
26
|
+
added = {entry.path for entry in entries if entry.change_type == ChangelogType.added}
|
|
27
|
+
for entry in entries:
|
|
28
|
+
segments = entry.path.split(".")
|
|
29
|
+
if any(".".join(segments[:i]) in added for i in range(1, len(segments))):
|
|
30
|
+
entry.level = BreakingChangeLevel.INFO
|
|
31
|
+
entries_by_prefix = defaultdict(list)
|
|
32
|
+
for entry in entries:
|
|
33
|
+
prefix = ""
|
|
34
|
+
for segment in entry.path.split("."):
|
|
35
|
+
prefix = f"{prefix}.{segment}" if prefix else segment
|
|
36
|
+
entries_by_prefix[prefix].append(entry)
|
|
37
|
+
summary = [self._summarize(entry, entries_by_prefix.get(entry.path, [])) for entry in changelog.summary]
|
|
38
|
+
return BreakingChangeResult(v1=changelog.v1, v2=changelog.v2, summary=summary, entries=entries)
|
|
39
|
+
|
|
40
|
+
def _classify(self, entry: ChangelogEntry) -> BreakingChangeEntry:
|
|
41
|
+
for rule in self._rules:
|
|
42
|
+
evaluation = rule.evaluate(entry)
|
|
43
|
+
if evaluation is not None:
|
|
44
|
+
return BreakingChangeEntry(
|
|
45
|
+
path=entry.path,
|
|
46
|
+
change_type=entry.type,
|
|
47
|
+
level=evaluation.level,
|
|
48
|
+
message=evaluation.message,
|
|
49
|
+
rule_id=evaluation.rule_id,
|
|
50
|
+
old_value=entry.old_value,
|
|
51
|
+
new_value=entry.new_value,
|
|
52
|
+
)
|
|
53
|
+
raise ValueError(f"No breaking-change rule classified {entry.path}")
|
|
54
|
+
|
|
55
|
+
@staticmethod
|
|
56
|
+
def _summarize(summary_entry: ChangelogEntry, entries: list[BreakingChangeEntry]) -> BreakingChangeEntry:
|
|
57
|
+
if not entries:
|
|
58
|
+
return BreakingChangeEntry(
|
|
59
|
+
path=summary_entry.path,
|
|
60
|
+
change_type=summary_entry.type,
|
|
61
|
+
level=BreakingChangeLevel.INFO,
|
|
62
|
+
message=f"Changed contract at {summary_entry.path}",
|
|
63
|
+
rule_id="summary-fallback",
|
|
64
|
+
)
|
|
65
|
+
highest = max(entries, key=lambda entry: _LEVEL_ORDER[entry.level])
|
|
66
|
+
return BreakingChangeEntry(
|
|
67
|
+
path=summary_entry.path,
|
|
68
|
+
change_type=summary_entry.type,
|
|
69
|
+
level=highest.level,
|
|
70
|
+
message=f"{highest.level.value.capitalize()} impact at {summary_entry.path}",
|
|
71
|
+
rule_id=f"summary:{highest.rule_id}",
|
|
72
|
+
old_value=highest.old_value,
|
|
73
|
+
new_value=highest.new_value,
|
|
74
|
+
)
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from datetime import date
|
|
4
|
+
|
|
5
|
+
from datacontract.model.breaking import BreakingChangeLevel
|
|
6
|
+
from datacontract.model.changelog import ChangelogEntry, ChangelogType
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass(frozen=True)
|
|
10
|
+
class RuleEvaluation:
|
|
11
|
+
rule_id: str
|
|
12
|
+
level: BreakingChangeLevel
|
|
13
|
+
message: str
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BreakingChangeRule(ABC):
|
|
17
|
+
rule_id: str
|
|
18
|
+
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def evaluate(self, entry: ChangelogEntry) -> RuleEvaluation | None:
|
|
21
|
+
"""Return a classification when this rule applies to ``entry``."""
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class SchemaRemovedRule(BreakingChangeRule):
|
|
25
|
+
rule_id = "schema-removed"
|
|
26
|
+
|
|
27
|
+
def evaluate(self, entry: ChangelogEntry) -> RuleEvaluation | None:
|
|
28
|
+
segments = entry.path.split(".")
|
|
29
|
+
if entry.type == ChangelogType.removed and len(segments) == 2 and segments[0] == "schema":
|
|
30
|
+
return RuleEvaluation(self.rule_id, BreakingChangeLevel.ERROR, f"Removed schema {segments[1]}")
|
|
31
|
+
return None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class FieldRemovedRule(BreakingChangeRule):
|
|
35
|
+
rule_id = "field-removed"
|
|
36
|
+
|
|
37
|
+
def evaluate(self, entry: ChangelogEntry) -> RuleEvaluation | None:
|
|
38
|
+
segments = entry.path.split(".")
|
|
39
|
+
if entry.type != ChangelogType.removed or not _is_schema_property_path(segments):
|
|
40
|
+
return None
|
|
41
|
+
property_name = segments[-1]
|
|
42
|
+
return RuleEvaluation(self.rule_id, BreakingChangeLevel.ERROR, f"Removed property {property_name}")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class RequiredChangedRule(BreakingChangeRule):
|
|
46
|
+
rule_id = "required-changed"
|
|
47
|
+
|
|
48
|
+
def evaluate(self, entry: ChangelogEntry) -> RuleEvaluation | None:
|
|
49
|
+
if not entry.path.endswith(".required"):
|
|
50
|
+
return None
|
|
51
|
+
old = _parse_bool(entry.old_value)
|
|
52
|
+
new = _parse_bool(entry.new_value)
|
|
53
|
+
if entry.type == ChangelogType.added and new is True:
|
|
54
|
+
level = BreakingChangeLevel.ERROR
|
|
55
|
+
elif entry.type == ChangelogType.removed or new is False:
|
|
56
|
+
# Dropping the requirement, or writing out the optional default, only loosens the contract.
|
|
57
|
+
level = BreakingChangeLevel.INFO
|
|
58
|
+
elif entry.type == ChangelogType.updated and old is False and new is True:
|
|
59
|
+
level = BreakingChangeLevel.ERROR
|
|
60
|
+
elif entry.type in (ChangelogType.added, ChangelogType.updated):
|
|
61
|
+
level = BreakingChangeLevel.WARNING
|
|
62
|
+
else:
|
|
63
|
+
return None
|
|
64
|
+
return RuleEvaluation(self.rule_id, level, _change_message("requiredness", entry))
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class TypeChangedRule(BreakingChangeRule):
|
|
68
|
+
rule_id = "type-changed"
|
|
69
|
+
|
|
70
|
+
def evaluate(self, entry: ChangelogEntry) -> RuleEvaluation | None:
|
|
71
|
+
if not entry.path.endswith((".logicalType", ".physicalType")):
|
|
72
|
+
return None
|
|
73
|
+
if entry.type == ChangelogType.updated:
|
|
74
|
+
level = BreakingChangeLevel.ERROR
|
|
75
|
+
elif entry.type == ChangelogType.added:
|
|
76
|
+
level = BreakingChangeLevel.INFO
|
|
77
|
+
elif entry.type == ChangelogType.removed:
|
|
78
|
+
level = BreakingChangeLevel.WARNING
|
|
79
|
+
else:
|
|
80
|
+
return None
|
|
81
|
+
return RuleEvaluation(self.rule_id, level, _change_message("type", entry))
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class UniqueConstraintRule(BreakingChangeRule):
|
|
85
|
+
rule_id = "unique-constraint-changed"
|
|
86
|
+
|
|
87
|
+
def evaluate(self, entry: ChangelogEntry) -> RuleEvaluation | None:
|
|
88
|
+
if not entry.path.endswith(".unique"):
|
|
89
|
+
return None
|
|
90
|
+
old = _parse_bool(entry.old_value)
|
|
91
|
+
new = _parse_bool(entry.new_value)
|
|
92
|
+
if new is True and old is not True:
|
|
93
|
+
level = BreakingChangeLevel.ERROR
|
|
94
|
+
elif old is True and new is not True:
|
|
95
|
+
level = BreakingChangeLevel.INFO
|
|
96
|
+
else:
|
|
97
|
+
level = BreakingChangeLevel.WARNING
|
|
98
|
+
return RuleEvaluation(self.rule_id, level, _change_message("uniqueness", entry))
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class KeyConstraintRule(BreakingChangeRule):
|
|
102
|
+
rule_id = "key-constraint-changed"
|
|
103
|
+
|
|
104
|
+
def evaluate(self, entry: ChangelogEntry) -> RuleEvaluation | None:
|
|
105
|
+
if not entry.path.endswith((".primaryKey", ".primary_key")):
|
|
106
|
+
return None
|
|
107
|
+
return RuleEvaluation(self.rule_id, BreakingChangeLevel.WARNING, _change_message("key constraint", entry))
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class ValidationConstraintRule(BreakingChangeRule):
|
|
111
|
+
rule_id = "validation-constraint-changed"
|
|
112
|
+
_suffixes = (
|
|
113
|
+
".pattern",
|
|
114
|
+
".minLength",
|
|
115
|
+
".maxLength",
|
|
116
|
+
".minimum",
|
|
117
|
+
".maximum",
|
|
118
|
+
".exclusiveMinimum",
|
|
119
|
+
".exclusiveMaximum",
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
def evaluate(self, entry: ChangelogEntry) -> RuleEvaluation | None:
|
|
123
|
+
if not entry.path.endswith(self._suffixes):
|
|
124
|
+
return None
|
|
125
|
+
old = _parse_number(entry.old_value)
|
|
126
|
+
new = _parse_number(entry.new_value)
|
|
127
|
+
if old is None or new is None:
|
|
128
|
+
level = BreakingChangeLevel.WARNING
|
|
129
|
+
elif _is_tightening(entry.path, old, new):
|
|
130
|
+
level = BreakingChangeLevel.ERROR
|
|
131
|
+
else:
|
|
132
|
+
level = BreakingChangeLevel.INFO
|
|
133
|
+
return RuleEvaluation(self.rule_id, level, _change_message("validation constraint", entry))
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class MetadataFallbackRule(BreakingChangeRule):
|
|
137
|
+
rule_id = "metadata-or-unknown-change"
|
|
138
|
+
|
|
139
|
+
def evaluate(self, entry: ChangelogEntry) -> RuleEvaluation:
|
|
140
|
+
return RuleEvaluation(self.rule_id, BreakingChangeLevel.INFO, _change_message("contract", entry))
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _is_schema_property_path(segments: list[str]) -> bool:
|
|
144
|
+
return len(segments) >= 3 and segments[0] == "schema" and segments[-2] == "properties"
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def _parse_bool(value: str | None) -> bool | None:
|
|
148
|
+
if value is None:
|
|
149
|
+
return None
|
|
150
|
+
normalized = value.strip().lower()
|
|
151
|
+
if normalized in {"true", "1"}:
|
|
152
|
+
return True
|
|
153
|
+
if normalized in {"false", "0"}:
|
|
154
|
+
return False
|
|
155
|
+
return None
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _parse_number(value: str | None) -> float | None:
|
|
159
|
+
if value is None:
|
|
160
|
+
return None
|
|
161
|
+
normalized = value.strip()
|
|
162
|
+
try:
|
|
163
|
+
return float(normalized)
|
|
164
|
+
except ValueError:
|
|
165
|
+
try:
|
|
166
|
+
return float(date.fromisoformat(normalized).toordinal())
|
|
167
|
+
except ValueError:
|
|
168
|
+
return None
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def _is_tightening(path: str, old: float, new: float) -> bool:
|
|
172
|
+
if path.endswith((".minLength", ".minimum", ".exclusiveMinimum")):
|
|
173
|
+
return new > old
|
|
174
|
+
if path.endswith((".maxLength", ".maximum", ".exclusiveMaximum")):
|
|
175
|
+
return new < old
|
|
176
|
+
return True
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _change_message(subject: str, entry: ChangelogEntry) -> str:
|
|
180
|
+
if entry.type == ChangelogType.added:
|
|
181
|
+
return f"Added {subject} at {entry.path}"
|
|
182
|
+
if entry.type == ChangelogType.removed:
|
|
183
|
+
return f"Removed {subject} at {entry.path}"
|
|
184
|
+
return f"Changed {subject} at {entry.path} from {entry.old_value!r} to {entry.new_value!r}"
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
DEFAULT_RULES: tuple[BreakingChangeRule, ...] = (
|
|
188
|
+
RequiredChangedRule(),
|
|
189
|
+
SchemaRemovedRule(),
|
|
190
|
+
FieldRemovedRule(),
|
|
191
|
+
TypeChangedRule(),
|
|
192
|
+
UniqueConstraintRule(),
|
|
193
|
+
KeyConstraintRule(),
|
|
194
|
+
ValidationConstraintRule(),
|
|
195
|
+
MetadataFallbackRule(),
|
|
196
|
+
)
|
|
@@ -28,6 +28,7 @@ COMMAND_ORDER = [
|
|
|
28
28
|
"edit",
|
|
29
29
|
"lint",
|
|
30
30
|
"changelog",
|
|
31
|
+
"breaking",
|
|
31
32
|
"sync", # `dbt sync` subcommand; no top-level `sync`, so this only orders the dbt group
|
|
32
33
|
"test",
|
|
33
34
|
"ci",
|
|
@@ -217,11 +218,19 @@ def enable_debug_logging(debug: bool, otherwise_disable_stderr: bool = False):
|
|
|
217
218
|
logging.getLogger(noisy_logger).setLevel(logging.ERROR)
|
|
218
219
|
|
|
219
220
|
|
|
220
|
-
def validate_publish_url(publish: str | None) -> None:
|
|
221
|
-
"""
|
|
222
|
-
|
|
221
|
+
def validate_publish_url(publish: str | None) -> str | None:
|
|
222
|
+
"""Normalize `--publish` and reject values that aren't http/https before any real work runs.
|
|
223
|
+
|
|
224
|
+
An empty value means "don't publish". CI templates that render the URL from an unset variable
|
|
225
|
+
pass `--publish ''` rather than omitting the option, e.g. GitHub Actions container actions,
|
|
226
|
+
where an argument list cannot drop an entry conditionally.
|
|
227
|
+
"""
|
|
228
|
+
if not publish:
|
|
229
|
+
return None
|
|
230
|
+
if not (publish.startswith("http://") or publish.startswith("https://")):
|
|
223
231
|
console.print(f"[red]--publish URL must start with http:// or https:// (got: {publish!r}).[/red]")
|
|
224
232
|
raise typer.Exit(code=1)
|
|
233
|
+
return publish
|
|
225
234
|
|
|
226
235
|
|
|
227
236
|
def resolve_output_format(output_format: Optional[OutputFormat], output: Optional[Path]) -> Optional[OutputFormat]:
|
|
@@ -263,6 +272,7 @@ def _print_publish_failure(run, out=None):
|
|
|
263
272
|
# Display order for `--help` is controlled by COMMAND_ORDER above, not by import order.
|
|
264
273
|
from datacontract import ( # noqa: E402, F401
|
|
265
274
|
command_api,
|
|
275
|
+
command_breaking,
|
|
266
276
|
command_catalog,
|
|
267
277
|
command_changelog,
|
|
268
278
|
command_ci,
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
from typing_extensions import Annotated
|
|
3
|
+
|
|
4
|
+
from datacontract.cli import app, console, debug_option, enable_debug_logging
|
|
5
|
+
from datacontract.config import cli_config
|
|
6
|
+
from datacontract.data_contract import DataContract
|
|
7
|
+
from datacontract.output.text_breaking_results import write_text_breaking_results
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@app.command(
|
|
11
|
+
name="breaking",
|
|
12
|
+
epilog="Example: datacontract breaking datacontract-v1.yaml datacontract-v2.yaml",
|
|
13
|
+
)
|
|
14
|
+
def breaking(
|
|
15
|
+
v1: Annotated[
|
|
16
|
+
str,
|
|
17
|
+
typer.Argument(help="The location (url, s3 url, or local path) of the source (before) data contract YAML."),
|
|
18
|
+
],
|
|
19
|
+
v2: Annotated[
|
|
20
|
+
str,
|
|
21
|
+
typer.Argument(help="The location (url, s3 url, or local path) of the target (after) data contract YAML."),
|
|
22
|
+
],
|
|
23
|
+
inline_references: Annotated[
|
|
24
|
+
bool,
|
|
25
|
+
typer.Option(
|
|
26
|
+
help="Resolve external references (currently: authoritativeDefinitions\\[type in {definition, semantics}]) "
|
|
27
|
+
"in the contract and inline the fetched content from the configured entropy-data host."
|
|
28
|
+
),
|
|
29
|
+
] = True,
|
|
30
|
+
debug: debug_option = None,
|
|
31
|
+
):
|
|
32
|
+
"""Show compatibility impact between two data contracts."""
|
|
33
|
+
enable_debug_logging(debug)
|
|
34
|
+
result = DataContract(config=cli_config(), data_contract_file=v1, inline_references=inline_references).breaking(
|
|
35
|
+
DataContract(config=cli_config(), data_contract_file=v2, inline_references=inline_references)
|
|
36
|
+
)
|
|
37
|
+
write_text_breaking_results(result, console)
|
|
38
|
+
if result.is_breaking:
|
|
39
|
+
raise typer.Exit(code=1)
|
|
@@ -92,7 +92,7 @@ def ci(
|
|
|
92
92
|
Run tests for CI/CD pipelines. Emits GitHub Actions annotations and step summary.
|
|
93
93
|
"""
|
|
94
94
|
enable_debug_logging(debug, otherwise_disable_stderr=True)
|
|
95
|
-
validate_publish_url(publish)
|
|
95
|
+
publish = validate_publish_url(publish)
|
|
96
96
|
|
|
97
97
|
if not locations:
|
|
98
98
|
locations = ["datacontract.yaml"]
|
|
@@ -347,7 +347,7 @@ def sync_command(
|
|
|
347
347
|
the generated tests.
|
|
348
348
|
"""
|
|
349
349
|
enable_debug_logging(debug)
|
|
350
|
-
validate_publish_url(publish)
|
|
350
|
+
publish = validate_publish_url(publish)
|
|
351
351
|
|
|
352
352
|
if publish is not None and not run_tests_flag:
|
|
353
353
|
console.print("[red]--publish requires --run-tests.[/red]")
|
|
@@ -476,7 +476,7 @@ def test_command(
|
|
|
476
476
|
them. Use `datacontract dbt sync` to create and update the tests first.
|
|
477
477
|
"""
|
|
478
478
|
enable_debug_logging(debug)
|
|
479
|
-
validate_publish_url(publish)
|
|
479
|
+
publish = validate_publish_url(publish)
|
|
480
480
|
check_dbt_on_path()
|
|
481
481
|
|
|
482
482
|
explicit_project_dir = project_dir is not None
|
|
@@ -66,6 +66,7 @@ def _export(
|
|
|
66
66
|
inline_references: bool = True,
|
|
67
67
|
clickhouse_engine: Optional[str] = None,
|
|
68
68
|
clickhouse_order_by: Optional[str] = None,
|
|
69
|
+
suite_name: Optional[str] = None,
|
|
69
70
|
):
|
|
70
71
|
result = DataContract(
|
|
71
72
|
config=cli_config(),
|
|
@@ -83,6 +84,7 @@ def _export(
|
|
|
83
84
|
template=template,
|
|
84
85
|
clickhouse_engine=clickhouse_engine,
|
|
85
86
|
clickhouse_order_by=clickhouse_order_by,
|
|
87
|
+
suite_name=suite_name,
|
|
86
88
|
)
|
|
87
89
|
if output is None:
|
|
88
90
|
console.print(result, markup=False, soft_wrap=True)
|
|
@@ -587,6 +589,10 @@ def export_great_expectations(
|
|
|
587
589
|
schema: schema_option = None,
|
|
588
590
|
inline_references: inline_references_option = True,
|
|
589
591
|
debug: debug_option = None,
|
|
592
|
+
suite_name: Annotated[
|
|
593
|
+
Optional[str],
|
|
594
|
+
typer.Option(help="The suite name for the Great Expectations run."),
|
|
595
|
+
] = None,
|
|
590
596
|
):
|
|
591
597
|
"""Export a data contract to Great Expectations suite."""
|
|
592
598
|
enable_debug_logging(debug)
|
|
@@ -600,6 +606,7 @@ def export_great_expectations(
|
|
|
600
606
|
engine=engine.value if engine is not None else None,
|
|
601
607
|
sql_server_type=dialect.value,
|
|
602
608
|
inline_references=inline_references,
|
|
609
|
+
suite_name=suite_name,
|
|
603
610
|
)
|
|
604
611
|
|
|
605
612
|
|
|
@@ -218,6 +218,13 @@ def test(
|
|
|
218
218
|
"Checks that read row values are skipped."
|
|
219
219
|
),
|
|
220
220
|
] = False,
|
|
221
|
+
dry_run: Annotated[
|
|
222
|
+
bool,
|
|
223
|
+
typer.Option(
|
|
224
|
+
help="Report the checks that would run, without connecting to the server or reading any data. "
|
|
225
|
+
"Reported checks have the result 'skipped', or 'warning' where a check could not be planned."
|
|
226
|
+
),
|
|
227
|
+
] = False,
|
|
221
228
|
include_failed_samples: Annotated[
|
|
222
229
|
bool,
|
|
223
230
|
typer.Option(
|
|
@@ -243,7 +250,7 @@ def test(
|
|
|
243
250
|
Run schema and quality tests on configured servers.
|
|
244
251
|
"""
|
|
245
252
|
enable_debug_logging(debug, otherwise_disable_stderr=True)
|
|
246
|
-
validate_publish_url(publish)
|
|
253
|
+
publish = validate_publish_url(publish)
|
|
247
254
|
|
|
248
255
|
check_categories = _parse_enum_csv(
|
|
249
256
|
checks,
|
|
@@ -284,6 +291,7 @@ def test(
|
|
|
284
291
|
filter=filter,
|
|
285
292
|
filters=parsed_filters,
|
|
286
293
|
metadata_only=metadata_only,
|
|
294
|
+
dry_run=dry_run,
|
|
287
295
|
).test()
|
|
288
296
|
if logs:
|
|
289
297
|
_print_logs(run)
|
|
@@ -162,6 +162,7 @@ class Config(BaseSettings):
|
|
|
162
162
|
kafka_schema_registry_password: SecretStr | None = None
|
|
163
163
|
kafka_max_messages: int | None = None
|
|
164
164
|
kafka_timeout: int | None = None
|
|
165
|
+
kafka_group_prefix: str | None = None
|
|
165
166
|
|
|
166
167
|
# mysql
|
|
167
168
|
mysql_username: str | None = None
|
|
@@ -588,6 +589,9 @@ class Config(BaseSettings):
|
|
|
588
589
|
def get_kafka_timeout(self) -> int | None:
|
|
589
590
|
return self._int_option("kafka_timeout")
|
|
590
591
|
|
|
592
|
+
def get_kafka_group_prefix(self, required: bool = False) -> str | None:
|
|
593
|
+
return self._str_option("kafka_group_prefix", required)
|
|
594
|
+
|
|
591
595
|
# --- mysql ---
|
|
592
596
|
def get_mysql_username(self, required: bool = False) -> str | None:
|
|
593
597
|
return self._str_option("mysql_username", required)
|