datacontract-cli 0.10.19__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/api.py +253 -0
- datacontract/cli.py +28 -7
- datacontract/export/custom_converter.py +40 -0
- datacontract/export/exporter.py +1 -0
- datacontract/export/exporter_factory.py +4 -0
- datacontract/lint/urls.py +13 -9
- 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.19.dist-info → datacontract_cli-0.10.21.dist-info}/METADATA +103 -21
- {datacontract_cli-0.10.19.dist-info → datacontract_cli-0.10.21.dist-info}/RECORD +19 -17
- datacontract/web.py +0 -67
- {datacontract_cli-0.10.19.dist-info → datacontract_cli-0.10.21.dist-info}/LICENSE +0 -0
- {datacontract_cli-0.10.19.dist-info → datacontract_cli-0.10.21.dist-info}/WHEEL +0 -0
- {datacontract_cli-0.10.19.dist-info → datacontract_cli-0.10.21.dist-info}/entry_points.txt +0 -0
- {datacontract_cli-0.10.19.dist-info → datacontract_cli-0.10.21.dist-info}/top_level.txt +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import os
|
|
2
|
-
from typing import Any, Dict, List
|
|
2
|
+
from typing import Any, Dict, List
|
|
3
3
|
|
|
4
4
|
import pydantic as pyd
|
|
5
5
|
import yaml
|
|
@@ -32,9 +32,9 @@ DATACONTRACT_TYPES = [
|
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
class Contact(pyd.BaseModel):
|
|
35
|
-
name: str = None
|
|
36
|
-
url: str = None
|
|
37
|
-
email: str = None
|
|
35
|
+
name: str | None = None
|
|
36
|
+
url: str | None = None
|
|
37
|
+
email: str | None = None
|
|
38
38
|
|
|
39
39
|
model_config = pyd.ConfigDict(
|
|
40
40
|
extra="allow",
|
|
@@ -42,37 +42,37 @@ class Contact(pyd.BaseModel):
|
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
class ServerRole(pyd.BaseModel):
|
|
45
|
-
name: str = None
|
|
46
|
-
description: str = None
|
|
45
|
+
name: str | None = None
|
|
46
|
+
description: str | None = None
|
|
47
47
|
model_config = pyd.ConfigDict(
|
|
48
48
|
extra="allow",
|
|
49
49
|
)
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
class Server(pyd.BaseModel):
|
|
53
|
-
type: str = None
|
|
54
|
-
description: str = None
|
|
55
|
-
environment: str = None
|
|
56
|
-
format: str = None
|
|
57
|
-
project: str = None
|
|
58
|
-
dataset: str = None
|
|
59
|
-
path: str = None
|
|
60
|
-
delimiter: str = None
|
|
61
|
-
endpointUrl: str = None
|
|
62
|
-
location: str = None
|
|
63
|
-
account: str = None
|
|
64
|
-
database: str = None
|
|
65
|
-
schema_: str = pyd.Field(default=None, alias="schema")
|
|
66
|
-
host: str = None
|
|
67
|
-
port: int = None
|
|
68
|
-
catalog: str = None
|
|
69
|
-
topic: str = None
|
|
70
|
-
http_path: str = None # Use ENV variable
|
|
71
|
-
token: str = None # Use ENV variable
|
|
72
|
-
dataProductId: str = None
|
|
73
|
-
outputPortId: str = None
|
|
74
|
-
driver: str = None
|
|
75
|
-
storageAccount: str = None
|
|
53
|
+
type: str | None = None
|
|
54
|
+
description: str | None = None
|
|
55
|
+
environment: str | None = None
|
|
56
|
+
format: str | None = None
|
|
57
|
+
project: str | None = None
|
|
58
|
+
dataset: str | None = None
|
|
59
|
+
path: str | None = None
|
|
60
|
+
delimiter: str | None = None
|
|
61
|
+
endpointUrl: str | None = None
|
|
62
|
+
location: str | None = None
|
|
63
|
+
account: str | None = None
|
|
64
|
+
database: str | None = None
|
|
65
|
+
schema_: str | None = pyd.Field(default=None, alias="schema")
|
|
66
|
+
host: str | None = None
|
|
67
|
+
port: int | None = None
|
|
68
|
+
catalog: str | None = None
|
|
69
|
+
topic: str | None = None
|
|
70
|
+
http_path: str | None = None # Use ENV variable
|
|
71
|
+
token: str | None = None # Use ENV variable
|
|
72
|
+
dataProductId: str | None = None
|
|
73
|
+
outputPortId: str | None = None
|
|
74
|
+
driver: str | None = None
|
|
75
|
+
storageAccount: str | None = None
|
|
76
76
|
roles: List[ServerRole] = None
|
|
77
77
|
|
|
78
78
|
model_config = pyd.ConfigDict(
|
|
@@ -81,11 +81,11 @@ class Server(pyd.BaseModel):
|
|
|
81
81
|
|
|
82
82
|
|
|
83
83
|
class Terms(pyd.BaseModel):
|
|
84
|
-
usage: str = None
|
|
85
|
-
limitations: str = None
|
|
86
|
-
billing: str = None
|
|
87
|
-
noticePeriod: str = None
|
|
88
|
-
description: str = None
|
|
84
|
+
usage: str | None = None
|
|
85
|
+
limitations: str | None = None
|
|
86
|
+
billing: str | None = None
|
|
87
|
+
noticePeriod: str | None = None
|
|
88
|
+
description: str | None = None
|
|
89
89
|
|
|
90
90
|
model_config = pyd.ConfigDict(
|
|
91
91
|
extra="allow",
|
|
@@ -93,26 +93,27 @@ class Terms(pyd.BaseModel):
|
|
|
93
93
|
|
|
94
94
|
|
|
95
95
|
class Definition(pyd.BaseModel):
|
|
96
|
-
domain: str = None
|
|
97
|
-
name: str = None
|
|
98
|
-
title: str = None
|
|
99
|
-
description: str = None
|
|
100
|
-
type: str = None
|
|
96
|
+
domain: str | None = None
|
|
97
|
+
name: str | None = None
|
|
98
|
+
title: str | None = None
|
|
99
|
+
description: str | None = None
|
|
100
|
+
type: str | None = None
|
|
101
101
|
enum: List[str] = []
|
|
102
|
-
format: str = None
|
|
103
|
-
minLength: int = None
|
|
104
|
-
maxLength: int = None
|
|
105
|
-
pattern: str = None
|
|
106
|
-
minimum: int = None
|
|
107
|
-
exclusiveMinimum: int = None
|
|
108
|
-
maximum: int = None
|
|
109
|
-
exclusiveMaximum: int = None
|
|
110
|
-
pii: bool = None
|
|
111
|
-
classification: str = None
|
|
102
|
+
format: str | None = None
|
|
103
|
+
minLength: int | None = None
|
|
104
|
+
maxLength: int | None = None
|
|
105
|
+
pattern: str | None = None
|
|
106
|
+
minimum: int | None = None
|
|
107
|
+
exclusiveMinimum: int | None = None
|
|
108
|
+
maximum: int | None = None
|
|
109
|
+
exclusiveMaximum: int | None = None
|
|
110
|
+
pii: bool | None = None
|
|
111
|
+
classification: str | None = None
|
|
112
112
|
fields: Dict[str, "Field"] = {}
|
|
113
|
+
items: "Field" = None
|
|
113
114
|
tags: List[str] = []
|
|
114
115
|
links: Dict[str, str] = {}
|
|
115
|
-
example: str = None
|
|
116
|
+
example: str | None = None
|
|
116
117
|
examples: List[Any] | None = None
|
|
117
118
|
|
|
118
119
|
model_config = pyd.ConfigDict(
|
|
@@ -121,20 +122,20 @@ class Definition(pyd.BaseModel):
|
|
|
121
122
|
|
|
122
123
|
|
|
123
124
|
class Quality(pyd.BaseModel):
|
|
124
|
-
type: str = None
|
|
125
|
-
description: str = None
|
|
126
|
-
query: str = None
|
|
127
|
-
dialect: str = None
|
|
128
|
-
mustBe: int = None
|
|
129
|
-
mustNotBe: int = None
|
|
130
|
-
mustBeGreaterThan: int = None
|
|
131
|
-
mustBeGreaterThanOrEqualTo: int = None
|
|
132
|
-
mustBeLessThan: int = None
|
|
133
|
-
mustBeLessThanOrEqualTo: int = None
|
|
125
|
+
type: str | None = None
|
|
126
|
+
description: str | None = None
|
|
127
|
+
query: str | None = None
|
|
128
|
+
dialect: str | None = None
|
|
129
|
+
mustBe: int | None = None
|
|
130
|
+
mustNotBe: int | None = None
|
|
131
|
+
mustBeGreaterThan: int | None = None
|
|
132
|
+
mustBeGreaterThanOrEqualTo: int | None = None
|
|
133
|
+
mustBeLessThan: int | None = None
|
|
134
|
+
mustBeLessThanOrEqualTo: int | None = None
|
|
134
135
|
mustBeBetween: List[int] = None
|
|
135
136
|
mustNotBeBetween: List[int] = None
|
|
136
|
-
engine: str = None
|
|
137
|
-
implementation: str | Dict[str, Any] = None
|
|
137
|
+
engine: str | None = None
|
|
138
|
+
implementation: str | Dict[str, Any] | None = None
|
|
138
139
|
|
|
139
140
|
model_config = pyd.ConfigDict(
|
|
140
141
|
extra="allow",
|
|
@@ -144,26 +145,26 @@ class Quality(pyd.BaseModel):
|
|
|
144
145
|
class Field(pyd.BaseModel):
|
|
145
146
|
ref: str = pyd.Field(default=None, alias="$ref")
|
|
146
147
|
title: str | None = None
|
|
147
|
-
type: str = None
|
|
148
|
-
format: str = None
|
|
149
|
-
required: bool = None
|
|
148
|
+
type: str | None = None
|
|
149
|
+
format: str | None = None
|
|
150
|
+
required: bool | None = None
|
|
150
151
|
primary: bool = pyd.Field(
|
|
151
152
|
default=None,
|
|
152
153
|
deprecated="Removed in Data Contract Specification v1.1.0. Use primaryKey instead.",
|
|
153
154
|
)
|
|
154
155
|
primaryKey: bool | None = None
|
|
155
156
|
unique: bool | None = None
|
|
156
|
-
references: str = None
|
|
157
|
+
references: str | None = None
|
|
157
158
|
description: str | None = None
|
|
158
159
|
pii: bool | None = None
|
|
159
160
|
classification: str | None = None
|
|
160
|
-
pattern: str = None
|
|
161
|
-
minLength: int = None
|
|
162
|
-
maxLength: int = None
|
|
163
|
-
minimum: int = None
|
|
164
|
-
exclusiveMinimum: int = None
|
|
165
|
-
maximum: int = None
|
|
166
|
-
exclusiveMaximum: int = None
|
|
161
|
+
pattern: str | None = None
|
|
162
|
+
minLength: int | None = None
|
|
163
|
+
maxLength: int | None = None
|
|
164
|
+
minimum: int | None = None
|
|
165
|
+
exclusiveMinimum: int | None = None
|
|
166
|
+
maximum: int | None = None
|
|
167
|
+
exclusiveMaximum: int | None = None
|
|
167
168
|
enum: List[str] | None = []
|
|
168
169
|
tags: List[str] | None = []
|
|
169
170
|
links: Dict[str, str] = {}
|
|
@@ -171,11 +172,11 @@ class Field(pyd.BaseModel):
|
|
|
171
172
|
items: "Field" = None
|
|
172
173
|
keys: "Field" = None
|
|
173
174
|
values: "Field" = None
|
|
174
|
-
precision: int = None
|
|
175
|
-
scale: int = None
|
|
176
|
-
example:
|
|
175
|
+
precision: int | None = None
|
|
176
|
+
scale: int | None = None
|
|
177
|
+
example: Any | None = pyd.Field(
|
|
177
178
|
default=None,
|
|
178
|
-
deprecated="Removed in Data Contract Specification v1.1.0. Use
|
|
179
|
+
deprecated="Removed in Data Contract Specification v1.1.0. Use examples instead.",
|
|
179
180
|
)
|
|
180
181
|
examples: List[Any] | None = None
|
|
181
182
|
quality: List[Quality] | None = []
|
|
@@ -187,10 +188,10 @@ class Field(pyd.BaseModel):
|
|
|
187
188
|
|
|
188
189
|
|
|
189
190
|
class Model(pyd.BaseModel):
|
|
190
|
-
description:
|
|
191
|
-
type:
|
|
192
|
-
namespace:
|
|
193
|
-
title:
|
|
191
|
+
description: str | None = None
|
|
192
|
+
type: str | None = None
|
|
193
|
+
namespace: str | None = None
|
|
194
|
+
title: str | None = None
|
|
194
195
|
fields: Dict[str, Field] = {}
|
|
195
196
|
quality: List[Quality] | None = []
|
|
196
197
|
primaryKey: List[str] | None = []
|
|
@@ -204,12 +205,12 @@ class Model(pyd.BaseModel):
|
|
|
204
205
|
|
|
205
206
|
|
|
206
207
|
class Info(pyd.BaseModel):
|
|
207
|
-
title: str = None
|
|
208
|
-
version: str = None
|
|
209
|
-
status: str = None
|
|
210
|
-
description: str = None
|
|
211
|
-
owner: str = None
|
|
212
|
-
contact: Contact = None
|
|
208
|
+
title: str | None = None
|
|
209
|
+
version: str | None = None
|
|
210
|
+
status: str | None = None
|
|
211
|
+
description: str | None = None
|
|
212
|
+
owner: str | None = None
|
|
213
|
+
contact: Contact | None = None
|
|
213
214
|
|
|
214
215
|
model_config = pyd.ConfigDict(
|
|
215
216
|
extra="allow",
|
|
@@ -217,91 +218,91 @@ class Info(pyd.BaseModel):
|
|
|
217
218
|
|
|
218
219
|
|
|
219
220
|
class Example(pyd.BaseModel):
|
|
220
|
-
type: str = None
|
|
221
|
-
description: str = None
|
|
222
|
-
model: str = None
|
|
221
|
+
type: str | None = None
|
|
222
|
+
description: str | None = None
|
|
223
|
+
model: str | None = None
|
|
223
224
|
data: str | object = None
|
|
224
225
|
|
|
225
226
|
|
|
226
227
|
# Deprecated Quality class
|
|
227
228
|
class DeprecatedQuality(pyd.BaseModel):
|
|
228
|
-
type: str = None
|
|
229
|
+
type: str | None = None
|
|
229
230
|
specification: str | object = None
|
|
230
231
|
|
|
231
232
|
|
|
232
233
|
class Availability(pyd.BaseModel):
|
|
233
|
-
description:
|
|
234
|
-
percentage:
|
|
234
|
+
description: str | None = None
|
|
235
|
+
percentage: str | None = None
|
|
235
236
|
|
|
236
237
|
|
|
237
238
|
class Retention(pyd.BaseModel):
|
|
238
|
-
description:
|
|
239
|
-
period:
|
|
240
|
-
unlimited:
|
|
241
|
-
timestampField:
|
|
239
|
+
description: str | None = None
|
|
240
|
+
period: str | None = None
|
|
241
|
+
unlimited: bool | None = None
|
|
242
|
+
timestampField: str | None = None
|
|
242
243
|
|
|
243
244
|
|
|
244
245
|
class Latency(pyd.BaseModel):
|
|
245
|
-
description:
|
|
246
|
-
threshold:
|
|
247
|
-
sourceTimestampField:
|
|
248
|
-
processedTimestampField:
|
|
246
|
+
description: str | None = None
|
|
247
|
+
threshold: str | None = None
|
|
248
|
+
sourceTimestampField: str | None = None
|
|
249
|
+
processedTimestampField: str | None = None
|
|
249
250
|
|
|
250
251
|
|
|
251
252
|
class Freshness(pyd.BaseModel):
|
|
252
|
-
description:
|
|
253
|
-
threshold:
|
|
254
|
-
timestampField:
|
|
253
|
+
description: str | None = None
|
|
254
|
+
threshold: str | None = None
|
|
255
|
+
timestampField: str | None = None
|
|
255
256
|
|
|
256
257
|
|
|
257
258
|
class Frequency(pyd.BaseModel):
|
|
258
|
-
description:
|
|
259
|
-
type:
|
|
260
|
-
interval:
|
|
261
|
-
cron:
|
|
259
|
+
description: str | None = None
|
|
260
|
+
type: str | None = None
|
|
261
|
+
interval: str | None = None
|
|
262
|
+
cron: str | None = None
|
|
262
263
|
|
|
263
264
|
|
|
264
265
|
class Support(pyd.BaseModel):
|
|
265
|
-
description:
|
|
266
|
-
time:
|
|
267
|
-
responseTime:
|
|
266
|
+
description: str | None = None
|
|
267
|
+
time: str | None = None
|
|
268
|
+
responseTime: str | None = None
|
|
268
269
|
|
|
269
270
|
|
|
270
271
|
class Backup(pyd.BaseModel):
|
|
271
|
-
description:
|
|
272
|
-
interval:
|
|
273
|
-
cron:
|
|
274
|
-
recoveryTime:
|
|
275
|
-
recoveryPoint:
|
|
272
|
+
description: str | None = None
|
|
273
|
+
interval: str | None = None
|
|
274
|
+
cron: str | None = None
|
|
275
|
+
recoveryTime: str | None = None
|
|
276
|
+
recoveryPoint: str | None = None
|
|
276
277
|
|
|
277
278
|
|
|
278
279
|
class ServiceLevel(pyd.BaseModel):
|
|
279
|
-
availability:
|
|
280
|
-
retention:
|
|
281
|
-
latency:
|
|
282
|
-
freshness:
|
|
283
|
-
frequency:
|
|
284
|
-
support:
|
|
285
|
-
backup:
|
|
280
|
+
availability: Availability | None = None
|
|
281
|
+
retention: Retention | None = None
|
|
282
|
+
latency: Latency | None = None
|
|
283
|
+
freshness: Freshness | None = None
|
|
284
|
+
frequency: Frequency | None = None
|
|
285
|
+
support: Support | None = None
|
|
286
|
+
backup: Backup | None = None
|
|
286
287
|
|
|
287
288
|
|
|
288
289
|
class DataContractSpecification(pyd.BaseModel):
|
|
289
|
-
dataContractSpecification: str = None
|
|
290
|
-
id: str = None
|
|
291
|
-
info: Info = None
|
|
290
|
+
dataContractSpecification: str | None = None
|
|
291
|
+
id: str | None = None
|
|
292
|
+
info: Info | None = None
|
|
292
293
|
servers: Dict[str, Server] = {}
|
|
293
|
-
terms: Terms = None
|
|
294
|
+
terms: Terms | None = None
|
|
294
295
|
models: Dict[str, Model] = {}
|
|
295
296
|
definitions: Dict[str, Definition] = {}
|
|
296
297
|
examples: List[Example] = pyd.Field(
|
|
297
298
|
default_factory=list,
|
|
298
299
|
deprecated="Removed in Data Contract Specification " "v1.1.0. Use models.examples instead.",
|
|
299
300
|
)
|
|
300
|
-
quality: DeprecatedQuality = pyd.Field(
|
|
301
|
+
quality: DeprecatedQuality | None = pyd.Field(
|
|
301
302
|
default=None,
|
|
302
303
|
deprecated="Removed in Data Contract Specification v1.1.0. Use " "model-level and field-level quality instead.",
|
|
303
304
|
)
|
|
304
|
-
servicelevels:
|
|
305
|
+
servicelevels: ServiceLevel | None = None
|
|
305
306
|
links: Dict[str, str] = {}
|
|
306
307
|
tags: List[str] = []
|
|
307
308
|
|
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
|
|