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.

@@ -1,5 +1,113 @@
1
+ *, ::before, ::after {
2
+ --tw-border-spacing-x: 0;
3
+ --tw-border-spacing-y: 0;
4
+ --tw-translate-x: 0;
5
+ --tw-translate-y: 0;
6
+ --tw-rotate: 0;
7
+ --tw-skew-x: 0;
8
+ --tw-skew-y: 0;
9
+ --tw-scale-x: 1;
10
+ --tw-scale-y: 1;
11
+ --tw-pan-x: ;
12
+ --tw-pan-y: ;
13
+ --tw-pinch-zoom: ;
14
+ --tw-scroll-snap-strictness: proximity;
15
+ --tw-gradient-from-position: ;
16
+ --tw-gradient-via-position: ;
17
+ --tw-gradient-to-position: ;
18
+ --tw-ordinal: ;
19
+ --tw-slashed-zero: ;
20
+ --tw-numeric-figure: ;
21
+ --tw-numeric-spacing: ;
22
+ --tw-numeric-fraction: ;
23
+ --tw-ring-inset: ;
24
+ --tw-ring-offset-width: 0px;
25
+ --tw-ring-offset-color: #fff;
26
+ --tw-ring-color: rgb(59 130 246 / 0.5);
27
+ --tw-ring-offset-shadow: 0 0 #0000;
28
+ --tw-ring-shadow: 0 0 #0000;
29
+ --tw-shadow: 0 0 #0000;
30
+ --tw-shadow-colored: 0 0 #0000;
31
+ --tw-blur: ;
32
+ --tw-brightness: ;
33
+ --tw-contrast: ;
34
+ --tw-grayscale: ;
35
+ --tw-hue-rotate: ;
36
+ --tw-invert: ;
37
+ --tw-saturate: ;
38
+ --tw-sepia: ;
39
+ --tw-drop-shadow: ;
40
+ --tw-backdrop-blur: ;
41
+ --tw-backdrop-brightness: ;
42
+ --tw-backdrop-contrast: ;
43
+ --tw-backdrop-grayscale: ;
44
+ --tw-backdrop-hue-rotate: ;
45
+ --tw-backdrop-invert: ;
46
+ --tw-backdrop-opacity: ;
47
+ --tw-backdrop-saturate: ;
48
+ --tw-backdrop-sepia: ;
49
+ --tw-contain-size: ;
50
+ --tw-contain-layout: ;
51
+ --tw-contain-paint: ;
52
+ --tw-contain-style: ;
53
+ }
54
+
55
+ ::backdrop {
56
+ --tw-border-spacing-x: 0;
57
+ --tw-border-spacing-y: 0;
58
+ --tw-translate-x: 0;
59
+ --tw-translate-y: 0;
60
+ --tw-rotate: 0;
61
+ --tw-skew-x: 0;
62
+ --tw-skew-y: 0;
63
+ --tw-scale-x: 1;
64
+ --tw-scale-y: 1;
65
+ --tw-pan-x: ;
66
+ --tw-pan-y: ;
67
+ --tw-pinch-zoom: ;
68
+ --tw-scroll-snap-strictness: proximity;
69
+ --tw-gradient-from-position: ;
70
+ --tw-gradient-via-position: ;
71
+ --tw-gradient-to-position: ;
72
+ --tw-ordinal: ;
73
+ --tw-slashed-zero: ;
74
+ --tw-numeric-figure: ;
75
+ --tw-numeric-spacing: ;
76
+ --tw-numeric-fraction: ;
77
+ --tw-ring-inset: ;
78
+ --tw-ring-offset-width: 0px;
79
+ --tw-ring-offset-color: #fff;
80
+ --tw-ring-color: rgb(59 130 246 / 0.5);
81
+ --tw-ring-offset-shadow: 0 0 #0000;
82
+ --tw-ring-shadow: 0 0 #0000;
83
+ --tw-shadow: 0 0 #0000;
84
+ --tw-shadow-colored: 0 0 #0000;
85
+ --tw-blur: ;
86
+ --tw-brightness: ;
87
+ --tw-contrast: ;
88
+ --tw-grayscale: ;
89
+ --tw-hue-rotate: ;
90
+ --tw-invert: ;
91
+ --tw-saturate: ;
92
+ --tw-sepia: ;
93
+ --tw-drop-shadow: ;
94
+ --tw-backdrop-blur: ;
95
+ --tw-backdrop-brightness: ;
96
+ --tw-backdrop-contrast: ;
97
+ --tw-backdrop-grayscale: ;
98
+ --tw-backdrop-hue-rotate: ;
99
+ --tw-backdrop-invert: ;
100
+ --tw-backdrop-opacity: ;
101
+ --tw-backdrop-saturate: ;
102
+ --tw-backdrop-sepia: ;
103
+ --tw-contain-size: ;
104
+ --tw-contain-layout: ;
105
+ --tw-contain-paint: ;
106
+ --tw-contain-style: ;
107
+ }
108
+
1
109
  /*
2
- ! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com
110
+ ! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com
3
111
  */
