-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathgenerate_examples.py
More file actions
executable file
·106 lines (86 loc) · 3.93 KB
/
generate_examples.py
File metadata and controls
executable file
·106 lines (86 loc) · 3.93 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
#!/usr/bin/env python
"""
generate_example.py
Usage:
generate_example.py SPEC_FILE OUT_DIR
"""
import json
import os
import os.path
from docopt import docopt
from jsonpath_rw import parse
def generate_resource_example(schema_dict, path=None): # noqa: C901 - complexity 11 instead of 10.
"""
Generates resource examples from an OAS schema
Incomplete, especially around multiple arity/polymorphic parts such as anyOf.
In future this should be replaced by an example generator that uses FHIR tooling.
"""
example = {}
if path is None:
path = []
for property_name, property_value in schema_dict.items():
if property_value["type"] == "array":
if "oneOf" in property_value["items"]:
example[property_name] = [
generate_resource_example(t["properties"], [*path, property_name])
for t in property_value["items"]["oneOf"]
]
elif "anyOf" in property_value["items"]:
example[property_name] = [
generate_resource_example(t["properties"], [*path, property_name])
for t in property_value["items"]["anyOf"]
]
elif property_value["items"]["type"] == "object":
example[property_name] = [
generate_resource_example(property_value["items"]["properties"], [*path, property_name])
]
else:
if {"example", "default"} & set(property_value.get("items", {}).keys()):
items = property_value["items"]
example[property_name] = [items.get("example", items.get("default"))]
elif ("example" not in property_value) and ("default" not in property_value):
property_path = ".".join(path)
raise RuntimeError(f"{property_path}.{property_name} has no example or default!")
else:
example[property_name] = property_value.get("example", property_value.get("default"))
elif property_value["type"] == "object":
example[property_name] = generate_resource_example(property_value["properties"], [*path, property_name])
else:
if ("example" not in property_value) and ("default" not in property_value):
property_path = ".".join(path)
raise RuntimeError(f"{property_path}.{property_name} has no example or default!")
example[property_name] = property_value.get("example", property_value.get("default"))
return example
def main(arguments):
"""Program entry point"""
arguments = docopt(__doc__, version="0")
# Load spec from file
with open(arguments["SPEC_FILE"]) as spec_file:
spec = json.loads(spec_file.read())
# Create default dir structure
for i in ["resources", "responses"]:
os.makedirs(os.path.join(arguments["OUT_DIR"], i), exist_ok=True)
# Generate resources
for component_name, component_spec in spec["components"]["schemas"].items():
with open(
os.path.join(arguments["OUT_DIR"], "resources", component_name + ".json"),
"w",
) as out_file:
out_file.write(json.dumps(generate_resource_example(component_spec["properties"], [component_name])))
# Pull out responses
match_expr = parse("paths.*.*.(response|(responses.*)).content.*.(example|(examples.*.value))")
for match in match_expr.find(spec):
if "patch" in str(match.full_path):
# PATCHes are not FHIR resources, so we should not be validating them
continue
with open(
os.path.join(
arguments["OUT_DIR"],
"responses",
str(match.full_path).replace("/", "_") + ".json",
),
"w",
) as out_file:
out_file.write(json.dumps(match.value))
if __name__ == "__main__":
main(arguments=docopt(__doc__, version="0"))