@@ -91,25 +91,27 @@ def _find(obj, predicate):
91
91
92
92
def _dereference (namespace , base_schema ):
93
93
# 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.
97
96
for struct in _find (namespace , lambda obj : "$ref" in obj ):
98
97
refs = struct ["$ref" ]
99
98
if isinstance (refs , str ):
100
99
refs = [refs ]
101
100
targets = []
102
101
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 )
106
109
targets .append (target )
110
+
107
111
if all (isinstance (target , Mapping ) for target in targets ):
108
112
struct .pop ("$ref" )
109
113
110
- combined_target = dict (ChainMap (* targets ))
111
- _dereference (combined_target , base_schema )
112
- struct .update ({** combined_target , ** struct })
114
+ struct .update ({** ChainMap (* targets ), ** struct })
113
115
114
116
# Use `key: null` to delete fields
115
117
for key , value in list (struct .items ()):
0 commit comments