datacontract-cli 1.0.10__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.
Files changed (378) hide show
  1. {datacontract_cli-1.0.10/datacontract_cli.egg-info → datacontract_cli-1.0.12}/PKG-INFO +1 -1
  2. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/checks/physical_type_match.py +11 -1
  3. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/checks/type_normalize.py +27 -1
  4. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/ibis/dtype_category.py +22 -14
  5. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/ibis/ibis_check_execute.py +43 -10
  6. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/ibis/native_type.py +4 -0
  7. datacontract_cli-1.0.12/datacontract/engines/ibis/snowflake_structured_types.py +134 -0
  8. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/bigquery_importer.py +3 -2
  9. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/lint/resolve.py +40 -12
  10. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12/datacontract_cli.egg-info}/PKG-INFO +1 -1
  11. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract_cli.egg-info/SOURCES.txt +2 -0
  12. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/pyproject.toml +1 -1
  13. datacontract_cli-1.0.12/tests/test_dtype_category.py +84 -0
  14. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_physical_type_match.py +51 -0
  15. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_resolve_definitions.py +20 -1
  16. datacontract_cli-1.0.12/tests/test_snowflake_structured_types.py +236 -0
  17. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_dataframe.py +2 -2
  18. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_s3_json_remote.py +3 -0
  19. datacontract_cli-1.0.12/tests/test_type_normalize.py +92 -0
  20. datacontract_cli-1.0.10/tests/test_dtype_category.py +0 -28
  21. datacontract_cli-1.0.10/tests/test_type_normalize.py +0 -15
  22. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/LICENSE +0 -0
  23. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/MANIFEST.in +0 -0
  24. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/README.md +0 -0
  25. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/__init__.py +0 -0
  26. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/api.py +0 -0
  27. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/catalog/catalog.py +0 -0
  28. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/changelog/__init__.py +0 -0
  29. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/changelog/changelog.py +0 -0
  30. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/changelog/normalize.py +0 -0
  31. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/cli.py +0 -0
  32. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/command_api.py +0 -0
  33. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/command_catalog.py +0 -0
  34. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/command_changelog.py +0 -0
  35. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/command_ci.py +0 -0
  36. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/command_dbt.py +0 -0
  37. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/command_edit.py +0 -0
  38. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/command_export.py +0 -0
  39. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/command_import.py +0 -0
  40. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/command_init.py +0 -0
  41. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/command_lint.py +0 -0
  42. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/command_publish.py +0 -0
  43. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/command_test.py +0 -0
  44. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/data_contract.py +0 -0
  45. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/VERSION +0 -0
  46. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/abap-Bs8kvjsq.js +0 -0
  47. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/apex-Dspwrl5m.js +0 -0
  48. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/assets/editor.worker-4.7.0.js +0 -0
  49. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/assets/yaml.worker-4.7.0.js +0 -0
  50. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/azcli-k1BiOau1.js +0 -0
  51. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/bat-BIP72KWc.js +0 -0
  52. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/bicep-VhQeYhS3.js +0 -0
  53. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/cameligo-DnuAXtHg.js +0 -0
  54. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/clojure-BAuDPsal.js +0 -0
  55. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/coffee-BV06qSnj.js +0 -0
  56. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/cpp-Cz8Jeyrf.js +0 -0
  57. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/csharp-F6hhlXFb.js +0 -0
  58. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/csp-KzlEHCyI.js +0 -0
  59. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/css-e4FKntZ3.js +0 -0
  60. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/cssMode-BNkTa2xp.js +0 -0
  61. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/cypher-CpvDGKRr.js +0 -0
  62. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/dart-DdHeFWR0.js +0 -0
  63. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/datacontract-editor.css +0 -0
  64. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/datacontract-editor.es.js +0 -0
  65. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/dockerfile-aoNXDcio.js +0 -0
  66. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/ecl-C4Q0DYuA.js +0 -0
  67. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/elixir-C9X42b0T.js +0 -0
  68. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/flow9-Bff42pfB.js +0 -0
  69. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/freemarker2-Dyfzmb5A.js +0 -0
  70. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/fsharp-C6vPAsHG.js +0 -0
  71. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/go-DEr8zx9f.js +0 -0
  72. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/graphql-BiNBBRFh.js +0 -0
  73. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/handlebars-BtDNI-uC.js +0 -0
  74. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/hcl-2T9lKuFg.js +0 -0
  75. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/html-Cn4TGw_o.js +0 -0
  76. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/htmlMode-Bf84vbo2.js +0 -0
  77. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/index.html +0 -0
  78. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/ini-CZGtssYM.js +0 -0
  79. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/java-B260NeH3.js +0 -0
  80. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/javascript-B86Kac07.js +0 -0
  81. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/jsonMode-Ckgg5lAE.js +0 -0
  82. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/julia-kuNLM9c5.js +0 -0
  83. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/kotlin-Bz6kAefA.js +0 -0
  84. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/less-AZUtS89I.js +0 -0
  85. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/lexon-BcmgnyRb.js +0 -0
  86. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/liquid-D0NPwuu_.js +0 -0
  87. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/logo_fuchsia_v2.svg +0 -0
  88. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/lua-Dz1RbATg.js +0 -0
  89. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/m3-CIMooLFn.js +0 -0
  90. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/markdown-C1BsCK9P.js +0 -0
  91. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/mdx-QFRSBtVQ.js +0 -0
  92. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/mips-BovsnfLQ.js +0 -0
  93. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/monaco-4.7.0.js +0 -0
  94. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/msdax-CiRB2ZB-.js +0 -0
  95. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/mysql-BwdpPE19.js +0 -0
  96. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/objective-c-D4nfHfso.js +0 -0
  97. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/odcs.svg +0 -0
  98. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/pascal--j5-PYtz.js +0 -0
  99. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/pascaligo-C7TcJxNL.js +0 -0
  100. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/perl-BzEWqUb5.js +0 -0
  101. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/pgsql-B_KZ0mGX.js +0 -0
  102. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/php-A19QHzQV.js +0 -0
  103. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/pla-COeKY1hA.js +0 -0
  104. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/postiats-BfMp7zJL.js +0 -0
  105. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/powerquery-B0TS_5Gb.js +0 -0
  106. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/powershell-5jSbKdYB.js +0 -0
  107. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/protobuf-YgnOutn3.js +0 -0
  108. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/pug-DLej6kn5.js +0 -0
  109. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/python-C8RW9B6A.js +0 -0
  110. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/qsharp-AhjqtSHB.js +0 -0
  111. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/r-D-F4P80w.js +0 -0
  112. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/razor-CLZqdY_r.js +0 -0
  113. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/redis-hwwIlMnV.js +0 -0
  114. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/redshift-Bcm_kjEG.js +0 -0
  115. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/restructuredtext-CrdzfPP-.js +0 -0
  116. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/ruby-QC2UNm1s.js +0 -0
  117. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/rust-5aqiQ3L5.js +0 -0
  118. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/sb-B1g1ZfLJ.js +0 -0
  119. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/scala-C2U4R5Gb.js +0 -0
  120. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/scheme-DeFRbslr.js +0 -0
  121. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/scss-RSTCiCmI.js +0 -0
  122. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/shell-BpF-iNu8.js +0 -0
  123. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/solidity-C00r2mbQ.js +0 -0
  124. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/sophia-DVW5ZKDB.js +0 -0
  125. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/sparql-B0nmpxeX.js +0 -0
  126. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/sql-CJwKPERn.js +0 -0
  127. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/st-DPlKG5DT.js +0 -0
  128. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/swift-YZBAbVHV.js +0 -0
  129. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/systemverilog-CDQSaH63.js +0 -0
  130. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/tcl-Dlu8sp6Q.js +0 -0
  131. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/tsMode-yleMwhPq.js +0 -0
  132. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/twig-C5TO7-kw.js +0 -0
  133. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/typescript-CJBeebKU.js +0 -0
  134. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/typespec-BsmjDEu7.js +0 -0
  135. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/vb-ChHvIDrk.js +0 -0
  136. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/wgsl-XEp1ju8c.js +0 -0
  137. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/xml-vC-NMVX1.js +0 -0
  138. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/editor_assets/yaml-Dlf2VF-T.js +0 -0
  139. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/__init__.py +0 -0
  140. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/checks/__init__.py +0 -0
  141. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/checks/check_spec.py +0 -0
  142. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/checks/create_checks.py +0 -0
  143. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/data_contract_test.py +0 -0
  144. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/datacontract/check_azure_blob_file.py +0 -0
  145. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/datacontract/check_that_datacontract_contains_valid_servers_configuration.py +0 -0
  146. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/datacontract/check_that_datacontract_file_exists.py +0 -0
  147. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/fastjsonschema/check_jsonschema.py +0 -0
  148. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/fastjsonschema/s3/s3_read_files.py +0 -0
  149. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/ibis/__init__.py +0 -0
  150. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/ibis/connections/__init__.py +0 -0
  151. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/ibis/connections/connect.py +0 -0
  152. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/ibis/connections/duckdb_connection.py +0 -0
  153. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/ibis/connections/kafka.py +0 -0
  154. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/ibis/connections/oracle_patch.py +0 -0
  155. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/engines/ibis/connections/redshift_patch.py +0 -0
  156. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/__init__.py +0 -0
  157. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/avro_exporter.py +0 -0
  158. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/avro_idl_exporter.py +0 -0
  159. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/bigquery_exporter.py +0 -0
  160. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/custom_exporter.py +0 -0
  161. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/data_caterer_exporter.py +0 -0
  162. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/dbml_exporter.py +0 -0
  163. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/dbt_exporter.py +0 -0
  164. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/dcs_exporter.py +0 -0
  165. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/dqx_exporter.py +0 -0
  166. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/duckdb_type_converter.py +0 -0
  167. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/excel_exporter.py +0 -0
  168. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/exporter.py +0 -0
  169. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/exporter_factory.py +0 -0
  170. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/go_exporter.py +0 -0
  171. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/great_expectations_exporter.py +0 -0
  172. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/html_exporter.py +0 -0
  173. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/iceberg_exporter.py +0 -0
  174. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/jsonschema_exporter.py +0 -0
  175. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/markdown_exporter.py +0 -0
  176. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/mermaid_exporter.py +0 -0
  177. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/odcs_export_helper.py +0 -0
  178. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/odcs_v3_exporter.py +0 -0
  179. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/pandas_type_converter.py +0 -0
  180. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/protobuf_exporter.py +0 -0
  181. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/pydantic_exporter.py +0 -0
  182. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/rdf_exporter.py +0 -0
  183. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/sodacl_check_builder.py +0 -0
  184. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/sodacl_exporter.py +0 -0
  185. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/spark_exporter.py +0 -0
  186. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/sql_exporter.py +0 -0
  187. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/sql_type_converter.py +0 -0
  188. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/export/sqlalchemy_exporter.py +0 -0
  189. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/avro_importer.py +0 -0
  190. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/csv_importer.py +0 -0
  191. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/dbml_importer.py +0 -0
  192. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/dbt_importer.py +0 -0
  193. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/dcs_importer.py +0 -0
  194. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/excel_importer.py +0 -0
  195. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/glue_importer.py +0 -0
  196. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/iceberg_importer.py +0 -0
  197. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/importer.py +0 -0
  198. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/importer_factory.py +0 -0
  199. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/json_importer.py +0 -0
  200. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/jsonschema_importer.py +0 -0
  201. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/odcs_helper.py +0 -0
  202. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/odcs_importer.py +0 -0
  203. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/parquet_importer.py +0 -0
  204. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/powerbi_importer.py +0 -0
  205. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/protobuf_importer.py +0 -0
  206. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/snowflake_importer.py +0 -0
  207. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/spark_importer.py +0 -0
  208. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/sql_importer.py +0 -0
  209. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/imports/unity_importer.py +0 -0
  210. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/init/init_template.py +0 -0
  211. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/integration/dbt_sync.py +0 -0
  212. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/integration/dbt_test_mapping.py +0 -0
  213. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/integration/entropy_data.py +0 -0
  214. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/lint/files.py +0 -0
  215. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/lint/resources.py +0 -0
  216. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/lint/schema.py +0 -0
  217. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/lint/urls.py +0 -0
  218. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/model/changelog.py +0 -0
  219. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/model/exceptions.py +0 -0
  220. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/model/odcs.py +0 -0
  221. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/model/run.py +0 -0
  222. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/model/server.py +0 -0
  223. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/output/__init__.py +0 -0
  224. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/output/ci_output.py +0 -0
  225. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/output/json_test_results.py +0 -0
  226. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/output/junit_test_results.py +0 -0
  227. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/output/output_format.py +0 -0
  228. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/output/test_results_writer.py +0 -0
  229. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/output/text_changelog_results.py +0 -0
  230. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/py.typed +0 -0
  231. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/schemas/datacontract-1.1.0.init.yaml +0 -0
  232. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/schemas/datacontract-1.1.0.schema.json +0 -0
  233. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/schemas/datacontract-1.2.0.init.yaml +0 -0
  234. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/schemas/datacontract-1.2.0.schema.json +0 -0
  235. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/schemas/datacontract-1.2.1.init.yaml +0 -0
  236. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/schemas/datacontract-1.2.1.schema.json +0 -0
  237. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/schemas/odcs-3.0.1.schema.json +0 -0
  238. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/schemas/odcs-3.0.2.schema.json +0 -0
  239. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/schemas/odcs-3.1.0.init.yaml +0 -0
  240. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/schemas/odcs-3.1.0.schema.json +0 -0
  241. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/templates/datacontract.html +0 -0
  242. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/templates/datacontract_odcs.html +0 -0
  243. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/templates/index.html +0 -0
  244. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/templates/partials/datacontract_information.html +0 -0
  245. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/templates/partials/datacontract_servicelevels.html +0 -0
  246. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/templates/partials/datacontract_terms.html +0 -0
  247. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/templates/partials/definition.html +0 -0
  248. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/templates/partials/example.html +0 -0
  249. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/templates/partials/model_field.html +0 -0
  250. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/templates/partials/quality.html +0 -0
  251. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/templates/partials/server.html +0 -0
  252. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract/templates/style/output.css +0 -0
  253. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract_cli.egg-info/dependency_links.txt +0 -0
  254. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract_cli.egg-info/entry_points.txt +0 -0
  255. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract_cli.egg-info/requires.txt +0 -0
  256. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/datacontract_cli.egg-info/top_level.txt +0 -0
  257. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/setup.cfg +0 -0
  258. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_api.py +0 -0
  259. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_catalog.py +0 -0
  260. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_changelog.py +0 -0
  261. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_changelog_engine.py +0 -0
  262. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_changelog_normalize.py +0 -0
  263. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_changelog_output_text.py +0 -0
  264. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_ci_output.py +0 -0
  265. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_cli.py +0 -0
  266. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_connect_databricks.py +0 -0
  267. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_connect_sqlserver.py +0 -0
  268. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_connect_trino.py +0 -0
  269. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_create_checks_physical_type.py +0 -0
  270. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_data_contract.py +0 -0
  271. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_data_contract_checks.py +0 -0
  272. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_data_contract_specification.py +0 -0
  273. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_dbt_sync.py +0 -0
  274. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_dbt_test_mapping.py +0 -0
  275. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_description_linter.py +0 -0
  276. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_download_datacontract_file.py +0 -0
  277. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_duckdb_json.py +0 -0
  278. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_edit.py +0 -0
  279. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_avro.py +0 -0
  280. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_avro_idl.py +0 -0
  281. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_bigquery.py +0 -0
  282. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_complex_data_contract.py +0 -0
  283. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_custom.py +0 -0
  284. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_custom_exporter.py +0 -0
  285. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_custom_model.py +0 -0
  286. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_data_caterer.py +0 -0
  287. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_dbml.py +0 -0
  288. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_dbt_models.py +0 -0
  289. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_dbt_sources.py +0 -0
  290. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_dbt_staging_sql.py +0 -0
  291. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_dqx.py +0 -0
  292. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_excel.py +0 -0
  293. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_go.py +0 -0
  294. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_great_expectations.py +0 -0
  295. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_html.py +0 -0
  296. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_iceberg.py +0 -0
  297. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_jsonschema.py +0 -0
  298. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_markdown.py +0 -0
  299. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_mermaid.py +0 -0
  300. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_odcs_v3.py +0 -0
  301. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_protobuf.py +0 -0
  302. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_pydantic.py +0 -0
  303. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_rdf.py +0 -0
  304. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_sodacl.py +0 -0
  305. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_spark.py +0 -0
  306. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_sql.py +0 -0
  307. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_sql_clickhouse.py +0 -0
  308. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_sql_query.py +0 -0
  309. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_export_sqlalchemy.py +0 -0
  310. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_ibis_mssql_pattern.py +0 -0
  311. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_ibis_oracle_schema.py +0 -0
  312. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_avro.py +0 -0
  313. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_bigquery.py +0 -0
  314. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_csv.py +0 -0
  315. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_dbml.py +0 -0
  316. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_dbt.py +0 -0
  317. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_excel.py +0 -0
  318. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_glue.py +0 -0
  319. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_iceberg.py +0 -0
  320. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_json.py +0 -0
  321. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_jsonschema.py +0 -0
  322. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_odcs_v3.py +0 -0
  323. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_parquet.py +0 -0
  324. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_powerbi.py +0 -0
  325. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_protobuf.py +0 -0
  326. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_snowflake.py +0 -0
  327. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_spark.py +0 -0
  328. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_sql_oracle.py +0 -0
  329. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_sql_postgres.py +0 -0
  330. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_sql_snowflake.py +0 -0
  331. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_sql_sqlserver.py +0 -0
  332. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_import_unity_file.py +0 -0
  333. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_integration_entropydata.py +0 -0
  334. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_lint.py +0 -0
  335. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_oracle_patch.py +0 -0
  336. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_redshift_patch.py +0 -0
  337. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_require_env.py +0 -0
  338. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_resolve.py +0 -0
  339. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_roundtrip_jsonschema.py +0 -0
  340. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_sql_type_converter_physicaltype.py +0 -0
  341. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_api.py +0 -0
  342. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_athena_iceberg.py +0 -0
  343. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_azure_blob_file.py +0 -0
  344. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_azure_remote.py +0 -0
  345. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_bigquery.py +0 -0
  346. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_checks_filter.py +0 -0
  347. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_databricks.py +0 -0
  348. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_delta.py +0 -0
  349. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_diagnostics.py +0 -0
  350. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_failed_samples.py +0 -0
  351. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_gcs_csv_remote.py +0 -0
  352. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_gcs_json_remote.py +0 -0
  353. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_kafka.py +0 -0
  354. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_kafka_remote.py +0 -0
  355. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_local_json.py +0 -0
  356. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_local_json_nd.py +0 -0
  357. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_mysql.py +0 -0
  358. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_oracle.py +0 -0
  359. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_oracle_xe.py +0 -0
  360. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_output_json.py +0 -0
  361. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_output_junit.py +0 -0
  362. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_parquet.py +0 -0
  363. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_postgres.py +0 -0
  364. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_quality.py +0 -0
  365. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_quality_local_fallback.py +0 -0
  366. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_quality_percent_severity.py +0 -0
  367. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_redshift.py +0 -0
  368. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_s3_csv.py +0 -0
  369. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_s3_delta.py +0 -0
  370. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_s3_json.py +0 -0
  371. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_s3_json_complex.py +0 -0
  372. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_s3_json_multiple_models.py +0 -0
  373. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_schema_evolution.py +0 -0
  374. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_server_not_found.py +0 -0
  375. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_snowflake.py +0 -0
  376. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_soda_connection_error.py +0 -0
  377. {datacontract_cli-1.0.10 → datacontract_cli-1.0.12}/tests/test_test_sqlserver.py +0 -0
  378. {datacontract_cli-1.0.10 → 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.10
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
@@ -90,6 +90,11 @@ def _raw_match(expected: str, actual: str) -> Optional[bool]:
90
90
  return True if not e_params else e == a
91
91
 
92
92
 
93
+ def _base_sql(dtype: exp.DataType, dialect) -> str:
94
+ """Render the bare base type in ``dialect``, collapsing that dialect's aliases."""
95
+ return exp.DataType(this=dtype.this).sql(dialect=dialect).lower()
96
+
97
+
93
98
  def physical_type_matches(
94
99
  expected: Optional[str],
95
100
  actual: Optional[str],
@@ -122,7 +127,12 @@ def physical_type_matches(
122
127
  f"server under test; skipping the physical type check"
123
128
  )
124
129
 
125
- same_base = exp_dt.this == act_dt.this or {exp_dt.this, act_dt.this} <= _TIMESTAMP_FAMILY
130
+ both_numeric = {exp_dt.this, act_dt.this} <= exp.DataType.NUMERIC_TYPES
131
+ same_base = (
132
+ exp_dt.this == act_dt.this
133
+ or {exp_dt.this, act_dt.this} <= _TIMESTAMP_FAMILY
134
+ or (both_numeric and _base_sql(exp_dt, dialect) == _base_sql(act_dt, dialect))
135
+ )
126
136
  if not same_base:
127
137
  return False, f"expected physical type '{expected}' but the column is '{actual}'"
128
138
 
@@ -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:
@@ -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 | None:
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. Returns ``None`` for unsupported types (binary, map, null, etc.)
57
- so the caller can skip comparison rather than raising a false failure.
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
- if child is not None:
79
- properties.append(
80
- SchemaProperty(
81
- name=field_name,
82
- logicalType=child.logicalType,
83
- items=child.items,
84
- properties=child.properties,
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
- return SchemaProperty(logicalType="object", properties=properties if properties else None)
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 None
93
- return None
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))
@@ -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
- actual_prop = ibis_dtype_to_schema_property(dtype)
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(metric="field_type", field=spec.field, expected=spec.expected_type_label, actual=str(dtype)),
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(run: Run, con, server, schema, columns, native_types, spec: CheckSpec):
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
- actual_native = native_types.get(spec.field.lower()) if native_types else None
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 '{schema[actual_col]}'",
742
+ mismatch or f"Expected type '{fallback.logicalType}' but column is '{actual_label}'",
710
743
  )
711
744
  return
712
745
 
@@ -124,6 +124,10 @@ def _rows(con, query: str):
124
124
  try:
125
125
  if hasattr(cursor, "fetchall"):
126
126
  return list(cursor.fetchall())
127
+ # The pyspark backend (also used for databricks with a Spark session)
128
+ # returns a DataFrame; iterating it would yield Column objects.
129
+ if hasattr(cursor, "collect"):
130
+ return list(cursor.collect())
127
131
  # Some backends (e.g. BigQuery) return an iterable result set
128
132
  # (RowIterator) instead of a DBAPI cursor.
129
133
  return list(cursor)
@@ -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
@@ -261,9 +261,9 @@ def map_type_from_bigquery(bigquery_type_str: str) -> str:
261
261
  "STRING": "string",
262
262
  "BYTES": "array",
263
263
  "INTEGER": "integer",
264
- "INT64": "integer",
264
+ "INT64": "integer", # for dbt-bigquery
265
265
  "FLOAT": "number",
266
- "FLOAT64": "number",
266
+ "FLOAT64": "number", # for dbt-bigquery
267
267
  "BOOLEAN": "boolean",
268
268
  "BOOL": "boolean",
269
269
  "TIMESTAMP": "timestamp",
@@ -274,6 +274,7 @@ def map_type_from_bigquery(bigquery_type_str: str) -> str:
274
274
  "BIGNUMERIC": "number",
275
275
  "GEOGRAPHY": "object",
276
276
  "JSON": "object",
277
+ "INTERVAL": "string",
277
278
  }
