datacontract-cli 0.10.2__py3-none-any.whl → 0.10.4__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.

Files changed (33) hide show
  1. datacontract/breaking/breaking.py +12 -0
  2. datacontract/breaking/breaking_rules.py +4 -0
  3. datacontract/catalog/catalog.py +3 -0
  4. datacontract/cli.py +36 -8
  5. datacontract/data_contract.py +62 -128
  6. datacontract/export/avro_converter.py +16 -2
  7. datacontract/export/bigquery_converter.py +106 -0
  8. datacontract/export/go_converter.py +98 -0
  9. datacontract/export/html_export.py +6 -1
  10. datacontract/export/jsonschema_converter.py +45 -5
  11. datacontract/export/sql_converter.py +1 -0
  12. datacontract/export/sql_type_converter.py +42 -1
  13. datacontract/imports/avro_importer.py +14 -1
  14. datacontract/imports/bigquery_importer.py +166 -0
  15. datacontract/imports/jsonschema_importer.py +150 -0
  16. datacontract/model/data_contract_specification.py +55 -1
  17. datacontract/publish/publish.py +32 -0
  18. datacontract/templates/datacontract.html +37 -346
  19. datacontract/templates/index.html +233 -0
  20. datacontract/templates/partials/datacontract_information.html +66 -0
  21. datacontract/templates/partials/datacontract_servicelevels.html +253 -0
  22. datacontract/templates/partials/datacontract_terms.html +44 -0
  23. datacontract/templates/partials/definition.html +99 -0
  24. datacontract/templates/partials/example.html +27 -0
  25. datacontract/templates/partials/model_field.html +97 -0
  26. datacontract/templates/partials/server.html +144 -0
  27. datacontract/templates/style/output.css +94 -13
  28. {datacontract_cli-0.10.2.dist-info → datacontract_cli-0.10.4.dist-info}/METADATA +139 -96
  29. {datacontract_cli-0.10.2.dist-info → datacontract_cli-0.10.4.dist-info}/RECORD +33 -20
  30. {datacontract_cli-0.10.2.dist-info → datacontract_cli-0.10.4.dist-info}/LICENSE +0 -0
  31. {datacontract_cli-0.10.2.dist-info → datacontract_cli-0.10.4.dist-info}/WHEEL +0 -0
  32. {datacontract_cli-0.10.2.dist-info → datacontract_cli-0.10.4.dist-info}/entry_points.txt +0 -0
  33. {datacontract_cli-0.10.2.dist-info → datacontract_cli-0.10.4.dist-info}/top_level.txt +0 -0
