diff options
author | Adam Turner <9087854+aa-turner@users.noreply.github.com> | 2022-04-27 02:53:13 +0100 |
---|---|---|
committer | Adam Turner <9087854+aa-turner@users.noreply.github.com> | 2022-04-27 02:59:50 +0100 |
commit | b536ffabc1ff7d8cf4c2ec60ac8b5f7b812e448a (patch) | |
tree | 781b54655906a74d5c069a1c136f9f981930759c /sphinx/util/jsdump.py | |
parent | 5eeeb9ce375e2f35807b54f17cec64696a7828d7 (diff) | |
download | sphinx-git-b536ffabc1ff7d8cf4c2ec60ac8b5f7b812e448a.tar.gz |
Deprecate `sphinx.util.jsdump`
Diffstat (limited to 'sphinx/util/jsdump.py')
-rw-r--r-- | sphinx/util/jsdump.py | 215 |
1 files changed, 21 insertions, 194 deletions
diff --git a/sphinx/util/jsdump.py b/sphinx/util/jsdump.py index ed5aea4ba..151d3e80a 100644 --- a/sphinx/util/jsdump.py +++ b/sphinx/util/jsdump.py @@ -1,194 +1,21 @@ -"""This module implements a simple JavaScript serializer. - -Uses the basestring encode function from simplejson by Bob Ippolito. -""" - -import re -from typing import IO, Any, Dict, List, Match, Union - -_str_re = re.compile(r'"(\\\\|\\"|[^"])*"') -_int_re = re.compile(r'\d+') -_name_re = re.compile(r'[a-zA-Z_]\w*') -_nameonly_re = re.compile(r'[a-zA-Z_][a-zA-Z0-9_]*$') - -# escape \, ", control characters and everything outside ASCII -ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])') -ESCAPE_DICT = { - '\\': '\\\\', - '"': '\\"', - '\b': '\\b', - '\f': '\\f', - '\n': '\\n', - '\r': '\\r', - '\t': '\\t', -} - -ESCAPED = re.compile(r'\\u.{4}|\\.') - - -def encode_string(s: str) -> str: - def replace(match: Match) -> str: - s = match.group(0) - try: - return ESCAPE_DICT[s] - except KeyError: - n = ord(s) - if n < 0x10000: - return '\\u%04x' % (n,) - else: - # surrogate pair - n -= 0x10000 - s1 = 0xd800 | ((n >> 10) & 0x3ff) - s2 = 0xdc00 | (n & 0x3ff) - return '\\u%04x\\u%04x' % (s1, s2) - return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"' - - -def decode_string(s: str) -> str: - return ESCAPED.sub(lambda m: eval('"' + m.group() + '"'), s) - - -reswords = set("""\ -abstract else instanceof switch -boolean enum int synchronized -break export interface this -byte extends long throw -case false native throws -catch final new transient -char finally null true -class float package try -const for private typeof -continue function protected var -debugger goto public void -default if return volatile -delete implements short while -do import static with -double in super""".split()) - - -def dumps(obj: Any, key: bool = False) -> str: - if key: - if not isinstance(obj, str): - obj = str(obj) - if _nameonly_re.match(obj) and obj not in reswords: - return obj # return it as a bare word - else: - return encode_string(obj) - if obj is None: - return 'null' - elif obj is True or obj is False: - return 'true' if obj else 'false' - elif isinstance(obj, (int, float)): - return str(obj) - elif isinstance(obj, dict): - return '{%s}' % ','.join(sorted('%s:%s' % ( - dumps(key, True), - dumps(value) - ) for key, value in obj.items())) - elif isinstance(obj, set): - return '[%s]' % ','.join(sorted(dumps(x) for x in obj)) - elif isinstance(obj, (tuple, list)): - return '[%s]' % ','.join(dumps(x) for x in obj) - elif isinstance(obj, str): - return encode_string(obj) - raise TypeError(type(obj)) - - -def dump(obj: Any, f: IO) -> None: - f.write(dumps(obj)) - - -def loads(x: str) -> Any: - """Loader that can read the JS subset the indexer produces.""" - nothing = object() - i = 0 - n = len(x) - stack: List[Union[List, Dict]] = [] - obj: Any = nothing - key = False - keys = [] - while i < n: - c = x[i] - if c == '{': - obj = {} - stack.append(obj) - key = True - keys.append(nothing) - i += 1 - elif c == '[': - obj = [] - stack.append(obj) - key = False - keys.append(nothing) - i += 1 - elif c in '}]': - if key: - if keys[-1] is not nothing: - raise ValueError("unfinished dict") - # empty dict - key = False - oldobj = stack.pop() - keys.pop() - if stack: - obj = stack[-1] - if isinstance(obj, dict): - if keys[-1] is nothing: - raise ValueError("invalid key object", oldobj) - obj[keys[-1]] = oldobj - else: - obj.append(oldobj) - else: - break - i += 1 - elif c == ',': - if key: - raise ValueError("multiple keys") - if isinstance(obj, dict): - key = True - i += 1 - elif c == ':': - if not isinstance(obj, dict): - raise ValueError("colon in list") - i += 1 - if not key: - raise ValueError("multiple values") - key = False - else: - y: Any = None - m = _str_re.match(x, i) - if m: - y = decode_string(m.group()[1:-1]) - else: - m = _int_re.match(x, i) - if m: - y = int(m.group()) - else: - m = _name_re.match(x, i) - if m: - y = m.group() - if y == 'true': - y = True - elif y == 'false': - y = False - elif y == 'null': - y = None - elif not key: - raise ValueError("bareword as value") - else: - raise ValueError("read error at pos %d" % i) - i = m.end() - if isinstance(obj, dict): - if key: - keys[-1] = y - else: - obj[keys[-1]] = y - key = False - else: - obj.append(y) - if obj is nothing: - raise ValueError("nothing loaded from string") - return obj - - -def load(f: IO) -> Any: - return loads(f.read()) +"""This module implements a simple JavaScript serializer.""" +import json + +from sphinx.deprecation import RemovedInSphinx60Warning, deprecated_alias + +deprecated_alias( + 'sphinx.util.jsdump', + { + 'dumps': lambda o, _key: json.dumps(o), + 'dump': json.dump, + 'loads': json.loads, + 'load': json.load, + }, + RemovedInSphinx60Warning, + { + 'dumps': 'json.dumps', + 'dump': 'json.dump', + 'loads': 'json.loads', + 'load': 'json.load', + } +) |