datacontract-cli 0.10.20__py3-none-any.whl → 0.10.21__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.
Potentially problematic release.
This version of datacontract-cli might be problematic. Click here for more details.
- datacontract/{web.py → api.py} +55 -3
- datacontract/cli.py +27 -5
- datacontract/export/custom_converter.py +40 -0
- datacontract/export/exporter.py +1 -0
- datacontract/export/exporter_factory.py +4 -0
- datacontract/lint/urls.py +4 -4
- datacontract/model/data_contract_specification.py +130 -129
- datacontract/model/run.py +18 -18
- datacontract/templates/datacontract.html +16 -2
- datacontract/templates/partials/definition.html +3 -95
- datacontract/templates/partials/model_field.html +13 -0
- datacontract/templates/partials/quality.html +49 -0
- datacontract/templates/style/output.css +151 -152
- {datacontract_cli-0.10.20.dist-info → datacontract_cli-0.10.21.dist-info}/METADATA +103 -22
- {datacontract_cli-0.10.20.dist-info → datacontract_cli-0.10.21.dist-info}/RECORD +19 -17
- {datacontract_cli-0.10.20.dist-info → datacontract_cli-0.10.21.dist-info}/LICENSE +0 -0
- {datacontract_cli-0.10.20.dist-info → datacontract_cli-0.10.21.dist-info}/WHEEL +0 -0
- {datacontract_cli-0.10.20.dist-info → datacontract_cli-0.10.21.dist-info}/entry_points.txt +0 -0
- {datacontract_cli-0.10.20.dist-info → datacontract_cli-0.10.21.dist-info}/top_level.txt +0 -0
datacontract/model/run.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from datetime import datetime, timezone
|
|
3
3
|
from enum import Enum
|
|
4
|
-
from typing import List
|
|
4
|
+
from typing import List
|
|
5
5
|
from uuid import UUID, uuid4
|
|
6
6
|
|
|
7
7
|
from pydantic import BaseModel
|
|
@@ -18,14 +18,14 @@ class ResultEnum(str, Enum):
|
|
|
18
18
|
|
|
19
19
|
class Check(BaseModel):
|
|
20
20
|
type: str
|
|
21
|
-
name:
|
|
22
|
-
result: ResultEnum
|
|
23
|
-
engine: str
|
|
24
|
-
reason:
|
|
25
|
-
model:
|
|
26
|
-
field:
|
|
27
|
-
details:
|
|
28
|
-
diagnostics:
|
|
21
|
+
name: str | None
|
|
22
|
+
result: ResultEnum | None
|
|
23
|
+
engine: str | None
|
|
24
|
+
reason: str | None = None
|
|
25
|
+
model: str | None = None
|
|
26
|
+
field: str | None = None
|
|
27
|
+
details: str | None = None
|
|
28
|
+
diagnostics: dict | None = None
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
class Log(BaseModel):
|
|
@@ -36,16 +36,16 @@ class Log(BaseModel):
|
|
|
36
36
|
|
|
37
37
|
class Run(BaseModel):
|
|
38
38
|
runId: UUID
|
|
39
|
-
dataContractId:
|
|
40
|
-
dataContractVersion:
|
|
41
|
-
dataProductId:
|
|
42
|
-
outputPortId:
|
|
43
|
-
server:
|
|
44
|
-
timestampStart: datetime
|
|
45
|
-
timestampEnd: datetime
|
|
39
|
+
dataContractId: str | None = None
|
|
40
|
+
dataContractVersion: str | None = None
|
|
41
|
+
dataProductId: str | None = None
|
|
42
|
+
outputPortId: str | None = None
|
|
43
|
+
server: str | None = None
|
|
44
|
+
timestampStart: datetime | None
|
|
45
|
+
timestampEnd: datetime | None
|
|
46
46
|
result: ResultEnum = ResultEnum.unknown
|
|
47
|
-
checks: List[Check]
|
|
48
|
-
logs: List[Log]
|
|
47
|
+
checks: List[Check] | None
|
|
48
|
+
logs: List[Log] | None
|
|
49
49
|
|
|
50
50
|
def has_passed(self):
|
|
51
51
|
self.calculate_result()
|
|
@@ -146,14 +146,28 @@
|
|
|
146
146
|
{{ render_partial('partials/model_field.html', nested = False, field_name=field_name, field = field, level = 0) }}
|
|
147
147
|
{% endfor %}
|
|
148
148
|
</tbody>
|
|
149
|
-
{% if model.primaryKey %}
|
|
150
|
-
<tfoot class="
|
|
149
|
+
{% if model.primaryKey or model.quality %}
|
|
150
|
+
<tfoot class="divide-y divide-gray-200 bg-white">
|
|
151
|
+
{% if model.quality %}
|
|
152
|
+
{% for quality in model.quality %}
|
|
151
153
|
<tr>
|
|
154
|
+
<th scope="colgroup" colspan="4"
|
|
155
|
+
class="py-2 pl-4 pr-3 text-left text-sm font-normal sm:pl-6 bg-white">
|
|
156
|
+
{{ render_partial('partials/quality.html', quality = quality)}}
|
|
157
|
+
</th>
|
|
158
|
+
</tr>
|
|
159
|
+
{% endfor %}
|
|
160
|
+
{% endif %}
|
|
161
|
+
|
|
162
|
+
{% if model.primaryKey %}
|
|
163
|
+
<tr class="bg-gray-50">
|
|
152
164
|
<th scope="colgroup" colspan="4"
|
|
153
165
|
class="py-2 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
|
|
154
166
|
<span>Primary Key: {{ model.primaryKey }}</span>
|
|
155
167
|
</th>
|
|
156
168
|
</tr>
|
|
169
|
+
{% endif %}
|
|
170
|
+
|
|
157
171
|
</tfoot>
|
|
158
172
|
{% endif %}
|
|
159
173
|
</table>
|
|
@@ -3,112 +3,20 @@
|
|
|
3
3
|
<div class="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8">
|
|
4
4
|
<div class="overflow-hidden shadow ring-1 ring-black ring-opacity-5 sm:rounded-lg">
|
|
5
5
|
|
|
6
|
-
<table class="min-w-full divide-y divide-gray-300">
|
|
6
|
+
<table class="min-w-full divide-y divide-gray-300" id="/definitions/{{ definition_name }}">
|
|
7
7
|
<thead class="bg-gray-50">
|
|
8
8
|
<tr>
|
|
9
9
|
<th scope="colgroup" colspan="3" class="py-2 pl-4 pr-3 text-left font-semibold text-gray-900 sm:pl-6">
|
|
10
10
|
<span>{{ definition_name }}</span>
|
|
11
|
-
<span class="inline-flex items-center rounded-md bg-gray-50 px-2 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10">{{ definition.domain }}</span>
|
|
12
11
|
<div class="text-sm font-medium text-gray-500">{{ definition.description }}</div>
|
|
13
12
|
</th>
|
|
14
13
|
</tr>
|
|
15
14
|
</thead>
|
|
16
15
|
<tbody class="divide-y divide-gray-200 bg-white">
|
|
17
|
-
<tr id="/definitions/{{ definition_name }}">
|
|
18
|
-
<td class="whitespace-nowrap py-2 pl-4 pr-2 text-sm font-medium text-gray-900 sm:pl-6 w-2/12">
|
|
19
|
-
<div class="py-2 text-sm">
|
|
20
|
-
{% if definition.title %}
|
|
21
|
-
<div>{{ definition.title }}</div>
|
|
22
|
-
{% endif %}
|
|
23
|
-
<div class="font-mono">{{ definition_name }}</div>
|
|
24
|
-
</div>
|
|
25
|
-
</td>
|
|
26
|
-
<td class="whitespace-nowrap px-1 py-2 text-sm text-gray-500 w-1/12">
|
|
27
|
-
<div class="py-2 text-sm">
|
|
28
|
-
{{ definition.type }}
|
|
29
|
-
{% if definition.format %}
|
|
30
|
-
<span class="inline-flex items-center rounded-md bg-blue-50 px-1 py-1 text-xs font-medium text-blue-600 ring-1 ring-inset ring-blue-500/10 mr-1 mt-1">{{ definition.format }}</span>
|
|
31
|
-
{% endif %}
|
|
32
|
-
</div>
|
|
33
|
-
</td>
|
|
34
|
-
<td class="px-3 py-2 text-sm text-gray-500 w-9/12">
|
|
35
|
-
{% if definition.example %}
|
|
36
|
-
<div class="mt-1 italic">
|
|
37
|
-
<span class="text-gray-600">Example:</span> <span class="font-mono">{{ definition.example }}</span>
|
|
38
|
-
</div>
|
|
39
|
-
{% endif %}
|
|
40
16
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
<span class="text-gray-600">Examples:</span>
|
|
44
|
-
{% for example in definition.examples %}
|
|
45
|
-
<span class="font-mono">{{ example }}</span>{% if not loop.last %}, {% endif %}
|
|
46
|
-
{% endfor %}
|
|
47
|
-
</div>
|
|
48
|
-
{% endif %}
|
|
17
|
+
{{ render_partial('partials/model_field.html', nested = False, field_name=definition_name,
|
|
18
|
+
field = definition, level = 0) }}
|
|
49
19
|
|
|
50
|
-
{% if definition.tags %}
|
|
51
|
-
<div>
|
|
52
|
-
<span class="text-gray-600 italic">Tags:</span>
|
|
53
|
-
{% for tag in definition.tags %}
|
|
54
|
-
<span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">{{ tag }}</span>
|
|
55
|
-
{% endfor %}
|
|
56
|
-
</div>
|
|
57
|
-
{% endif %}
|
|
58
|
-
{% if definition.enum %}
|
|
59
|
-
<div class="py-2 text-sm">
|
|
60
|
-
<span class="text-gray-600 italic">Enum:</span>
|
|
61
|
-
{% for value in definition.enum %}
|
|
62
|
-
<span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">{{ value }}</span>
|
|
63
|
-
{% endfor %}
|
|
64
|
-
</div>
|
|
65
|
-
{% endif %}
|
|
66
|
-
<div>
|
|
67
|
-
{% if definition.minLength %}
|
|
68
|
-
<span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">minLength:{{ definition.minLength }}</span>
|
|
69
|
-
{% endif %}
|
|
70
|
-
{% if definition.maxLength %}
|
|
71
|
-
<span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">maxLength:{{ definition.maxLength }}</span>
|
|
72
|
-
{% endif %}
|
|
73
|
-
{% if definition.pattern %}
|
|
74
|
-
<span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">pattern:{{ definition.pattern }}</span>
|
|
75
|
-
{% endif %}
|
|
76
|
-
{% if definition.precision %}
|
|
77
|
-
<span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">precision:{{ definition.precision }}</span>
|
|
78
|
-
{% endif %}
|
|
79
|
-
{% if definition.scale %}
|
|
80
|
-
<span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">scale:{{ definition.scale }}</span>
|
|
81
|
-
{% endif %}
|
|
82
|
-
{% if definition.minimum %}
|
|
83
|
-
<span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">minimum:{{ definition.minimum }}</span>
|
|
84
|
-
{% endif %}
|
|
85
|
-
{% if definition.exclusiveMinimum %}
|
|
86
|
-
<span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">exclusiveMinimum:{{ definition.exclusiveMinimum }}</span>
|
|
87
|
-
{% endif %}
|
|
88
|
-
{% if definition.maximum %}
|
|
89
|
-
<span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">maximum:{{ definition.maximum }}</span>
|
|
90
|
-
{% endif %}
|
|
91
|
-
{% if definition.exclusiveMaximum %}
|
|
92
|
-
<span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">exclusiveMaximum:{{ definition.exclusiveMaximum }}</span>
|
|
93
|
-
{% endif %}
|
|
94
|
-
{% if definition.classification %}
|
|
95
|
-
<span class="inline-flex items-center rounded-md bg-blue-50 px-1 py-1 text-xs font-medium text-blue-600 ring-1 ring-inset ring-blue-500/10 mr-1 mt-1">{{ definition.classification }}</span>
|
|
96
|
-
{% endif %}
|
|
97
|
-
{% if definition.pii %}
|
|
98
|
-
<span class="inline-flex items-center rounded-md bg-yellow-50 px-1 py-1 text-xs font-medium text-yellow-600 ring-1 ring-inset ring-yellow-500/10 mr-1 mt-1">PII</span>
|
|
99
|
-
{% endif %}
|
|
100
|
-
{% for key, value in definition.model_extra.items() %}
|
|
101
|
-
<span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">{{ key }}:{{ value }}</span>
|
|
102
|
-
{% endfor %}
|
|
103
|
-
{% if definition.links %}
|
|
104
|
-
{% for name,href in definition.links.items() %}
|
|
105
|
-
<a href="{{ href }}" class="inline-flex items-center px-1 py-1 mr-1 mt-1 text-sky-500 hover:text-gray-700 text-xs font-semibold">{{ name }}</a>
|
|
106
|
-
{% endfor %}
|
|
107
|
-
{% endif %}
|
|
108
|
-
</div>
|
|
109
|
-
</td>
|
|
110
|
-
|
|
111
|
-
</tr>
|
|
112
20
|
</tbody>
|
|
113
21
|
</table>
|
|
114
22
|
</div>
|
|
@@ -48,6 +48,14 @@
|
|
|
48
48
|
</div>
|
|
49
49
|
{% endif %}
|
|
50
50
|
|
|
51
|
+
{% if field.enum %}
|
|
52
|
+
<div class="mt-1 italic">
|
|
53
|
+
Enum:
|
|
54
|
+
{% for enum_value in field.enum %}
|
|
55
|
+
<span class="font-mono">{{ enum_value }}</span>{% if not loop.last %}, {% endif %}
|
|
56
|
+
{% endfor %}
|
|
57
|
+
</div>
|
|
58
|
+
{% endif %}
|
|
51
59
|
<div>
|
|
52
60
|
{% if field.primaryKey or field.primary %}
|
|
53
61
|
<span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">primary</span>
|
|
@@ -103,6 +111,11 @@
|
|
|
103
111
|
{% endfor %}
|
|
104
112
|
{% endif %}
|
|
105
113
|
</div>
|
|
114
|
+
{% if field.quality %}
|
|
115
|
+
{% for quality in field.quality %}
|
|
116
|
+
{{ render_partial('partials/quality.html', quality = quality) }}
|
|
117
|
+
{% endfor %}
|
|
118
|
+
{% endif %}
|
|
106
119
|
</td>
|
|
107
120
|
</tr>
|
|
108
121
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<div class="mt-2">
|
|
2
|
+
<span class="italic">Quality | {{quality.type|upper}}:</span> {{ quality.description }}
|
|
3
|
+
{% if quality.type == 'sql' and quality.query %}
|
|
4
|
+
<div class="pl-4">
|
|
5
|
+
Query:
|
|
6
|
+
<div class="ring-1 ring-inset ring-gray-500/10 bg-gray-50 p-2 rounded-md"><pre><code>{{ quality.query }}</code></pre></div>
|
|
7
|
+
{% if quality.mustBe != None %}
|
|
8
|
+
<div>
|
|
9
|
+
Must Be: <span class="font-mono font-bold"> {{quality.mustBe}}</span>
|
|
10
|
+
</div>
|
|
11
|
+
{% endif %}
|
|
12
|
+
{% if quality.mustNotBe != None %}
|
|
13
|
+
<div>
|
|
14
|
+
Must Not Be: <span class="font-mono font-bold"> {{quality.mustNotBe}}</span>
|
|
15
|
+
</div>
|
|
16
|
+
{% endif %}
|
|
17
|
+
{% if quality.mustBeGreaterThan != None %}
|
|
18
|
+
<div>
|
|
19
|
+
Must Be Greater Than: <span class="font-mono font-bold"> {{quality.mustBeGreaterThan}}</span>
|
|
20
|
+
</div>
|
|
21
|
+
{% endif %}
|
|
22
|
+
{% if quality.mustBeGreaterThanOrEqualTo != None %}
|
|
23
|
+
<div>
|
|
24
|
+
Must Be Greater Than Or Equal To: <span class="font-mono font-bold"> {{quality.mustBeGreaterThanOrEqualTo}}</span>
|
|
25
|
+
</div>
|
|
26
|
+
{% endif %}
|
|
27
|
+
{% if quality.mustBeLessThan != None %}
|
|
28
|
+
<div>
|
|
29
|
+
Must Be Less Than: <span class="font-mono font-bold"> {{quality.mustBeLessThan}}</span>
|
|
30
|
+
</div>
|
|
31
|
+
{% endif %}
|
|
32
|
+
{% if quality.mustBeLessThanOrEqualTo != None %}
|
|
33
|
+
<div>
|
|
34
|
+
Must Be Less Than Or Equal To: <span class="font-mono font-bold"> {{quality.mustBeLessThanOrEqualTo}}</span>
|
|
35
|
+
</div>
|
|
36
|
+
{% endif %}
|
|
37
|
+
{% if quality.mustBeBetween %}
|
|
38
|
+
<div>
|
|
39
|
+
Must Be Between: <span class="font-mono font-bold"> {{quality.mustBeBetween|join(' and ')}}</span>
|
|
40
|
+
</div>
|
|
41
|
+
{% endif %}
|
|
42
|
+
{% if quality.mustNotBeBetween %}
|
|
43
|
+
<div>
|
|
44
|
+
Must Not Be Between: <span class="font-mono font-bold"> {{quality.mustNotBeBetween}}</span>
|
|
45
|
+
</div>
|
|
46
|
+
{% endif %}
|
|
47
|
+
</div>
|
|
48
|
+
{% endif %}
|
|
49
|
+
</div>
|