Skip to content

Commit e478733

Browse files
committed
MaD: update generator scripts to support writing JSON data extensions
The `generate_mad.py` script accepts a flag that lets you choose between YAML or JSON, but YAML is still the default. We can change the default later, when CLI support for JSON is widely available. `convert_extensions.py` also still hard-codes `.yml` as the output extension/format.
1 parent 8df660a commit e478733

4 files changed

Lines changed: 49 additions & 8 deletions

File tree

‎misc/scripts/models-as-data/bulk_generate_mad.py‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -430,10 +430,11 @@ def download_and_decompress(analyzed_database: dict) -> str:
430430
def clean_up_mad_destination_for_project(config, name: str):
431431
target = pathlib.Path(config["destination"], name)
432432
if config.get("single-file", False):
433-
target = target.with_suffix(".model.yml")
434-
if target.exists():
435-
print(f"Deleting existing MaD file at {target}")
436-
target.unlink()
433+
for extension in (".model.json", ".model.yml"):
434+
model_target = target.with_suffix(extension)
435+
if model_target.exists():
436+
print(f"Deleting existing MaD file at {model_target}")
437+
model_target.unlink()
437438
elif target.exists():
438439
print(f"Deleting existing MaD directory at {target}")
439440
shutil.rmtree(target, ignore_errors=True)

‎misc/scripts/models-as-data/data_extension_file.py‎

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import json
22

3-
# Simple class for representing a data extension file and writing it to disk in a pretty-printed YAML format.
3+
# Simple class for representing a data extension file and writing it to disk in a pretty-printed
4+
# YAML or JSON format.
45
class DataExtensionFile:
56
def __init__(self, pack):
67
self.pack = pack
@@ -37,3 +38,31 @@ def write_yaml(self, f):
3738
f.write('extensions:\n')
3839
for predicate in sorted(self.predicates.keys()):
3940
f.write(self.yaml_for_predicate(predicate))
41+
42+
def json_for_row(self, row):
43+
return "[" + ", ".join(json.dumps(value) for value in row) +"]"
44+
45+
def json_for_predicate(self, predicate):
46+
return f""" {{
47+
"addsTo": {{
48+
"pack": "{self.pack}",
49+
"extensible": "{predicate}"
50+
}},
51+
"data": [
52+
{',\n '.join(self.json_for_row(row) for row in self.predicates[predicate])}
53+
]
54+
}}"""
55+
56+
def write_json(self, f):
57+
# It would be preferable to use a serializer like Python's json.dumps, but it can't
58+
# pretty-print with one line per tuple.
59+
f.write('// THIS FILE IS AN AUTO-GENERATED MODELS AS DATA FILE. DO NOT EDIT.\n')
60+
f.write('{\n')
61+
f.write(' "extensions": [\n')
62+
for i, predicate in enumerate(self.predicates):
63+
if i > 0:
64+
f.write(',\n')
65+
f.write(self.json_for_predicate(predicate))
66+
f.write('\n')
67+
f.write(' ]\n')
68+
f.write('}')

‎misc/scripts/models-as-data/generate_mad.py‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ def make():
119119
"--single-file",
120120
help="Generate a single file with all models instead of separate files for each namespace, using provided argument as the base filename.",
121121
)
122+
p.add_argument(
123+
"--extension-format",
124+
choices=["json", "yaml"],
125+
default="yaml",
126+
help="Format for the generated data extension files (default %(default)s)",
127+
)
122128
generator = p.parse_args(namespace=Generator())
123129

124130
if (
@@ -210,16 +216,18 @@ def run(self):
210216
print("Models as data extensions generated, but not written to file.")
211217
sys.exit(0)
212218

219+
file_extension = ".json" if self.extension_format == "json" else ".yml"
220+
213221
if (
214222
self.with_sinks
215223
or self.with_sources
216224
or self.with_summaries
217225
or self.with_neutrals
218226
):
219-
merger.save(self.generated_frameworks, ".model.yml")
227+
merger.save(self.generated_frameworks, f".model{file_extension}")
220228

221229
if self.with_typebased_summaries:
222-
type_based_extensions.save(self.generated_frameworks, ".typebased.model.yml")
230+
type_based_extensions.save(self.generated_frameworks, f".typebased.model{file_extension}")
223231

224232

225233
if __name__ == "__main__":

‎misc/scripts/models-as-data/helpers.py‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@ def save(self, dir, file_extension):
5050
)
5151
target = os.path.join(dir, f"{sanitized_namespace}{file_extension}")
5252
with open(target, "w") as f:
53-
extension.write_yaml(f)
53+
if file_extension.endswith(".json"):
54+
extension.write_json(f)
55+
else:
56+
extension.write_yaml(f)
5457
print("Models as data extensions written to " + target)
5558

5659

0 commit comments

Comments
 (0)