mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Remove support for the `jsdump format in sphinx.search` (#11365)
This commit is contained in:
1
CHANGES
1
CHANGES
@@ -14,6 +14,7 @@ Incompatible changes
|
||||
* #11363: Remove the Setuptools integration (``build_sphinx`` hook in
|
||||
``setup.py``).
|
||||
* #11364: Remove deprecated ``sphinx.ext.napoleon.iterators`` module.
|
||||
* #11365: Remove support for the ``jsdump`` format in ``sphinx.search``.
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
@@ -7,7 +7,6 @@ import html
|
||||
import json
|
||||
import pickle
|
||||
import re
|
||||
import warnings
|
||||
from importlib import import_module
|
||||
from os import path
|
||||
from typing import (
|
||||
@@ -31,7 +30,6 @@ from docutils import nodes
|
||||
from docutils.nodes import Element, Node
|
||||
|
||||
from sphinx import addnodes, package_dir
|
||||
from sphinx.deprecation import RemovedInSphinx70Warning
|
||||
from sphinx.environment import BuildEnvironment
|
||||
from sphinx.util import split_into
|
||||
|
||||
@@ -308,11 +306,7 @@ class IndexBuilder:
|
||||
|
||||
def load(self, stream: IO, format: Any) -> None:
|
||||
"""Reconstruct from frozen data."""
|
||||
if format == "jsdump":
|
||||
warnings.warn("format=jsdump is deprecated, use json instead",
|
||||
RemovedInSphinx70Warning, stacklevel=2)
|
||||
format = self.formats["json"]
|
||||
elif isinstance(format, str):
|
||||
if isinstance(format, str):
|
||||
format = self.formats[format]
|
||||
frozen = format.load(stream)
|
||||
# if an old index is present, we treat it as not existing.
|
||||
@@ -345,11 +339,7 @@ class IndexBuilder:
|
||||
|
||||
def dump(self, stream: IO, format: Any) -> None:
|
||||
"""Dump the frozen index to a stream."""
|
||||
if format == "jsdump":
|
||||
warnings.warn("format=jsdump is deprecated, use json instead",
|
||||
RemovedInSphinx70Warning, stacklevel=2)
|
||||
format = self.formats["json"]
|
||||
elif isinstance(format, str):
|
||||
if isinstance(format, str):
|
||||
format = self.formats[format]
|
||||
format.dump(self.freeze(), stream)
|
||||
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
"""This module implements a simple JavaScript serializer.
|
||||
|
||||
Uses the basestring encode function from simplejson by Bob Ippolito.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import warnings
|
||||
from typing import IO, Any
|
||||
|
||||
from sphinx.deprecation import RemovedInSphinx70Warning
|
||||
|
||||
warnings.warn('"sphinx.util.jsdump" has been deprecated. Please use "json" instead.',
|
||||
RemovedInSphinx70Warning)
|
||||
|
||||
_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: re.Match) -> str:
|
||||
s = match.group(0)
|
||||
try:
|
||||
return ESCAPE_DICT[s]
|
||||
except KeyError:
|
||||
n = ord(s)
|
||||
if n < 0x10000:
|
||||
return f'\\u{n:04x}'
|
||||
else:
|
||||
# surrogate pair
|
||||
n -= 0x10000
|
||||
s1 = 0xd800 | ((n >> 10) & 0x3ff)
|
||||
s2 = 0xdc00 | (n & 0x3ff)
|
||||
return f'\\u{s1:04x}\\u{s2:04x}'
|
||||
return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"'
|
||||
|
||||
|
||||
def decode_string(s: str) -> str:
|
||||
return ESCAPED.sub(lambda m: eval('"' + m.group() + '"'), s) # NoQA: PGH001
|
||||
|
||||
|
||||
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(f'{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[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())
|
||||
Reference in New Issue
Block a user