@@ -6,7 +6,7 @@
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
7
  {# <script src="https://cdn.tailwindcss.com"></script> #}
8
8
  <style>
9
- {{style | safe }}
9
+ {{ style | safe }}
10
10
  </style>
11
11
  </head>
12
12
  <body class="h-full">
@@ -58,78 +58,13 @@
58
58
 
59
59
  <div>
60
60
  <div class="space-y-6 mt-6">
61
- <section>
62
- <div class=" px-4 sm:px-0">
63
- <h1 class="text-base font-semibold leading-6 text-gray-900" id="info">Info</h1>
64
- <p class="text-sm text-gray-500">Information about the data contract</p>
65
- </div>
66
- <div class="mt-2 overflow-hidden shadow sm:rounded-lg bg-white">
67
-
68
- <div class="px-4 py-5 sm:px-6">
69
-
70
- <dl class="grid grid-cols-1 gap-x-4 gap-y-6 sm:grid-cols-2">
71
- <div class="sm:col-span-1">
72
- <dt class="text-sm font-medium text-gray-500">Title</dt>
73
- <dd class="mt-1 text-sm text-gray-900">{{ datacontract.info.title }}</dd>
74
- </div>
75
-
76
- <div class="sm:col-span-1">
77
- <dt class="text-sm font-medium text-gray-500">Version</dt>
78
- <dd class="mt-1 text-sm text-gray-900">{{ datacontract.info.version }}</dd>
79
- </div>
80
-
81
- {% if datacontract.info.status %}
82
- <div class="sm:col-span-1">
83
- <dt class="text-sm font-medium text-gray-500">Status</dt>
84
- <dd class="mt-1 text-sm text-gray-900">{{ datacontract.info.status }}</dd>
85
- </div>
86
- {% endif %}
87
-
88
- {% if datacontract.info.description %}
89
- <div class="sm:col-span-2">
90
- <dt class="text-sm font-medium text-gray-500">Description</dt>
91
- <dd class="mt-1 text-sm text-gray-900" >
92
- <span class="whitespace-pre-wrap">{{ datacontract.info.description }}</span>
93
- </dd>
94
- </div>
95
- {% endif %}
96
-
97
- {% if datacontract.info.owner %}
98
- <div class="sm:col-span-1">
99
- <dt class="text-sm font-medium text-gray-500">Owner</dt>
100
- <dd class="mt-1 text-sm text-gray-900">
101
- <span>{{ datacontract.info.owner }}</span>
102
- </dd>
103
- </div>
104
- {% endif %}
105
-
106
- {% if datacontract.info.contact %}
107
- <div class="sm:col-span-1">
108
- <dt class="text-sm font-medium text-gray-500">Contact</dt>
109
- <dd class="mt-1 text-sm text-gray-900">
110
- {% if datacontract.info.contact.name %}
111
- {{ datacontract.info.contact.name }}
112
- {% endif %}
113
- {% if datacontract.info.contact.email %}
114
- <a href="mailto:{{ datacontract.info.contact.email }}" class="text-sky-500 hover:text-gray-700">{{ datacontract.info.contact.email }}</a>
115
- {% endif %}
116
- {% if datacontract.info.contact.url %}
117
- <div>
118
- <a href="{{ datacontract.info.contact.url }}" class="text-sky-500 hover:text-gray-700">{{ datacontract.info.contact.url }}</a>
119
- </div>
120
- {% endif %}
121
- </dd>
122
- </div>
123
- {% endif %}
124
-
125
- </dl>
126
- </div>
127
- </div>
61
+ <section id="information">
62
+ {{ render_partial('partials/datacontract_information.html', datacontract = datacontract) }}
128
63
  </section>
129
64
 
130
65
 
131
66
  {% if datacontract.servers %}
132
- <section>
67
+ <section id="servers">
133
68
  <div class="px-4 sm:px-0">
134
69
  <h1 class="text-base font-semibold leading-6 text-gray-900" id="servers">Servers</h1>
135
70
  <p class="text-sm text-gray-500">Servers of the data contract</p>
@@ -138,150 +73,7 @@
138
73
  <ul role="list" class="mt-2 divide-y divide-gray-100 overflow-hidden bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-lg">
139
74
 
140
75
  {% for server_name, server in datacontract.servers.items() %}
141
- <li class="relative flex gap-x-6 px-4 py-5 sm:px-6">
142
- <div class="flex items-center gap-x-4">
143
- <div class="hidden sm:flex sm:flex-col">
144
- <dt class="text-sm font-medium text-gray-500">Server</dt>
145
- <dd class="mt-1 text-sm text-gray-900">{{server_name}}</dd>
146
- </div>
147
- </div>
148
-
149
- {% if server.type %}
150
- <div class="flex items-center gap-x-4">
151
- <div class="hidden sm:flex sm:flex-col">
152
- <dt class="text-sm font-medium text-gray-500">Type</dt>
153
- <dd class="mt-1 text-sm text-gray-900">{{server.type}}</dd>
154
- </div>
155
- </div>
156
- {% endif %}
157
-
158
- {% if server.project %}
159
- <div class="flex items-center gap-x-4">
160
- <div class="hidden sm:flex sm:flex-col">
161
- <dt class="text-sm font-medium text-gray-500">Project</dt>
162
- <dd class="mt-1 text-sm text-gray-900">{{server.project}}</dd>
163
- </div>
164
- </div>
165
- {% endif %}
166
-
167
- {% if server.dataset %}
168
- <div class="flex items-center gap-x-4">
169
- <div class="hidden sm:flex sm:flex-col">
170
- <dt class="text-sm font-medium text-gray-500">Dataset</dt>
171
- <dd class="mt-1 text-sm text-gray-900">{{server.dataset}}</dd>
172
- </div>
173
- </div>
174
- {% endif %}
175
-
176
- {% if server.location %}
177
- <div class="flex items-center gap-x-4">
178
- <div class="hidden sm:flex sm:flex-col">
179
- <dt class="text-sm font-medium text-gray-500">Location</dt>
180
- <dd class="mt-1 text-sm text-gray-900">{{server.location}}</dd>
181
- </div>
182
- </div>
183
- {% endif %}
184
-
185
- {% if server.endpointUrl %}
186
- <div class="flex items-center gap-x-4">
187
- <div class="hidden sm:flex sm:flex-col">
188
- <dt class="text-sm font-medium text-gray-500">Endpoint URL</dt>
189
- <dd class="mt-1 text-sm text-gray-900">{{server.endpointUrl}}</dd>
190
- </div>
191
- </div>
192
- {% endif %}
193
-
194
- {% if server.account %}
195
- <div class="flex items-center gap-x-4">
196
- <div class="hidden sm:flex sm:flex-col">
197
- <dt class="text-sm font-medium text-gray-500">Account</dt>
198
- <dd class="mt-1 text-sm text-gray-900">{{server.account}}</dd>
199
- </div>
200
- </div>
201
- {% endif %}
202
-
203
- {% if server.host %}
204
- <div class="flex items-center gap-x-4">
205
- <div class="hidden sm:flex sm:flex-col">
206
- <dt class="text-sm font-medium text-gray-500">Host</dt>
207
- <dd class="mt-1 text-sm text-gray-900">{{server.host}}</dd>
208
- </div>
209
- </div>
210
- {% endif %}
211
-
212
- {% if server.port %}
213
- <div class="flex items-center gap-x-4">
214
- <div class="hidden sm:flex sm:flex-col">
215
- <dt class="text-sm font-medium text-gray-500">Port</dt>
216
- <dd class="mt-1 text-sm text-gray-900">{{server.port}}</dd>
217
- </div>
218
- </div>
219
- {% endif %}
220
-
221
- {% if server.catalog %}
222
- <div class="flex items-center gap-x-4">
223
- <div class="hidden sm:flex sm:flex-col">
224
- <dt class="text-sm font-medium text-gray-500">Catalog</dt>
225
- <dd class="mt-1 text-sm text-gray-900">{{server.catalog}}</dd>
226
- </div>
227
- </div>
228
- {% endif %}
229
-
230
- {% if server.database %}
231
- <div class="flex items-center gap-x-4">
232
- <div class="hidden sm:flex sm:flex-col">
233
- <dt class="text-sm font-medium text-gray-500">Database</dt>
234
- <dd class="mt-1 text-sm text-gray-900">{{server.database}}</dd>
235
- </div>
236
- </div>
237
- {% endif %}
238
-
239
- {% if server.schema_ %}
240
- <div class="flex items-center gap-x-4">
241
- <div class="hidden sm:flex sm:flex-col">
242
- <dt class="text-sm font-medium text-gray-500">Schema</dt>
243
- <dd class="mt-1 text-sm text-gray-900">{{server.schema_}}</dd>
244
- </div>
245
- </div>
246
- {% endif %}
247
-
248
- {% if server.topic %}
249
- <div class="flex items-center gap-x-4">
250
- <div class="hidden sm:flex sm:flex-col">
251
- <dt class="text-sm font-medium text-gray-500">Topic</dt>
252
- <dd class="mt-1 text-sm text-gray-900">{{server.topic}}</dd>
253
- </div>
254
- </div>
255
- {% endif %}
256
-
257
- {% if server.path %}
258
- <div class="flex items-center gap-x-4">
259
- <div class="hidden sm:flex sm:flex-col">
260
- <dt class="text-sm font-medium text-gray-500">Path</dt>
261
- <dd class="mt-1 text-sm text-gray-900">{{server.path}}</dd>
262
- </div>
263
- </div>
264
- {% endif %}
265
-
266
- {% if server.format %}
267
- <div class="flex items-center gap-x-4">
268
- <div class="hidden sm:flex sm:flex-col">
269
- <dt class="text-sm font-medium text-gray-500">Format</dt>
270
- <dd class="mt-1 text-sm text-gray-900">{{server.format}}</dd>
271
- </div>
272
- </div>
273
- {% endif %}
274
-
275
- {% if server.delimiter %}
276
- <div class="flex items-center gap-x-4">
277
- <div class="hidden sm:flex sm:flex-col">
278
- <dt class="text-sm font-medium text-gray-500">Delimiter</dt>
279
- <dd class="mt-1 text-sm text-gray-900">{{server.delimiter}}</dd>
280
- </div>
281
- </div>
282
- {% endif %}
283
-
284
- </li>
76
+ {{ render_partial('partials/server.html', server_name = server_name, server = server) }}
285
77
  {% endfor %}
286
78
 
287
79
  </ul>
@@ -291,51 +83,8 @@
291
83
 
292
84
 
293
85
  {% if datacontract.terms %}
294
- <section>
295
- <div class="px-4 sm:px-0">
296
- <h1 class="text-base font-semibold leading-6 text-gray-900" id="terms">Terms</h1>
297
- <p class="text-sm text-gray-500">Terms and conditions of the data contract</p>
298
- </div>
299
- <div class="mt-2 overflow-hidden shadow sm:rounded-lg bg-white">
300
-
301
- <div class="px-4 py-5 sm:px-6">
302
-
303
- <dl class="grid grid-cols-1 gap-x-4 gap-y-6 sm:grid-cols-2">
304
- <div class="sm:col-span-1">
305
- <dt class="text-sm font-medium text-gray-500">Usage</dt>
306
- <dd class="mt-1 text-sm text-gray-900" >
307
- <span class="whitespace-pre-wrap">{{ datacontract.terms.usage }}</span>
308
- </dd>
309
- </div>
310
-
311
- <div class="sm:col-span-1">
312
- <dt class="text-sm font-medium text-gray-500">Limitations</dt>
313
- <dd class="mt-1 text-sm text-gray-900" >
314
- <span class="whitespace-pre-wrap">{{ datacontract.terms.limitations }}</span>
315
- </dd>
316
- </div>
317
-
318
- {% if datacontract.terms.billing %}
319
- <div class="sm:col-span-1">
320
- <dt class="text-sm font-medium text-gray-500">Billing</dt>
321
- <dd class="mt-1 text-sm text-gray-900" >
322
- <span class="whitespace-pre-wrap">{{ datacontract.terms.billing }}</span>
323
- </dd>
324
- </div>
325
- {% endif %}
326
-
327
- {% if datacontract.terms.noticePeriod %}
328
- <div class="sm:col-span-1">
329
- <dt class="text-sm font-medium text-gray-500">Notice Period</dt>
330
- <dd class="mt-1 text-sm text-gray-900 flex" >
331
- <span class="whitespace-pre-wrap">{{ datacontract.terms.noticePeriod }}</span>
332
- </dd>
333
- </div>
334
- {% endif %}
335
-
336
- </dl>
337
- </div>
338
- </div>
86
+ <section id="terms">
87
+ {{ render_partial('partials/datacontract_terms.html', datacontract = datacontract) }}
339
88
  </section>
340
89
  {% endif %}
341
90
 
@@ -369,90 +118,9 @@
369
118
  </tr>
370
119
  </thead>
371
120
  <tbody class="divide-y divide-gray-200 bg-white">
372
-
373
121
  {% for field_name, field in model.fields.items() %}
374
-
375
- <tr>
376
- <td class="whitespace-nowrap py-2 pl-4 pr-2 text-sm font-medium text-gray-900 sm:pl-6 w-2/12">
377
- <div class="py-2 text-sm">
378
- {% if field.title %}
379
- <div>{{ field.title }}</div>
380
- {% endif %}
381
- <div class="font-mono">{{ field_name }}</div>
382
- {# TODO nested fields #}
383
- </div>
384
- </td>
385
- <td class="whitespace-nowrap px-1 py-2 text-sm text-gray-500 w-1/12">
386
- {% if field.type %}
387
- {{ field.type }}
388
- {% endif %}
389
- </td>
390
- <td class="px-3 py-2 text-sm text-gray-500 w-7/12">
391
- {% if field.description %}
392
- <div class="text-gray-500">{{ field.description }}</div>
393
- {% else %}
394
- <div class="text-gray-400">No description</div>
395
- {% endif %}
396
-
397
- {% if field.example %}
398
- <div class="mt-1 italic">
399
- Example: {{ field.example }}
400
- </div>
401
- {% endif %}
402
-
403
- <div>
404
- {% if field.primary %}
405
- <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>
406
- {% endif %}
407
- {% if field.required %}
408
- <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">required</span>
409
- {% endif %}
410
- {% if field.unique %}
411
- <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">unique</span>
412
- {% endif %}
413
- {% if field.format %}
414
- <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">format:{{ field.format }}</span>
415
- {% endif %}
416
- {% if field.minLength %}
417
- <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:{{ field.minLength }}</span>
418
- {% endif %}
419
- {% if field.maxLength %}
420
- <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:{{ field.maxLength }}</span>
421
- {% endif %}
422
- {% if field.pattern %}
423
- <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:{{ field.pattern }}</span>
424
- {% endif %}
425
- {% if field.precision %}
426
- <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:{{ field.precision }}</span>
427
- {% endif %}
428
- {% if field.scale %}
429
- <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:{{ field.scale }}</span>
430
- {% endif %}
431
- {% if field.minimum %}
432
- <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:{{ field.minimum }}</span>
433
- {% endif %}
434
- {% if field.exclusiveMinimum %}
435
- <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:{{ field.exclusiveMinimum }}</span>
436
- {% endif %}
437
- {% if field.maximum %}
438
- <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:{{ field.maximum }}</span>
439
- {% endif %}
440
- {% if field.exclusiveMaximum %}
441
- <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:{{ field.exclusiveMaximum }}</span>
442
- {% endif %}
443
- {% if field.classification %}
444
- <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">{{ field.classification }}</span>
445
- {% endif %}
446
- {% if field.pii %}
447
- <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>
448
- {% endif %}
449
- </div>
450
-
451
- </td>
452
-
453
- </tr>
122
+ {{ render_partial('partials/model_field.html', nested = False, field_name=field_name, field = field, level = 0) }}
454
123
  {% endfor %}
455
-
456
124
  </tbody>
457
125
  </table>
458
126
  </div>
@@ -460,12 +128,38 @@
460
128
  </div>
461
129
  </div>
462
130
  {% endfor %}
463
-
464
131
  </section>
132
+
133
+ {% if datacontract.definitions %}
134
+ <section id="definitions">
135
+ <div class="px-4 sm:px-0">
136
+ <h1 class="text-base font-semibold leading-6 text-gray-900">Definitions</h1>
137
+ <p class="text-sm text-gray-500">Domain specific definitions in the data contract</p>
138
+ </div>
139
+
140
+ {% for definition_name, definition in datacontract.definitions.items() %}
141
+ {{ render_partial('partials/definition.html', definition_name = definition_name, definition = definition)}}
142
+ {% endfor %}
143
+ </section>
144
+ {% endif %}
465
145
 
466
- {# TODO add definitions #}
146
+ {% if datacontract.examples %}
147
+ <section id="examples">
148
+ <div class="px-4 sm:px-0">
149
+ <h1 class="text-base font-semibold leading-6 text-gray-900">Examples</h1>
150
+ <p class="text-sm text-gray-500">Examples for models in the data contract</p>
151
+ </div>
152
+ {% for example in datacontract.examples %}
153
+ {{ render_partial('partials/example.html', example = example) }}
154
+ {% endfor %}
155
+ </section>
156
+ {% endif %}
467
157
 
468
- {# TODO add service levels #}
158
+ {% if datacontract.servicelevels %}
159
+ <section id="servicelevels">
160
+ {{ render_partial('partials/datacontract_servicelevels.html', datacontract = datacontract ) }}
161
+ </section>
162
+ {% endif %}
469
163
 
470
164
  {% if quality_specification %}
471
165
  <section id="quality">
@@ -476,8 +170,6 @@
476
170
  <p class="text-sm text-gray-500">
477
171
  <span>{{ datacontract.quality.type }}</span>
478
172
  </p>
479
-
480
-
481
173
  </div>
482
174
  <div class="mt-2 overflow-hidden shadow sm:rounded-lg bg-white">
483
175
  <div class="px-4 py-5 sm:px-6">
@@ -490,7 +182,6 @@
490
182
  {% endif %}
491
183
 
492
184
  </div>
493
-
494
185
  </div>
495
186
 
496
187
  <div class="mt-6 text-sm text-gray-400">