-
Notifications
You must be signed in to change notification settings - Fork 276
Expand file tree
/
Copy pathupdate_export_examples.py
More file actions
138 lines (127 loc) · 5.7 KB
/
Copy pathupdate_export_examples.py
File metadata and controls
138 lines (127 loc) · 5.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/env python3
"""Regenerate the example command + output blocks on the export reference pages.
Runs `datacontract export <format>` against the example contracts in examples/
and injects the real output into docs/docs/exports/<format>.md between the
AUTOGENERATED markers. Re-run whenever an exporter's output changes.
python update_export_examples.py
"""
import re
from docs_examples import DOCS, EXAMPLES_URL, fence, run_cli, upsert
ORDERS = "examples/orders/orders.odcs.yaml"
USER_INTERACTIONS = "examples/user_interactions/user_interactions.odcs.yaml"
# format -> (display command, contract file, extra run args, fence language, max lines)
EXPORTS = {
"sql": ("datacontract export sql orders.odcs.yaml --output orders.sql", ORDERS, [], "sql", None),
"sql-query": (
"datacontract export sql-query orders.odcs.yaml --schema-name orders",
ORDERS,
["--schema-name", "orders"],
"sql",
None,
),
"dbt-models": ("datacontract export dbt-models orders.odcs.yaml", ORDERS, [], "yaml", 40),
"dbt-sources": ("datacontract export dbt-sources orders.odcs.yaml", ORDERS, [], "yaml", 40),
"dbt-staging-sql": (
"datacontract export dbt-staging-sql orders.odcs.yaml --schema-name orders",
ORDERS,
["--schema-name", "orders"],
"sql",
None,
),
"avro": (
"datacontract export avro orders.odcs.yaml --schema-name orders --output orders.avsc",
ORDERS,
["--schema-name", "orders"],
"json",
None,
),
"avro-idl": ("datacontract export avro-idl orders.odcs.yaml --output orders.avdl", ORDERS, [], "text", None),
"jsonschema": (
"datacontract export jsonschema orders.odcs.yaml --schema-name orders --output orders.schema.json",
ORDERS,
["--schema-name", "orders"],
"json",
None,
),
"pydantic-model": (
"datacontract export pydantic-model orders.odcs.yaml --output orders.py",
ORDERS,
[],
"python",
None,
),
"protobuf": ("datacontract export protobuf orders.odcs.yaml --output orders.proto", ORDERS, [], "protobuf", None),
"odcs": ("datacontract export odcs orders.odcs.yaml --output orders.normalized.yaml", ORDERS, [], "yaml", 32),
# rdf is intentionally not managed here: its Turtle serialization orders
# triples non-deterministically, so a regenerated example would churn on
# every run. exports/rdf.md keeps a committed, hand-checked example.
"markdown": ("datacontract export markdown orders.odcs.yaml --output orders.md", ORDERS, [], "markdown", 34),
"mermaid": ("datacontract export mermaid orders.odcs.yaml", ORDERS, [], "mermaid", None),
"bigquery": (
"datacontract export bigquery orders.odcs.yaml --schema-name orders --server bigquery --output orders.bigquery.json",
ORDERS,
["--schema-name", "orders", "--server", "bigquery"],
"json",
None,
),
"dbml": ("datacontract export dbml orders.odcs.yaml --output orders.dbml", ORDERS, [], "text", None),
"go": ("datacontract export go orders.odcs.yaml --output orders.go", ORDERS, [], "go", None),
"spark": ("datacontract export spark orders.odcs.yaml", ORDERS, [], "python", 34),
"sqlalchemy": (
"datacontract export sqlalchemy orders.odcs.yaml --output orders_models.py",
ORDERS,
[],
"python",
None,
),
"iceberg": (
"datacontract export iceberg orders.odcs.yaml --schema-name orders --output orders.iceberg.json",
ORDERS,
["--schema-name", "orders"],
"json",
None,
),
"sodacl": ("datacontract export sodacl orders.odcs.yaml --output sodacl.yaml", ORDERS, [], "yaml", 32),
"great-expectations": (
"datacontract export great-expectations orders.odcs.yaml --schema-name orders",
ORDERS,
["--schema-name", "orders"],
"json",
None,
),
"data-caterer": ("datacontract export data-caterer orders.odcs.yaml", ORDERS, [], "yaml", None),
"dcs": ("datacontract export dcs orders.odcs.yaml --output datacontract.yaml", ORDERS, [], "yaml", 34),
"dqx": (
"datacontract export dqx user_interactions.odcs.yaml --schema-name user_interactions",
USER_INTERACTIONS,
["--schema-name", "user_interactions"],
"yaml",
None,
),
}
# The hand-written example block to replace on the first run (before markers exist):
# the command fence, the "Running this against …" sentence, and the output fence.
FALLBACK = re.compile(
r"```bash\n.*?\n```\n\nRunning this against the [^\n]*\n\n```[a-z-]*\n.*?\n```",
re.DOTALL,
)
def main() -> None:
for fmt, (display, contract, extra, lang, max_lines) in EXPORTS.items():
output = run_cli(["export", fmt, contract, *extra])
if fmt == "dbml":
# Drop the "Generated at <date> by datacontract-cli version <x>"
# header so the committed example stays deterministic.
output = re.sub(r"^/\*\nGenerated at .*?\*/\n", "", output, flags=re.DOTALL)
label = "user_interactions" if contract == USER_INTERACTIONS else "orders"
url = f"{EXAMPLES_URL}/{contract.split('examples/')[1].rsplit('/', 1)[0]}/{contract.rsplit('/', 1)[1]}"
excerpt = bool(max_lines and len(output.split("\n")) > max_lines)
verb = "produces (excerpt)" if excerpt else "produces"
block = (
f"```bash\n{display}\n```\n\n"
f"Running this against the [example `{label}` contract]({url}) {verb}:\n\n"
f"{fence(lang, output, max_lines)}"
)
upsert(DOCS / "exports" / f"{fmt}.md", block, FALLBACK)
print(f"ok exports/{fmt}.md{' (excerpt)' if excerpt else ''}")
if __name__ == "__main__":
main()