278
279
 
279
280
  if bigquery_type_str in type_mapping:
@@ -206,15 +206,18 @@ def _resolve_definition(url: str, type_: str) -> SchemaProperty:
206
206
  if url in _definition_cache:
207
207
  return _definition_cache[url]
208
208
 
209
- target_url, headers = _build_request(url, type_)
209
+ target_url, headers, host_hint = _build_request(url, type_)
210
210
 
211
211
  try:
212
212
  response = requests.get(target_url, headers=headers, timeout=10)
213
213
  except requests.RequestException as e:
214
- raise _definition_resolution_error(url, target_url, str(e), original_exception=e)
214
+ raise _definition_resolution_error(url, target_url, str(e), original_exception=e, hint=host_hint)
215
215
 
216
216
  if response.status_code != 200:
217
- raise _definition_resolution_error(url, target_url, f"HTTP {response.status_code} {response.reason}")
217
+ # 401/403 here almost always means the configured host is the wrong
218
+ # deployment for this IRI, so surface the ENTROPY_DATA_HOST hint.
219
+ hint = host_hint if response.status_code in (401, 403) else None
220
+ raise _definition_resolution_error(url, target_url, f"HTTP {response.status_code} {response.reason}", hint=hint)
218
221
 
219
222
  try:
220
223
  definition = SchemaProperty.model_validate_json(response.content)
