tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

jsonlib.py (2637B)


      1 import re
      2 import json
      3 from typing import Any, AnyStr, Callable, Dict, IO, Text
      4 
      5 
      6 __all__ = ["load", "dump_local", "dump_local", "dump_dist", "dumps_dist"]
      7 
      8 
      9 try:
     10    import ujson
     11 except ImportError:
     12    has_ujson = False
     13 else:
     14    has_ujson = True
     15 
     16 #
     17 # load
     18 #
     19 
     20 if has_ujson:
     21    load: Callable[[IO[AnyStr]], Any] = ujson.load
     22 
     23 else:
     24    load = json.load
     25 
     26 
     27 #
     28 # loads
     29 #
     30 
     31 if has_ujson:
     32    loads: Callable[[AnyStr], Any] = ujson.loads
     33 
     34 else:
     35    loads = json.loads
     36 
     37 
     38 #
     39 # dump/dumps_local options for some libraries
     40 #
     41 _ujson_dump_local_kwargs: Dict[str, Any] = {
     42    'ensure_ascii': False,
     43    'escape_forward_slashes': False,
     44    'indent': 1,
     45    'reject_bytes': True,
     46 }
     47 
     48 
     49 _json_dump_local_kwargs: Dict[str, Any] = {
     50    'ensure_ascii': False,
     51    'indent': 1,
     52    'separators': (',', ': '),
     53 }
     54 
     55 
     56 #
     57 # dump_local (for local, non-distributed usage of JSON)
     58 #
     59 
     60 if has_ujson:
     61    def dump_local(obj: Any, fp: IO[str]) -> None:
     62        return ujson.dump(obj, fp, **_ujson_dump_local_kwargs)
     63 
     64 else:
     65    def dump_local(obj: Any, fp: IO[str]) -> None:
     66        return json.dump(obj, fp, **_json_dump_local_kwargs)
     67 
     68 
     69 #
     70 # dumps_local (for local, non-distributed usage of JSON)
     71 #
     72 
     73 if has_ujson:
     74    def dumps_local(obj: Any) -> Text:
     75        return ujson.dumps(obj, **_ujson_dump_local_kwargs)
     76 
     77 else:
     78    def dumps_local(obj: Any) -> Text:
     79        return json.dumps(obj, **_json_dump_local_kwargs)
     80 
     81 
     82 #
     83 # dump/dumps_dist (for distributed usage of JSON where files should safely roundtrip)
     84 #
     85 
     86 _ujson_dump_dist_kwargs: Dict[str, Any] = {
     87    'sort_keys': True,
     88    'indent': 1,
     89    'reject_bytes': True,
     90    'escape_forward_slashes': False,
     91 }
     92 
     93 
     94 _json_dump_dist_kwargs: Dict[str, Any] = {
     95    'sort_keys': True,
     96    'indent': 1,
     97    'separators': (',', ': '),
     98 }
     99 
    100 
    101 if has_ujson:
    102    if ujson.dumps([], indent=1) == "[]":
    103        # optimistically see if https://github.com/ultrajson/ultrajson/issues/429 is fixed
    104        def _ujson_fixup(s: str) -> str:
    105            return s
    106    else:
    107        _ujson_fixup_re = re.compile(r"([\[{])[\n\x20]+([}\]])")
    108 
    109        def _ujson_fixup(s: str) -> str:
    110            return _ujson_fixup_re.sub(
    111                lambda m: m.group(1) + m.group(2),
    112                s
    113            )
    114 
    115    def dump_dist(obj: Any, fp: IO[str]) -> None:
    116        fp.write(_ujson_fixup(ujson.dumps(obj, **_ujson_dump_dist_kwargs)))
    117 
    118    def dumps_dist(obj: Any) -> Text:
    119        return _ujson_fixup(ujson.dumps(obj, **_ujson_dump_dist_kwargs))
    120 else:
    121    def dump_dist(obj: Any, fp: IO[str]) -> None:
    122        json.dump(obj, fp, **_json_dump_dist_kwargs)
    123 
    124    def dumps_dist(obj: Any) -> Text:
    125        return json.dumps(obj, **_json_dump_dist_kwargs)