datacontract-cli 0.9.7__tar.gz → 0.9.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of datacontract-cli might be problematic. Click here for more details.

Files changed (129) hide show
  1. {datacontract-cli-0.9.7/datacontract_cli.egg-info → datacontract-cli-0.9.8}/PKG-INFO +176 -37
  2. datacontract-cli-0.9.7/PKG-INFO → datacontract-cli-0.9.8/README.md +161 -68
  3. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/breaking/breaking.py +48 -57
  4. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/cli.py +98 -80
  5. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/data_contract.py +156 -106
  6. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/engines/datacontract/check_that_datacontract_contains_valid_servers_configuration.py +5 -1
  7. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/engines/datacontract/check_that_datacontract_file_exists.py +9 -8
  8. datacontract-cli-0.9.8/datacontract/engines/datacontract/check_that_datacontract_str_is_valid.py +48 -0
  9. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/engines/fastjsonschema/check_jsonschema.py +31 -25
  10. datacontract-cli-0.9.8/datacontract/engines/fastjsonschema/s3/s3_read_files.py +24 -0
  11. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/engines/soda/check_soda_execute.py +46 -35
  12. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/engines/soda/connections/bigquery.py +5 -3
  13. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/engines/soda/connections/dask.py +0 -1
  14. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/engines/soda/connections/databricks.py +2 -2
  15. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/engines/soda/connections/duckdb.py +4 -4
  16. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/engines/soda/connections/kafka.py +36 -17
  17. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/engines/soda/connections/postgres.py +3 -3
  18. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/engines/soda/connections/snowflake.py +4 -4
  19. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/export/avro_converter.py +3 -7
  20. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/export/avro_idl_converter.py +65 -42
  21. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/export/dbt_converter.py +43 -32
  22. datacontract-cli-0.9.8/datacontract/export/great_expectations_converter.py +141 -0
  23. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/export/jsonschema_converter.py +3 -1
  24. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/export/odcs_converter.py +5 -7
  25. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/export/protobuf_converter.py +12 -10
  26. datacontract-cli-0.9.8/datacontract/export/pydantic_converter.py +140 -0
  27. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/export/rdf_converter.py +34 -11
  28. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/export/sodacl_converter.py +24 -24
  29. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/export/sql_converter.py +20 -9
  30. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/export/sql_type_converter.py +44 -4
  31. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/export/terraform_converter.py +4 -3
  32. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/imports/avro_importer.py +32 -10
  33. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/imports/sql_importer.py +0 -2
  34. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/init/download_datacontract_file.py +2 -2
  35. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/integration/publish_datamesh_manager.py +4 -9
  36. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/integration/publish_opentelemetry.py +30 -16
  37. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/lint/files.py +2 -2
  38. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/lint/lint.py +26 -31
  39. datacontract-cli-0.9.8/datacontract/lint/linters/description_linter.py +34 -0
  40. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/lint/linters/example_model_linter.py +28 -29
  41. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/lint/linters/field_pattern_linter.py +8 -8
  42. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/lint/linters/field_reference_linter.py +11 -10
  43. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/lint/linters/notice_period_linter.py +18 -22
  44. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/lint/linters/primary_field_linter.py +10 -12
  45. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/lint/linters/quality_schema_linter.py +16 -20
  46. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/lint/linters/valid_constraints_linter.py +42 -37
  47. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/lint/resolve.py +7 -10
  48. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/lint/schema.py +2 -3
  49. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/lint/urls.py +4 -5
  50. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/model/breaking_change.py +2 -1
  51. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/model/data_contract_specification.py +8 -7
  52. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/model/exceptions.py +13 -2
  53. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/model/run.py +1 -1
  54. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/web.py +3 -7
  55. datacontract-cli-0.9.7/README.md → datacontract-cli-0.9.8/datacontract_cli.egg-info/PKG-INFO +207 -26
  56. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract_cli.egg-info/SOURCES.txt +4 -0
  57. datacontract-cli-0.9.8/datacontract_cli.egg-info/requires.txt +33 -0
  58. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/pyproject.toml +20 -11
  59. datacontract-cli-0.9.8/tests/test_breaking.py +224 -0
  60. datacontract-cli-0.9.8/tests/test_changelog.py +948 -0
  61. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_documentation_linter.py +15 -28
  62. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_download_datacontract_file.py +5 -11
  63. datacontract-cli-0.9.8/tests/test_example_model_linter.py +82 -0
  64. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_examples_bigquery.py +6 -2
  65. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_examples_databricks.py +6 -3
  66. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_examples_examples_csv.py +1 -2
  67. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_examples_examples_inline.py +1 -3
  68. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_examples_examples_json.py +1 -3
  69. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_examples_examples_missing.py +0 -2
  70. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_examples_kafka.py +4 -3
  71. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_examples_kafka_remote.py +9 -5
  72. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_examples_local_json.py +0 -2
  73. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_examples_parquet.py +2 -2
  74. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_examples_postgres.py +4 -2
  75. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_examples_s3_csv.py +6 -6
  76. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_examples_s3_json.py +6 -6
  77. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_examples_s3_json_complex.py +5 -5
  78. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_examples_s3_json_multiple_models.py +5 -5
  79. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_examples_s3_json_remote.py +8 -9
  80. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_export_avro.py +2 -6
  81. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_export_avro_idl.py +53 -31
  82. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_export_dbt_models.py +3 -8
  83. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_export_dbt_sources.py +4 -8
  84. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_export_dbt_staging_sql.py +11 -8
  85. datacontract-cli-0.9.8/tests/test_export_great_expectations.py +222 -0
  86. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_export_jsonschema.py +4 -8
  87. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_export_odcs.py +2 -6
  88. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_export_protobuf.py +1 -10
  89. datacontract-cli-0.9.8/tests/test_export_pydantic.py +115 -0
  90. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_export_rdf.py +13 -21
  91. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_export_sodacl.py +4 -5
  92. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_export_sql.py +21 -6
  93. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_export_sql_query.py +4 -8
  94. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_export_terraform.py +1 -5
  95. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_field_constraint_linter.py +26 -28
  96. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_field_pattern_linter.py +11 -16
  97. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_field_reference_linter.py +20 -22
  98. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_import_avro.py +26 -9
  99. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_import_sql.py +12 -7
  100. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_integration_datameshmanager.py +0 -1
  101. datacontract-cli-0.9.8/tests/test_integration_opentelemetry.py +76 -0
  102. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_lint.py +6 -3
  103. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_notice_period_linter.py +10 -15
  104. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_primary_field_linter.py +12 -23
  105. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_quality_schema_linter.py +6 -11
  106. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_schema.py +4 -2
  107. datacontract-cli-0.9.8/tests/test_web.py +17 -0
  108. datacontract-cli-0.9.7/datacontract/engines/datacontract/check_that_datacontract_str_is_valid.py +0 -44
  109. datacontract-cli-0.9.7/datacontract/engines/fastjsonschema/s3/s3_read_files.py +0 -22
  110. datacontract-cli-0.9.7/datacontract/lint/linters/description_linter.py +0 -43
  111. datacontract-cli-0.9.7/datacontract_cli.egg-info/requires.txt +0 -29
  112. datacontract-cli-0.9.7/tests/test_breaking.py +0 -245
  113. datacontract-cli-0.9.7/tests/test_changelog.py +0 -885
  114. datacontract-cli-0.9.7/tests/test_example_model_linter.py +0 -108
  115. datacontract-cli-0.9.7/tests/test_integration_opentelemetry.py +0 -31
  116. datacontract-cli-0.9.7/tests/test_web.py +0 -16
  117. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/LICENSE +0 -0
  118. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/__init__.py +0 -0
  119. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/breaking/breaking_rules.py +0 -0
  120. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/engines/__init__.py +0 -0
  121. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/engines/soda/__init__.py +0 -0
  122. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract/lint/linters/__init__.py +0 -0
  123. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract_cli.egg-info/dependency_links.txt +0 -0
  124. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract_cli.egg-info/entry_points.txt +0 -0
  125. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/datacontract_cli.egg-info/top_level.txt +0 -0
  126. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/setup.cfg +0 -0
  127. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_cli.py +0 -0
  128. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_description_linter.py +0 -0
  129. {datacontract-cli-0.9.7 → datacontract-cli-0.9.8}/tests/test_examples_snowflake.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: datacontract-cli