@@ -227,8 +230,13 @@ def _resolve_definition(url: str, type_: str) -> SchemaProperty:
227
230
  return definition
228
231
 
229
232
 
230
- def _build_request(url: str, type_: str) -> tuple[str, dict[str, str]]:
231
- """Return the URL to fetch and the headers to use for a given reference.
233
+ def _build_request(url: str, type_: str) -> tuple[str, dict[str, str], str | None]:
234
+ """Return the URL to fetch, the headers to use, and an optional host hint.
235
+
236
+ The third element is a copy-pasteable ENTROPY_DATA_HOST suggestion that
237
+ callers append to any auth/transport error from the lookup. It is only set
238
+ for the off-host semantics IRI case below, where a host mismatch is the most
239
+ common reason the lookup fails (401/403); it is None otherwise.
232
240
 
233
241
  Three cases:
234
242
  - URL on the configured host (relative path or matching absolute URL):
@@ -252,25 +260,26 @@ def _build_request(url: str, type_: str) -> tuple[str, dict[str, str]]:
252
260
  api_key = _get_api_key_or_none()
253
261
  if api_key is not None:
254
262
  headers["x-api-key"] = api_key
255
- return direct_url, headers
263
+ return direct_url, headers, None
256
264
 
257
265
  if type_ == "definition":
