Skip to content

Commit 734a966

Browse files
committed
resolve all refs for load_schema (can produce a recursive schema)
1 parent 0e7c50c commit 734a966

File tree

3 files changed

+46
-21
lines changed

3 files changed

+46
-21
lines changed

asdf/_tests/test_schema.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ def test_load_schema(tmp_path):
132132
schema_path = tmp_path / "nugatory.yaml"
133133
schema_path.write_bytes(schema_def.encode())
134134

135-
schema_tree = schema.load_schema(str(schema_path), resolve_references=True)
135+
schema_tree = schema.load_schema(str(schema_path))
136136
schema.check_schema(schema_tree)
137137

138138

@@ -156,7 +156,7 @@ def test_load_schema_with_file_url(tmp_path):
156156
schema_path = tmp_path / "nugatory.yaml"
157157
schema_path.write_bytes(schema_def.encode())
158158

159-
schema_tree = schema.load_schema(str(schema_path), resolve_references=True)
159+
schema_tree = schema.load_schema(str(schema_path))
160160
schema.check_schema(schema_tree)
161161

162162

@@ -814,6 +814,11 @@ def test_self_reference_resolution(test_data_path):
814814
assert s["anyOf"][1] == s["anyOf"][0]
815815

816816

817+
def test_resolve_references():
818+
s = schema.load_schema("http://stsci.edu/schemas/asdf/core/ndarray-1.0.0", resolve_references=True)
819+
assert "$ref" not in repr(s)
820+
821+
817822
def test_schema_resolved_via_entry_points():
818823
"""Test that entry points mappings to core schema works"""
819824
tag = "tag:stsci.edu:asdf/fits/fits-1.0.0"

asdf/schema.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -442,15 +442,14 @@ def resolve_refs(node, json_id):
442442

443443
if suburl_base == url or suburl_base == schema.get("id"):
444444
# This is a local ref, which we'll resolve in both cases.
445-
subschema = schema
445+
return reference.resolve_fragment(schema, suburl_fragment)
446446
else:
447447
subschema = load_schema(suburl_base, True)
448-
449-
return reference.resolve_fragment(subschema, suburl_fragment)
448+
return reference.resolve_fragment(subschema, suburl_fragment)
450449

451450
return node
452451

453-
schema = treeutil.walk_and_modify(schema, resolve_refs)
452+
schema = treeutil.walk_and_modify(schema, resolve_refs, in_place=True)
454453

455454
return schema
456455

asdf/treeutil.py

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ def __repr__(self):
219219
RemoveNode = _RemoveNode()
220220

221221

222-
def walk_and_modify(top, callback, postorder=True, _context=None):
222+
def walk_and_modify(top, callback, postorder=True, _context=None, in_place=False):
223223
"""Modify a tree by walking it with a callback function. It also has
224224
the effect of doing a deep copy.
225225
@@ -279,14 +279,17 @@ def _handle_callback(node, json_id):
279279
return _handle_generator(result)
280280

281281
def _handle_mapping(node, json_id):
282-
if isinstance(node, lazy_nodes.AsdfOrderedDictNode):
283-
result = collections.OrderedDict()
284-
elif isinstance(node, lazy_nodes.AsdfDictNode):
285-
result = {}
282+
if in_place:
283+
result = node
286284
else:
287-
result = node.__class__()
288-
if isinstance(node, tagged.Tagged):
289-
result._tag = node._tag
285+
if isinstance(node, lazy_nodes.AsdfOrderedDictNode):
286+
result = collections.OrderedDict()
287+
elif isinstance(node, lazy_nodes.AsdfDictNode):
288+
result = {}
289+
else:
290+
result = node.__class__()
291+
if isinstance(node, tagged.Tagged):
292+
result._tag = node._tag
290293

291294
pending_items = {}
292295
for key, value in node.items():
@@ -300,13 +303,15 @@ def _handle_mapping(node, json_id):
300303

301304
elif (val := _recurse(value, json_id)) is not RemoveNode:
302305
result[key] = val
306+
# TODO handle RemoveNode
303307

304308
yield result
305309

306310
if len(pending_items) > 0:
307311
# Now that we've yielded, the pending children should
308312
# be available.
309313
for key, value in pending_items.items():
314+
# TODO handle RemoveNode
310315
if (val := _recurse(value, json_id)) is not RemoveNode:
311316
result[key] = val
312317
else:
@@ -315,12 +320,23 @@ def _handle_mapping(node, json_id):
315320
del result[key]
316321

317322
def _handle_mutable_sequence(node, json_id):
318-
if isinstance(node, lazy_nodes.AsdfListNode):
319-
result = []
323+
if in_place:
324+
result = node
325+
326+
def setter(i, v):
327+
result[i] = v
328+
320329
else:
321-
result = node.__class__()
322-
if isinstance(node, tagged.Tagged):
323-
result._tag = node._tag
330+
331+
def setter(i, v):
332+
result.append(v)
333+
334+
if isinstance(node, lazy_nodes.AsdfListNode):
335+
result = []
336+
else:
337+
result = node.__class__()
338+
if isinstance(node, tagged.Tagged):
339+
result._tag = node._tag
324340

325341
pending_items = {}
326342
for i, value in enumerate(node):
@@ -330,9 +346,11 @@ def _handle_mutable_sequence(node, json_id):
330346
# PendingValue instance for now, and note that we'll
331347
# need to fill in the real value later.
332348
pending_items[i] = value
333-
result.append(PendingValue)
349+
setter(i, PendingValue)
350+
# result.append(PendingValue)
334351
else:
335-
result.append(_recurse(value, json_id))
352+
setter(i, _recurse(value, json_id))
353+
# result.append(_recurse(value, json_id))
336354

337355
yield result
338356

@@ -346,6 +364,9 @@ def _handle_immutable_sequence(node, json_id):
346364
# to construct (well, maybe possible in a C extension, but
347365
# we're not going to worry about that), so we don't need
348366
# to yield here.
367+
if in_place:
368+
# TODO better error
369+
raise Exception("fail")
349370
contents = [_recurse(value, json_id) for value in node]
350371

351372
result = node.__class__(contents)

0 commit comments

Comments
 (0)