3
- Version: 0.9.7
3
+ Version: 0.9.8
4
4
  Summary: Test data contracts
5
5
  Author-email: Jochen Christ <jochen.christ@innoq.com>, Stefan Negele <stefan.negele@innoq.com>
6
6
  Project-URL: Homepage, https://cli.datacontract.com
@@ -11,7 +11,7 @@ Classifier: Operating System :: OS Independent
11
11
  Requires-Python: >=3.10
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
- Requires-Dist: typer[all]~=0.9.0
14
+ Requires-Dist: typer[all]<0.13,>=0.9
15
15
  Requires-Dist: pydantic<2.7.0,>=2.5.3
16
16
  Requires-Dist: pyyaml~=6.0.1
17
17
  Requires-Dist: requests~=2.31.0
@@ -19,23 +19,27 @@ Requires-Dist: fastapi==0.110.0
19
19
  Requires-Dist: fastparquet==2024.2.0
20
20
  Requires-Dist: python-multipart==0.0.9
21
21
  Requires-Dist: rich~=13.7.0
22
- Requires-Dist: simple-ddl-parser==1.0.3
23
- Requires-Dist: soda-core-bigquery~=3.2.1
24
- Requires-Dist: soda-core-duckdb~=3.2.1
25
- Requires-Dist: soda-core-postgres~=3.2.1
26
- Requires-Dist: soda-core-snowflake~=3.2.1
27
- Requires-Dist: soda-core-spark[databricks]~=3.2.1
28
- Requires-Dist: soda-core-spark-df~=3.2.1
22
+ Requires-Dist: simple-ddl-parser==1.0.4
23
+ Requires-Dist: soda-core-bigquery<3.4.0,>=3.3.1
24
+ Requires-Dist: soda-core-duckdb<3.4.0,>=3.3.1
25
+ Requires-Dist: soda-core-postgres<3.4.0,>=3.3.1
26
+ Requires-Dist: soda-core-snowflake<3.4.0,>=3.3.1
27
+ Requires-Dist: soda-core-spark[databricks]<3.4.0,>=3.3.1
28
+ Requires-Dist: soda-core-spark-df<3.4.0,>=3.3.1
29
29
  Requires-Dist: snowflake-connector-python[pandas]<3.8,>=3.6