258
266
  # Third-party REST URL: fetch anonymously, no IRI fallback.
259
- return direct_url, headers
267
+ return direct_url, headers, None
260
268
 
261
269
  # Off-host semantics reference: IRI lookup against the configured host.
270
+ host_hint = _host_mismatch_hint(url, configured_host)
262
271
  api_key = _get_api_key_or_none()
263
272
  if api_key is None:
264
273
  raise _definition_resolution_error(
265
274
  url,
266
275
  f"{configured_host.rstrip('/')}/api/semantics",
267
- "the reference looks like an IRI (host does not match the configured "
268
- "entropy-data host); resolving an IRI goes through /api/semantics which "
269
- "requires an API key (set ENTROPY_DATA_API_KEY)",
276
+ "the reference looks like an IRI, so it is resolved through /api/semantics, "
277
+ "which requires an API key: set ENTROPY_DATA_API_KEY",
278
+ hint=host_hint,
270
279
  )
271
280
  headers["x-api-key"] = api_key
272
281
  lookup_url = f"{configured_host.rstrip('/')}/api/semantics?iri={quote(url, safe='')}"
273
- return lookup_url, headers
282
+ return lookup_url, headers, host_hint
274
283
 
275
284
 
276
285
  def _apply_definition_to_property(prop: SchemaProperty, definition: SchemaProperty):
