davidtran999 commited on
Commit
4e9434f
·
verified ·
1 Parent(s): 319f0f6

Upload backend/venv/lib/python3.10/site-packages/jsonref.py with huggingface_hub

Browse files
backend/venv/lib/python3.10/site-packages/jsonref.py ADDED
@@ -0,0 +1,578 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import functools
2
+ import json
3
+ import warnings
4
+ from collections.abc import Mapping, MutableMapping, Sequence
5
+ from urllib import parse as urlparse
6
+ from urllib.parse import unquote
7
+ from urllib.request import urlopen
8
+
9
+ try:
10
+ # If requests >=1.0 is available, we will use it
11
+ import requests
12
+
13
+ if not callable(requests.Response.json):
14
+ requests = None
15
+ except ImportError:
16
+ requests = None
17
+
18
+ from proxytypes import LazyProxy
19
+
20
+ __version__ = "1.1.0"
21
+
22
+
23
+ class JsonRefError(Exception):
24
+ def __init__(self, message, reference, uri="", base_uri="", path=(), cause=None):
25
+ self.message = message
26
+ self.reference = reference
27
+ self.uri = uri
28
+ self.base_uri = base_uri
29
+ self.path = path
30
+ self.cause = self.__cause__ = cause
31
+
32
+ def __repr__(self):
33
+ return "<%s: %r>" % (self.__class__.__name__, self.message)
34
+
35
+ def __str__(self):
36
+ return str(self.message)
37
+
38
+
39
+ class JsonRef(LazyProxy):
40
+ """
41
+ A lazy loading proxy to the dereferenced data pointed to by a JSON
42
+ Reference object.
43
+
44
+ """
45
+
46
+ __notproxied__ = ("__reference__",)
47
+
48
+ @classmethod
49
+ def replace_refs(
50
+ cls, obj, base_uri="", loader=None, jsonschema=False, load_on_repr=True
51
+ ):
52
+ """
53
+ .. deprecated:: 0.4
54
+ Use :func:`replace_refs` instead.
55
+
56
+ Returns a deep copy of `obj` with all contained JSON reference objects
57
+ replaced with :class:`JsonRef` instances.
58
+
59
+ :param obj: If this is a JSON reference object, a :class:`JsonRef`
60
+ instance will be created. If `obj` is not a JSON reference object,
61
+ a deep copy of it will be created with all contained JSON
62
+ reference objects replaced by :class:`JsonRef` instances
63
+ :param base_uri: URI to resolve relative references against
64
+ :param loader: Callable that takes a URI and returns the parsed JSON
65
+ (defaults to global ``jsonloader``)
66
+ :param jsonschema: Flag to turn on `JSON Schema mode
67
+ <http://json-schema.org/latest/json-schema-core.html#anchor25>`_.
68
+ 'id' keyword changes the `base_uri` for references contained within
69
+ the object
70
+ :param load_on_repr: If set to ``False``, :func:`repr` call on a
71
+ :class:`JsonRef` object will not cause the reference to be loaded
72
+ if it hasn't already. (defaults to ``True``)
73
+
74
+ """
75
+ return replace_refs(
76
+ obj,
77
+ base_uri=base_uri,
78
+ loader=loader,
79
+ jsonschema=jsonschema,
80
+ load_on_repr=load_on_repr,
81
+ )
82
+
83
+ def __init__(
84
+ self,
85
+ refobj,
86
+ base_uri="",
87
+ loader=None,
88
+ jsonschema=False,
89
+ load_on_repr=True,
90
+ merge_props=False,
91
+ _path=(),
92
+ _store=None,
93
+ ):
94
+ if not isinstance(refobj.get("$ref"), str):
95
+ raise ValueError("Not a valid json reference object: %s" % refobj)
96
+ self.__reference__ = refobj
97
+ self.base_uri = base_uri
98
+ self.loader = loader or jsonloader
99
+ self.jsonschema = jsonschema
100
+ self.load_on_repr = load_on_repr
101
+ self.merge_props = merge_props
102
+ self.path = _path
103
+ self.store = _store # Use the same object to be shared with children
104
+ if self.store is None:
105
+ self.store = URIDict()
106
+
107
+ @property
108
+ def _ref_kwargs(self):
109
+ return dict(
110
+ base_uri=self.base_uri,
111
+ loader=self.loader,
112
+ jsonschema=self.jsonschema,
113
+ load_on_repr=self.load_on_repr,
114
+ merge_props=self.merge_props,
115
+ path=self.path,
116
+ store=self.store,
117
+ )
118
+
119
+ @property
120
+ def full_uri(self):
121
+ return urlparse.urljoin(self.base_uri, self.__reference__["$ref"])
122
+
123
+ def callback(self):
124
+ uri, fragment = urlparse.urldefrag(self.full_uri)
125
+
126
+ # If we already looked this up, return a reference to the same object
127
+ if uri not in self.store:
128
+ # Remote ref
129
+ try:
130
+ base_doc = self.loader(uri)
131
+ except Exception as e:
132
+ raise self._error(
133
+ "%s: %s" % (e.__class__.__name__, str(e)), cause=e
134
+ ) from e
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)
141
+ if result is self:
142
+ raise self._error("Reference refers directly to itself.")
143
+ if hasattr(result, "__subject__"):
144
+ result = result.__subject__
145
+ if (
146
+ self.merge_props
147
+ and isinstance(result, Mapping)
148
+ and len(self.__reference__) > 1
149
+ ):
150
+ result = {
151
+ **result,
152
+ **{k: v for k, v in self.__reference__.items() if k != "$ref"},
153
+ }
154
+ return result
155
+
156
+ def resolve_pointer(self, document, pointer):
157
+ """
158
+ Resolve a json pointer ``pointer`` within the referenced ``document``.
159
+
160
+ :argument document: the referent document
161
+ :argument str pointer: a json pointer URI fragment to resolve within it
162
+
163
+ """
164
+ parts = unquote(pointer.lstrip("/")).split("/") if pointer else []
165
+
166
+ for part in parts:
167
+ part = part.replace("~1", "/").replace("~0", "~")
168
+
169
+ if isinstance(document, Sequence):
170
+ # Try to turn an array index to an int
171
+ try:
172
+ part = int(part)
173
+ except ValueError:
174
+ 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__
178
+ try:
179
+ document = document[part]
180
+ except (TypeError, LookupError) as e:
181
+ raise self._error(
182
+ "Unresolvable JSON pointer: %r" % pointer, cause=e
183
+ ) from e
184
+ return document
185
+
186
+ def _error(self, message, cause=None):
187
+ message = "Error while resolving `{}`: {}".format(self.full_uri, message)
188
+ return JsonRefError(
189
+ message,
190
+ self.__reference__,
191
+ uri=self.full_uri,
192
+ base_uri=self.base_uri,
193
+ path=self.path,
194
+ cause=cause,
195
+ )
196
+
197
+ def __repr__(self):
198
+ if hasattr(self, "cache") or self.load_on_repr:
199
+ return repr(self.__subject__)
200
+ return "JsonRef(%r)" % self.__reference__
201
+
202
+
203
+ class URIDict(MutableMapping):
204
+ """
205
+ Dictionary which uses normalized URIs as keys.
206
+ """
207
+
208
+ def normalize(self, uri):
209
+ return urlparse.urlsplit(uri).geturl()
210
+
211
+ def __init__(self, *args, **kwargs):
212
+ self.store = dict()
213
+ self.store.update(*args, **kwargs)
214
+
215
+ def __getitem__(self, uri):
216
+ return self.store[self.normalize(uri)]
217
+
218
+ def __setitem__(self, uri, value):
219
+ self.store[self.normalize(uri)] = value
220
+
221
+ def __delitem__(self, uri):
222
+ del self.store[self.normalize(uri)]
223
+
224
+ def __iter__(self):
225
+ return iter(self.store)
226
+
227
+ def __len__(self):
228
+ return len(self.store)
229
+
230
+ def __repr__(self):
231
+ return repr(self.store)
232
+
233
+
234
+ def jsonloader(uri, **kwargs):
235
+ """
236
+ Provides a callable which takes a URI, and returns the loaded JSON referred
237
+ to by that URI. Uses :mod:`requests` if available for HTTP URIs, and falls
238
+ back to :mod:`urllib`.
239
+ """
240
+ scheme = urlparse.urlsplit(uri).scheme
241
+
242
+ if scheme in ["http", "https"] and requests:
243
+ # Prefer requests, it has better encoding detection
244
+ resp = requests.get(uri)
245
+ # If the http server doesn't respond normally then raise exception
246
+ # e.g. 404, 500 error
247
+ resp.raise_for_status()
248
+ try:
249
+ result = resp.json(**kwargs)
250
+ except TypeError:
251
+ warnings.warn("requests >=1.2 required for custom kwargs to json.loads")
252
+ result = resp.json()
253
+ else:
254
+ # Otherwise, pass off to urllib and assume utf-8
255
+ with urlopen(uri) as content:
256
+ result = json.loads(content.read().decode("utf-8"), **kwargs)
257
+
258
+ return result
259
+
260
+
261
+ def _walk_refs(obj, func, replace=False, _processed=None):
262
+ # Keep track of already processed items to prevent recursion
263
+ _processed = _processed or {}
264
+ oid = id(obj)
265
+ if oid in _processed:
266
+ return _processed[oid]
267
+ if type(obj) is JsonRef:
268
+ r = func(obj)
269
+ obj = r if replace else obj
270
+ _processed[oid] = obj
271
+ if isinstance(obj, Mapping):
272
+ for k, v in obj.items():
273
+ r = _walk_refs(v, func, replace=replace, _processed=_processed)
274
+ if replace:
275
+ obj[k] = r
276
+ elif isinstance(obj, Sequence) and not isinstance(obj, str):
277
+ for i, v in enumerate(obj):
278
+ r = _walk_refs(v, func, replace=replace, _processed=_processed)
279
+ if replace:
280
+ obj[i] = r
281
+ return obj
282
+
283
+
284
+ def replace_refs(
285
+ obj,
286
+ base_uri="",
287
+ loader=jsonloader,
288
+ jsonschema=False,
289
+ load_on_repr=True,
290
+ merge_props=False,
291
+ proxies=True,
292
+ lazy_load=True,
293
+ ):
294
+ """
295
+ Returns a deep copy of `obj` with all contained JSON reference objects
296
+ replaced with :class:`JsonRef` instances.
297
+
298
+ :param obj: If this is a JSON reference object, a :class:`JsonRef`
299
+ instance will be created. If `obj` is not a JSON reference object,
300
+ a deep copy of it will be created with all contained JSON
301
+ reference objects replaced by :class:`JsonRef` instances
302
+ :param base_uri: URI to resolve relative references against
303
+ :param loader: Callable that takes a URI and returns the parsed JSON
304
+ (defaults to global ``jsonloader``, a :class:`JsonLoader` instance)
305
+ :param jsonschema: Flag to turn on `JSON Schema mode
306
+ <http://json-schema.org/latest/json-schema-core.html#anchor25>`_.
307
+ 'id' or '$id' keyword changes the `base_uri` for references contained
308
+ within the object
309
+ :param load_on_repr: If set to ``False``, :func:`repr` call on a
310
+ :class:`JsonRef` object will not cause the reference to be loaded
311
+ if it hasn't already. (defaults to ``True``)
312
+ :param merge_props: When ``True``, JSON reference objects that
313
+ have extra keys other than '$ref' in them will be merged into the
314
+ document resolved by the reference (if it is a dictionary.) NOTE: This
315
+ is not part of the JSON Reference spec, and may not behave the same as
316
+ other libraries.
317
+ :param proxies: If `True`, references will be replaced with transparent
318
+ proxy objects. Otherwise, they will be replaced directly with the
319
+ referred data. (defaults to ``True``)
320
+ :param lazy_load: When proxy objects are used, and this is `True`, the
321
+ references will not be resolved until that section of the JSON
322
+ document is accessed. (defaults to ``True``)
323
+
324
+ """
325
+ result = _replace_refs(
326
+ obj,
327
+ base_uri=base_uri,
328
+ loader=loader,
329
+ jsonschema=jsonschema,
330
+ load_on_repr=load_on_repr,
331
+ merge_props=merge_props,
332
+ store=URIDict(),
333
+ path=(),
334
+ recursing=False,
335
+ )
336
+ if not proxies:
337
+ _walk_refs(result, lambda r: r.__subject__, replace=True)
338
+ elif not lazy_load:
339
+ _walk_refs(result, lambda r: r.__subject__)
340
+ return result
341
+
342
+
343
+ def _replace_refs(
344
+ obj,
345
+ *,
346
+ base_uri,
347
+ loader,
348
+ jsonschema,
349
+ load_on_repr,
350
+ merge_props,
351
+ store,
352
+ path,
353
+ recursing
354
+ ):
355
+ base_uri, frag = urlparse.urldefrag(base_uri)
356
+ store_uri = None # If this does not get set, we won't store the result
357
+ if not frag and not recursing:
358
+ store_uri = base_uri
359
+ if jsonschema and isinstance(obj, Mapping):
360
+ # id changed to $id in later jsonschema versions
361
+ id_ = obj.get("$id") or obj.get("id")
362
+ if isinstance(id_, str):
363
+ base_uri = urlparse.urljoin(base_uri, id_)
364
+ store_uri = base_uri
365
+
366
+ # First recursively iterate through our object, replacing children with JsonRefs
367
+ if isinstance(obj, Mapping):
368
+ obj = {
369
+ k: _replace_refs(
370
+ v,
371
+ base_uri=base_uri,
372
+ loader=loader,
373
+ jsonschema=jsonschema,
374
+ load_on_repr=load_on_repr,
375
+ merge_props=merge_props,
376
+ store=store,
377
+ path=path + (k,),
378
+ recursing=True,
379
+ )
380
+ for k, v in obj.items()
381
+ }
382
+ elif isinstance(obj, Sequence) and not isinstance(obj, str):
383
+ obj = [
384
+ _replace_refs(
385
+ v,
386
+ base_uri=base_uri,
387
+ loader=loader,
388
+ jsonschema=jsonschema,
389
+ load_on_repr=load_on_repr,
390
+ merge_props=merge_props,
391
+ store=store,
392
+ path=path + (i,),
393
+ recursing=True,
394
+ )
395
+ for i, v in enumerate(obj)
396
+ ]
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
412
+ if store_uri is not None:
413
+ store[store_uri] = obj
414
+
415
+ return obj
416
+
417
+
418
+ def load(
419
+ fp,
420
+ base_uri="",
421
+ loader=None,
422
+ jsonschema=False,
423
+ load_on_repr=True,
424
+ merge_props=False,
425
+ proxies=True,
426
+ lazy_load=True,
427
+ **kwargs
428
+ ):
429
+ """
430
+ Drop in replacement for :func:`json.load`, where JSON references are
431
+ proxied to their referent data.
432
+
433
+ :param fp: File-like object containing JSON document
434
+ :param **kwargs: This function takes any of the keyword arguments from
435
+ :func:`replace_refs`. Any other keyword arguments will be passed to
436
+ :func:`json.load`
437
+
438
+ """
439
+
440
+ if loader is None:
441
+ loader = functools.partial(jsonloader, **kwargs)
442
+
443
+ return replace_refs(
444
+ json.load(fp, **kwargs),
445
+ base_uri=base_uri,
446
+ loader=loader,
447
+ jsonschema=jsonschema,
448
+ load_on_repr=load_on_repr,
449
+ merge_props=merge_props,
450
+ proxies=proxies,
451
+ lazy_load=lazy_load,
452
+ )
453
+
454
+
455
+ def loads(
456
+ s,
457
+ base_uri="",
458
+ loader=None,
459
+ jsonschema=False,
460
+ load_on_repr=True,
461
+ merge_props=False,
462
+ proxies=True,
463
+ lazy_load=True,
464
+ **kwargs
465
+ ):
466
+ """
467
+ Drop in replacement for :func:`json.loads`, where JSON references are
468
+ proxied to their referent data.
469
+
470
+ :param s: String containing JSON document
471
+ :param **kwargs: This function takes any of the keyword arguments from
472
+ :func:`replace_refs`. Any other keyword arguments will be passed to
473
+ :func:`json.loads`
474
+
475
+ """
476
+
477
+ if loader is None:
478
+ loader = functools.partial(jsonloader, **kwargs)
479
+
480
+ return replace_refs(
481
+ json.loads(s, **kwargs),
482
+ base_uri=base_uri,
483
+ loader=loader,
484
+ jsonschema=jsonschema,
485
+ load_on_repr=load_on_repr,
486
+ merge_props=merge_props,
487
+ proxies=proxies,
488
+ lazy_load=lazy_load,
489
+ )
490
+
491
+
492
+ def load_uri(
493
+ uri,
494
+ base_uri=None,
495
+ loader=None,
496
+ jsonschema=False,
497
+ load_on_repr=True,
498
+ merge_props=False,
499
+ proxies=True,
500
+ lazy_load=True,
501
+ ):
502
+ """
503
+ Load JSON data from ``uri`` with JSON references proxied to their referent
504
+ data.
505
+
506
+ :param uri: URI to fetch the JSON from
507
+ :param **kwargs: This function takes any of the keyword arguments from
508
+ :func:`replace_refs`
509
+
510
+ """
511
+
512
+ if loader is None:
513
+ loader = jsonloader
514
+ if base_uri is None:
515
+ base_uri = uri
516
+
517
+ return replace_refs(
518
+ loader(uri),
519
+ base_uri=base_uri,
520
+ loader=loader,
521
+ jsonschema=jsonschema,
522
+ load_on_repr=load_on_repr,
523
+ merge_props=merge_props,
524
+ proxies=proxies,
525
+ lazy_load=lazy_load,
526
+ )
527
+
528
+
529
+ def dump(obj, fp, **kwargs):
530
+ """
531
+ Serialize `obj`, which may contain :class:`JsonRef` objects, as a JSON
532
+ formatted stream to file-like `fp`. `JsonRef` objects will be dumped as the
533
+ original reference object they were created from.
534
+
535
+ :param obj: Object to serialize
536
+ :param fp: File-like to output JSON string
537
+ :param kwargs: Keyword arguments are the same as to :func:`json.dump`
538
+
539
+ """
540
+ # Strangely, json.dumps does not use the custom serialization from our
541
+ # encoder on python 2.7+. Instead, just write json.dumps output to a file.
542
+ fp.write(dumps(obj, **kwargs))
543
+
544
+
545
+ def dumps(obj, **kwargs):
546
+ """
547
+ Serialize `obj`, which may contain :class:`JsonRef` objects, to a JSON
548
+ formatted string. `JsonRef` objects will be dumped as the original
549
+ reference object they were created from.
550
+
551
+ :param obj: Object to serialize
552
+ :param kwargs: Keyword arguments are the same as to :func:`json.dumps`
553
+
554
+ """
555
+ kwargs["cls"] = _ref_encoder_factory(kwargs.get("cls", json.JSONEncoder))
556
+ return json.dumps(obj, **kwargs)
557
+
558
+
559
+ def _ref_encoder_factory(cls):
560
+ class JSONRefEncoder(cls):
561
+ def default(self, o):
562
+ if hasattr(o, "__reference__"):
563
+ return o.__reference__
564
+ return super(JSONRefEncoder, cls).default(o)
565
+
566
+ # Python 2.6 doesn't work with the default method
567
+ def _iterencode(self, o, *args, **kwargs):
568
+ if hasattr(o, "__reference__"):
569
+ o = o.__reference__
570
+ return super(JSONRefEncoder, self)._iterencode(o, *args, **kwargs)
571
+
572
+ # Pypy doesn't work with either of the other methods
573
+ def _encode(self, o, *args, **kwargs):
574
+ if hasattr(o, "__reference__"):
575
+ o = o.__reference__
576
+ return super(JSONRefEncoder, self)._encode(o, *args, **kwargs)
577
+
578
+ return JSONRefEncoder