@@ -91,25 +91,27 @@ def _find(obj, predicate):
9191
9292def _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