@@ -90,6 +90,21 @@ def _find(obj, predicate):
9090 yield from _find (item , predicate )
9191
9292
93+ def _dereference (namespace , base_schema ):
94+ # In-place, recursively dereference objects
95+ # This allows a referenced object to itself contain a reference
96+ # A dependency graph could be constructed, but would likely be slower
97+ # to build than to duplicate a couple dereferences
98+ for struct in _find (namespace , lambda obj : "$ref" in obj ):
99+ target = base_schema .get (struct ["$ref" ])
100+ if target is None :
101+ raise ValueError (f"Reference { struct ['$ref' ]} not found in schema." )
102+ if isinstance (target , Mapping ):
103+ struct .pop ("$ref" )
104+ _dereference (target , base_schema )
105+ struct .update ({** target , ** struct })
106+
107+
93108def dereference (namespace , inplace = True ):
94109 """Replace references in namespace with the contents of the referred object.
95110
@@ -109,11 +124,7 @@ def dereference(namespace, inplace=True):
109124 if not inplace :
110125 namespace = deepcopy (namespace )
111126
112- for struct in _find (namespace , lambda obj : "$ref" in obj ):
113- target = namespace .get (struct ["$ref" ])
114- if isinstance (target , Mapping ):
115- struct .pop ("$ref" )
116- struct .update ({** target , ** struct })
127+ _dereference (namespace , namespace )
117128
118129 # At this point, any remaining refs are one-off objects in lists
119130 for struct in _find (namespace , lambda obj : any ("$ref" in sub for sub in obj )):
0 commit comments