30
- Requires-Dist: duckdb==0.10.0
30
+ Requires-Dist: duckdb==0.10.1
31
31
  Requires-Dist: fastjsonschema~=2.19.1
32
32
  Requires-Dist: python-dotenv~=1.0.0
33
- Requires-Dist: s3fs==2024.2.0
33
+ Requires-Dist: s3fs==2024.3.1
34
34
  Requires-Dist: rdflib==7.0.0
35
35
  Requires-Dist: avro==1.11.3
36
+ Requires-Dist: opentelemetry-exporter-otlp-proto-grpc~=1.16.0
37
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http~=1.16.0
36
38
  Provides-Extra: dev
37
39
  Requires-Dist: httpx==0.27.0; extra == "dev"
40
+ Requires-Dist: ruff; extra == "dev"
38
41
  Requires-Dist: pytest; extra == "dev"
42
+ Requires-Dist: testcontainers<4.0; extra == "dev"
39
43
  Requires-Dist: testcontainers-minio; extra == "dev"
40
44
  Requires-Dist: testcontainers-postgres; extra == "dev"
41
45
  Requires-Dist: testcontainers-kafka; extra == "dev"
@@ -55,6 +59,15 @@ It uses data contract YAML files to lint the data contract, connect to data sour
55
59
 
56
60
  ![Main features of the Data Contract CLI](datacontractcli.png)
57
61
 
62
+ <div align="center">
63
+ <a href="https://www.youtube.com/watch?v=B1dixhgO2vQ">
64
+ <img
65
+ src="https://img.youtube.com/vi/B1dixhgO2vQ/0.jpg"
66
+ alt="Demo of Data Contract CLI"
67
+ style="width:100%;">
68
+ </a>
69
+ </div>
70
+
58
71
  ## Getting started
59
72
 
60
73
  Let's look at this data contract:
@@ -139,9 +152,6 @@ $ datacontract import --format sql --source my_ddl.sql
139
152
 
140
153
  # import avro
141
154
  $ datacontract import --format avro --source avro_schema.avsc
142
-
143
- # import protobuf as model (Coming Soon)
144
- $ datacontract import --format protobuf --source my_protobuf_file.proto datacontract.yaml
145
155
  ```
146
156
 
147
157
  ## Programmatic (Python)
@@ -155,7 +165,15 @@ if not run.has_passed():
155
165
  # Abort pipeline, alert, or take corrective actions...
156
166
  ```
157
167
 
