datacontract-cli 0.10.23__py3-none-any.whl → 0.10.40__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- datacontract/__init__.py +13 -0
- datacontract/api.py +12 -5
- datacontract/catalog/catalog.py +5 -3
- datacontract/cli.py +119 -13
- datacontract/data_contract.py +145 -67
- datacontract/engines/data_contract_checks.py +366 -60
- datacontract/engines/data_contract_test.py +50 -4
- datacontract/engines/fastjsonschema/check_jsonschema.py +37 -19
- datacontract/engines/fastjsonschema/s3/s3_read_files.py +3 -2
- datacontract/engines/soda/check_soda_execute.py +27 -3
- datacontract/engines/soda/connections/athena.py +79 -0
- datacontract/engines/soda/connections/duckdb_connection.py +65 -6
- datacontract/engines/soda/connections/kafka.py +4 -2
- datacontract/engines/soda/connections/oracle.py +50 -0
- datacontract/export/avro_converter.py +20 -3
- datacontract/export/bigquery_converter.py +1 -1
- datacontract/export/dbt_converter.py +36 -7
- datacontract/export/dqx_converter.py +126 -0
- datacontract/export/duckdb_type_converter.py +57 -0
- datacontract/export/excel_exporter.py +923 -0
- datacontract/export/exporter.py +3 -0
- datacontract/export/exporter_factory.py +17 -1
- datacontract/export/great_expectations_converter.py +55 -5
- datacontract/export/{html_export.py → html_exporter.py} +31 -20
- datacontract/export/markdown_converter.py +134 -5
- datacontract/export/mermaid_exporter.py +110 -0
- datacontract/export/odcs_v3_exporter.py +193 -149
- datacontract/export/protobuf_converter.py +163 -69
- datacontract/export/rdf_converter.py +2 -2
- datacontract/export/sodacl_converter.py +9 -1
- datacontract/export/spark_converter.py +31 -4
- datacontract/export/sql_converter.py +6 -2
- datacontract/export/sql_type_converter.py +124 -8
- datacontract/imports/avro_importer.py +63 -12
- datacontract/imports/csv_importer.py +111 -57
- datacontract/imports/excel_importer.py +1112 -0
- datacontract/imports/importer.py +16 -3
- datacontract/imports/importer_factory.py +17 -0
- datacontract/imports/json_importer.py +325 -0
- datacontract/imports/odcs_importer.py +2 -2
- datacontract/imports/odcs_v3_importer.py +367 -151
- datacontract/imports/protobuf_importer.py +264 -0
- datacontract/imports/spark_importer.py +117 -13
- datacontract/imports/sql_importer.py +32 -16
- datacontract/imports/unity_importer.py +84 -38
- datacontract/init/init_template.py +1 -1
- datacontract/integration/entropy_data.py +126 -0
- datacontract/lint/resolve.py +112 -23
- datacontract/lint/schema.py +24 -15
- datacontract/lint/urls.py +17 -3
- datacontract/model/data_contract_specification/__init__.py +1 -0
- datacontract/model/odcs.py +13 -0
- datacontract/model/run.py +3 -0
- datacontract/output/junit_test_results.py +3 -3
- datacontract/schemas/datacontract-1.1.0.init.yaml +1 -1
- datacontract/schemas/datacontract-1.2.0.init.yaml +91 -0
- datacontract/schemas/datacontract-1.2.0.schema.json +2029 -0
- datacontract/schemas/datacontract-1.2.1.init.yaml +91 -0
- datacontract/schemas/datacontract-1.2.1.schema.json +2058 -0
- datacontract/schemas/odcs-3.0.2.schema.json +2382 -0
- datacontract/schemas/odcs-3.1.0.schema.json +2809 -0
- datacontract/templates/datacontract.html +54 -3
- datacontract/templates/datacontract_odcs.html +685 -0
- datacontract/templates/index.html +5 -2
- datacontract/templates/partials/server.html +2 -0
- datacontract/templates/style/output.css +319 -145
- {datacontract_cli-0.10.23.dist-info → datacontract_cli-0.10.40.dist-info}/METADATA +711 -433
- datacontract_cli-0.10.40.dist-info/RECORD +121 -0
- {datacontract_cli-0.10.23.dist-info → datacontract_cli-0.10.40.dist-info}/WHEEL +1 -1
- {datacontract_cli-0.10.23.dist-info → datacontract_cli-0.10.40.dist-info/licenses}/LICENSE +1 -1
- datacontract/export/csv_type_converter.py +0 -36
- datacontract/integration/datamesh_manager.py +0 -72
- datacontract/lint/lint.py +0 -142
- datacontract/lint/linters/description_linter.py +0 -35
- datacontract/lint/linters/field_pattern_linter.py +0 -34
- datacontract/lint/linters/field_reference_linter.py +0 -48
- datacontract/lint/linters/notice_period_linter.py +0 -55
- datacontract/lint/linters/quality_schema_linter.py +0 -52
- datacontract/lint/linters/valid_constraints_linter.py +0 -100
- datacontract/model/data_contract_specification.py +0 -327
- datacontract_cli-0.10.23.dist-info/RECORD +0 -113
- /datacontract/{lint/linters → output}/__init__.py +0 -0
- {datacontract_cli-0.10.23.dist-info → datacontract_cli-0.10.40.dist-info}/entry_points.txt +0 -0
- {datacontract_cli-0.10.23.dist-info → datacontract_cli-0.10.40.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,18 @@
|
|
|
1
|
-
from typing import Dict
|
|
2
|
-
|
|
3
|
-
import
|
|
1
|
+
from typing import Any, Dict
|
|
2
|
+
|
|
3
|
+
from open_data_contract_standard.model import (
|
|
4
|
+
CustomProperty,
|
|
5
|
+
DataQuality,
|
|
6
|
+
Description,
|
|
7
|
+
OpenDataContractStandard,
|
|
8
|
+
Role,
|
|
9
|
+
SchemaObject,
|
|
10
|
+
SchemaProperty,
|
|
11
|
+
Server,
|
|
12
|
+
ServiceLevelAgreementProperty,
|
|
13
|
+
Support,
|
|
14
|
+
Team,
|
|
15
|
+
)
|
|
4
16
|
|
|
5
17
|
from datacontract.export.exporter import Exporter
|
|
6
18
|
from datacontract.model.data_contract_specification import DataContractSpecification, Field, Model
|
|
@@ -12,154 +24,149 @@ class OdcsV3Exporter(Exporter):
|
|
|
12
24
|
|
|
13
25
|
|
|
14
26
|
def to_odcs_v3_yaml(data_contract_spec: DataContractSpecification) -> str:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"name": data_contract_spec.info.title,
|
|
20
|
-
"version": data_contract_spec.info.version,
|
|
21
|
-
"domain": data_contract_spec.info.owner,
|
|
22
|
-
"status": to_status(data_contract_spec.info.status),
|
|
23
|
-
}
|
|
27
|
+
result = to_odcs_v3(data_contract_spec)
|
|
28
|
+
|
|
29
|
+
return result.to_yaml()
|
|
30
|
+
|
|
24
31
|
|
|
32
|
+
def to_odcs_v3(data_contract_spec: DataContractSpecification) -> OpenDataContractStandard:
|
|
33
|
+
result = OpenDataContractStandard(
|
|
34
|
+
apiVersion="v3.1.0",
|
|
35
|
+
kind="DataContract",
|
|
36
|
+
id=data_contract_spec.id,
|
|
37
|
+
name=data_contract_spec.info.title,
|
|
38
|
+
version=data_contract_spec.info.version,
|
|
39
|
+
status=to_status(data_contract_spec.info.status),
|
|
40
|
+
)
|
|
25
41
|
if data_contract_spec.terms is not None:
|
|
26
|
-
|
|
27
|
-
|
|
42
|
+
result.description = Description(
|
|
43
|
+
purpose=data_contract_spec.terms.description.strip()
|
|
28
44
|
if data_contract_spec.terms.description is not None
|
|
29
45
|
else None,
|
|
30
|
-
|
|
31
|
-
|
|
46
|
+
usage=data_contract_spec.terms.usage.strip() if data_contract_spec.terms.usage is not None else None,
|
|
47
|
+
limitations=data_contract_spec.terms.limitations.strip()
|
|
32
48
|
if data_contract_spec.terms.limitations is not None
|
|
33
49
|
else None,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
odcs["schema"] = []
|
|
50
|
+
)
|
|
51
|
+
result.schema_ = []
|
|
37
52
|
for model_key, model_value in data_contract_spec.models.items():
|
|
38
53
|
odcs_schema = to_odcs_schema(model_key, model_value)
|
|
39
|
-
|
|
40
|
-
|
|
54
|
+
result.schema_.append(odcs_schema)
|
|
41
55
|
if data_contract_spec.servicelevels is not None:
|
|
42
56
|
slas = []
|
|
43
57
|
if data_contract_spec.servicelevels.availability is not None:
|
|
44
58
|
slas.append(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
59
|
+
ServiceLevelAgreementProperty(
|
|
60
|
+
property="generalAvailability", value=data_contract_spec.servicelevels.availability.description
|
|
61
|
+
)
|
|
49
62
|
)
|
|
50
63
|
if data_contract_spec.servicelevels.retention is not None:
|
|
51
|
-
slas.append(
|
|
64
|
+
slas.append(
|
|
65
|
+
ServiceLevelAgreementProperty(
|
|
66
|
+
property="retention", value=data_contract_spec.servicelevels.retention.period
|
|
67
|
+
)
|
|
68
|
+
)
|
|
52
69
|
|
|
53
70
|
if len(slas) > 0:
|
|
54
|
-
|
|
55
|
-
|
|
71
|
+
result.slaProperties = slas
|
|
56
72
|
if data_contract_spec.info.contact is not None:
|
|
57
73
|
support = []
|
|
58
74
|
if data_contract_spec.info.contact.email is not None:
|
|
59
|
-
support.append(
|
|
60
|
-
{
|
|
61
|
-
"channel": "email",
|
|
62
|
-
"url": "mailto:" + data_contract_spec.info.contact.email,
|
|
63
|
-
}
|
|
64
|
-
)
|
|
75
|
+
support.append(Support(channel="email", url="mailto:" + data_contract_spec.info.contact.email))
|
|
65
76
|
if data_contract_spec.info.contact.url is not None:
|
|
66
|
-
support.append(
|
|
67
|
-
{
|
|
68
|
-
"channel": "other",
|
|
69
|
-
"url": data_contract_spec.info.contact.url,
|
|
70
|
-
}
|
|
71
|
-
)
|
|
77
|
+
support.append(Support(channel="other", url=data_contract_spec.info.contact.url))
|
|
72
78
|
if len(support) > 0:
|
|
73
|
-
|
|
74
|
-
|
|
79
|
+
result.support = support
|
|
75
80
|
if data_contract_spec.servers is not None and len(data_contract_spec.servers) > 0:
|
|
76
81
|
servers = []
|
|
77
82
|
|
|
78
83
|
for server_key, server_value in data_contract_spec.servers.items():
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
server_dict["type"] = server_value.type
|
|
84
|
+
server = Server(server=server_key, type=server_value.type or "")
|
|
85
|
+
|
|
86
|
+
# Set all the attributes that are not None
|
|
83
87
|
if server_value.environment is not None:
|
|
84
|
-
|
|
88
|
+
server.environment = server_value.environment
|
|
85
89
|
if server_value.account is not None:
|
|
86
|
-
|
|
90
|
+
server.account = server_value.account
|
|
87
91
|
if server_value.database is not None:
|
|
88
|
-
|
|
92
|
+
if server.type == "oracle":
|
|
93
|
+
server.serviceName = server_value.database
|
|
94
|
+
else:
|
|
95
|
+
server.database = server_value.database
|
|
89
96
|
if server_value.schema_ is not None:
|
|
90
|
-
|
|
97
|
+
server.schema_ = server_value.schema_
|
|
91
98
|
if server_value.format is not None:
|
|
92
|
-
|
|
99
|
+
server.format = server_value.format
|
|
93
100
|
if server_value.project is not None:
|
|
94
|
-
|
|
101
|
+
server.project = server_value.project
|
|
95
102
|
if server_value.dataset is not None:
|
|
96
|
-
|
|
103
|
+
server.dataset = server_value.dataset
|
|
97
104
|
if server_value.path is not None:
|
|
98
|
-
|
|
105
|
+
server.path = server_value.path
|
|
99
106
|
if server_value.delimiter is not None:
|
|
100
|
-
|
|
107
|
+
server.delimiter = server_value.delimiter
|
|
101
108
|
if server_value.endpointUrl is not None:
|
|
102
|
-
|
|
109
|
+
server.endpointUrl = server_value.endpointUrl
|
|
103
110
|
if server_value.location is not None:
|
|
104
|
-
|
|
111
|
+
server.location = server_value.location
|
|
105
112
|
if server_value.host is not None:
|
|
106
|
-
|
|
113
|
+
server.host = server_value.host
|
|
107
114
|
if server_value.port is not None:
|
|
108
|
-
|
|
115
|
+
server.port = server_value.port
|
|
109
116
|
if server_value.catalog is not None:
|
|
110
|
-
|
|
117
|
+
server.catalog = server_value.catalog
|
|
111
118
|
if server_value.topic is not None:
|
|
112
|
-
|
|
119
|
+
server.topic = server_value.topic
|
|
113
120
|
if server_value.http_path is not None:
|
|
114
|
-
|
|
121
|
+
server.http_path = server_value.http_path
|
|
115
122
|
if server_value.token is not None:
|
|
116
|
-
|
|
123
|
+
server.token = server_value.token
|
|
117
124
|
if server_value.driver is not None:
|
|
118
|
-
|
|
125
|
+
server.driver = server_value.driver
|
|
126
|
+
|
|
119
127
|
if server_value.roles is not None:
|
|
120
|
-
|
|
121
|
-
{"name": role.name, "description": role.description} for role in server_value.roles
|
|
122
|
-
]
|
|
123
|
-
servers.append(server_dict)
|
|
128
|
+
server.roles = [Role(role=role.name, description=role.description) for role in server_value.roles]
|
|
124
129
|
|
|
125
|
-
|
|
126
|
-
odcs["servers"] = servers
|
|
130
|
+
servers.append(server)
|
|
127
131
|
|
|
128
|
-
|
|
132
|
+
if len(servers) > 0:
|
|
133
|
+
result.servers = servers
|
|
134
|
+
if (data_contract_spec.info.owner is not None) and (data_contract_spec.info.owner != ""):
|
|
135
|
+
result.team = Team(name=data_contract_spec.info.owner)
|
|
136
|
+
custom_properties = []
|
|
129
137
|
if data_contract_spec.info.model_extra is not None:
|
|
130
138
|
for key, value in data_contract_spec.info.model_extra.items():
|
|
131
|
-
|
|
132
|
-
if len(
|
|
133
|
-
|
|
139
|
+
custom_properties.append(CustomProperty(property=key, value=value))
|
|
140
|
+
if len(custom_properties) > 0:
|
|
141
|
+
result.customProperties = custom_properties
|
|
142
|
+
return result
|
|
134
143
|
|
|
135
|
-
return yaml.dump(odcs, indent=2, sort_keys=False, allow_unicode=True)
|
|
136
144
|
|
|
145
|
+
def to_odcs_schema(model_key, model_value: Model) -> SchemaObject:
|
|
146
|
+
schema_obj = SchemaObject(
|
|
147
|
+
name=model_key, physicalName=model_key, logicalType="object", physicalType=model_value.type
|
|
148
|
+
)
|
|
137
149
|
|
|
138
|
-
def to_odcs_schema(model_key, model_value: Model) -> dict:
|
|
139
|
-
odcs_table = {
|
|
140
|
-
"name": model_key,
|
|
141
|
-
"physicalName": model_key,
|
|
142
|
-
"logicalType": "object",
|
|
143
|
-
"physicalType": model_value.type,
|
|
144
|
-
}
|
|
145
150
|
if model_value.description is not None:
|
|
146
|
-
|
|
151
|
+
schema_obj.description = model_value.description
|
|
152
|
+
|
|
147
153
|
properties = to_properties(model_value.fields)
|
|
148
154
|
if properties:
|
|
149
|
-
|
|
155
|
+
schema_obj.properties = properties
|
|
150
156
|
|
|
151
157
|
model_quality = to_odcs_quality_list(model_value.quality)
|
|
152
158
|
if len(model_quality) > 0:
|
|
153
|
-
|
|
159
|
+
schema_obj.quality = model_quality
|
|
154
160
|
|
|
155
|
-
|
|
161
|
+
custom_properties = []
|
|
156
162
|
if model_value.model_extra is not None:
|
|
157
163
|
for key, value in model_value.model_extra.items():
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
164
|
+
custom_properties.append(CustomProperty(property=key, value=value))
|
|
165
|
+
|
|
166
|
+
if len(custom_properties) > 0:
|
|
167
|
+
schema_obj.customProperties = custom_properties
|
|
161
168
|
|
|
162
|
-
return
|
|
169
|
+
return schema_obj
|
|
163
170
|
|
|
164
171
|
|
|
165
172
|
def to_properties(fields: Dict[str, Field]) -> list:
|
|
@@ -191,88 +198,123 @@ def to_logical_type(type: str) -> str | None:
|
|
|
191
198
|
return "integer"
|
|
192
199
|
if type.lower() in ["boolean"]:
|
|
193
200
|
return "boolean"
|
|
194
|
-
if type.lower() in ["object", "record", "struct"]:
|
|
201
|
+
if type.lower() in ["object", "record", "struct", "map", "variant"]:
|
|
195
202
|
return "object"
|
|
196
|
-
if type.lower() in ["bytes"]:
|
|
197
|
-
return "array"
|
|
198
|
-
if type.lower() in ["array"]:
|
|
203
|
+
if type.lower() in ["bytes", "array"]:
|
|
199
204
|
return "array"
|
|
200
205
|
if type.lower() in ["null"]:
|
|
201
206
|
return None
|
|
202
207
|
return None
|
|
203
208
|
|
|
204
209
|
|
|
205
|
-
def to_physical_type(
|
|
206
|
-
|
|
207
|
-
|
|
210
|
+
def to_physical_type(config: Dict[str, Any]) -> str | None:
|
|
211
|
+
if config is None:
|
|
212
|
+
return None
|
|
213
|
+
if "postgresType" in config:
|
|
214
|
+
return config["postgresType"]
|
|
215
|
+
elif "bigqueryType" in config:
|
|
216
|
+
return config["bigqueryType"]
|
|
217
|
+
elif "snowflakeType" in config:
|
|
218
|
+
return config["snowflakeType"]
|
|
219
|
+
elif "redshiftType" in config:
|
|
220
|
+
return config["redshiftType"]
|
|
221
|
+
elif "sqlserverType" in config:
|
|
222
|
+
return config["sqlserverType"]
|
|
223
|
+
elif "databricksType" in config:
|
|
224
|
+
return config["databricksType"]
|
|
225
|
+
elif "physicalType" in config:
|
|
226
|
+
return config["physicalType"]
|
|
227
|
+
elif "oracleType" in config:
|
|
228
|
+
return config["oracleType"]
|
|
229
|
+
return None
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def to_property(field_name: str, field: Field) -> SchemaProperty:
|
|
233
|
+
property = SchemaProperty(name=field_name)
|
|
208
234
|
|
|
235
|
+
if field.fields:
|
|
236
|
+
properties = []
|
|
237
|
+
for field_name_, field_ in field.fields.items():
|
|
238
|
+
property_ = to_property(field_name_, field_)
|
|
239
|
+
properties.append(property_)
|
|
240
|
+
property.properties = properties
|
|
241
|
+
|
|
242
|
+
if field.items:
|
|
243
|
+
items = to_property(field_name, field.items)
|
|
244
|
+
items.name = None # Clear the name for items
|
|
245
|
+
property.items = items
|
|
209
246
|
|
|
210
|
-
def to_property(field_name: str, field: Field) -> dict:
|
|
211
|
-
property = {"name": field_name}
|
|
212
247
|
if field.title is not None:
|
|
213
|
-
property
|
|
248
|
+
property.businessName = field.title
|
|
249
|
+
|
|
214
250
|
if field.type is not None:
|
|
215
|
-
property
|
|
216
|
-
property
|
|
251
|
+
property.logicalType = to_logical_type(field.type)
|
|
252
|
+
property.physicalType = to_physical_type(field.config) or field.type
|
|
253
|
+
|
|
217
254
|
if field.description is not None:
|
|
218
|
-
property
|
|
255
|
+
property.description = field.description
|
|
256
|
+
|
|
219
257
|
if field.required is not None:
|
|
220
|
-
property
|
|
258
|
+
property.required = field.required
|
|
259
|
+
|
|
221
260
|
if field.unique is not None:
|
|
222
|
-
property
|
|
261
|
+
property.unique = field.unique
|
|
262
|
+
|
|
223
263
|
if field.classification is not None:
|
|
224
|
-
property
|
|
264
|
+
property.classification = field.classification
|
|
265
|
+
|
|
225
266
|
if field.examples is not None:
|
|
226
|
-
property
|
|
267
|
+
property.examples = field.examples.copy()
|
|
268
|
+
|
|
227
269
|
if field.example is not None:
|
|
228
|
-
property
|
|
270
|
+
property.examples = [field.example]
|
|
271
|
+
|
|
229
272
|
if field.primaryKey is not None and field.primaryKey:
|
|
230
|
-
property
|
|
231
|
-
property
|
|
273
|
+
property.primaryKey = field.primaryKey
|
|
274
|
+
property.primaryKeyPosition = 1
|
|
275
|
+
|
|
232
276
|
if field.primary is not None and field.primary:
|
|
233
|
-
property
|
|
234
|
-
property
|
|
277
|
+
property.primaryKey = field.primary
|
|
278
|
+
property.primaryKeyPosition = 1
|
|
235
279
|
|
|
236
|
-
|
|
280
|
+
custom_properties = []
|
|
237
281
|
if field.model_extra is not None:
|
|
238
282
|
for key, value in field.model_extra.items():
|
|
239
|
-
|
|
283
|
+
custom_properties.append(CustomProperty(property=key, value=value))
|
|
284
|
+
|
|
240
285
|
if field.pii is not None:
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
286
|
+
custom_properties.append(CustomProperty(property="pii", value=field.pii))
|
|
287
|
+
|
|
288
|
+
if len(custom_properties) > 0:
|
|
289
|
+
property.customProperties = custom_properties
|
|
244
290
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
property["tags"].extend(field.tags)
|
|
248
|
-
if not property["tags"]:
|
|
249
|
-
del property["tags"]
|
|
291
|
+
if field.tags is not None and len(field.tags) > 0:
|
|
292
|
+
property.tags = field.tags
|
|
250
293
|
|
|
251
|
-
|
|
294
|
+
logical_type_options = {}
|
|
252
295
|
if field.minLength is not None:
|
|
253
|
-
|
|
296
|
+
logical_type_options["minLength"] = field.minLength
|
|
254
297
|
if field.maxLength is not None:
|
|
255
|
-
|
|
298
|
+
logical_type_options["maxLength"] = field.maxLength
|
|
256
299
|
if field.pattern is not None:
|
|
257
|
-
|
|
300
|
+
logical_type_options["pattern"] = field.pattern
|
|
258
301
|
if field.minimum is not None:
|
|
259
|
-
|
|
302
|
+
logical_type_options["minimum"] = field.minimum
|
|
260
303
|
if field.maximum is not None:
|
|
261
|
-
|
|
304
|
+
logical_type_options["maximum"] = field.maximum
|
|
262
305
|
if field.exclusiveMinimum is not None:
|
|
263
|
-
|
|
306
|
+
logical_type_options["exclusiveMinimum"] = field.exclusiveMinimum
|
|
264
307
|
if field.exclusiveMaximum is not None:
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
308
|
+
logical_type_options["exclusiveMaximum"] = field.exclusiveMaximum
|
|
309
|
+
|
|
310
|
+
if logical_type_options:
|
|
311
|
+
property.logicalTypeOptions = logical_type_options
|
|
268
312
|
|
|
269
313
|
if field.quality is not None:
|
|
270
314
|
quality_list = field.quality
|
|
271
315
|
quality_property = to_odcs_quality_list(quality_list)
|
|
272
316
|
if len(quality_property) > 0:
|
|
273
|
-
property
|
|
274
|
-
|
|
275
|
-
# todo enum
|
|
317
|
+
property.quality = quality_property
|
|
276
318
|
|
|
277
319
|
return property
|
|
278
320
|
|
|
@@ -285,33 +327,35 @@ def to_odcs_quality_list(quality_list):
|
|
|
285
327
|
|
|
286
328
|
|
|
287
329
|
def to_odcs_quality(quality):
|
|
288
|
-
|
|
330
|
+
quality_obj = DataQuality(type=quality.type)
|
|
331
|
+
|
|
289
332
|
if quality.description is not None:
|
|
290
|
-
|
|
333
|
+
quality_obj.description = quality.description
|
|
291
334
|
if quality.query is not None:
|
|
292
|
-
|
|
335
|
+
quality_obj.query = quality.query
|
|
293
336
|
# dialect is not supported in v3.0.0
|
|
294
337
|
if quality.mustBe is not None:
|
|
295
|
-
|
|
338
|
+
quality_obj.mustBe = quality.mustBe
|
|
296
339
|
if quality.mustNotBe is not None:
|
|
297
|
-
|
|
340
|
+
quality_obj.mustNotBe = quality.mustNotBe
|
|
298
341
|
if quality.mustBeGreaterThan is not None:
|
|
299
|
-
|
|
342
|
+
quality_obj.mustBeGreaterThan = quality.mustBeGreaterThan
|
|
300
343
|
if quality.mustBeGreaterThanOrEqualTo is not None:
|
|
301
|
-
|
|
344
|
+
quality_obj.mustBeGreaterOrEqualTo = quality.mustBeGreaterThanOrEqualTo
|
|
302
345
|
if quality.mustBeLessThan is not None:
|
|
303
|
-
|
|
346
|
+
quality_obj.mustBeLessThan = quality.mustBeLessThan
|
|
304
347
|
if quality.mustBeLessThanOrEqualTo is not None:
|
|
305
|
-
|
|
348
|
+
quality_obj.mustBeLessOrEqualTo = quality.mustBeLessThanOrEqualTo
|
|
306
349
|
if quality.mustBeBetween is not None:
|
|
307
|
-
|
|
350
|
+
quality_obj.mustBeBetween = quality.mustBeBetween
|
|
308
351
|
if quality.mustNotBeBetween is not None:
|
|
309
|
-
|
|
352
|
+
quality_obj.mustNotBeBetween = quality.mustNotBeBetween
|
|
310
353
|
if quality.engine is not None:
|
|
311
|
-
|
|
354
|
+
quality_obj.engine = quality.engine
|
|
312
355
|
if quality.implementation is not None:
|
|
313
|
-
|
|
314
|
-
|
|
356
|
+
quality_obj.implementation = quality.implementation
|
|
357
|
+
|
|
358
|
+
return quality_obj
|
|
315
359
|
|
|
316
360
|
|
|
317
361
|
def to_status(status):
|