Skip to content

Commit 2e78f75

Browse files
committed
rf: Dereference while looking up references
1 parent f891a55 commit 2e78f75

File tree

1 file changed

+11
-9
lines changed
  • tools/schemacode/src/bidsschematools

1 file changed

+11
-9
lines changed

tools/schemacode/src/bidsschematools/schema.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,25 +91,27 @@ def _find(obj, predicate):
9191

9292
def _dereference(namespace, base_schema):
9393
# In-place, recursively dereference objects
94-
# This allows a referenced object to itself contain a reference
95-
# A dependency graph could be constructed, but would likely be slower
96-
# to build than to duplicate a couple dereferences
94+
# This allows for referencing objects that contain references,
95+
# as well as objects that do not exist until a parent is dereferenced.
9796
for struct in _find(namespace, lambda obj: "$ref" in obj):
9897
refs = struct["$ref"]
9998
if isinstance(refs, str):
10099
refs = [refs]
101100
targets = []
102101
for ref in refs:
103-
target = base_schema.get(ref)
104-
if target is None:
105-
raise ValueError(f"Reference {ref} not found in schema.")
102+
target = base_schema
103+
for part in ref.split("."):
104+
target = target.get(part)
105+
if target is None:
106+
raise ValueError(f"Reference {ref} not found in schema.")
107+
if "$ref" in target:
108+
_dereference(target, base_schema)
106109
targets.append(target)
110+
107111
if all(isinstance(target, Mapping) for target in targets):
108112
struct.pop("$ref")
109113

110-
combined_target = dict(ChainMap(*targets))
111-
_dereference(combined_target, base_schema)
112-
struct.update({**combined_target, **struct})
114+
struct.update({**ChainMap(*targets), **struct})
113115

114116
# Use `key: null` to delete fields
115117
for key, value in list(struct.items()):

0 commit comments

Comments
 (0)