Skip to content

Commit 4ea7d91

Browse files
braingramemolter
andauthored
Retain id and other top-level attributes in merge_property_trees (#364)
Co-authored-by: Ned Molter <[email protected]>
1 parent ab0cba5 commit 4ea7d91

File tree

4 files changed

+32
-13
lines changed

4 files changed

+32
-13
lines changed

changes/364.bugfix.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Allow ``merge_property_trees`` to retain input schema id in ``model.schema["id"]``.

src/stdatamodels/jwst/datamodels/tests/test_models.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,15 @@ def test_imagemodel():
129129

130130

131131
def test_model_with_nonstandard_primary_array():
132-
class NonstandardPrimaryArrayModel(JwstDataModel):
132+
class _NonstandardPrimaryArrayModel(JwstDataModel):
133133
schema_url = os.path.join(ROOT_DIR, "nonstandard_primary_array.schema.yaml")
134134

135135
# The wavelength array is the primary array.
136136
# Try commenting this function out and the problem goes away.
137137
def get_primary_array_name(self):
138138
return 'wavelength'
139139

140-
m = NonstandardPrimaryArrayModel((10,))
140+
m = _NonstandardPrimaryArrayModel((10,))
141141
assert 'wavelength' in list(m.keys())
142142
assert m.wavelength.sum() == 0
143143

src/stdatamodels/schema.py

+16-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# Licensed under a 3-clause BSD style license - see LICENSE.rst
22

33
import re
4-
from collections import OrderedDict
54

65

76
# return_result included for backward compatibility
@@ -169,11 +168,17 @@ def merge_property_trees(schema):
169168
can be represented in individual files and then referenced elsewhere. They
170169
are then combined by this function into a single schema data structure.
171170
"""
172-
newschema = OrderedDict()
171+
# track the "combined" and "top" items separately
172+
# this allows the top level "id", "$schema", etc to overwrite
173+
# combined items (so that the schema["id"] doesn't change).
174+
combined_items = {}
175+
top_items = {}
173176

174177
def add_entry(path, schema, combiner):
178+
if not top_items:
179+
top_items.update(schema)
175180
# TODO: Simplify?
176-
cursor = newschema
181+
cursor = combined_items
177182
for i in range(len(path)):
178183
part = path[i]
179184
if part == combiner:
@@ -185,23 +190,23 @@ def add_entry(path, schema, combiner):
185190
cursor.append({})
186191
cursor = cursor[part]
187192
elif part == 'items':
188-
cursor = cursor.setdefault('items', OrderedDict())
193+
cursor = cursor.setdefault('items', {})
189194
else:
190-
cursor = cursor.setdefault('properties', OrderedDict())
195+
cursor = cursor.setdefault('properties', {})
191196
if i < len(path) - 1 and isinstance(path[i + 1], int):
192197
cursor = cursor.setdefault(part, [])
193198
else:
194-
cursor = cursor.setdefault(part, OrderedDict())
199+
cursor = cursor.setdefault(part, {})
195200

196201
cursor.update(schema)
197202

198203
def callback(schema, path, combiner, ctx, recurse):
199-
type = schema.get('type')
200-
schema = OrderedDict(schema)
201-
if type == 'object':
204+
schema_type = schema.get('type')
205+
schema = dict(schema) # shallow copy
206+
if schema_type == 'object':
202207
if 'properties' in schema:
203208
del schema['properties']
204-
elif type == 'array':
209+
elif schema_type == 'array':
205210
del schema['items']
206211
if 'allOf' in schema:
207212
del schema['allOf']
@@ -210,7 +215,7 @@ def callback(schema, path, combiner, ctx, recurse):
210215

211216
walk_schema(schema, callback)
212217

213-
return newschema
218+
return combined_items | top_items
214219

215220

216221
def build_docstring(klass, template="{fits_hdu} {title}"):

tests/test_schema.py

+13
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,19 @@ def test_merge_property_trees(combiner):
206206
assert f == s
207207

208208

209+
def test_merge_property_tree_top():
210+
s = {
211+
"id": "foo",
212+
"allOf": [
213+
{
214+
"id": "bar",
215+
},
216+
]
217+
}
218+
f = merge_property_trees(s)
219+
assert f["id"] == "foo"
220+
221+
209222
def test_schema_docstring():
210223
template = "{fits_hdu} {title}"
211224
docstring = build_docstring(FitsModel, template).split("\n")

0 commit comments

Comments
 (0)