1717
1818from proxytypes import LazyProxy
1919
20- __version__ = "1.0.1 "
20+ __version__ = "1.1.0 "
2121
2222
2323class JsonRefError (Exception ):
@@ -124,22 +124,20 @@ def callback(self):
124124 uri , fragment = urlparse .urldefrag (self .full_uri )
125125
126126 # If we already looked this up, return a reference to the same object
127- if uri in self .store :
128- result = self .resolve_pointer (self .store [uri ], fragment )
129- else :
127+ if uri not in self .store :
130128 # Remote ref
131129 try :
132130 base_doc = self .loader (uri )
133131 except Exception as e :
134132 raise self ._error (
135133 "%s: %s" % (e .__class__ .__name__ , str (e )), cause = e
136134 ) from e
137-
138- kwargs = self ._ref_kwargs
139- kwargs [ "base_uri" ] = uri
140- kwargs [ "recursing" ] = False
141- base_doc = _replace_refs ( base_doc , ** kwargs )
142- result = self .resolve_pointer (base_doc , fragment )
135+ base_doc = _replace_refs (
136+ base_doc , ** { ** self ._ref_kwargs , "base_uri" : uri , "recursing" : False }
137+ )
138+ else :
139+ base_doc = self . store [ uri ]
140+ result = self .resolve_pointer (base_doc , fragment )
143141 if result is self :
144142 raise self ._error ("Reference refers directly to itself." )
145143 if hasattr (result , "__subject__" ):
@@ -174,6 +172,9 @@ def resolve_pointer(self, document, pointer):
174172 part = int (part )
175173 except ValueError :
176174 pass
175+ # If a reference points inside itself, it must mean inside reference object, not the referent data
176+ if document is self :
177+ document = self .__reference__
177178 try :
178179 document = document [part ]
179180 except (TypeError , LookupError ) as e :
@@ -362,25 +363,7 @@ def _replace_refs(
362363 base_uri = urlparse .urljoin (base_uri , id_ )
363364 store_uri = base_uri
364365
365- try :
366- if not isinstance (obj ["$ref" ], str ):
367- raise TypeError
368- except (TypeError , LookupError ):
369- pass
370- else :
371- return JsonRef (
372- obj ,
373- base_uri = base_uri ,
374- loader = loader ,
375- jsonschema = jsonschema ,
376- load_on_repr = load_on_repr ,
377- merge_props = merge_props ,
378- _path = path ,
379- _store = store ,
380- )
381-
382- # If our obj was not a json reference object, iterate through it,
383- # replacing children with JsonRefs
366+ # First recursively iterate through our object, replacing children with JsonRefs
384367 if isinstance (obj , Mapping ):
385368 obj = {
386369 k : _replace_refs (
@@ -411,8 +394,24 @@ def _replace_refs(
411394 )
412395 for i , v in enumerate (obj )
413396 ]
397+
398+ # If this object itself was a reference, replace it with a JsonRef
399+ if isinstance (obj , Mapping ) and isinstance (obj .get ("$ref" ), str ):
400+ obj = JsonRef (
401+ obj ,
402+ base_uri = base_uri ,
403+ loader = loader ,
404+ jsonschema = jsonschema ,
405+ load_on_repr = load_on_repr ,
406+ merge_props = merge_props ,
407+ _path = path ,
408+ _store = store ,
409+ )
410+
411+ # Store the document with all references replaced in our cache
414412 if store_uri is not None :
415413 store [store_uri ] = obj
414+
416415 return obj
417416
418417
@@ -432,7 +431,7 @@ def load(
432431 proxied to their referent data.
433432
434433 :param fp: File-like object containing JSON document
435- :param kwargs: This function takes any of the keyword arguments from
434+ :param ** kwargs: This function takes any of the keyword arguments from
436435 :func:`replace_refs`. Any other keyword arguments will be passed to
437436 :func:`json.load`
438437
@@ -469,7 +468,7 @@ def loads(
469468 proxied to their referent data.
470469
471470 :param s: String containing JSON document
472- :param kwargs: This function takes any of the keyword arguments from
471+ :param ** kwargs: This function takes any of the keyword arguments from
473472 :func:`replace_refs`. Any other keyword arguments will be passed to
474473 :func:`json.loads`
475474
@@ -505,7 +504,7 @@ def load_uri(
505504 data.
506505
507506 :param uri: URI to fetch the JSON from
508- :param kwargs: This function takes any of the keyword arguments from
507+ :param ** kwargs: This function takes any of the keyword arguments from
509508 :func:`replace_refs`
510509
511510 """
0 commit comments