17db96d56Sopenharmony_ci"""Implementation of JSONEncoder
27db96d56Sopenharmony_ci"""
37db96d56Sopenharmony_ciimport re
47db96d56Sopenharmony_ci
57db96d56Sopenharmony_citry:
67db96d56Sopenharmony_ci    from _json import encode_basestring_ascii as c_encode_basestring_ascii
77db96d56Sopenharmony_ciexcept ImportError:
87db96d56Sopenharmony_ci    c_encode_basestring_ascii = None
97db96d56Sopenharmony_citry:
107db96d56Sopenharmony_ci    from _json import encode_basestring as c_encode_basestring
117db96d56Sopenharmony_ciexcept ImportError:
127db96d56Sopenharmony_ci    c_encode_basestring = None
137db96d56Sopenharmony_citry:
147db96d56Sopenharmony_ci    from _json import make_encoder as c_make_encoder
157db96d56Sopenharmony_ciexcept ImportError:
167db96d56Sopenharmony_ci    c_make_encoder = None
177db96d56Sopenharmony_ci
187db96d56Sopenharmony_ciESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]')
197db96d56Sopenharmony_ciESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')
207db96d56Sopenharmony_ciHAS_UTF8 = re.compile(b'[\x80-\xff]')
217db96d56Sopenharmony_ciESCAPE_DCT = {
227db96d56Sopenharmony_ci    '\\': '\\\\',
237db96d56Sopenharmony_ci    '"': '\\"',
247db96d56Sopenharmony_ci    '\b': '\\b',
257db96d56Sopenharmony_ci    '\f': '\\f',
267db96d56Sopenharmony_ci    '\n': '\\n',
277db96d56Sopenharmony_ci    '\r': '\\r',
287db96d56Sopenharmony_ci    '\t': '\\t',
297db96d56Sopenharmony_ci}
307db96d56Sopenharmony_cifor i in range(0x20):
317db96d56Sopenharmony_ci    ESCAPE_DCT.setdefault(chr(i), '\\u{0:04x}'.format(i))
327db96d56Sopenharmony_ci    #ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,))
337db96d56Sopenharmony_cidel i
347db96d56Sopenharmony_ci
357db96d56Sopenharmony_ciINFINITY = float('inf')
367db96d56Sopenharmony_ci
377db96d56Sopenharmony_cidef py_encode_basestring(s):
387db96d56Sopenharmony_ci    """Return a JSON representation of a Python string
397db96d56Sopenharmony_ci
407db96d56Sopenharmony_ci    """
417db96d56Sopenharmony_ci    def replace(match):
427db96d56Sopenharmony_ci        return ESCAPE_DCT[match.group(0)]
437db96d56Sopenharmony_ci    return '"' + ESCAPE.sub(replace, s) + '"'
447db96d56Sopenharmony_ci
457db96d56Sopenharmony_ci
467db96d56Sopenharmony_ciencode_basestring = (c_encode_basestring or py_encode_basestring)
477db96d56Sopenharmony_ci
487db96d56Sopenharmony_ci
497db96d56Sopenharmony_cidef py_encode_basestring_ascii(s):
507db96d56Sopenharmony_ci    """Return an ASCII-only JSON representation of a Python string
517db96d56Sopenharmony_ci
527db96d56Sopenharmony_ci    """
537db96d56Sopenharmony_ci    def replace(match):
547db96d56Sopenharmony_ci        s = match.group(0)
557db96d56Sopenharmony_ci        try:
567db96d56Sopenharmony_ci            return ESCAPE_DCT[s]
577db96d56Sopenharmony_ci        except KeyError:
587db96d56Sopenharmony_ci            n = ord(s)
597db96d56Sopenharmony_ci            if n < 0x10000:
607db96d56Sopenharmony_ci                return '\\u{0:04x}'.format(n)
617db96d56Sopenharmony_ci                #return '\\u%04x' % (n,)
627db96d56Sopenharmony_ci            else:
637db96d56Sopenharmony_ci                # surrogate pair
647db96d56Sopenharmony_ci                n -= 0x10000
657db96d56Sopenharmony_ci                s1 = 0xd800 | ((n >> 10) & 0x3ff)
667db96d56Sopenharmony_ci                s2 = 0xdc00 | (n & 0x3ff)
677db96d56Sopenharmony_ci                return '\\u{0:04x}\\u{1:04x}'.format(s1, s2)
687db96d56Sopenharmony_ci    return '"' + ESCAPE_ASCII.sub(replace, s) + '"'
697db96d56Sopenharmony_ci
707db96d56Sopenharmony_ci
717db96d56Sopenharmony_ciencode_basestring_ascii = (
727db96d56Sopenharmony_ci    c_encode_basestring_ascii or py_encode_basestring_ascii)
737db96d56Sopenharmony_ci
747db96d56Sopenharmony_ciclass JSONEncoder(object):
757db96d56Sopenharmony_ci    """Extensible JSON <https://json.org> encoder for Python data structures.
767db96d56Sopenharmony_ci
777db96d56Sopenharmony_ci    Supports the following objects and types by default:
787db96d56Sopenharmony_ci
797db96d56Sopenharmony_ci    +-------------------+---------------+
807db96d56Sopenharmony_ci    | Python            | JSON          |
817db96d56Sopenharmony_ci    +===================+===============+
827db96d56Sopenharmony_ci    | dict              | object        |
837db96d56Sopenharmony_ci    +-------------------+---------------+
847db96d56Sopenharmony_ci    | list, tuple       | array         |
857db96d56Sopenharmony_ci    +-------------------+---------------+
867db96d56Sopenharmony_ci    | str               | string        |
877db96d56Sopenharmony_ci    +-------------------+---------------+
887db96d56Sopenharmony_ci    | int, float        | number        |
897db96d56Sopenharmony_ci    +-------------------+---------------+
907db96d56Sopenharmony_ci    | True              | true          |
917db96d56Sopenharmony_ci    +-------------------+---------------+
927db96d56Sopenharmony_ci    | False             | false         |
937db96d56Sopenharmony_ci    +-------------------+---------------+
947db96d56Sopenharmony_ci    | None              | null          |
957db96d56Sopenharmony_ci    +-------------------+---------------+
967db96d56Sopenharmony_ci
977db96d56Sopenharmony_ci    To extend this to recognize other objects, subclass and implement a
987db96d56Sopenharmony_ci    ``.default()`` method with another method that returns a serializable
997db96d56Sopenharmony_ci    object for ``o`` if possible, otherwise it should call the superclass
1007db96d56Sopenharmony_ci    implementation (to raise ``TypeError``).
1017db96d56Sopenharmony_ci
1027db96d56Sopenharmony_ci    """
1037db96d56Sopenharmony_ci    item_separator = ', '
1047db96d56Sopenharmony_ci    key_separator = ': '
1057db96d56Sopenharmony_ci    def __init__(self, *, skipkeys=False, ensure_ascii=True,
1067db96d56Sopenharmony_ci            check_circular=True, allow_nan=True, sort_keys=False,
1077db96d56Sopenharmony_ci            indent=None, separators=None, default=None):
1087db96d56Sopenharmony_ci        """Constructor for JSONEncoder, with sensible defaults.
1097db96d56Sopenharmony_ci
1107db96d56Sopenharmony_ci        If skipkeys is false, then it is a TypeError to attempt
1117db96d56Sopenharmony_ci        encoding of keys that are not str, int, float or None.  If
1127db96d56Sopenharmony_ci        skipkeys is True, such items are simply skipped.
1137db96d56Sopenharmony_ci
1147db96d56Sopenharmony_ci        If ensure_ascii is true, the output is guaranteed to be str
1157db96d56Sopenharmony_ci        objects with all incoming non-ASCII characters escaped.  If
1167db96d56Sopenharmony_ci        ensure_ascii is false, the output can contain non-ASCII characters.
1177db96d56Sopenharmony_ci
1187db96d56Sopenharmony_ci        If check_circular is true, then lists, dicts, and custom encoded
1197db96d56Sopenharmony_ci        objects will be checked for circular references during encoding to
1207db96d56Sopenharmony_ci        prevent an infinite recursion (which would cause an RecursionError).
1217db96d56Sopenharmony_ci        Otherwise, no such check takes place.
1227db96d56Sopenharmony_ci
1237db96d56Sopenharmony_ci        If allow_nan is true, then NaN, Infinity, and -Infinity will be
1247db96d56Sopenharmony_ci        encoded as such.  This behavior is not JSON specification compliant,
1257db96d56Sopenharmony_ci        but is consistent with most JavaScript based encoders and decoders.
1267db96d56Sopenharmony_ci        Otherwise, it will be a ValueError to encode such floats.
1277db96d56Sopenharmony_ci
1287db96d56Sopenharmony_ci        If sort_keys is true, then the output of dictionaries will be
1297db96d56Sopenharmony_ci        sorted by key; this is useful for regression tests to ensure
1307db96d56Sopenharmony_ci        that JSON serializations can be compared on a day-to-day basis.
1317db96d56Sopenharmony_ci
1327db96d56Sopenharmony_ci        If indent is a non-negative integer, then JSON array
1337db96d56Sopenharmony_ci        elements and object members will be pretty-printed with that
1347db96d56Sopenharmony_ci        indent level.  An indent level of 0 will only insert newlines.
1357db96d56Sopenharmony_ci        None is the most compact representation.
1367db96d56Sopenharmony_ci
1377db96d56Sopenharmony_ci        If specified, separators should be an (item_separator, key_separator)
1387db96d56Sopenharmony_ci        tuple.  The default is (', ', ': ') if *indent* is ``None`` and
1397db96d56Sopenharmony_ci        (',', ': ') otherwise.  To get the most compact JSON representation,
1407db96d56Sopenharmony_ci        you should specify (',', ':') to eliminate whitespace.
1417db96d56Sopenharmony_ci
1427db96d56Sopenharmony_ci        If specified, default is a function that gets called for objects
1437db96d56Sopenharmony_ci        that can't otherwise be serialized.  It should return a JSON encodable
1447db96d56Sopenharmony_ci        version of the object or raise a ``TypeError``.
1457db96d56Sopenharmony_ci
1467db96d56Sopenharmony_ci        """
1477db96d56Sopenharmony_ci
1487db96d56Sopenharmony_ci        self.skipkeys = skipkeys
1497db96d56Sopenharmony_ci        self.ensure_ascii = ensure_ascii
1507db96d56Sopenharmony_ci        self.check_circular = check_circular
1517db96d56Sopenharmony_ci        self.allow_nan = allow_nan
1527db96d56Sopenharmony_ci        self.sort_keys = sort_keys
1537db96d56Sopenharmony_ci        self.indent = indent
1547db96d56Sopenharmony_ci        if separators is not None:
1557db96d56Sopenharmony_ci            self.item_separator, self.key_separator = separators
1567db96d56Sopenharmony_ci        elif indent is not None:
1577db96d56Sopenharmony_ci            self.item_separator = ','
1587db96d56Sopenharmony_ci        if default is not None:
1597db96d56Sopenharmony_ci            self.default = default
1607db96d56Sopenharmony_ci
1617db96d56Sopenharmony_ci    def default(self, o):
1627db96d56Sopenharmony_ci        """Implement this method in a subclass such that it returns
1637db96d56Sopenharmony_ci        a serializable object for ``o``, or calls the base implementation
1647db96d56Sopenharmony_ci        (to raise a ``TypeError``).
1657db96d56Sopenharmony_ci
1667db96d56Sopenharmony_ci        For example, to support arbitrary iterators, you could
1677db96d56Sopenharmony_ci        implement default like this::
1687db96d56Sopenharmony_ci
1697db96d56Sopenharmony_ci            def default(self, o):
1707db96d56Sopenharmony_ci                try:
1717db96d56Sopenharmony_ci                    iterable = iter(o)
1727db96d56Sopenharmony_ci                except TypeError:
1737db96d56Sopenharmony_ci                    pass
1747db96d56Sopenharmony_ci                else:
1757db96d56Sopenharmony_ci                    return list(iterable)
1767db96d56Sopenharmony_ci                # Let the base class default method raise the TypeError
1777db96d56Sopenharmony_ci                return JSONEncoder.default(self, o)
1787db96d56Sopenharmony_ci
1797db96d56Sopenharmony_ci        """
1807db96d56Sopenharmony_ci        raise TypeError(f'Object of type {o.__class__.__name__} '
1817db96d56Sopenharmony_ci                        f'is not JSON serializable')
1827db96d56Sopenharmony_ci
1837db96d56Sopenharmony_ci    def encode(self, o):
1847db96d56Sopenharmony_ci        """Return a JSON string representation of a Python data structure.
1857db96d56Sopenharmony_ci
1867db96d56Sopenharmony_ci        >>> from json.encoder import JSONEncoder
1877db96d56Sopenharmony_ci        >>> JSONEncoder().encode({"foo": ["bar", "baz"]})
1887db96d56Sopenharmony_ci        '{"foo": ["bar", "baz"]}'
1897db96d56Sopenharmony_ci
1907db96d56Sopenharmony_ci        """
1917db96d56Sopenharmony_ci        # This is for extremely simple cases and benchmarks.
1927db96d56Sopenharmony_ci        if isinstance(o, str):
1937db96d56Sopenharmony_ci            if self.ensure_ascii:
1947db96d56Sopenharmony_ci                return encode_basestring_ascii(o)
1957db96d56Sopenharmony_ci            else:
1967db96d56Sopenharmony_ci                return encode_basestring(o)
1977db96d56Sopenharmony_ci        # This doesn't pass the iterator directly to ''.join() because the
1987db96d56Sopenharmony_ci        # exceptions aren't as detailed.  The list call should be roughly
1997db96d56Sopenharmony_ci        # equivalent to the PySequence_Fast that ''.join() would do.
2007db96d56Sopenharmony_ci        chunks = self.iterencode(o, _one_shot=True)
2017db96d56Sopenharmony_ci        if not isinstance(chunks, (list, tuple)):
2027db96d56Sopenharmony_ci            chunks = list(chunks)
2037db96d56Sopenharmony_ci        return ''.join(chunks)
2047db96d56Sopenharmony_ci
2057db96d56Sopenharmony_ci    def iterencode(self, o, _one_shot=False):
2067db96d56Sopenharmony_ci        """Encode the given object and yield each string
2077db96d56Sopenharmony_ci        representation as available.
2087db96d56Sopenharmony_ci
2097db96d56Sopenharmony_ci        For example::
2107db96d56Sopenharmony_ci
2117db96d56Sopenharmony_ci            for chunk in JSONEncoder().iterencode(bigobject):
2127db96d56Sopenharmony_ci                mysocket.write(chunk)
2137db96d56Sopenharmony_ci
2147db96d56Sopenharmony_ci        """
2157db96d56Sopenharmony_ci        if self.check_circular:
2167db96d56Sopenharmony_ci            markers = {}
2177db96d56Sopenharmony_ci        else:
2187db96d56Sopenharmony_ci            markers = None
2197db96d56Sopenharmony_ci        if self.ensure_ascii:
2207db96d56Sopenharmony_ci            _encoder = encode_basestring_ascii
2217db96d56Sopenharmony_ci        else:
2227db96d56Sopenharmony_ci            _encoder = encode_basestring
2237db96d56Sopenharmony_ci
2247db96d56Sopenharmony_ci        def floatstr(o, allow_nan=self.allow_nan,
2257db96d56Sopenharmony_ci                _repr=float.__repr__, _inf=INFINITY, _neginf=-INFINITY):
2267db96d56Sopenharmony_ci            # Check for specials.  Note that this type of test is processor
2277db96d56Sopenharmony_ci            # and/or platform-specific, so do tests which don't depend on the
2287db96d56Sopenharmony_ci            # internals.
2297db96d56Sopenharmony_ci
2307db96d56Sopenharmony_ci            if o != o:
2317db96d56Sopenharmony_ci                text = 'NaN'
2327db96d56Sopenharmony_ci            elif o == _inf:
2337db96d56Sopenharmony_ci                text = 'Infinity'
2347db96d56Sopenharmony_ci            elif o == _neginf:
2357db96d56Sopenharmony_ci                text = '-Infinity'
2367db96d56Sopenharmony_ci            else:
2377db96d56Sopenharmony_ci                return _repr(o)
2387db96d56Sopenharmony_ci
2397db96d56Sopenharmony_ci            if not allow_nan:
2407db96d56Sopenharmony_ci                raise ValueError(
2417db96d56Sopenharmony_ci                    "Out of range float values are not JSON compliant: " +
2427db96d56Sopenharmony_ci                    repr(o))
2437db96d56Sopenharmony_ci
2447db96d56Sopenharmony_ci            return text
2457db96d56Sopenharmony_ci
2467db96d56Sopenharmony_ci
2477db96d56Sopenharmony_ci        if (_one_shot and c_make_encoder is not None
2487db96d56Sopenharmony_ci                and self.indent is None):
2497db96d56Sopenharmony_ci            _iterencode = c_make_encoder(
2507db96d56Sopenharmony_ci                markers, self.default, _encoder, self.indent,
2517db96d56Sopenharmony_ci                self.key_separator, self.item_separator, self.sort_keys,
2527db96d56Sopenharmony_ci                self.skipkeys, self.allow_nan)
2537db96d56Sopenharmony_ci        else:
2547db96d56Sopenharmony_ci            _iterencode = _make_iterencode(
2557db96d56Sopenharmony_ci                markers, self.default, _encoder, self.indent, floatstr,
2567db96d56Sopenharmony_ci                self.key_separator, self.item_separator, self.sort_keys,
2577db96d56Sopenharmony_ci                self.skipkeys, _one_shot)
2587db96d56Sopenharmony_ci        return _iterencode(o, 0)
2597db96d56Sopenharmony_ci
2607db96d56Sopenharmony_cidef _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
2617db96d56Sopenharmony_ci        _key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot,
2627db96d56Sopenharmony_ci        ## HACK: hand-optimized bytecode; turn globals into locals
2637db96d56Sopenharmony_ci        ValueError=ValueError,
2647db96d56Sopenharmony_ci        dict=dict,
2657db96d56Sopenharmony_ci        float=float,
2667db96d56Sopenharmony_ci        id=id,
2677db96d56Sopenharmony_ci        int=int,
2687db96d56Sopenharmony_ci        isinstance=isinstance,
2697db96d56Sopenharmony_ci        list=list,
2707db96d56Sopenharmony_ci        str=str,
2717db96d56Sopenharmony_ci        tuple=tuple,
2727db96d56Sopenharmony_ci        _intstr=int.__repr__,
2737db96d56Sopenharmony_ci    ):
2747db96d56Sopenharmony_ci
2757db96d56Sopenharmony_ci    if _indent is not None and not isinstance(_indent, str):
2767db96d56Sopenharmony_ci        _indent = ' ' * _indent
2777db96d56Sopenharmony_ci
2787db96d56Sopenharmony_ci    def _iterencode_list(lst, _current_indent_level):
2797db96d56Sopenharmony_ci        if not lst:
2807db96d56Sopenharmony_ci            yield '[]'
2817db96d56Sopenharmony_ci            return
2827db96d56Sopenharmony_ci        if markers is not None:
2837db96d56Sopenharmony_ci            markerid = id(lst)
2847db96d56Sopenharmony_ci            if markerid in markers:
2857db96d56Sopenharmony_ci                raise ValueError("Circular reference detected")
2867db96d56Sopenharmony_ci            markers[markerid] = lst
2877db96d56Sopenharmony_ci        buf = '['
2887db96d56Sopenharmony_ci        if _indent is not None:
2897db96d56Sopenharmony_ci            _current_indent_level += 1
2907db96d56Sopenharmony_ci            newline_indent = '\n' + _indent * _current_indent_level
2917db96d56Sopenharmony_ci            separator = _item_separator + newline_indent
2927db96d56Sopenharmony_ci            buf += newline_indent
2937db96d56Sopenharmony_ci        else:
2947db96d56Sopenharmony_ci            newline_indent = None
2957db96d56Sopenharmony_ci            separator = _item_separator
2967db96d56Sopenharmony_ci        first = True
2977db96d56Sopenharmony_ci        for value in lst:
2987db96d56Sopenharmony_ci            if first:
2997db96d56Sopenharmony_ci                first = False
3007db96d56Sopenharmony_ci            else:
3017db96d56Sopenharmony_ci                buf = separator
3027db96d56Sopenharmony_ci            if isinstance(value, str):
3037db96d56Sopenharmony_ci                yield buf + _encoder(value)
3047db96d56Sopenharmony_ci            elif value is None:
3057db96d56Sopenharmony_ci                yield buf + 'null'
3067db96d56Sopenharmony_ci            elif value is True:
3077db96d56Sopenharmony_ci                yield buf + 'true'
3087db96d56Sopenharmony_ci            elif value is False:
3097db96d56Sopenharmony_ci                yield buf + 'false'
3107db96d56Sopenharmony_ci            elif isinstance(value, int):
3117db96d56Sopenharmony_ci                # Subclasses of int/float may override __repr__, but we still
3127db96d56Sopenharmony_ci                # want to encode them as integers/floats in JSON. One example
3137db96d56Sopenharmony_ci                # within the standard library is IntEnum.
3147db96d56Sopenharmony_ci                yield buf + _intstr(value)
3157db96d56Sopenharmony_ci            elif isinstance(value, float):
3167db96d56Sopenharmony_ci                # see comment above for int
3177db96d56Sopenharmony_ci                yield buf + _floatstr(value)
3187db96d56Sopenharmony_ci            else:
3197db96d56Sopenharmony_ci                yield buf
3207db96d56Sopenharmony_ci                if isinstance(value, (list, tuple)):
3217db96d56Sopenharmony_ci                    chunks = _iterencode_list(value, _current_indent_level)
3227db96d56Sopenharmony_ci                elif isinstance(value, dict):
3237db96d56Sopenharmony_ci                    chunks = _iterencode_dict(value, _current_indent_level)
3247db96d56Sopenharmony_ci                else:
3257db96d56Sopenharmony_ci                    chunks = _iterencode(value, _current_indent_level)
3267db96d56Sopenharmony_ci                yield from chunks
3277db96d56Sopenharmony_ci        if newline_indent is not None:
3287db96d56Sopenharmony_ci            _current_indent_level -= 1
3297db96d56Sopenharmony_ci            yield '\n' + _indent * _current_indent_level
3307db96d56Sopenharmony_ci        yield ']'
3317db96d56Sopenharmony_ci        if markers is not None:
3327db96d56Sopenharmony_ci            del markers[markerid]
3337db96d56Sopenharmony_ci
3347db96d56Sopenharmony_ci    def _iterencode_dict(dct, _current_indent_level):
3357db96d56Sopenharmony_ci        if not dct:
3367db96d56Sopenharmony_ci            yield '{}'
3377db96d56Sopenharmony_ci            return
3387db96d56Sopenharmony_ci        if markers is not None:
3397db96d56Sopenharmony_ci            markerid = id(dct)
3407db96d56Sopenharmony_ci            if markerid in markers:
3417db96d56Sopenharmony_ci                raise ValueError("Circular reference detected")
3427db96d56Sopenharmony_ci            markers[markerid] = dct
3437db96d56Sopenharmony_ci        yield '{'
3447db96d56Sopenharmony_ci        if _indent is not None:
3457db96d56Sopenharmony_ci            _current_indent_level += 1
3467db96d56Sopenharmony_ci            newline_indent = '\n' + _indent * _current_indent_level
3477db96d56Sopenharmony_ci            item_separator = _item_separator + newline_indent
3487db96d56Sopenharmony_ci            yield newline_indent
3497db96d56Sopenharmony_ci        else:
3507db96d56Sopenharmony_ci            newline_indent = None
3517db96d56Sopenharmony_ci            item_separator = _item_separator
3527db96d56Sopenharmony_ci        first = True
3537db96d56Sopenharmony_ci        if _sort_keys:
3547db96d56Sopenharmony_ci            items = sorted(dct.items())
3557db96d56Sopenharmony_ci        else:
3567db96d56Sopenharmony_ci            items = dct.items()
3577db96d56Sopenharmony_ci        for key, value in items:
3587db96d56Sopenharmony_ci            if isinstance(key, str):
3597db96d56Sopenharmony_ci                pass
3607db96d56Sopenharmony_ci            # JavaScript is weakly typed for these, so it makes sense to
3617db96d56Sopenharmony_ci            # also allow them.  Many encoders seem to do something like this.
3627db96d56Sopenharmony_ci            elif isinstance(key, float):
3637db96d56Sopenharmony_ci                # see comment for int/float in _make_iterencode
3647db96d56Sopenharmony_ci                key = _floatstr(key)
3657db96d56Sopenharmony_ci            elif key is True:
3667db96d56Sopenharmony_ci                key = 'true'
3677db96d56Sopenharmony_ci            elif key is False:
3687db96d56Sopenharmony_ci                key = 'false'
3697db96d56Sopenharmony_ci            elif key is None:
3707db96d56Sopenharmony_ci                key = 'null'
3717db96d56Sopenharmony_ci            elif isinstance(key, int):
3727db96d56Sopenharmony_ci                # see comment for int/float in _make_iterencode
3737db96d56Sopenharmony_ci                key = _intstr(key)
3747db96d56Sopenharmony_ci            elif _skipkeys:
3757db96d56Sopenharmony_ci                continue
3767db96d56Sopenharmony_ci            else:
3777db96d56Sopenharmony_ci                raise TypeError(f'keys must be str, int, float, bool or None, '
3787db96d56Sopenharmony_ci                                f'not {key.__class__.__name__}')
3797db96d56Sopenharmony_ci            if first:
3807db96d56Sopenharmony_ci                first = False
3817db96d56Sopenharmony_ci            else:
3827db96d56Sopenharmony_ci                yield item_separator
3837db96d56Sopenharmony_ci            yield _encoder(key)
3847db96d56Sopenharmony_ci            yield _key_separator
3857db96d56Sopenharmony_ci            if isinstance(value, str):
3867db96d56Sopenharmony_ci                yield _encoder(value)
3877db96d56Sopenharmony_ci            elif value is None:
3887db96d56Sopenharmony_ci                yield 'null'
3897db96d56Sopenharmony_ci            elif value is True:
3907db96d56Sopenharmony_ci                yield 'true'
3917db96d56Sopenharmony_ci            elif value is False:
3927db96d56Sopenharmony_ci                yield 'false'
3937db96d56Sopenharmony_ci            elif isinstance(value, int):
3947db96d56Sopenharmony_ci                # see comment for int/float in _make_iterencode
3957db96d56Sopenharmony_ci                yield _intstr(value)
3967db96d56Sopenharmony_ci            elif isinstance(value, float):
3977db96d56Sopenharmony_ci                # see comment for int/float in _make_iterencode
3987db96d56Sopenharmony_ci                yield _floatstr(value)
3997db96d56Sopenharmony_ci            else:
4007db96d56Sopenharmony_ci                if isinstance(value, (list, tuple)):
4017db96d56Sopenharmony_ci                    chunks = _iterencode_list(value, _current_indent_level)
4027db96d56Sopenharmony_ci                elif isinstance(value, dict):
4037db96d56Sopenharmony_ci                    chunks = _iterencode_dict(value, _current_indent_level)
4047db96d56Sopenharmony_ci                else:
4057db96d56Sopenharmony_ci                    chunks = _iterencode(value, _current_indent_level)
4067db96d56Sopenharmony_ci                yield from chunks
4077db96d56Sopenharmony_ci        if newline_indent is not None:
4087db96d56Sopenharmony_ci            _current_indent_level -= 1
4097db96d56Sopenharmony_ci            yield '\n' + _indent * _current_indent_level
4107db96d56Sopenharmony_ci        yield '}'
4117db96d56Sopenharmony_ci        if markers is not None:
4127db96d56Sopenharmony_ci            del markers[markerid]
4137db96d56Sopenharmony_ci
4147db96d56Sopenharmony_ci    def _iterencode(o, _current_indent_level):
4157db96d56Sopenharmony_ci        if isinstance(o, str):
4167db96d56Sopenharmony_ci            yield _encoder(o)
4177db96d56Sopenharmony_ci        elif o is None:
4187db96d56Sopenharmony_ci            yield 'null'
4197db96d56Sopenharmony_ci        elif o is True:
4207db96d56Sopenharmony_ci            yield 'true'
4217db96d56Sopenharmony_ci        elif o is False:
4227db96d56Sopenharmony_ci            yield 'false'
4237db96d56Sopenharmony_ci        elif isinstance(o, int):
4247db96d56Sopenharmony_ci            # see comment for int/float in _make_iterencode
4257db96d56Sopenharmony_ci            yield _intstr(o)
4267db96d56Sopenharmony_ci        elif isinstance(o, float):
4277db96d56Sopenharmony_ci            # see comment for int/float in _make_iterencode
4287db96d56Sopenharmony_ci            yield _floatstr(o)
4297db96d56Sopenharmony_ci        elif isinstance(o, (list, tuple)):
4307db96d56Sopenharmony_ci            yield from _iterencode_list(o, _current_indent_level)
4317db96d56Sopenharmony_ci        elif isinstance(o, dict):
4327db96d56Sopenharmony_ci            yield from _iterencode_dict(o, _current_indent_level)
4337db96d56Sopenharmony_ci        else:
4347db96d56Sopenharmony_ci            if markers is not None:
4357db96d56Sopenharmony_ci                markerid = id(o)
4367db96d56Sopenharmony_ci                if markerid in markers:
4377db96d56Sopenharmony_ci                    raise ValueError("Circular reference detected")
4387db96d56Sopenharmony_ci                markers[markerid] = o
4397db96d56Sopenharmony_ci            o = _default(o)
4407db96d56Sopenharmony_ci            yield from _iterencode(o, _current_indent_level)
4417db96d56Sopenharmony_ci            if markers is not None:
4427db96d56Sopenharmony_ci                del markers[markerid]
4437db96d56Sopenharmony_ci    return _iterencode
444