Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
decoder.py365 linesDownload Raw Back to json
1"""Implementation of JSONDecoder2"""3import re4 5from json import scanner6try:7    from _json import scanstring as c_scanstring8except ImportError:9    c_scanstring = None10 11__all__ = ['JSONDecoder', 'JSONDecodeError']12 13FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL14 15NaN = float('nan')16PosInf = float('inf')17NegInf = float('-inf')18 19 20class JSONDecodeError(ValueError):21    """Subclass of ValueError with the following additional properties:22 23    msg: The unformatted error message24    doc: The JSON document being parsed25    pos: The start index of doc where parsing failed26    lineno: The line corresponding to pos27    colno: The column corresponding to pos28 29    """30    # Note that this exception is used from _json31    def __init__(self, msg, doc, pos):32        lineno = doc.count('\n', 0, pos) + 133        colno = pos - doc.rfind('\n', 0, pos)34        errmsg = '%s: line %d column %d (char %d)' % (msg, lineno, colno, pos)35        ValueError.__init__(self, errmsg)36        self.msg = msg37        self.doc = doc38        self.pos = pos39        self.lineno = lineno40        self.colno = colno41 42    def __reduce__(self):43        return self.__class__, (self.msg, self.doc, self.pos)44 45 46_CONSTANTS = {47    '-Infinity': NegInf,48    'Infinity': PosInf,49    'NaN': NaN,50}51 52 53HEXDIGITS = re.compile(r'[0-9A-Fa-f]{4}', FLAGS)54STRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS)55BACKSLASH = {56    '"': '"', '\\': '\\', '/': '/',57    'b': '\b', 'f': '\f', 'n': '\n', 'r': '\r', 't': '\t',58}59 60def _decode_uXXXX(s, pos, _m=HEXDIGITS.match):61    esc = _m(s, pos + 1)62    if esc is not None:63        try:64            return int(esc.group(), 16)65        except ValueError:66            pass67    msg = "Invalid \\uXXXX escape"68    raise JSONDecodeError(msg, s, pos)69 70def py_scanstring(s, end, strict=True,71        _b=BACKSLASH, _m=STRINGCHUNK.match):72    """Scan the string s for a JSON string. End is the index of the73    character in s after the quote that started the JSON string.74    Unescapes all valid JSON string escape sequences and raises ValueError75    on attempt to decode an invalid string. If strict is False then literal76    control characters are allowed in the string.77 78    Returns a tuple of the decoded string and the index of the character in s79    after the end quote."""80    chunks = []81    _append = chunks.append82    begin = end - 183    while 1:84        chunk = _m(s, end)85        if chunk is None:86            raise JSONDecodeError("Unterminated string starting at", s, begin)87        end = chunk.end()88        content, terminator = chunk.groups()89        # Content is contains zero or more unescaped string characters90        if content:91            _append(content)92        # Terminator is the end of string, a literal control character,93        # or a backslash denoting that an escape sequence follows94        if terminator == '"':95            break96        elif terminator != '\\':97            if strict:98                #msg = "Invalid control character %r at" % (terminator,)99                msg = "Invalid control character {0!r} at".format(terminator)100                raise JSONDecodeError(msg, s, end)101            else:102                _append(terminator)103                continue104        try:105            esc = s[end]106        except IndexError:107            raise JSONDecodeError("Unterminated string starting at",108                                  s, begin) from None109        # If not a unicode escape sequence, must be in the lookup table110        if esc != 'u':111            try:112                char = _b[esc]113            except KeyError:114                msg = "Invalid \\escape: {0!r}".format(esc)115                raise JSONDecodeError(msg, s, end)116            end += 1117        else:118            uni = _decode_uXXXX(s, end)119            end += 5120            if 0xd800 <= uni <= 0xdbff and s[end:end + 2] == '\\u':121                uni2 = _decode_uXXXX(s, end + 1)122                if 0xdc00 <= uni2 <= 0xdfff:123                    uni = 0x10000 + (((uni - 0xd800) << 10) | (uni2 - 0xdc00))124                    end += 6125            char = chr(uni)126        _append(char)127    return ''.join(chunks), end128 129 130# Use speedup if available131scanstring = c_scanstring or py_scanstring132 133WHITESPACE = re.compile(r'[ \t\n\r]*', FLAGS)134WHITESPACE_STR = ' \t\n\r'135 136 137def JSONObject(s_and_end, strict, scan_once, object_hook, object_pairs_hook,138               memo=None, _w=WHITESPACE.match, _ws=WHITESPACE_STR):139    s, end = s_and_end140    pairs = []141    pairs_append = pairs.append142    # Backwards compatibility143    if memo is None:144        memo = {}145    memo_get = memo.setdefault146    # Use a slice to prevent IndexError from being raised, the following147    # check will raise a more specific ValueError if the string is empty148    nextchar = s[end:end + 1]149    # Normally we expect nextchar == '"'150    if nextchar != '"':151        if nextchar in _ws:152            end = _w(s, end).end()153            nextchar = s[end:end + 1]154        # Trivial empty object155        if nextchar == '}':156            if object_pairs_hook is not None:157                result = object_pairs_hook(pairs)158                return result, end + 1159            pairs = {}160            if object_hook is not None:161                pairs = object_hook(pairs)162            return pairs, end + 1163        elif nextchar != '"':164            raise JSONDecodeError(165                "Expecting property name enclosed in double quotes", s, end)166    end += 1167    while True:168        key, end = scanstring(s, end, strict)169        key = memo_get(key, key)170        # To skip some function call overhead we optimize the fast paths where171        # the JSON key separator is ": " or just ":".172        if s[end:end + 1] != ':':173            end = _w(s, end).end()174            if s[end:end + 1] != ':':175                raise JSONDecodeError("Expecting ':' delimiter", s, end)176        end += 1177 178        try:179            if s[end] in _ws:180                end += 1181                if s[end] in _ws:182                    end = _w(s, end + 1).end()183        except IndexError:184            pass185 186        try:187            value, end = scan_once(s, end)188        except StopIteration as err:189            raise JSONDecodeError("Expecting value", s, err.value) from None190        pairs_append((key, value))191        try:192            nextchar = s[end]193            if nextchar in _ws:194                end = _w(s, end + 1).end()195                nextchar = s[end]196        except IndexError:197            nextchar = ''198        end += 1199 200        if nextchar == '}':201            break202        elif nextchar != ',':203            raise JSONDecodeError("Expecting ',' delimiter", s, end - 1)204        comma_idx = end - 1205        end = _w(s, end).end()206        nextchar = s[end:end + 1]207        end += 1208        if nextchar != '"':209            if nextchar == '}':210                raise JSONDecodeError("Illegal trailing comma before end of object", s, comma_idx)211            raise JSONDecodeError(212                "Expecting property name enclosed in double quotes", s, end - 1)213    if object_pairs_hook is not None:214        result = object_pairs_hook(pairs)215        return result, end216    pairs = dict(pairs)217    if object_hook is not None:218        pairs = object_hook(pairs)219    return pairs, end220 221def JSONArray(s_and_end, scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR):222    s, end = s_and_end223    values = []224    nextchar = s[end:end + 1]225    if nextchar in _ws:226        end = _w(s, end + 1).end()227        nextchar = s[end:end + 1]228    # Look-ahead for trivial empty array229    if nextchar == ']':230        return values, end + 1231    _append = values.append232    while True:233        try:234            value, end = scan_once(s, end)235        except StopIteration as err:236            raise JSONDecodeError("Expecting value", s, err.value) from None237        _append(value)238        nextchar = s[end:end + 1]239        if nextchar in _ws:240            end = _w(s, end + 1).end()241            nextchar = s[end:end + 1]242        end += 1243        if nextchar == ']':244            break245        elif nextchar != ',':246            raise JSONDecodeError("Expecting ',' delimiter", s, end - 1)247        comma_idx = end - 1248        try:249            if s[end] in _ws:250                end += 1251                if s[end] in _ws:252                    end = _w(s, end + 1).end()253            nextchar = s[end:end + 1]254        except IndexError:255            pass256        if nextchar == ']':257            raise JSONDecodeError("Illegal trailing comma before end of array", s, comma_idx)258 259    return values, end260 261 262class JSONDecoder(object):263    """Simple JSON <https://json.org> decoder264 265    Performs the following translations in decoding by default:266 267    +---------------+-------------------+268    | JSON          | Python            |269    +===============+===================+270    | object        | dict              |271    +---------------+-------------------+272    | array         | list              |273    +---------------+-------------------+274    | string        | str               |275    +---------------+-------------------+276    | number (int)  | int               |277    +---------------+-------------------+278    | number (real) | float             |279    +---------------+-------------------+280    | true          | True              |281    +---------------+-------------------+282    | false         | False             |283    +---------------+-------------------+284    | null          | None              |285    +---------------+-------------------+286 287    It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as288    their corresponding ``float`` values, which is outside the JSON spec.289 290    """291 292    def __init__(self, *, object_hook=None, parse_float=None,293            parse_int=None, parse_constant=None, strict=True,294            object_pairs_hook=None):295        """``object_hook``, if specified, will be called with the result296        of every JSON object decoded and its return value will be used in297        place of the given ``dict``.  This can be used to provide custom298        deserializations (e.g. to support JSON-RPC class hinting).299 300        ``object_pairs_hook``, if specified will be called with the result301        of every JSON object decoded with an ordered list of pairs.  The302        return value of ``object_pairs_hook`` will be used instead of the303        ``dict``.  This feature can be used to implement custom decoders.304        If ``object_hook`` is also defined, the ``object_pairs_hook`` takes305        priority.306 307        ``parse_float``, if specified, will be called with the string308        of every JSON float to be decoded. By default this is equivalent to309        float(num_str). This can be used to use another datatype or parser310        for JSON floats (e.g. decimal.Decimal).311 312        ``parse_int``, if specified, will be called with the string313        of every JSON int to be decoded. By default this is equivalent to314        int(num_str). This can be used to use another datatype or parser315        for JSON integers (e.g. float).316 317        ``parse_constant``, if specified, will be called with one of the318        following strings: -Infinity, Infinity, NaN.319        This can be used to raise an exception if invalid JSON numbers320        are encountered.321 322        If ``strict`` is false (true is the default), then control323        characters will be allowed inside strings.  Control characters in324        this context are those with character codes in the 0-31 range,325        including ``'\\t'`` (tab), ``'\\n'``, ``'\\r'`` and ``'\\0'``.326        """327        self.object_hook = object_hook328        self.parse_float = parse_float or float329        self.parse_int = parse_int or int330        self.parse_constant = parse_constant or _CONSTANTS.__getitem__331        self.strict = strict332        self.object_pairs_hook = object_pairs_hook333        self.parse_object = JSONObject334        self.parse_array = JSONArray335        self.parse_string = scanstring336        self.memo = {}337        self.scan_once = scanner.make_scanner(self)338 339 340    def decode(self, s, _w=WHITESPACE.match):341        """Return the Python representation of ``s`` (a ``str`` instance342        containing a JSON document).343 344        """345        obj, end = self.raw_decode(s, idx=_w(s, 0).end())346        end = _w(s, end).end()347        if end != len(s):348            raise JSONDecodeError("Extra data", s, end)349        return obj350 351    def raw_decode(self, s, idx=0):352        """Decode a JSON document from ``s`` (a ``str`` beginning with353        a JSON document) and return a 2-tuple of the Python354        representation and the index in ``s`` where the document ended.355 356        This can be used to decode a JSON document from a string that may357        have extraneous data at the end.358 359        """360        try:361            obj, end = self.scan_once(s, idx)362        except StopIteration as err:363            raise JSONDecodeError("Expecting value", s, err.value) from None364        return obj, end365 
codekingpro/portable-devtools · Team Ai