4
112
 
5
113
  /*
@@ -442,118 +550,10 @@ video {
442
550
 
443
551
  /* Make elements with the HTML hidden attribute stay hidden by default */
444
552
 
445
- [hidden] {
553
+ [hidden]:where(:not([hidden="until-found"])) {
446
554
  display: none;
447
555
  }
448
556
 
449
- *, ::before, ::after {
450
- --tw-border-spacing-x: 0;
451
- --tw-border-spacing-y: 0;
452
- --tw-translate-x: 0;
453
- --tw-translate-y: 0;
454
- --tw-rotate: 0;
455
- --tw-skew-x: 0;
456
- --tw-skew-y: 0;
457
- --tw-scale-x: 1;
458
- --tw-scale-y: 1;
459
- --tw-pan-x: ;
460
- --tw-pan-y: ;
461
- --tw-pinch-zoom: ;
462
- --tw-scroll-snap-strictness: proximity;
463
- --tw-gradient-from-position: ;
464
- --tw-gradient-via-position: ;
465
- --tw-gradient-to-position: ;
466
- --tw-ordinal: ;
467
- --tw-slashed-zero: ;
468
- --tw-numeric-figure: ;
469
- --tw-numeric-spacing: ;
470
- --tw-numeric-fraction: ;
471
- --tw-ring-inset: ;
472
- --tw-ring-offset-width: 0px;
473
- --tw-ring-offset-color: #fff;
474
- --tw-ring-color: rgb(59 130 246 / 0.5);
475
- --tw-ring-offset-shadow: 0 0 #0000;
476
- --tw-ring-shadow: 0 0 #0000;
477
- --tw-shadow: 0 0 #0000;
478
- --tw-shadow-colored: 0 0 #0000;
479
- --tw-blur: ;
480
- --tw-brightness: ;
481
- --tw-contrast: ;
482
- --tw-grayscale: ;
483
- --tw-hue-rotate: ;
484
- --tw-invert: ;
485
- --tw-saturate: ;
486
- --tw-sepia: ;
487
- --tw-drop-shadow: ;
488
- --tw-backdrop-blur: ;
489
- --tw-backdrop-brightness: ;
490
- --tw-backdrop-contrast: ;
491
- --tw-backdrop-grayscale: ;
492
- --tw-backdrop-hue-rotate: ;
493
- --tw-backdrop-invert: ;
494
- --tw-backdrop-opacity: ;
495
- --tw-backdrop-saturate: ;
496
- --tw-backdrop-sepia: ;
497
- --tw-contain-size: ;
498
- --tw-contain-layout: ;
499
- --tw-contain-paint: ;
500
- --tw-contain-style: ;
501
- }
502
-
503
- ::backdrop {
504
- --tw-border-spacing-x: 0;
505
- --tw-border-spacing-y: 0;
506
- --tw-translate-x: 0;
507
- --tw-translate-y: 0;
508
- --tw-rotate: 0;
509
- --tw-skew-x: 0;
510
- --tw-skew-y: 0;
511
- --tw-scale-x: 1;
512
- --tw-scale-y: 1;
513
- --tw-pan-x: ;
514
- --tw-pan-y: ;
515
- --tw-pinch-zoom: ;
516
- --tw-scroll-snap-strictness: proximity;
517
- --tw-gradient-from-position: ;
518
- --tw-gradient-via-position: ;
519
- --tw-gradient-to-position: ;
520
- --tw-ordinal: ;
521
- --tw-slashed-zero: ;
522
- --tw-numeric-figure: ;
523
- --tw-numeric-spacing: ;
524
- --tw-numeric-fraction: ;
525
- --tw-ring-inset: ;
526
- --tw-ring-offset-width: 0px;
527
- --tw-ring-offset-color: #fff;
528
- --tw-ring-color: rgb(59 130 246 / 0.5);
529
- --tw-ring-offset-shadow: 0 0 #0000;
530
- --tw-ring-shadow: 0 0 #0000;
531
- --tw-shadow: 0 0 #0000;
532
- --tw-shadow-colored: 0 0 #0000;
533
- --tw-blur: ;
534
- --tw-brightness: ;
535
- --tw-contrast: ;
536
- --tw-grayscale: ;
537
- --tw-hue-rotate: ;
538
- --tw-invert: ;
539
- --tw-saturate: ;
540
- --tw-sepia: ;
541
- --tw-drop-shadow: ;
542
- --tw-backdrop-blur: ;
543
- --tw-backdrop-brightness: ;
544
- --tw-backdrop-contrast: ;
545
- --tw-backdrop-grayscale: ;
546
- --tw-backdrop-hue-rotate: ;
547
- --tw-backdrop-invert: ;
548
- --tw-backdrop-opacity: ;
549
- --tw-backdrop-saturate: ;
550
- --tw-backdrop-sepia: ;
551
- --tw-contain-size: ;
552
- --tw-contain-layout: ;
553
- --tw-contain-paint: ;
554
- --tw-contain-style: ;
555
- }
556
-
557
557
  .sr-only {
558
558
  position: absolute;
559
559
  width: 1px;
@@ -635,14 +635,14 @@ video {
635
635
  margin-bottom: 0.5rem;
636
636
  }
637
637
 
638
- .-ml-0 {
639
- margin-left: -0px;
640
- }
641
-
642
638
  .-ml-0\.5 {
643
639
  margin-left: -0.125rem;
644
640
  }
645
641
 
642
+ .mb-2 {
643
+ margin-bottom: 0.5rem;
644
+ }
645
+
646
646
  .mb-3 {
647
647
  margin-bottom: 0.75rem;
648
648
  }
@@ -798,10 +798,6 @@ video {
798
798
  width: 2rem;
799
799
  }
800
800
 
801
- .w-9\/12 {
802
- width: 75%;
803
- }
804
-
805
801
  .w-full {
806
802
  width: 100%;
807
803
  }
@@ -930,17 +926,17 @@ video {
930
926
 
931
927
  .divide-gray-100 > :not([hidden]) ~ :not([hidden]) {
932
928
  --tw-divide-opacity: 1;
933
- border-color: rgb(243 244 246 / var(--tw-divide-opacity));
929
+ border-color: rgb(243 244 246 / var(--tw-divide-opacity, 1));
934
930
  }
935
931
 
936
932
  .divide-gray-200 > :not([hidden]) ~ :not([hidden]) {
937
933
  --tw-divide-opacity: 1;
938
- border-color: rgb(229 231 235 / var(--tw-divide-opacity));
934
+ border-color: rgb(229 231 235 / var(--tw-divide-opacity, 1));
939
935
  }
940
936
 
941
937
  .divide-gray-300 > :not([hidden]) ~ :not([hidden]) {
942
938
  --tw-divide-opacity: 1;
943
- border-color: rgb(209 213 219 / var(--tw-divide-opacity));
939
+ border-color: rgb(209 213 219 / var(--tw-divide-opacity, 1));
944
940
  }
945
941
 
946
942
  .overflow-hidden {
@@ -987,48 +983,52 @@ video {
987
983
 
988
984
  .bg-blue-50 {
989
985
  --tw-bg-opacity: 1;
990
- background-color: rgb(239 246 255 / var(--tw-bg-opacity));
986
+ background-color: rgb(239 246 255 / var(--tw-bg-opacity, 1));
991
987
  }
992
988
 
993
989
  .bg-gray-100 {
994
990
  --tw-bg-opacity: 1;
995
- background-color: rgb(243 244 246 / var(--tw-bg-opacity));
991
+ background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
996
992
  }
997
993
 
998
994
  .bg-gray-50 {
999
995
  --tw-bg-opacity: 1;
1000
- background-color: rgb(249 250 251 / var(--tw-bg-opacity));
996
+ background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));
1001
997
  }
1002
998
 
1003
999
  .bg-gray-500 {
1004
1000
  --tw-bg-opacity: 1;
1005
- background-color: rgb(107 114 128 / var(--tw-bg-opacity));
1001
+ background-color: rgb(107 114 128 / var(--tw-bg-opacity, 1));
1006
1002
  }
1007
1003
 
1008
1004
  .bg-indigo-100 {
1009
1005
  --tw-bg-opacity: 1;
1010
- background-color: rgb(224 231 255 / var(--tw-bg-opacity));
1006
+ background-color: rgb(224 231 255 / var(--tw-bg-opacity, 1));
1011
1007
  }
1012
1008
 
1013
1009
  .bg-indigo-600 {
1014
1010
  --tw-bg-opacity: 1;
1015
- background-color: rgb(79 70 229 / var(--tw-bg-opacity));
1011
+ background-color: rgb(79 70 229 / var(--tw-bg-opacity, 1));
1016
1012
  }
1017
1013
 
1018
1014
  .bg-white {
1019
1015
  --tw-bg-opacity: 1;
1020
- background-color: rgb(255 255 255 / var(--tw-bg-opacity));
1016
+ background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
1021
1017
  }
1022
1018
 
1023
1019
  .bg-yellow-50 {
1024
1020
  --tw-bg-opacity: 1;
1025
- background-color: rgb(254 252 232 / var(--tw-bg-opacity));
1021
+ background-color: rgb(254 252 232 / var(--tw-bg-opacity, 1));
1026
1022
  }
1027
1023
 
1028
1024
  .bg-opacity-75 {
1029
1025
  --tw-bg-opacity: 0.75;
1030
1026
  }
1031
1027
 
1028
+ .p-2 {
1029
+ padding: 0.5rem;
1030
+ }
1031
+
1032
1032
  .p-4 {
1033
1033
  padding: 1rem;
1034
1034
  }
@@ -1072,11 +1072,6 @@ video {
1072
1072
  padding-right: 1.5rem;
1073
1073
  }
1074
1074
 
1075
- .py-0 {
1076
- padding-top: 0px;
1077
- padding-bottom: 0px;
1078
- }
1079
-
1080
1075
  .py-0\.5 {
1081
1076
  padding-top: 0.125rem;
1082
1077
  padding-bottom: 0.125rem;
@@ -1199,6 +1194,10 @@ video {
1199
1194
  font-weight: 600;
1200
1195
  }
1201
1196
 
1197
+ .font-normal {
1198
+ font-weight: 400;
1199
+ }
1200
+
1202
1201
  .italic {
1203
1202
  font-style: italic;
1204
1203
  }
@@ -1217,47 +1216,47 @@ video {
1217
1216
 
1218
1217
  .text-blue-600 {
1219
1218
  --tw-text-opacity: 1;
1220
- color: rgb(37 99 235 / var(--tw-text-opacity));
1219
+ color: rgb(37 99 235 / var(--tw-text-opacity, 1));
1221
1220
  }
1222
1221
 
1223
1222
  .text-gray-400 {
1224
1223
  --tw-text-opacity: 1;
1225
- color: rgb(156 163 175 / var(--tw-text-opacity));
1224
+ color: rgb(156 163 175 / var(--tw-text-opacity, 1));
1226
1225
  }
1227
1226
 
1228
1227
  .text-gray-500 {
1229
1228
  --tw-text-opacity: 1;
1230
- color: rgb(107 114 128 / var(--tw-text-opacity));
1229
+ color: rgb(107 114 128 / var(--tw-text-opacity, 1));
1231
1230
  }
1232
1231
 
1233
1232
  .text-gray-600 {
1234
1233
  --tw-text-opacity: 1;
1235
- color: rgb(75 85 99 / var(--tw-text-opacity));
1234
+ color: rgb(75 85 99 / var(--tw-text-opacity, 1));
1236
1235
  }
1237
1236
 
1238
1237
  .text-gray-800 {
1239
1238
  --tw-text-opacity: 1;
1240
- color: rgb(31 41 55 / var(--tw-text-opacity));
1239
+ color: rgb(31 41 55 / var(--tw-text-opacity, 1));
1241
1240
  }
1242
1241
 
1243
1242
  .text-gray-900 {
1244
1243
  --tw-text-opacity: 1;
1245
- color: rgb(17 24 39 / var(--tw-text-opacity));
1244
+ color: rgb(17 24 39 / var(--tw-text-opacity, 1));
1246
1245
  }
1247
1246
 
1248
1247
  .text-sky-500 {
1249
1248
  --tw-text-opacity: 1;
1250
- color: rgb(14 165 233 / var(--tw-text-opacity));
1249
+ color: rgb(14 165 233 / var(--tw-text-opacity, 1));
1251
1250
  }
1252
1251
 
1253
1252
  .text-white {
1254
1253
  --tw-text-opacity: 1;
1255
- color: rgb(255 255 255 / var(--tw-text-opacity));
1254
+ color: rgb(255 255 255 / var(--tw-text-opacity, 1));
1256
1255
  }
1257
1256
 
1258
1257
  .text-yellow-600 {
1259
1258
  --tw-text-opacity: 1;
1260
- color: rgb(202 138 4 / var(--tw-text-opacity));
1259
+ color: rgb(202 138 4 / var(--tw-text-opacity, 1));
1261
1260
  }
1262
1261
 
1263
1262
  .shadow {
@@ -1290,7 +1289,7 @@ video {
1290
1289
 
1291
1290
  .ring-black {
1292
1291
  --tw-ring-opacity: 1;
1293
- --tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity));
1292
+ --tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity, 1));
1294
1293
  }
1295
1294
 
1296
1295
  .ring-blue-500\/10 {
@@ -1299,7 +1298,7 @@ video {
1299
1298
 
1300
1299
  .ring-gray-300 {
1301
1300
  --tw-ring-opacity: 1;
1302
- --tw-ring-color: rgb(209 213 219 / var(--tw-ring-opacity));
1301
+ --tw-ring-color: rgb(209 213 219 / var(--tw-ring-opacity, 1));
1303
1302
  }
1304
1303
 
1305
1304
  .ring-gray-500\/10 {
@@ -1332,32 +1331,32 @@ video {
1332
1331
 
1333
1332
  .placeholder\:text-gray-400::-moz-placeholder {
1334
1333
  --tw-text-opacity: 1;
1335
- color: rgb(156 163 175 / var(--tw-text-opacity));
1334
+ color: rgb(156 163 175 / var(--tw-text-opacity, 1));
1336
1335
  }
1337
1336
 
1338
1337
  .placeholder\:text-gray-400::placeholder {
1339
1338
  --tw-text-opacity: 1;
1340
- color: rgb(156 163 175 / var(--tw-text-opacity));
1339
+ color: rgb(156 163 175 / var(--tw-text-opacity, 1));
1341
1340
  }
1342
1341
 
1343
1342
  .hover\:bg-gray-50:hover {
1344
1343
  --tw-bg-opacity: 1;
1345
- background-color: rgb(249 250 251 / var(--tw-bg-opacity));
1344
+ background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));
1346
1345
  }
1347
1346
 
1348
1347
  .hover\:bg-indigo-500:hover {
1349
1348
  --tw-bg-opacity: 1;
1350
- background-color: rgb(99 102 241 / var(--tw-bg-opacity));
1349
+ background-color: rgb(99 102 241 / var(--tw-bg-opacity, 1));
1351
1350
  }
1352
1351
 
1353
1352
  .hover\:text-gray-500:hover {
1354
1353
  --tw-text-opacity: 1;
1355
- color: rgb(107 114 128 / var(--tw-text-opacity));
1354
+ color: rgb(107 114 128 / var(--tw-text-opacity, 1));
1356
1355
  }
1357
1356
 
1358
1357
  .hover\:text-gray-700:hover {
1359
1358
  --tw-text-opacity: 1;
1360
- color: rgb(55 65 81 / var(--tw-text-opacity));
1359
+ color: rgb(55 65 81 / var(--tw-text-opacity, 1));
1361
1360
  }
1362
1361
 
1363
1362
  .focus\:ring-2:focus {
@@ -1372,7 +1371,7 @@ video {
1372
1371
 
1373
1372
  .focus\:ring-indigo-600:focus {
1374
1373
  --tw-ring-opacity: 1;
1375
- --tw-ring-color: rgb(79 70 229 / var(--tw-ring-opacity));
1374
+ --tw-ring-color: rgb(79 70 229 / var(--tw-ring-opacity, 1));
1376
1375
  }
1377
1376
 
1378
1377
  .focus-visible\:outline:focus-visible {
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: datacontract-cli
3
- Version: 0.10.20
3
+ Version: 0.10.21
4
4
  Summary: The datacontract CLI is an open source command-line tool for working with Data Contracts. It uses data contract YAML files to lint the data contract, connect to data sources and execute schema and quality tests, detect breaking changes, and export to different formats. The tool is written in Python. It can be used as a standalone CLI tool, in a CI/CD pipeline, or directly as a Python library.
5
5
  Author-email: Jochen Christ <jochen.christ@innoq.com>, Stefan Negele <stefan.negele@innoq.com>, Simon Harrer <simon.harrer@innoq.com>
6
6
  Project-URL: Homepage, https://cli.datacontract.com
@@ -49,7 +49,7 @@ Provides-Extra: postgres
49
49
  Requires-Dist: soda-core-postgres<3.4.0,>=3.3.20; extra == "postgres"
50
50
  Provides-Extra: s3
51
51
  Requires-Dist: s3fs==2024.12.0; extra == "s3"
52
- Requires-Dist: aiobotocore<2.18.0,>=2.17.0; extra == "s3"
52
+ Requires-Dist: aiobotocore<2.20.0,>=2.17.0; extra == "s3"
53
53
  Provides-Extra: snowflake
54
54
  Requires-Dist: snowflake-connector-python[pandas]<3.13,>=3.6; extra == "snowflake"
55
55
  Requires-Dist: soda-core-snowflake<3.4.0,>=3.3.20; extra == "snowflake"
@@ -63,16 +63,18 @@ Provides-Extra: dbml
63
63
  Requires-Dist: pydbml>=1.1.1; extra == "dbml"
64
64
  Provides-Extra: parquet
65
65
  Requires-Dist: pyarrow>=18.1.0; extra == "parquet"
66
- Provides-Extra: web
67
- Requires-Dist: fastapi==0.115.6; extra == "web"
68
- Requires-Dist: uvicorn==0.34.0; extra == "web"
66
+ Provides-Extra: api
67
+ Requires-Dist: fastapi==0.115.6; extra == "api"
68
+ Requires-Dist: uvicorn==0.34.0; extra == "api"
69
+ Provides-Extra: custom
70
+ Requires-Dist: Jinja2>=3.1.5; extra == "custom"
69
71
  Provides-Extra: all
70
- Requires-Dist: datacontract-cli[bigquery,csv,databricks,dbml,dbt,iceberg,kafka,parquet,postgres,s3,snowflake,sqlserver,trino,web]; extra == "all"
72
+ Requires-Dist: datacontract-cli[api,bigquery,csv,custom,databricks,dbml,dbt,iceberg,kafka,parquet,postgres,s3,snowflake,sqlserver,trino]; extra == "all"
71
73
  Provides-Extra: dev
72
74
  Requires-Dist: datacontract-cli[all]; extra == "dev"
73
75
  Requires-Dist: httpx==0.28.1; extra == "dev"
74
76
  Requires-Dist: kafka-python; extra == "dev"
75
- Requires-Dist: moto==5.0.26; extra == "dev"
77
+ Requires-Dist: moto==5.0.27; extra == "dev"
76
78
  Requires-Dist: pandas>=2.1.0; extra == "dev"
77
79
  Requires-Dist: pre-commit<4.1.0,>=3.7.1; extra == "dev"
78
80
  Requires-Dist: pytest; extra == "dev"
@@ -305,7 +307,7 @@ Commands
305
307
  - [diff](#diff)
306
308
  - [catalog](#catalog)
307
309
  - [publish](#publish)
308
- - [serve](#serve)
310
+ - [api](#api)
309
311
 
310
312
  ### init
311
313
  ```
@@ -881,7 +883,7 @@ models:
881
883
  │ vro-idl|sql|sql-query|html| │
882
884
  │ go|bigquery|dbml|spark|sqla │
883
885
  │ lchemy|data-caterer|dcs|mar │
884
- │ kdown|iceberg]
886
+ │ kdown|iceberg|custom]
885
887
  │ --output PATH Specify the file path where │
886
888
  │ the exported data will be │
887
889
  │ saved. If no path is │
@@ -904,6 +906,9 @@ models:
904
906
  │ --engine TEXT [engine] The engine used for │
905
907
  │ great expection run. │
906
908
  │ [default: None] │
909
+ │ --template PATH [custom] The file path of │
910
+ │ Jinja template. │
911
+ │ [default: None] │
907
912
  │ --help Show this message and exit. │
908
913
  ╰──────────────────────────────────────────────────────────────────────────────╯
909
914
  ╭─ RDF Options ────────────────────────────────────────────────────────────────╮
@@ -955,6 +960,7 @@ Available export options:
955
960
  | `dcs` | Export to Data Contract Specification in YAML format | ✅ |
956
961
  | `markdown` | Export to Markdown | ✅ |
957
962
  | `iceberg` | Export to an Iceberg JSON Schema Definition | partial |
963
+ | `custom` | Export to Custom format with Jinja | ✅ |
958
964
  | Missing something? | Please create an issue on GitHub | TBD |
959
965
 
960
966
 
@@ -1136,6 +1142,76 @@ to limit your contract export to a single model.
1136
1142
  }
1137
1143
  ```
1138
1144
 
1145
+ #### Custom
1146
+
1147
+ The export function converts the data contract specification into the custom format with Jinja. You can specify the path to a Jinja template with the `--template` argument, allowing you to output files in any format.
1148
+
1149
+ ```shell
1150
+ datacontract export --format custom --template template.txt datacontract.yaml
1151
+ ```
1152
+
1153
+ ##### Jinja variables
1154
+
1155
+ You can directly use the Data Contract Specification as template variables.
1156
+
1157
+ ```shell
1158
+ $ cat template.txt
1159
+ title: {{ data_contract.info.title }}
1160
+
1161
+ $ datacontract export --format custom --template template.txt datacontract.yaml
1162
+ title: Orders Latest
1163
+ ```
1164
+
1165
+ ##### Example Jinja Templates
1166
+
1167
+ ###### Customized dbt model
1168
+
1169
+ You can export the dbt models containing any logic.
1170
+
1171
+ Below is an example of a dbt staging layer that converts a field of `type: timestamp` to a `DATETIME` type with time zone conversion.
1172
+
1173
+ template.sql
1174
+
1175
+ {% raw %}
1176
+ ```sql
1177
+ {%- for model_name, model in data_contract.models.items() %}
1178
+ {#- Export only the first model #}
1179
+ {%- if loop.first -%}
1180
+ SELECT
1181
+ {%- for field_name, field in model.fields.items() %}
1182
+ {%- if field.type == "timestamp" %}
1183
+ DATETIME({{ field_name }}, "Asia/Tokyo") AS {{ field_name }},
1184
+ {%- else %}
1185
+ {{ field_name }} AS {{ field_name }},
1186
+ {%- endif %}
1187
+ {%- endfor %}
1188
+ FROM
1189
+ {{ "{{" }} ref('{{ model_name }}') {{ "}}" }}
1190
+ {%- endif %}
1191
+ {%- endfor %}
1192
+ ```
1193
+ {% endraw %}
1194
+
1195
+ command
1196
+
1197
+ ```shell
1198
+ datacontract export --format custom --template template.sql --output output.sql datacontract.yaml
1199
+ ```
1200
+
1201
+ output.sql
1202
+
1203
+ ```sql
1204
+ SELECT
1205
+ order_id AS order_id,
1206
+ DATETIME(order_timestamp, "Asia/Tokyo") AS order_timestamp,
1207
+ order_total AS order_total,
1208
+ customer_id AS customer_id,
1209
+ customer_email_address AS customer_email_address,
1210
+ DATETIME(processed_timestamp, "Asia/Tokyo") AS processed_timestamp,
1211
+ FROM
1212
+ {{ ref('orders') }}
1213
+ ```
1214
+
1139
1215
  ### import
1140
1216
  ```
1141
1217
 
@@ -1540,18 +1616,23 @@ datacontract catalog --files "*.odcs.yaml"
1540
1616
 
1541
1617
  ```
1542
1618
 
1543
- ### serve
1619
+ ### api
1544
1620
  ```
1545
-
1546
- Usage: datacontract serve [OPTIONS]
1547
-
1548
- Start the datacontract web server.
1549
-
1550
- ╭─ Options ────────────────────────────────────────────────────────────────────╮
1551
- --port INTEGER Bind socket to this port. [default: 4242] │
1552
- --host TEXT Bind socket to this host. [default: 127.0.0.1] │
1553
- │ --help Show this message and exit. │
1554
- ╰──────────────────────────────────────────────────────────────────────────────╯
1621
+
1622
+ Usage: datacontract api [OPTIONS]
1623
+
1624
+ Start the datacontract CLI as server application with REST API.
1625
+ The OpenAPI documentation as Swagger UI is available on http://localhost:4242. You can execute the commands directly from the Swagger UI.
1626
+ To protect the API, you can set the environment variable DATACONTRACT_CLI_API_KEY to a secret API key. To authenticate, requests must include the header 'x-api-key' with the
1627
+ correct API key. This is highly recommended, as data contract tests may be subject to SQL injections or leak sensitive information.
1628
+ To connect to servers (such as a Snowflake data source), set the credentials as environment variables as documented in https://cli.datacontract.com/#test
1629
+
1630
+ ╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
1631
+ │ --port INTEGER Bind socket to this port. [default: 4242] │
1632
+ │ --host TEXT Bind socket to this host. Hint: For running in docker, set it to 0.0.0.0 [default: 127.0.0.1] │
1633
+ │ --help Show this message and exit. │
1634
+ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
1635
+
1555
1636
 
1556
1637
  ```
1557
1638
 
@@ -1709,7 +1790,7 @@ class CustomExporter(Exporter):
1709
1790
 
1710
1791
 
1711
1792
  # Register the new custom class into factory
1712
- exporter_factory.register_exporter("custom", CustomExporter)
1793
+ exporter_factory.register_exporter("custom_exporter", CustomExporter)
1713
1794
 
1714
1795
 
1715
1796
  if __name__ == "__main__":
@@ -1719,7 +1800,7 @@ if __name__ == "__main__":
1719
1800
  )
1720
1801
  # Call export
1721
1802
  result = data_contract.export(
1722
- export_format="custom", model="orders", server="production", custom_arg="my_custom_arg"
1803
+ export_format="custom_exporter", model="orders", server="production", custom_arg="my_custom_arg"
1723
1804
  )
1724
1805
  print(result)
1725
1806