datacontract-cli 1.0.11__tar.gz → 1.0.12__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.0.11/datacontract_cli.egg-info → datacontract_cli-1.0.12}/PKG-INFO +1 -1
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/checks/type_normalize.py +27 -1
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/ibis/dtype_category.py +22 -14
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/ibis/ibis_check_execute.py +43 -10
- datacontract_cli-1.0.12/datacontract/engines/ibis/snowflake_structured_types.py +134 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12/datacontract_cli.egg-info}/PKG-INFO +1 -1
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract_cli.egg-info/SOURCES.txt +2 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/pyproject.toml +1 -1
- datacontract_cli-1.0.12/tests/test_dtype_category.py +84 -0
- datacontract_cli-1.0.12/tests/test_snowflake_structured_types.py +236 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_dataframe.py +2 -2
- datacontract_cli-1.0.12/tests/test_type_normalize.py +92 -0
- datacontract_cli-1.0.11/tests/test_dtype_category.py +0 -28
- datacontract_cli-1.0.11/tests/test_type_normalize.py +0 -15
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/LICENSE +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/MANIFEST.in +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/README.md +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/__init__.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/api.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/catalog/catalog.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/changelog/__init__.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/changelog/changelog.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/changelog/normalize.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/cli.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/command_api.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/command_catalog.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/command_changelog.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/command_ci.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/command_dbt.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/command_edit.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/command_export.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/command_import.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/command_init.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/command_lint.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/command_publish.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/command_test.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/data_contract.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/VERSION +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/abap-Bs8kvjsq.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/apex-Dspwrl5m.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/assets/editor.worker-4.7.0.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/assets/yaml.worker-4.7.0.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/azcli-k1BiOau1.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/bat-BIP72KWc.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/bicep-VhQeYhS3.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/cameligo-DnuAXtHg.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/clojure-BAuDPsal.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/coffee-BV06qSnj.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/cpp-Cz8Jeyrf.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/csharp-F6hhlXFb.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/csp-KzlEHCyI.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/css-e4FKntZ3.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/cssMode-BNkTa2xp.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/cypher-CpvDGKRr.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/dart-DdHeFWR0.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/datacontract-editor.css +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/datacontract-editor.es.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/dockerfile-aoNXDcio.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/ecl-C4Q0DYuA.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/elixir-C9X42b0T.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/flow9-Bff42pfB.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/freemarker2-Dyfzmb5A.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/fsharp-C6vPAsHG.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/go-DEr8zx9f.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/graphql-BiNBBRFh.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/handlebars-BtDNI-uC.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/hcl-2T9lKuFg.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/html-Cn4TGw_o.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/htmlMode-Bf84vbo2.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/index.html +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/ini-CZGtssYM.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/java-B260NeH3.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/javascript-B86Kac07.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/jsonMode-Ckgg5lAE.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/julia-kuNLM9c5.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/kotlin-Bz6kAefA.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/less-AZUtS89I.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/lexon-BcmgnyRb.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/liquid-D0NPwuu_.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/logo_fuchsia_v2.svg +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/lua-Dz1RbATg.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/m3-CIMooLFn.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/markdown-C1BsCK9P.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/mdx-QFRSBtVQ.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/mips-BovsnfLQ.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/monaco-4.7.0.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/msdax-CiRB2ZB-.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/mysql-BwdpPE19.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/objective-c-D4nfHfso.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/odcs.svg +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/pascal--j5-PYtz.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/pascaligo-C7TcJxNL.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/perl-BzEWqUb5.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/pgsql-B_KZ0mGX.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/php-A19QHzQV.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/pla-COeKY1hA.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/postiats-BfMp7zJL.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/powerquery-B0TS_5Gb.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/powershell-5jSbKdYB.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/protobuf-YgnOutn3.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/pug-DLej6kn5.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/python-C8RW9B6A.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/qsharp-AhjqtSHB.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/r-D-F4P80w.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/razor-CLZqdY_r.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/redis-hwwIlMnV.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/redshift-Bcm_kjEG.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/restructuredtext-CrdzfPP-.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/ruby-QC2UNm1s.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/rust-5aqiQ3L5.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/sb-B1g1ZfLJ.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/scala-C2U4R5Gb.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/scheme-DeFRbslr.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/scss-RSTCiCmI.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/shell-BpF-iNu8.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/solidity-C00r2mbQ.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/sophia-DVW5ZKDB.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/sparql-B0nmpxeX.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/sql-CJwKPERn.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/st-DPlKG5DT.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/swift-YZBAbVHV.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/systemverilog-CDQSaH63.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/tcl-Dlu8sp6Q.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/tsMode-yleMwhPq.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/twig-C5TO7-kw.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/typescript-CJBeebKU.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/typespec-BsmjDEu7.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/vb-ChHvIDrk.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/wgsl-XEp1ju8c.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/xml-vC-NMVX1.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/editor_assets/yaml-Dlf2VF-T.js +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/__init__.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/checks/__init__.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/checks/check_spec.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/checks/create_checks.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/checks/physical_type_match.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/data_contract_test.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/datacontract/check_azure_blob_file.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/datacontract/check_that_datacontract_contains_valid_servers_configuration.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/datacontract/check_that_datacontract_file_exists.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/fastjsonschema/check_jsonschema.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/fastjsonschema/s3/s3_read_files.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/ibis/__init__.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/ibis/connections/__init__.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/ibis/connections/connect.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/ibis/connections/duckdb_connection.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/ibis/connections/kafka.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/ibis/connections/oracle_patch.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/ibis/connections/redshift_patch.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/ibis/native_type.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/__init__.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/avro_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/avro_idl_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/bigquery_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/custom_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/data_caterer_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/dbml_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/dbt_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/dcs_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/dqx_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/duckdb_type_converter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/excel_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/exporter_factory.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/go_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/great_expectations_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/html_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/iceberg_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/jsonschema_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/markdown_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/mermaid_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/odcs_export_helper.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/odcs_v3_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/pandas_type_converter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/protobuf_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/pydantic_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/rdf_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/sodacl_check_builder.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/sodacl_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/spark_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/sql_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/sql_type_converter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/export/sqlalchemy_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/avro_importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/bigquery_importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/csv_importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/dbml_importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/dbt_importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/dcs_importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/excel_importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/glue_importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/iceberg_importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/importer_factory.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/json_importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/jsonschema_importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/odcs_helper.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/odcs_importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/parquet_importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/powerbi_importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/protobuf_importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/snowflake_importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/spark_importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/sql_importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/imports/unity_importer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/init/init_template.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/integration/dbt_sync.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/integration/dbt_test_mapping.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/integration/entropy_data.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/lint/files.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/lint/resolve.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/lint/resources.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/lint/schema.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/lint/urls.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/model/changelog.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/model/exceptions.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/model/odcs.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/model/run.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/model/server.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/output/__init__.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/output/ci_output.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/output/json_test_results.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/output/junit_test_results.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/output/output_format.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/output/test_results_writer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/output/text_changelog_results.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/py.typed +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/schemas/datacontract-1.1.0.init.yaml +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/schemas/datacontract-1.1.0.schema.json +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/schemas/datacontract-1.2.0.init.yaml +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/schemas/datacontract-1.2.0.schema.json +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/schemas/datacontract-1.2.1.init.yaml +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/schemas/datacontract-1.2.1.schema.json +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/schemas/odcs-3.0.1.schema.json +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/schemas/odcs-3.0.2.schema.json +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/schemas/odcs-3.1.0.init.yaml +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/schemas/odcs-3.1.0.schema.json +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/templates/datacontract.html +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/templates/datacontract_odcs.html +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/templates/index.html +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/templates/partials/datacontract_information.html +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/templates/partials/datacontract_servicelevels.html +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/templates/partials/datacontract_terms.html +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/templates/partials/definition.html +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/templates/partials/example.html +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/templates/partials/model_field.html +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/templates/partials/quality.html +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/templates/partials/server.html +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/templates/style/output.css +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract_cli.egg-info/dependency_links.txt +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract_cli.egg-info/entry_points.txt +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract_cli.egg-info/requires.txt +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract_cli.egg-info/top_level.txt +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/setup.cfg +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_api.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_catalog.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_changelog.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_changelog_engine.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_changelog_normalize.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_changelog_output_text.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_ci_output.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_cli.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_connect_databricks.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_connect_sqlserver.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_connect_trino.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_create_checks_physical_type.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_data_contract.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_data_contract_checks.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_data_contract_specification.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_dbt_sync.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_dbt_test_mapping.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_description_linter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_download_datacontract_file.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_duckdb_json.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_edit.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_avro.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_avro_idl.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_bigquery.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_complex_data_contract.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_custom.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_custom_exporter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_custom_model.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_data_caterer.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_dbml.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_dbt_models.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_dbt_sources.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_dbt_staging_sql.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_dqx.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_excel.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_go.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_great_expectations.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_html.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_iceberg.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_jsonschema.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_markdown.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_mermaid.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_odcs_v3.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_protobuf.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_pydantic.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_rdf.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_sodacl.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_spark.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_sql.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_sql_clickhouse.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_sql_query.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_export_sqlalchemy.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_ibis_mssql_pattern.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_ibis_oracle_schema.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_avro.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_bigquery.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_csv.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_dbml.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_dbt.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_excel.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_glue.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_iceberg.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_json.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_jsonschema.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_odcs_v3.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_parquet.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_powerbi.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_protobuf.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_snowflake.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_spark.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_sql_oracle.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_sql_postgres.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_sql_snowflake.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_sql_sqlserver.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_import_unity_file.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_integration_entropydata.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_lint.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_oracle_patch.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_physical_type_match.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_redshift_patch.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_require_env.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_resolve.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_resolve_definitions.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_roundtrip_jsonschema.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_sql_type_converter_physicaltype.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_api.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_athena_iceberg.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_azure_blob_file.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_azure_remote.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_bigquery.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_checks_filter.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_databricks.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_delta.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_diagnostics.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_failed_samples.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_gcs_csv_remote.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_gcs_json_remote.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_kafka.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_kafka_remote.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_local_json.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_local_json_nd.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_mysql.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_oracle.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_oracle_xe.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_output_json.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_output_junit.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_parquet.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_postgres.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_quality.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_quality_local_fallback.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_quality_percent_severity.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_redshift.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_s3_csv.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_s3_delta.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_s3_json.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_s3_json_complex.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_s3_json_multiple_models.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_s3_json_remote.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_schema_evolution.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_server_not_found.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_snowflake.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_soda_connection_error.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_sqlserver.py +0 -0
- {datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/tests/test_test_trino.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: datacontract-cli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.12
|
|
4
4
|
Summary: The datacontract CLI is an open source command-line tool for working with Data Contracts. It uses data contract YAML files to lint the data contract, connect to data sources and execute schema and quality tests, detect breaking changes, and export to different formats. The tool is written in Python. It can be used as a standalone CLI tool, in a CI/CD pipeline, or directly as a Python library.
|
|
5
5
|
Author-email: Jochen Christ <jochen.christ@innoq.com>, Stefan Negele <stefan.negele@innoq.com>, Simon Harrer <simon.harrer@innoq.com>
|
|
6
6
|
License-Expression: MIT
|
{datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/checks/type_normalize.py
RENAMED
|
@@ -14,6 +14,13 @@ import re
|
|
|
14
14
|
|
|
15
15
|
from open_data_contract_standard.model import SchemaProperty
|
|
16
16
|
|
|
17
|
+
# logicalType marker for a field whose type the backend cannot describe: a
|
|
18
|
+
# dynamically-typed column (ibis json: Snowflake VARIANT, Postgres JSONB,
|
|
19
|
+
# BigQuery JSON) or an unsupported one (binary, geography). No declared type can
|
|
20
|
+
# be confirmed against it, so any expected type fails rather than silently passing.
|
|
21
|
+
# Distinct from a missing field, which is what dropping it would look like.
|
|
22
|
+
UNKNOWN_LOGICAL_TYPE = "__unknown__"
|
|
23
|
+
|
|
17
24
|
|
|
18
25
|
def normalize_type_name(type_name: str | None) -> str | None:
|
|
19
26
|
"""Map a contract type name (logical or physical) to one of the 9 ODCS categories.
|
|
@@ -139,6 +146,8 @@ def schema_property_matches(expected: SchemaProperty | None, actual: SchemaPrope
|
|
|
139
146
|
if expected_base is None:
|
|
140
147
|
return True
|
|
141
148
|
if actual_base is None:
|
|
149
|
+
# actual is unsupported or dynamically typed (json element/variant): a
|
|
150
|
+
# declared concrete type can't be confirmed against it, so it fails.
|
|
142
151
|
return False
|
|
143
152
|
if expected_base != actual_base and not (expected_base in _NUMERIC and actual_base in _NUMERIC):
|
|
144
153
|
return False
|
|
@@ -151,6 +160,8 @@ def schema_property_matches(expected: SchemaProperty | None, actual: SchemaPrope
|
|
|
151
160
|
if expected_base == "object":
|
|
152
161
|
if not expected.properties:
|
|
153
162
|
return True
|
|
163
|
+
# actual.properties is None for an untyped object (ibis map/variant): the
|
|
164
|
+
# empty lookup below fails every declared field, which is what we want.
|
|
154
165
|
actual_by_name = {p.name.lower(): p for p in (actual.properties or []) if p.name}
|
|
155
166
|
for exp_field in expected.properties:
|
|
156
167
|
if not exp_field.name:
|
|
@@ -197,13 +208,22 @@ def schema_property_mismatch_reasons(
|
|
|
197
208
|
exp_str = expected.logicalType or expected.physicalType
|
|
198
209
|
errors.append(f"{field_label}: expected type '{exp_str}' but the column type could not be determined")
|
|
199
210
|
return errors
|
|
200
|
-
|
|
201
211
|
expected_base = normalize_type_name(expected.logicalType or expected.physicalType)
|
|
202
212
|
actual_base = normalize_type_name(actual.logicalType or actual.physicalType)
|
|
203
213
|
|
|
204
214
|
if expected_base is None:
|
|
205
215
|
return errors
|
|
206
216
|
|
|
217
|
+
if actual_base is None:
|
|
218
|
+
exp_str = expected.logicalType or expected.physicalType
|
|
219
|
+
act_str = actual.physicalType or "unknown"
|
|
220
|
+
errors.append(
|
|
221
|
+
f"{field_label}: has type '{act_str}', but the contract specifies '{exp_str}'. "
|
|
222
|
+
f"A '{act_str}' value has no verifiable logical type. "
|
|
223
|
+
f"If this is intentional, specify `physicalType: {act_str}`."
|
|
224
|
+
)
|
|
225
|
+
return errors
|
|
226
|
+
|
|
207
227
|
if expected_base != actual_base and not (expected_base in _NUMERIC and actual_base in _NUMERIC):
|
|
208
228
|
exp_str = expected.logicalType or expected.physicalType
|
|
209
229
|
act_str = actual.logicalType or actual.physicalType
|
|
@@ -218,6 +238,12 @@ def schema_property_mismatch_reasons(
|
|
|
218
238
|
if expected_base == "object":
|
|
219
239
|
if not expected.properties:
|
|
220
240
|
return errors
|
|
241
|
+
if actual.properties is None:
|
|
242
|
+
errors.append(
|
|
243
|
+
f"{field_label}: declared with nested fields but the column is an untyped object "
|
|
244
|
+
"(map/variant) whose structure can't be verified; use a structured type or specify physicalType"
|
|
245
|
+
)
|
|
246
|
+
return errors
|
|
221
247
|
|
|
222
248
|
actual_by_name = {p.name.lower(): p for p in (actual.properties or []) if p.name}
|
|
223
249
|
for exp_field in expected.properties:
|
{datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/ibis/dtype_category.py
RENAMED
|
@@ -6,6 +6,8 @@ from typing import TYPE_CHECKING
|
|
|
6
6
|
|
|
7
7
|
from open_data_contract_standard.model import SchemaProperty
|
|
8
8
|
|
|
9
|
+
from datacontract.engines.checks.type_normalize import UNKNOWN_LOGICAL_TYPE
|
|
10
|
+
|
|
9
11
|
if TYPE_CHECKING:
|
|
10
12
|
from ibis.expr.datatypes import DataType
|
|
11
13
|
|
|
@@ -48,13 +50,14 @@ def ibis_dtype_category(dtype) -> str:
|
|
|
48
50
|
return "other"
|
|
49
51
|
|
|
50
52
|
|
|
51
|
-
def ibis_dtype_to_schema_property(dtype: DataType) -> SchemaProperty
|
|
53
|
+
def ibis_dtype_to_schema_property(dtype: DataType) -> SchemaProperty:
|
|
52
54
|
"""Map an ibis DataType to a SchemaProperty for structural type comparison.
|
|
53
55
|
|
|
54
56
|
Returns a ``SchemaProperty`` with ``logicalType`` set to one of the 9 ODCS
|
|
55
57
|
categories, recursively populating ``properties`` for structs and ``items``
|
|
56
|
-
for arrays.
|
|
57
|
-
|
|
58
|
+
for arrays. A type that carries no verifiable logical type (json, binary,
|
|
59
|
+
null, …) becomes ``UNKNOWN_LOGICAL_TYPE`` with the actual type kept in
|
|
60
|
+
``physicalType``, so the failure message can name it.
|
|
58
61
|
"""
|
|
59
62
|
try:
|
|
60
63
|
if dtype.is_boolean():
|
|
@@ -74,20 +77,25 @@ def ibis_dtype_to_schema_property(dtype: DataType) -> SchemaProperty | None:
|
|
|
74
77
|
if dtype.is_struct():
|
|
75
78
|
properties = []
|
|
76
79
|
for field_name, ftype in dtype.fields.items():
|
|
80
|
+
# an unverifiable field type is still a field: keep it, so it is not reported missing
|
|
77
81
|
child = ibis_dtype_to_schema_property(ftype)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
)
|
|
82
|
+
properties.append(
|
|
83
|
+
SchemaProperty(
|
|
84
|
+
name=field_name,
|
|
85
|
+
logicalType=child.logicalType,
|
|
86
|
+
physicalType=child.physicalType,
|
|
87
|
+
items=child.items,
|
|
88
|
+
properties=child.properties,
|
|
86
89
|
)
|
|
87
|
-
|
|
90
|
+
)
|
|
91
|
+
return SchemaProperty(logicalType="object", properties=properties)
|
|
88
92
|
if dtype.is_array():
|
|
89
93
|
element = ibis_dtype_to_schema_property(dtype.value_type)
|
|
90
94
|
return SchemaProperty(logicalType="array", items=element)
|
|
95
|
+
if dtype.is_map():
|
|
96
|
+
# base is confirmable, inner values are not (yet)
|
|
97
|
+
return SchemaProperty(logicalType="object", properties=None)
|
|
91
98
|
except AttributeError:
|
|
92
|
-
return
|
|
93
|
-
|
|
99
|
+
return SchemaProperty(logicalType=UNKNOWN_LOGICAL_TYPE)
|
|
100
|
+
# json holds a different type per row; binary and null have no ODCS category
|
|
101
|
+
return SchemaProperty(logicalType=UNKNOWN_LOGICAL_TYPE, physicalType=str(dtype))
|
{datacontract_cli-1.0.11 → datacontract_cli-1.0.12}/datacontract/engines/ibis/ibis_check_execute.py
RENAMED
|
@@ -14,7 +14,7 @@ import uuid
|
|
|
14
14
|
from collections import defaultdict
|
|
15
15
|
from typing import List, Optional
|
|
16
16
|
|
|
17
|
-
from open_data_contract_standard.model import OpenDataContractStandard, Server
|
|
17
|
+
from open_data_contract_standard.model import OpenDataContractStandard, SchemaProperty, Server
|
|
18
18
|
|
|
19
19
|
from datacontract.engines.checks.check_spec import CheckSpec, MetricType
|
|
20
20
|
from datacontract.engines.checks.physical_type_match import physical_type_matches
|
|
@@ -22,6 +22,7 @@ from datacontract.engines.checks.type_normalize import schema_property_matches,
|
|
|
22
22
|
from datacontract.engines.ibis.connections.connect import connect_ibis
|
|
23
23
|
from datacontract.engines.ibis.dtype_category import ibis_dtype_to_schema_property
|
|
24
24
|
from datacontract.engines.ibis.native_type import fetch_native_types, sqlglot_dialect
|
|
25
|
+
from datacontract.engines.ibis.snowflake_structured_types import fetch_structured_types, has_nesting
|
|
25
26
|
from datacontract.model.exceptions import DataContractException
|
|
26
27
|
from datacontract.model.run import Check, ResultEnum, Run
|
|
27
28
|
from datacontract.model.server import get_server_type
|
|
@@ -196,6 +197,14 @@ def _run_model(
|
|
|
196
197
|
if any(spec.metric == MetricType.FIELD_PHYSICAL_TYPE for spec in specs):
|
|
197
198
|
native_types = fetch_native_types(con, server, model)
|
|
198
199
|
|
|
200
|
+
# Snowflake collapses structured OBJECT/ARRAY nesting in the ibis dtype; read
|
|
201
|
+
# the real nested types from SHOW COLUMNS so field_type checks can recurse.
|
|
202
|
+
structured_types = None
|
|
203
|
+
if get_server_type(server) == "snowflake" and any(
|
|
204
|
+
spec.metric in (MetricType.FIELD_TYPE, MetricType.FIELD_PHYSICAL_TYPE) for spec in specs
|
|
205
|
+
):
|
|
206
|
+
structured_types = fetch_structured_types(con, server, t.get_name())
|
|
207
|
+
|
|
199
208
|
agg_exprs = [] # list[(spec, named_expr)]
|
|
200
209
|
for spec in specs:
|
|
201
210
|
try:
|
|
@@ -219,9 +228,9 @@ def _run_model(
|
|
|
219
228
|
elif spec.metric == MetricType.FIELD_PRESENT:
|
|
220
229
|
_run_present(run, con, model, columns, spec)
|
|
221
230
|
elif spec.metric == MetricType.FIELD_TYPE:
|
|
222
|
-
_run_type(run, schema, columns, spec)
|
|
231
|
+
_run_type(run, schema, columns, spec, structured_types)
|
|
223
232
|
elif spec.metric == MetricType.FIELD_PHYSICAL_TYPE:
|
|
224
|
-
_run_physical_type(run, con, server, schema, columns, native_types, spec)
|
|
233
|
+
_run_physical_type(run, con, server, schema, columns, native_types, spec, structured_types)
|
|
225
234
|
elif spec.metric in (MetricType.FRESHNESS, MetricType.RETENTION):
|
|
226
235
|
_run_freshness(run, t, columns, spec)
|
|
227
236
|
elif spec.metric == MetricType.CUSTOM_SQL:
|
|
@@ -615,7 +624,7 @@ def _run_present(run: Run, con, model: str, columns, spec: CheckSpec):
|
|
|
615
624
|
)
|
|
616
625
|
|
|
617
626
|
|
|
618
|
-
def _run_type(run: Run, schema, columns, spec: CheckSpec):
|
|
627
|
+
def _run_type(run: Run, schema, columns, spec: CheckSpec, structured_types: dict[str, SchemaProperty] | None = None):
|
|
619
628
|
_set_impl(
|
|
620
629
|
run,
|
|
621
630
|
spec.key,
|
|
@@ -628,11 +637,19 @@ def _run_type(run: Run, schema, columns, spec: CheckSpec):
|
|
|
628
637
|
_set_result(run, spec.key, ResultEnum.failed, f"Column '{spec.field}' is missing")
|
|
629
638
|
return
|
|
630
639
|
dtype = schema[actual_col]
|
|
631
|
-
|
|
640
|
+
# Snowflake structured types come back collapsed from ibis; prefer the nested
|
|
641
|
+
# tree recovered from SHOW COLUMNS when available.
|
|
642
|
+
structured_prop = structured_types.get(spec.field.lower()) if structured_types else None
|
|
643
|
+
actual_prop = structured_prop or ibis_dtype_to_schema_property(dtype)
|
|
632
644
|
_set_diagnostics(
|
|
633
645
|
run,
|
|
634
646
|
spec.key,
|
|
635
|
-
_diag(
|
|
647
|
+
_diag(
|
|
648
|
+
metric="field_type",
|
|
649
|
+
field=spec.field,
|
|
650
|
+
expected=spec.expected_type_label,
|
|
651
|
+
actual=structured_prop.physicalType if structured_prop else str(dtype),
|
|
652
|
+
),
|
|
636
653
|
)
|
|
637
654
|
if schema_property_matches(spec.expected_schema_property, actual_prop):
|
|
638
655
|
_set_result(run, spec.key, ResultEnum.passed, None)
|
|
@@ -646,7 +663,16 @@ def _run_type(run: Run, schema, columns, spec: CheckSpec):
|
|
|
646
663
|
)
|
|
647
664
|
|
|
648
665
|
|
|
649
|
-
def _run_physical_type(
|
|
666
|
+
def _run_physical_type(
|
|
667
|
+
run: Run,
|
|
668
|
+
con,
|
|
669
|
+
server,
|
|
670
|
+
schema,
|
|
671
|
+
columns,
|
|
672
|
+
native_types,
|
|
673
|
+
spec: CheckSpec,
|
|
674
|
+
structured_types: dict[str, SchemaProperty] | None = None,
|
|
675
|
+
):
|
|
650
676
|
"""Compare a column's real native type against the contract's physicalType.
|
|
651
677
|
|
|
652
678
|
When the native type cannot be read for this backend, or the declared
|
|
@@ -668,7 +694,13 @@ def _run_physical_type(run: Run, con, server, schema, columns, native_types, spe
|
|
|
668
694
|
_set_result(run, spec.key, ResultEnum.failed, f"Column '{spec.field}' is missing")
|
|
669
695
|
return
|
|
670
696
|
|
|
671
|
-
|
|
697
|
+
# The catalog reports a structured OBJECT/ARRAY as its bare token, dropping the
|
|
698
|
+
# nested types; the tree recovered from SHOW COLUMNS renders the real native type.
|
|
699
|
+
structured_prop = structured_types.get(spec.field.lower()) if structured_types else None
|
|
700
|
+
if structured_prop is not None and has_nesting(structured_prop):
|
|
701
|
+
actual_native = structured_prop.physicalType
|
|
702
|
+
else:
|
|
703
|
+
actual_native = native_types.get(spec.field.lower()) if native_types else None
|
|
672
704
|
_set_diagnostics(
|
|
673
705
|
run,
|
|
674
706
|
spec.key,
|
|
@@ -697,16 +729,17 @@ def _run_physical_type(run: Run, con, server, schema, columns, native_types, spe
|
|
|
697
729
|
# logicalType category check when the property declares one.
|
|
698
730
|
fallback = spec.expected_schema_property
|
|
699
731
|
if fallback is not None and fallback.logicalType is not None:
|
|
700
|
-
actual_prop = ibis_dtype_to_schema_property(schema[actual_col])
|
|
732
|
+
actual_prop = structured_prop or ibis_dtype_to_schema_property(schema[actual_col])
|
|
701
733
|
if schema_property_matches(fallback, actual_prop):
|
|
702
734
|
_set_result(run, spec.key, ResultEnum.passed, None)
|
|
703
735
|
else:
|
|
704
736
|
mismatch = schema_property_mismatch_reason(fallback, actual_prop)
|
|
737
|
+
actual_label = actual_native or schema[actual_col]
|
|
705
738
|
_set_result(
|
|
706
739
|
run,
|
|
707
740
|
spec.key,
|
|
708
741
|
ResultEnum.failed,
|
|
709
|
-
mismatch or f"Expected type '{fallback.logicalType}' but column is '{
|
|
742
|
+
mismatch or f"Expected type '{fallback.logicalType}' but column is '{actual_label}'",
|
|
710
743
|
)
|
|
711
744
|
return
|
|
712
745
|
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""Rebuild Snowflake structured OBJECT/ARRAY nesting, which ibis collapses, from SHOW COLUMNS."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
|
|
7
|
+
from open_data_contract_standard.model import SchemaProperty, Server
|
|
8
|
+
|
|
9
|
+
from datacontract.engines.checks.type_normalize import UNKNOWN_LOGICAL_TYPE
|
|
10
|
+
from datacontract.engines.ibis.native_type import _quote, _rows
|
|
11
|
+
|
|
12
|
+
# SHOW COLUMNS leaf ``type`` tokens -> ODCS logical type. FIXED and REAL both map
|
|
13
|
+
# to "number" (the comparator treats integer/number as compatible). Tokens not
|
|
14
|
+
# listed (BINARY, GEOGRAPHY, VARIANT, …) carry no verifiable logical type.
|
|
15
|
+
_LEAF_TYPES = {
|
|
16
|
+
"FIXED": "number",
|
|
17
|
+
"REAL": "number",
|
|
18
|
+
"TEXT": "string",
|
|
19
|
+
"BOOLEAN": "boolean",
|
|
20
|
+
"DATE": "date",
|
|
21
|
+
"TIME": "time",
|
|
22
|
+
"TIMESTAMP_NTZ": "timestamp",
|
|
23
|
+
"TIMESTAMP_LTZ": "timestamp",
|
|
24
|
+
"TIMESTAMP_TZ": "timestamp",
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _to_property(node: dict) -> SchemaProperty:
|
|
29
|
+
"""Convert one ``data_type`` JSON node to a ``SchemaProperty``."""
|
|
30
|
+
node_type = node.get("type")
|
|
31
|
+
if node_type == "OBJECT":
|
|
32
|
+
fields = node.get("fields")
|
|
33
|
+
if not fields:
|
|
34
|
+
# untyped OBJECT: same shape as the collapsed ibis map
|
|
35
|
+
return SchemaProperty(logicalType="object", properties=None)
|
|
36
|
+
properties = []
|
|
37
|
+
for field in fields:
|
|
38
|
+
name = field.get("fieldName")
|
|
39
|
+
if not name:
|
|
40
|
+
continue
|
|
41
|
+
child = _to_property(field.get("fieldType") or {})
|
|
42
|
+
properties.append(
|
|
43
|
+
SchemaProperty(
|
|
44
|
+
name=name,
|
|
45
|
+
logicalType=child.logicalType,
|
|
46
|
+
physicalType=child.physicalType,
|
|
47
|
+
items=child.items,
|
|
48
|
+
properties=child.properties,
|
|
49
|
+
)
|
|
50
|
+
)
|
|
51
|
+
return SchemaProperty(logicalType="object", properties=properties or None)
|
|
52
|
+
if node_type == "ARRAY":
|
|
53
|
+
element = node.get("elementType")
|
|
54
|
+
# untyped ARRAY: no element type to recurse into
|
|
55
|
+
return SchemaProperty(logicalType="array", items=_to_property(element) if element else None)
|
|
56
|
+
if node_type == "MAP":
|
|
57
|
+
# dynamic keys can't be matched to named contract properties
|
|
58
|
+
return SchemaProperty(logicalType="object", properties=None)
|
|
59
|
+
logical = _LEAF_TYPES.get(node_type)
|
|
60
|
+
if logical:
|
|
61
|
+
return SchemaProperty(logicalType=logical)
|
|
62
|
+
# VARIANT, BINARY, GEOGRAPHY, …: keep the Snowflake token for the failure message
|
|
63
|
+
return SchemaProperty(logicalType=UNKNOWN_LOGICAL_TYPE, physicalType=node_type)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def has_nesting(prop: SchemaProperty) -> bool:
|
|
67
|
+
"""True only when the property is a structured OBJECT/ARRAY worth substituting."""
|
|
68
|
+
return bool(prop.properties) or prop.items is not None
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _render_native(node: dict) -> str:
|
|
72
|
+
"""Render one ``data_type`` JSON node back to its Snowflake type string."""
|
|
73
|
+
node_type = node.get("type")
|
|
74
|
+
if node_type == "OBJECT":
|
|
75
|
+
fields = node.get("fields")
|
|
76
|
+
if not fields:
|
|
77
|
+
return "OBJECT"
|
|
78
|
+
rendered = [
|
|
79
|
+
f"{field['fieldName']} {_render_native(field.get('fieldType') or {})}"
|
|
80
|
+
for field in fields
|
|
81
|
+
if field.get("fieldName")
|
|
82
|
+
]
|
|
83
|
+
return "OBJECT({})".format(", ".join(rendered)) if rendered else "OBJECT"
|
|
84
|
+
if node_type == "ARRAY":
|
|
85
|
+
element = node.get("elementType")
|
|
86
|
+
return "ARRAY({})".format(_render_native(element)) if element else "ARRAY"
|
|
87
|
+
if node_type == "MAP":
|
|
88
|
+
key, value = node.get("keyType"), node.get("valueType")
|
|
89
|
+
if key and value:
|
|
90
|
+
return "MAP({}, {})".format(_render_native(key), _render_native(value))
|
|
91
|
+
return "MAP"
|
|
92
|
+
if node_type == "FIXED":
|
|
93
|
+
return "NUMBER({},{})".format(node.get("precision", 38), node.get("scale", 0))
|
|
94
|
+
if node_type == "REAL":
|
|
95
|
+
return "FLOAT"
|
|
96
|
+
if node_type == "TEXT":
|
|
97
|
+
length = node.get("length")
|
|
98
|
+
return f"VARCHAR({length})" if length is not None else "VARCHAR"
|
|
99
|
+
return str(node_type)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def fetch_structured_types(con, server: Server, table_name: str) -> dict[str, SchemaProperty] | None:
|
|
103
|
+
"""Return ``{column_name_lower: SchemaProperty}`` for the columns whose real type
|
|
104
|
+
the collapsed ibis dtype does not convey: structured OBJECT/ARRAY, and leaves with
|
|
105
|
+
no verifiable logical type. Other columns are omitted. Any failure returns ``None``.
|
|
106
|
+
"""
|
|
107
|
+
quoted_table = '"{}"'.format(table_name.replace('"', '""'))
|
|
108
|
+
path = ".".join(part for part in (server.database, server.schema_, quoted_table) if part)
|
|
109
|
+
identifier = "IDENTIFIER('{}')".format(_quote(path))
|
|
110
|
+
rows = _rows(con, f"SHOW COLUMNS IN TABLE {identifier}")
|
|
111
|
+
if not rows:
|
|
112
|
+
return None
|
|
113
|
+
|
|
114
|
+
# SHOW COLUMNS columns: table_name, schema_name, column_name, data_type, ...
|
|
115
|
+
result: dict[str, SchemaProperty] = {}
|
|
116
|
+
for row in rows:
|
|
117
|
+
column_name, data_type = row[2], row[3]
|
|
118
|
+
if not column_name or not data_type:
|
|
119
|
+
continue
|
|
120
|
+
try:
|
|
121
|
+
node = json.loads(data_type)
|
|
122
|
+
except (TypeError, ValueError):
|
|
123
|
+
continue
|
|
124
|
+
prop = _to_property(node)
|
|
125
|
+
if has_nesting(prop):
|
|
126
|
+
# the real native type, for diagnostics the collapsed ibis dtype can't give
|
|
127
|
+
prop.physicalType = _render_native(node)
|
|
128
|
+
elif prop.logicalType != UNKNOWN_LOGICAL_TYPE:
|
|
129
|
+
# scalars and untyped OBJECT/ARRAY: the collapsed ibis dtype says the same
|
|
130
|
+
continue
|
|
131
|
+
# an unverifiable leaf (VARIANT, GEOGRAPHY, …) keeps its Snowflake token, which
|
|
132
|
+
# the ibis dtype renders as the useless 'json'
|
|
133
|
+
result[str(column_name).lower()] = prop
|
|
134
|
+
return result or None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: datacontract-cli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.12
|
|
4
4
|
Summary: The datacontract CLI is an open source command-line tool for working with Data Contracts. It uses data contract YAML files to lint the data contract, connect to data sources and execute schema and quality tests, detect breaking changes, and export to different formats. The tool is written in Python. It can be used as a standalone CLI tool, in a CI/CD pipeline, or directly as a Python library.
|
|
5
5
|
Author-email: Jochen Christ <jochen.christ@innoq.com>, Stefan Negele <stefan.negele@innoq.com>, Simon Harrer <simon.harrer@innoq.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -133,6 +133,7 @@ datacontract/engines/ibis/__init__.py
|
|
|
133
133
|
datacontract/engines/ibis/dtype_category.py
|
|
134
134
|
datacontract/engines/ibis/ibis_check_execute.py
|
|
135
135
|
datacontract/engines/ibis/native_type.py
|
|
136
|
+
datacontract/engines/ibis/snowflake_structured_types.py
|
|
136
137
|
datacontract/engines/ibis/connections/__init__.py
|
|
137
138
|
datacontract/engines/ibis/connections/connect.py
|
|
138
139
|
datacontract/engines/ibis/connections/duckdb_connection.py
|
|
@@ -328,6 +329,7 @@ tests/test_require_env.py
|
|
|
328
329
|
tests/test_resolve.py
|
|
329
330
|
tests/test_resolve_definitions.py
|
|
330
331
|
tests/test_roundtrip_jsonschema.py
|
|
332
|
+
tests/test_snowflake_structured_types.py
|
|
331
333
|
tests/test_sql_type_converter_physicaltype.py
|
|
332
334
|
tests/test_test_api.py
|
|
333
335
|
tests/test_test_athena_iceberg.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "datacontract-cli"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.12"
|
|
4
4
|
description = "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
|
license = "MIT"
|
|
6
6
|
readme = "README.md"
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import ibis.expr.datatypes as dt
|
|
2
|
+
from open_data_contract_standard.model import SchemaProperty
|
|
3
|
+
|
|
4
|
+
from datacontract.engines.checks.type_normalize import (
|
|
5
|
+
UNKNOWN_LOGICAL_TYPE,
|
|
6
|
+
schema_property_matches,
|
|
7
|
+
schema_property_mismatch_reason,
|
|
8
|
+
)
|
|
9
|
+
from datacontract.engines.ibis.dtype_category import (
|
|
10
|
+
ibis_dtype_category,
|
|
11
|
+
ibis_dtype_to_schema_property,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_uuid_maps_to_string_category():
|
|
16
|
+
# SQL Server `uniqueidentifier` columns surface as ibis UUID; they must be
|
|
17
|
+
# treated as strings, not "other" (regression for #1354).
|
|
18
|
+
assert ibis_dtype_category(dt.UUID()) == "string"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_uuid_dtype_to_schema_property_is_string():
|
|
22
|
+
prop = ibis_dtype_to_schema_property(dt.UUID())
|
|
23
|
+
assert prop is not None
|
|
24
|
+
assert prop.logicalType == "string"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_uuid_column_matches_string_contract_property():
|
|
28
|
+
# A property declared as logicalType string (physicalType uniqueidentifier)
|
|
29
|
+
# must match a column ibis reports as UUID.
|
|
30
|
+
expected = SchemaProperty(logicalType="string", physicalType="uniqueidentifier")
|
|
31
|
+
actual = ibis_dtype_to_schema_property(dt.UUID())
|
|
32
|
+
assert schema_property_matches(expected, actual)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_json_maps_to_unknown_marker():
|
|
36
|
+
# Snowflake VARIANT / Postgres JSONB / BigQuery JSON reflect as ibis json.
|
|
37
|
+
prop = ibis_dtype_to_schema_property(dt.JSON())
|
|
38
|
+
assert prop.logicalType == UNKNOWN_LOGICAL_TYPE
|
|
39
|
+
assert prop.physicalType == "json"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_unsupported_types_are_unknown_and_name_themselves():
|
|
43
|
+
# binary/null have no ODCS category; the type is kept for the failure message
|
|
44
|
+
for dtype, name in ((dt.binary, "binary"), (dt.null, "null")):
|
|
45
|
+
prop = ibis_dtype_to_schema_property(dtype)
|
|
46
|
+
assert prop.logicalType == UNKNOWN_LOGICAL_TYPE
|
|
47
|
+
assert prop.physicalType == name
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_map_maps_to_untyped_object():
|
|
51
|
+
# Snowflake OBJECT reflects as ibis map<string, json>: base confirmable,
|
|
52
|
+
# inner structure unknowable (properties=None).
|
|
53
|
+
prop = ibis_dtype_to_schema_property(dt.Map(dt.string, dt.JSON()))
|
|
54
|
+
assert prop.logicalType == "object"
|
|
55
|
+
assert prop.properties is None
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_struct_keeps_unsupported_field_as_unknown():
|
|
59
|
+
# a binary field is present but unverifiable: keep it, so it is not reported missing
|
|
60
|
+
actual = ibis_dtype_to_schema_property(dt.Struct({"blob": dt.binary}))
|
|
61
|
+
assert [(p.name, p.logicalType, p.physicalType) for p in actual.properties] == [
|
|
62
|
+
("blob", UNKNOWN_LOGICAL_TYPE, "binary")
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
expected = SchemaProperty(logicalType="object", properties=[SchemaProperty(name="blob", logicalType="string")])
|
|
66
|
+
assert not schema_property_matches(expected, actual)
|
|
67
|
+
reason = schema_property_mismatch_reason(expected, actual)
|
|
68
|
+
assert "missing" not in reason
|
|
69
|
+
assert "field 'blob': has type 'binary'" in reason
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_struct_still_reports_a_genuinely_absent_field_as_missing():
|
|
73
|
+
actual = ibis_dtype_to_schema_property(dt.Struct({"blob": dt.binary}))
|
|
74
|
+
expected = SchemaProperty(logicalType="object", properties=[SchemaProperty(name="city", logicalType="string")])
|
|
75
|
+
assert not schema_property_matches(expected, actual)
|
|
76
|
+
assert schema_property_mismatch_reason(expected, actual) == "field 'city' is missing"
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def test_array_of_json_items_are_unknown():
|
|
80
|
+
# Snowflake ARRAY reflects as ibis array<json>: array base with an
|
|
81
|
+
# unknown-typed element.
|
|
82
|
+
prop = ibis_dtype_to_schema_property(dt.Array(dt.JSON()))
|
|
83
|
+
assert prop.logicalType == "array"
|
|
84
|
+
assert prop.items.logicalType == UNKNOWN_LOGICAL_TYPE
|