158
- ## Scenario: Integration with Data Mesh Manager
168
+ ## Integrations
169
+
170
+
171
+ | Integration | Option | Description |
172
+ |-------------------|------------------------------|-------------------------------------------------------------------------------------------------------|
173
+ | Data Mesh Manager | `--publish` | Push full results to the [Data Mesh Manager API](https://api.datamesh-manager.com/swagger/index.html) |
174
+ | OpenTelemetry | `--publish-to-opentelemetry` | Push result as gauge metrics (logs are planned) |
175
+
176
+ ### Integration with Data Mesh Manager
159
177
 
160
178
  If you use [Data Mesh Manager](https://datamesh-manager.com/), you can use the data contract URL and append the `--publish` option to send and display the test results. Set an environment variable for your API key.
161
179
 
@@ -165,7 +183,7 @@ $ EXPORT DATAMESH_MANAGER_API_KEY=xxx
165
183
  $ datacontract test https://demo.datamesh-manager.com/demo279750347121/datacontracts/4df9d6ee-e55d-4088-9598-b635b2fdcbbc/datacontract.yaml --server production --publish
166
184
  ```
167
185
 
168
- ## Scenario: Integration with OpenTelemetry
186
+ ### Integration with OpenTelemetry
169
187
 
170
188
  If you use OpenTelemetry, you can use the data contract URL and append the `--publish-to-opentelemetry` option to send the test results to your OLTP-compatible instance, e.g., Prometheus.
171
189
 
@@ -184,14 +202,13 @@ The metric name is "datacontract.cli.test.result" and it uses the following enco
184
202
  # Fetch current data contract, execute tests on production, and publish result to open telemetry
185
203
  $ EXPORT OTEL_SERVICE_NAME=datacontract-cli
186
204
  $ EXPORT OTEL_EXPORTER_OTLP_ENDPOINT=https://YOUR_ID.apm.westeurope.azure.elastic-cloud.com:443
187
- $ EXPORT OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer%20secret (Optional, when using SaaS Products)
188
- $ EXPORT OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf (Optional, because it is the default value)
205
+ $ EXPORT OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer%20secret # Optional, when using SaaS Products
206
+ $ EXPORT OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf # Optional, default is http/protobuf - use value grpc to use the gRPC protocol instead
189
207
  # Send to OpenTelemetry
190
208
  $ datacontract test https://demo.datamesh-manager.com/demo279750347121/datacontracts/4df9d6ee-e55d-4088-9598-b635b2fdcbbc/datacontract.yaml --server production --publish-to-opentelemetry
191
209
  ```
192
210
 
193
211
  Current limitations:
194
- - no gRPC support
195
212
  - currently, only ConsoleExporter and OTLP Exporter
196
213
  - Metrics only, no logs yet (but loosely planned)
197
214
 
@@ -482,22 +499,36 @@ datacontract export --format dbt
482
499
 
483
500
  Available export options:
484
501
 
485
- | Type | Description | Status |
486
- |--------------------|---------------------------------------------------------|--------|
487
- | `jsonschema` | Export to JSON Schema | ✅ |
488
- | `odcs` | Export to Open Data Contract Standard (ODCS) | ✅ |
489
- | `sodacl` | Export to SodaCL quality checks in YAML format | ✅ |
490
- | `dbt` | Export to dbt models in YAML format | ✅ |
491
- | `dbt-sources` | Export to dbt sources in YAML format | ✅ |
492
- | `dbt-staging-sql` | Export to dbt staging SQL models | ✅ |
493
- | `rdf` | Export data contract to RDF representation in N3 format | ✅ |
494
- | `avro` | Export to AVRO models | ✅ |
495
- | `protobuf` | Export to Protobuf | ✅ |
496
- | `terraform` | Export to terraform resources | ✅ |
497
- | `sql` | Export to SQL DDL | ✅ |
498
- | `sql-query` | Export to SQL Query | ✅ |
499
- | `pydantic` | Export to pydantic models | TBD |
500
- | Missing something? | Please create an issue on GitHub | TBD |
502
+ | Type | Description | Status |
503
+ |----------------------|---------------------------------------------------------|--------|
504
+ | `jsonschema` | Export to JSON Schema | ✅ |
505
+ | `odcs` | Export to Open Data Contract Standard (ODCS) | ✅ |
506
+ | `sodacl` | Export to SodaCL quality checks in YAML format | ✅ |
507
+ | `dbt` | Export to dbt models in YAML format | ✅ |
508
+ | `dbt-sources` | Export to dbt sources in YAML format | ✅ |
509
+ | `dbt-staging-sql` | Export to dbt staging SQL models | ✅ |
510
+ | `rdf` | Export data contract to RDF representation in N3 format | ✅ |
511
+ | `avro` | Export to AVRO models | ✅ |
512
+ | `protobuf` | Export to Protobuf | ✅ |
513
+ | `terraform` | Export to terraform resources | ✅ |
514
+ | `sql` | Export to SQL DDL | ✅ |
515
+ | `sql-query` | Export to SQL Query | ✅ |
516
+ | `great-expectations` | Export to Great Expectations Suites in JSON Format | |
517
+ | `bigquery` | Export to BigQuery Schemas | TBD |
518
+ | `pydantic` | Export to pydantic models | TBD |
519
+ | `html` | Export to HTML page | TBD |
520
+ | Missing something? | Please create an issue on GitHub | TBD |
521
+
522
+ #### Great Expectations
523
+ The export function transforms a specified data contract into a comprehensive Great Expectations JSON suite.
524
+ If the contract includes multiple models, you need to specify the names of the model you wish to export.
525
+ ```shell
526
+ datacontract export datacontract.yaml --format great-expectations --model orders
527
+ ```
528
+ The export creates a list of expectations by utilizing:
529
+
530
+ - The data from the Model definition with a fixed mapping
531
+ - The expectations provided in the quality field for each model (find here the expectations gallery https://greatexpectations.io/expectations/)
501
532
 
502
533
  #### RDF
503
534
 
@@ -535,13 +566,120 @@ Available import options:
535
566
  | Type | Description | Status |
536
567
  |--------------------|------------------------------------------------|---------|
537
568
  | `sql` | Import from SQL DDL | ✅ |
538
- | `protobuf` | Import from Protobuf schemas | TBD |
539
569
  | `avro` | Import from AVRO schemas | ✅ |
570
+ | `protobuf` | Import from Protobuf schemas | TBD |
540
571
  | `jsonschema` | Import from JSON Schemas | TBD |
572
+ | `bigquery` | Import from BigQuery Schemas | TBD |
541
573
  | `dbt` | Import from dbt models | TBD |
542
574
  | `odcs` | Import from Open Data Contract Standard (ODCS) | TBD |
543
575
  | Missing something? | Please create an issue on GitHub | TBD |
544
576
 
577
+ ## Best Practices
578
+
579
+ We share best practices in using the Data Contract CLI.
580
+
581
+ ### Data-first Approach
582
+
583
+ Create a data contract based on the actual data. This is the fastest way to get started and to get feedback from the data consumers.
584
+
585
+ 1. Use an existing physical schema (e.g., SQL DDL) as a starting point to define your logical data model in the contract. Double check right after the import whether the actual data meets the imported logical data model. Just to be sure.
586
+ ```bash
587
+ $ datacontract import --format sql ddl.sql
588
+ $ datacontract test
589
+ ```
590
+
591
+ 2. Add examples to the `datacontract.yaml`. If you can, use actual data and anonymize. Make sure that the examples match the imported logical data model.
592
+ ```bash
593
+ $ datacontract test --examples
594
+ ```
595
+
596
+
597
+ 3. Add quality checks and additional type constraints one by one to the contract and make sure the examples and the actual data still adheres to the contract. Check against examples for a very fast feedback loop.
598
+ ```bash
599
+ $ datacontract test --examples
600
+ $ datacontract test
601
+ ```
602
+
603
+ 4. Make sure that all the best practices for a `datacontract.yaml` are met using the linter. You probably forgot to document some fields and add the terms and conditions.
604
+ ```bash
605
+ $ datacontract lint
606
+ ```
607
+
608
+ 5. Set up a CI pipeline that executes daily and reports the results to the [Data Mesh Manager](https://datamesh-manager.com). Or to some place else. You can even publish to any opentelemetry compatible system.
609
+ ```bash
610
+ $ datacontract test --publish https://api.datamesh-manager.com/api/runs
611
+ ```
612
+
613
+ ### Contract-First
614
+
615
+ Create a data contract based on the requirements from use cases.
616
+
617
+ 1. Start with a `datacontract.yaml` template.
618
+ ```bash
619
+ $ datacontract init
620
+ ```
621
+
622
+ 2. Add examples to the `datacontract.yaml`. Do not start with the data model, although you are probably tempted to do that. Examples are the fastest way to get feedback from everybody and not loose someone in the discussion.
623
+
624
+ 3. Create the model based on the examples. Test the model against the examples to double-check whether the model matches the examples.
625
+ ```bash
626
+ $ datacontract test --examples
627
+ ```
628
+
629
+ 4. Add quality checks and additional type constraints one by one to the contract and make sure the examples and the actual data still adheres to the contract. Check against examples for a very fast feedback loop.
630
+ ```bash
631
+ $ datacontract test --examples
632
+ ```
633
+
634
+ 5. Fill in the terms, descriptions, etc. Make sure you follow all best practices for a `datacontract.yaml` using the linter.
635
+ ```bash
636
+ $ datacontract lint
637
+ ```
638
+
639
+ 6. Set up a CI pipeline that lints and tests the examples so you make sure that any changes later do not decrease the quality of the contract.
640
+ ```bash
641
+ $ datacontract lint
642
+ $ datacontract test --examples
643
+ ```
644
+
645
+ 7. Use the export function to start building the providing data product as well as the integration into the consuming data products.
646
+ ```bash
647
+ # data provider
648
+ $ datacontract export --format dbt
649
+ # data consumer
650
+ $ datacontract export --format dbt-sources
651
+ $ datacontract export --format dbt-staging-sql
652
+ ```
653
+
654
+ ### Schema Evolution
655
+
656
+ #### Non-breaking Changes
657
+ Examples: adding models or fields
658
+
659
+ - Add the models or fields in the datacontract.yaml
660
+ - Increment the minor version of the datacontract.yaml on any change. Simply edit the datacontract.yaml for this.
661
+ - You need a policy that these changes are non-breaking. That means that one cannot use the star expression in SQL to query a table under contract. Make the consequences known.
662
+ - Fail the build in the Pull Request if a datacontract.yaml accidentially adds a breaking change even despite only a minor version change
663
+ ```bash
664
+ $ datacontract breaking datacontract-from-pr.yaml datacontract-from-main.yaml
665
+ ```
666
+ - Create a changelog of this minor change.
667
+ ```bash
668
+ $ datacontract changelog datacontract-from-pr.yaml datacontract-from-main.yaml
669
+ ```
670
+ #### Breaking Changes
671
+ Examples: Removing or renaming models and fields.
672
+
673
+ - Remove or rename models and fields in the datacontract.yaml, and any other change that might be part of this new major version of this data contract.
674
+ - Increment the major version of the datacontract.yaml for this and create a new file for the major version. The reason being, that one needs to offer an upgrade path for the data consumers from the old to the new major version.
675
+ - As data consumers need to migrate, try to reduce the frequency of major versions by making multiple breaking changes together if possible.
676
+ - Be aware of the notice period in the data contract as this is the minimum amount of time you have to offer both the old and the new version for a migration path.
677
+ - Do not fear making breaking changes with data contracts. It's okay to do them in this controlled way. Really!
678
+ - Create a changelog of this major change.
679
+ ```bash
680
+ $ datacontract changelog datacontract-from-pr.yaml datacontract-from-main.yaml
681
+ ```
682
+
545
683
  ## Development Setup
546
684
 
547
685
  Python base interpreter should be 3.11.x (unless working on 3.12 release candidate).
@@ -554,7 +692,8 @@ source venv/bin/activate
554
692
  # Install Requirements
555
693
  pip install --upgrade pip setuptools wheel
556
694
  pip install -e '.[dev]'
557
- cd tests/
695
+ ruff check --fix
696
+ ruff format --check
558
697
  pytest
559
698
  ```
560
699
 
@@ -1,45 +1,3 @@
1
- Metadata-Version: 2.1
2
- Name: datacontract-cli
3
- Version: 0.9.7
4
- Summary: Test data contracts
5
- Author-email: Jochen Christ <jochen.christ@innoq.com>, Stefan Negele <stefan.negele@innoq.com>
6
- Project-URL: Homepage, https://cli.datacontract.com
7
- Project-URL: Issues, https://github.com/datacontract/cli/issues
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.10
12
- Description-Content-Type: text/markdown
13
- License-File: LICENSE
14
- Requires-Dist: typer[all]~=0.9.0
15
- Requires-Dist: pydantic<2.7.0,>=2.5.3
16
- Requires-Dist: pyyaml~=6.0.1
17
- Requires-Dist: requests~=2.31.0
18
- Requires-Dist: fastapi==0.110.0
19
- Requires-Dist: fastparquet==2024.2.0
20
- Requires-Dist: python-multipart==0.0.9
21
- Requires-Dist: rich~=13.7.0
22
- Requires-Dist: simple-ddl-parser==1.0.3
23
- Requires-Dist: soda-core-bigquery~=3.2.1
24
- Requires-Dist: soda-core-duckdb~=3.2.1
25
- Requires-Dist: soda-core-postgres~=3.2.1
26
- Requires-Dist: soda-core-snowflake~=3.2.1
27
- Requires-Dist: soda-core-spark[databricks]~=3.2.1
28
- Requires-Dist: soda-core-spark-df~=3.2.1
29
- Requires-Dist: snowflake-connector-python[pandas]<3.8,>=3.6
30
- Requires-Dist: duckdb==0.10.0
31
- Requires-Dist: fastjsonschema~=2.19.1
32
- Requires-Dist: python-dotenv~=1.0.0
33
- Requires-Dist: s3fs==2024.2.0
34
- Requires-Dist: rdflib==7.0.0
35
- Requires-Dist: avro==1.11.3
36
- Provides-Extra: dev
37
- Requires-Dist: httpx==0.27.0; extra == "dev"
38
- Requires-Dist: pytest; extra == "dev"
39
- Requires-Dist: testcontainers-minio; extra == "dev"
40
- Requires-Dist: testcontainers-postgres; extra == "dev"
41
- Requires-Dist: testcontainers-kafka; extra == "dev"
42
-
43
1
  # Data Contract CLI
44
2
 
45
3
  <p>
@@ -55,6 +13,15 @@ It uses data contract YAML files to lint the data contract, connect to data sour
55
13
 
56
14
  ![Main features of the Data Contract CLI](datacontractcli.png)
57
15
 
16
+ <div align="center">
17
+ <a href="https://www.youtube.com/watch?v=B1dixhgO2vQ">
18
+ <img
19
+ src="https://img.youtube.com/vi/B1dixhgO2vQ/0.jpg"
20
+ alt="Demo of Data Contract CLI"
21
+ style="width:100%;">
22
+ </a>
23
+ </div>
24
+
58
25
  ## Getting started
59
26
 
60
27
  Let's look at this data contract:
@@ -139,9 +106,6 @@ $ datacontract import --format sql --source my_ddl.sql
139
106
 
140
107
  # import avro
141
108
  $ datacontract import --format avro --source avro_schema.avsc
142
-
143
- # import protobuf as model (Coming Soon)
144
- $ datacontract import --format protobuf --source my_protobuf_file.proto datacontract.yaml
145
109
  ```
146
110
 
147
111
  ## Programmatic (Python)
@@ -155,7 +119,15 @@ if not run.has_passed():
155
119
  # Abort pipeline, alert, or take corrective actions...
156
120
  ```
157
121
 
158
- ## Scenario: Integration with Data Mesh Manager
122
+ ## Integrations
123
+
124
+
125
+ | Integration | Option | Description |
126
+ |-------------------|------------------------------|-------------------------------------------------------------------------------------------------------|
127
+ | Data Mesh Manager | `--publish` | Push full results to the [Data Mesh Manager API](https://api.datamesh-manager.com/swagger/index.html) |
128
+ | OpenTelemetry | `--publish-to-opentelemetry` | Push result as gauge metrics (logs are planned) |
129
+
130
+ ### Integration with Data Mesh Manager
159
131
 
160
132
  If you use [Data Mesh Manager](https://datamesh-manager.com/), you can use the data contract URL and append the `--publish` option to send and display the test results. Set an environment variable for your API key.
161
133
 
@@ -165,7 +137,7 @@ $ EXPORT DATAMESH_MANAGER_API_KEY=xxx
165
137
  $ datacontract test https://demo.datamesh-manager.com/demo279750347121/datacontracts/4df9d6ee-e55d-4088-9598-b635b2fdcbbc/datacontract.yaml --server production --publish
166
138
  ```
167
139
 
168
- ## Scenario: Integration with OpenTelemetry
140
+ ### Integration with OpenTelemetry
169
141
 
170
142
  If you use OpenTelemetry, you can use the data contract URL and append the `--publish-to-opentelemetry` option to send the test results to your OLTP-compatible instance, e.g., Prometheus.
171
143
 
@@ -184,14 +156,13 @@ The metric name is "datacontract.cli.test.result" and it uses the following enco
184
156
  # Fetch current data contract, execute tests on production, and publish result to open telemetry
185
157
  $ EXPORT OTEL_SERVICE_NAME=datacontract-cli
186
158
  $ EXPORT OTEL_EXPORTER_OTLP_ENDPOINT=https://YOUR_ID.apm.westeurope.azure.elastic-cloud.com:443
187
- $ EXPORT OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer%20secret (Optional, when using SaaS Products)
188
- $ EXPORT OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf (Optional, because it is the default value)
159
+ $ EXPORT OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer%20secret # Optional, when using SaaS Products
160
+ $ EXPORT OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf # Optional, default is http/protobuf - use value grpc to use the gRPC protocol instead
189
161
  # Send to OpenTelemetry
190
162
  $ datacontract test https://demo.datamesh-manager.com/demo279750347121/datacontracts/4df9d6ee-e55d-4088-9598-b635b2fdcbbc/datacontract.yaml --server production --publish-to-opentelemetry
191
163
  ```
192
164
 
193
165
  Current limitations:
194
- - no gRPC support
195
166
  - currently, only ConsoleExporter and OTLP Exporter
196
167
  - Metrics only, no logs yet (but loosely planned)
197
168
 
@@ -482,22 +453,36 @@ datacontract export --format dbt
482
453
 
483
454
  Available export options:
484
455
 
485
- | Type | Description | Status |
486
- |--------------------|---------------------------------------------------------|--------|
487
- | `jsonschema` | Export to JSON Schema | ✅ |
488
- | `odcs` | Export to Open Data Contract Standard (ODCS) | ✅ |
489
- | `sodacl` | Export to SodaCL quality checks in YAML format | ✅ |
490
- | `dbt` | Export to dbt models in YAML format | ✅ |
491
- | `dbt-sources` | Export to dbt sources in YAML format | ✅ |
492
- | `dbt-staging-sql` | Export to dbt staging SQL models | ✅ |
493
- | `rdf` | Export data contract to RDF representation in N3 format | ✅ |
494
- | `avro` | Export to AVRO models | ✅ |
495
- | `protobuf` | Export to Protobuf | ✅ |
496
- | `terraform` | Export to terraform resources | ✅ |
497
- | `sql` | Export to SQL DDL | ✅ |
498
- | `sql-query` | Export to SQL Query | ✅ |
499
- | `pydantic` | Export to pydantic models | TBD |
500
- | Missing something? | Please create an issue on GitHub | TBD |
456
+ | Type | Description | Status |
457
+ |----------------------|---------------------------------------------------------|--------|
458
+ | `jsonschema` | Export to JSON Schema | ✅ |
459
+ | `odcs` | Export to Open Data Contract Standard (ODCS) | ✅ |
460
+ | `sodacl` | Export to SodaCL quality checks in YAML format | ✅ |
461
+ | `dbt` | Export to dbt models in YAML format | ✅ |
462
+ | `dbt-sources` | Export to dbt sources in YAML format | ✅ |
463
+ | `dbt-staging-sql` | Export to dbt staging SQL models | ✅ |
464
+ | `rdf` | Export data contract to RDF representation in N3 format | ✅ |
465
+ | `avro` | Export to AVRO models | ✅ |
466
+ | `protobuf` | Export to Protobuf | ✅ |
467
+ | `terraform` | Export to terraform resources | ✅ |
468
+ | `sql` | Export to SQL DDL | ✅ |
469
+ | `sql-query` | Export to SQL Query | ✅ |
470
+ | `great-expectations` | Export to Great Expectations Suites in JSON Format | |
471
+ | `bigquery` | Export to BigQuery Schemas | TBD |
472
+ | `pydantic` | Export to pydantic models | TBD |
473
+ | `html` | Export to HTML page | TBD |
474
+ | Missing something? | Please create an issue on GitHub | TBD |
475
+
476
+ #### Great Expectations
477
+ The export function transforms a specified data contract into a comprehensive Great Expectations JSON suite.
478
+ If the contract includes multiple models, you need to specify the names of the model you wish to export.
479
+ ```shell
480
+ datacontract export datacontract.yaml --format great-expectations --model orders
481
+ ```
482
+ The export creates a list of expectations by utilizing:
483
+
484
+ - The data from the Model definition with a fixed mapping
485
+ - The expectations provided in the quality field for each model (find here the expectations gallery https://greatexpectations.io/expectations/)
501
486
 
502
487
  #### RDF
503
488
 
@@ -535,13 +520,120 @@ Available import options:
535
520
  | Type | Description | Status |
536
521
  |--------------------|------------------------------------------------|---------|
537
522
  | `sql` | Import from SQL DDL | ✅ |
538
- | `protobuf` | Import from Protobuf schemas | TBD |
539
523
  | `avro` | Import from AVRO schemas | ✅ |
524
+ | `protobuf` | Import from Protobuf schemas | TBD |
540
525
  | `jsonschema` | Import from JSON Schemas | TBD |
526
+ | `bigquery` | Import from BigQuery Schemas | TBD |
541
527
  | `dbt` | Import from dbt models | TBD |
542
528
  | `odcs` | Import from Open Data Contract Standard (ODCS) | TBD |
543
529
  | Missing something? | Please create an issue on GitHub | TBD |
544
530
 
531
+ ## Best Practices
532
+
533
+ We share best practices in using the Data Contract CLI.
534
+
535
+ ### Data-first Approach
536
+
537
+ Create a data contract based on the actual data. This is the fastest way to get started and to get feedback from the data consumers.
538
+
539
+ 1. Use an existing physical schema (e.g., SQL DDL) as a starting point to define your logical data model in the contract. Double check right after the import whether the actual data meets the imported logical data model. Just to be sure.
540
+ ```bash
541
+ $ datacontract import --format sql ddl.sql
542
+ $ datacontract test
543
+ ```
544
+
545
+ 2. Add examples to the `datacontract.yaml`. If you can, use actual data and anonymize. Make sure that the examples match the imported logical data model.
546
+ ```bash
547
+ $ datacontract test --examples
548
+ ```
549
+
550
+
551
+ 3. Add quality checks and additional type constraints one by one to the contract and make sure the examples and the actual data still adheres to the contract. Check against examples for a very fast feedback loop.
552
+ ```bash
553
+ $ datacontract test --examples
554
+ $ datacontract test
555
+ ```
556
+
557
+ 4. Make sure that all the best practices for a `datacontract.yaml` are met using the linter. You probably forgot to document some fields and add the terms and conditions.
558
+ ```bash
559
+ $ datacontract lint
560
+ ```
561
+
562
+ 5. Set up a CI pipeline that executes daily and reports the results to the [Data Mesh Manager](https://datamesh-manager.com). Or to some place else. You can even publish to any opentelemetry compatible system.
563
+ ```bash
564
+ $ datacontract test --publish https://api.datamesh-manager.com/api/runs
565
+ ```
566
+
567
+ ### Contract-First
568
+
569
+ Create a data contract based on the requirements from use cases.
570
+
571
+ 1. Start with a `datacontract.yaml` template.
572
+ ```bash
573
+ $ datacontract init
574
+ ```
575
+
576
+ 2. Add examples to the `datacontract.yaml`. Do not start with the data model, although you are probably tempted to do that. Examples are the fastest way to get feedback from everybody and not loose someone in the discussion.
577
+
578
+ 3. Create the model based on the examples. Test the model against the examples to double-check whether the model matches the examples.
579
+ ```bash
580
+ $ datacontract test --examples
581
+ ```
582
+
583
+ 4. Add quality checks and additional type constraints one by one to the contract and make sure the examples and the actual data still adheres to the contract. Check against examples for a very fast feedback loop.
584
+ ```bash
585
+ $ datacontract test --examples
586
+ ```
587
+
588
+ 5. Fill in the terms, descriptions, etc. Make sure you follow all best practices for a `datacontract.yaml` using the linter.
589
+ ```bash
590
+ $ datacontract lint
591
+ ```
592
+
593
+ 6. Set up a CI pipeline that lints and tests the examples so you make sure that any changes later do not decrease the quality of the contract.
594
+ ```bash
595
+ $ datacontract lint
596
+ $ datacontract test --examples
597
+ ```
598
+
599
+ 7. Use the export function to start building the providing data product as well as the integration into the consuming data products.
600
+ ```bash
601
+ # data provider
602
+ $ datacontract export --format dbt
603
+ # data consumer
604
+ $ datacontract export --format dbt-sources
605
+ $ datacontract export --format dbt-staging-sql
606
+ ```
607
+
608
+ ### Schema Evolution
609
+
610
+ #### Non-breaking Changes
611
+ Examples: adding models or fields
612
+
613
+ - Add the models or fields in the datacontract.yaml
614
+ - Increment the minor version of the datacontract.yaml on any change. Simply edit the datacontract.yaml for this.
615
+ - You need a policy that these changes are non-breaking. That means that one cannot use the star expression in SQL to query a table under contract. Make the consequences known.
616
+ - Fail the build in the Pull Request if a datacontract.yaml accidentially adds a breaking change even despite only a minor version change
617
+ ```bash
618
+ $ datacontract breaking datacontract-from-pr.yaml datacontract-from-main.yaml
619
+ ```
620
+ - Create a changelog of this minor change.
621
+ ```bash
622
+ $ datacontract changelog datacontract-from-pr.yaml datacontract-from-main.yaml
623
+ ```
624
+ #### Breaking Changes
625
+ Examples: Removing or renaming models and fields.
626
+
627
+ - Remove or rename models and fields in the datacontract.yaml, and any other change that might be part of this new major version of this data contract.
628
+ - Increment the major version of the datacontract.yaml for this and create a new file for the major version. The reason being, that one needs to offer an upgrade path for the data consumers from the old to the new major version.
629
+ - As data consumers need to migrate, try to reduce the frequency of major versions by making multiple breaking changes together if possible.
630
+ - Be aware of the notice period in the data contract as this is the minimum amount of time you have to offer both the old and the new version for a migration path.
631
+ - Do not fear making breaking changes with data contracts. It's okay to do them in this controlled way. Really!
632
+ - Create a changelog of this major change.
633
+ ```bash
634
+ $ datacontract changelog datacontract-from-pr.yaml datacontract-from-main.yaml
635
+ ```
636
+
545
637
  ## Development Setup
546
638
 
547
639
  Python base interpreter should be 3.11.x (unless working on 3.12 release candidate).
@@ -554,7 +646,8 @@ source venv/bin/activate
554
646
  # Install Requirements
555
647
  pip install --upgrade pip setuptools wheel
556
648
  pip install -e '.[dev]'
557
- cd tests/
649
+ ruff check --fix
650
+ ruff format --check
558
651
  pytest
559
652
  ```
560
653