@@ -291,10 +300,29 @@ def _hosts_match(url: str, host: str) -> bool:
291
300
  return urlparse(url).netloc == urlparse(host).netloc
292
301
 
293
302
 
303
+ def _host_mismatch_hint(url: str, configured_host: str) -> str:
304
+ """Actionable hint for the usual cause of a failed IRI lookup: the
305
+ configured entropy-data host (default https://api.entropy-data.com) is not
306
+ the deployment that serves this IRI. Names the exact ENTROPY_DATA_HOST value
307
+ to set -- derived from the IRI's own host -- so the fix is copy-pasteable
308
+ instead of leaving the user to guess that the host, not the API key, is wrong.
309
+ """
310
+ iri = urlparse(url)
311
+ suggested = f"{iri.scheme}://{iri.netloc}" if iri.scheme and iri.netloc else iri.netloc
312
+ return (
313
+ f"the IRI's host '{iri.netloc}' does not match the configured entropy-data host "
314
+ f"'{urlparse(configured_host).netloc}'; if your contract is served from "
315
+ f"'{iri.netloc}', set ENTROPY_DATA_HOST={suggested} so the /api/semantics lookup "
316
+ f"and your API key target that deployment"
317
+ )
318
+
319
+
294
320
  def _definition_resolution_error(
295
- url: str, target_url: str, detail: str, original_exception: Exception | None = None
321
+ url: str, target_url: str, detail: str, original_exception: Exception | None = None, hint: str | None = None
296
322
  ) -> DataContractException:
297
323
  reason = f"Could not resolve business definition '{url}' from {target_url}: {detail}"
324
+ if hint:
325
+ reason = f"{reason} — {hint}"
298
326
  logging.warning(reason)
299
327
  return DataContractException(
300
328
  type="lint",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datacontract-cli
3
- Version: 1.0.10
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.10"
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"