-
Notifications
You must be signed in to change notification settings - Fork 75
Expand file tree
/
Copy pathpopulate_schema.py
More file actions
122 lines (112 loc) · 4.11 KB
/
Copy pathpopulate_schema.py
File metadata and controls
122 lines (112 loc) · 4.11 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
import json
import sys
obj = json.load(open(sys.argv[1]))
known_quants = {
"planeAngle": {"quantityKind": "Plane angle"}, # Added
"thermodynamicTemperatue": {"quantityKind": "Thermodynamic temperatue"}, # Added
"celsiusTemperature": {"quantityKind": "Celsius temperature"}, # Added
"electricCurrent": {"quantityKind": "Electric current"}, # Added
"time": {"quantityKind": "Time"}, # Added
"frequency": {"quantityKind": "Frequency"}, # Added
"mass": {"quantityKind": "Mass"}, # Added
"length": {"quantityKind": "Length"}, # Changed "height" into "length" !
"linearVelocity": {"quantityKind": "Linear velocity"}, # Added
"force": {"quantityKind": "Force"}, # Added
"pressure": {"quantityKind": "Pressure"}, # Added
"area": {"quantityKind": "Area"}, # Added
"volume": {"quantityKind": "Volume"},
"massDensity": {"quantityKind": "Mass density"}, # Added
"thermalConductivity": {"quantityKind": "Thermal conductivity"}, # Added
"thermalTransmittance": {"quantityKind": "Thermal transmittance"} # Added
}
def make_schema(v, path=[]):
if isinstance(v, dict):
return {
"dataType": "Object",
"objectRestrictions": {
"values": {k: make_schema(v, [*path, k]) for k, v in v.items()}
}
}
elif isinstance(v, list):
if set(map(type, v)) == {int, float}:
return {
"dataType": "Array",
"arrayRestrictions": {
"value": {
"dataType": "Real"
}
}
}
else:
assert len(set(map(type, v))) == 1
return {
"dataType": "Array",
"arrayRestrictions": {
"value": make_schema(v[0], [*path, k])
}
}
elif isinstance(v, float):
return {
"dataType": "Real",
**known_quants.get(path[-1].split('::')[-1], {})
}
elif isinstance(v, bool):
return {
"dataType": "Boolean"
}
elif isinstance(v, int):
if "points" in path or "transform" in path:
return {
"dataType": "Real"
}
return {
"dataType": "Integer"
}
elif isinstance(v, str):
return {
"dataType": "String"
}
else:
breakpoint()
def unify_schemas(left, right):
if None in (left, right):
return left or right
types = set(map(type, (left, right)))
assert types in ({str}, {dict})
if types == {str}:
if {left, right} == {'Integer', 'Real'}:
return 'Real'
elif left == right:
return left
else:
return None
if not (left.keys() <= right.keys() or right.keys() <= left.keys()):
return None
di = {
k: unify_schemas(left.get(k), right.get(k)) for k in (left.keys() | right.keys())
}
if None in di.values():
return None
return di
schema = {}
for elem in obj["data"]:
if attr := elem.get("attributes"):
for k, v in attr.items():
new_schema = { "value": make_schema(v, [k]) }
if old_schema := schema.get(k):
if new_schema != old_schema:
unified = unify_schemas(old_schema, new_schema)
if unified:
schema[k] = unified
else:
breakpoint()
assert False
else:
schema[k] = new_schema
obj["schemas"] = schema
ostream = None
try:
ostream = open(sys.argv[2], 'w')
except:
ostream = sys.stdout
json.dump(obj, ostream, indent=2)