17db96d56Sopenharmony_ci"""Create portable serialized representations of Python objects.
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ciSee module copyreg for a mechanism for registering custom picklers.
47db96d56Sopenharmony_ciSee module pickletools source for extensive comments.
57db96d56Sopenharmony_ci
67db96d56Sopenharmony_ciClasses:
77db96d56Sopenharmony_ci
87db96d56Sopenharmony_ci    Pickler
97db96d56Sopenharmony_ci    Unpickler
107db96d56Sopenharmony_ci
117db96d56Sopenharmony_ciFunctions:
127db96d56Sopenharmony_ci
137db96d56Sopenharmony_ci    dump(object, file)
147db96d56Sopenharmony_ci    dumps(object) -> string
157db96d56Sopenharmony_ci    load(file) -> object
167db96d56Sopenharmony_ci    loads(bytes) -> object
177db96d56Sopenharmony_ci
187db96d56Sopenharmony_ciMisc variables:
197db96d56Sopenharmony_ci
207db96d56Sopenharmony_ci    __version__
217db96d56Sopenharmony_ci    format_version
227db96d56Sopenharmony_ci    compatible_formats
237db96d56Sopenharmony_ci
247db96d56Sopenharmony_ci"""
257db96d56Sopenharmony_ci
267db96d56Sopenharmony_cifrom types import FunctionType
277db96d56Sopenharmony_cifrom copyreg import dispatch_table
287db96d56Sopenharmony_cifrom copyreg import _extension_registry, _inverted_registry, _extension_cache
297db96d56Sopenharmony_cifrom itertools import islice
307db96d56Sopenharmony_cifrom functools import partial
317db96d56Sopenharmony_ciimport sys
327db96d56Sopenharmony_cifrom sys import maxsize
337db96d56Sopenharmony_cifrom struct import pack, unpack
347db96d56Sopenharmony_ciimport re
357db96d56Sopenharmony_ciimport io
367db96d56Sopenharmony_ciimport codecs
377db96d56Sopenharmony_ciimport _compat_pickle
387db96d56Sopenharmony_ci
397db96d56Sopenharmony_ci__all__ = ["PickleError", "PicklingError", "UnpicklingError", "Pickler",
407db96d56Sopenharmony_ci           "Unpickler", "dump", "dumps", "load", "loads"]
417db96d56Sopenharmony_ci
427db96d56Sopenharmony_citry:
437db96d56Sopenharmony_ci    from _pickle import PickleBuffer
447db96d56Sopenharmony_ci    __all__.append("PickleBuffer")
457db96d56Sopenharmony_ci    _HAVE_PICKLE_BUFFER = True
467db96d56Sopenharmony_ciexcept ImportError:
477db96d56Sopenharmony_ci    _HAVE_PICKLE_BUFFER = False
487db96d56Sopenharmony_ci
497db96d56Sopenharmony_ci
507db96d56Sopenharmony_ci# Shortcut for use in isinstance testing
517db96d56Sopenharmony_cibytes_types = (bytes, bytearray)
527db96d56Sopenharmony_ci
537db96d56Sopenharmony_ci# These are purely informational; no code uses these.
547db96d56Sopenharmony_ciformat_version = "4.0"                  # File format version we write
557db96d56Sopenharmony_cicompatible_formats = ["1.0",            # Original protocol 0
567db96d56Sopenharmony_ci                      "1.1",            # Protocol 0 with INST added
577db96d56Sopenharmony_ci                      "1.2",            # Original protocol 1
587db96d56Sopenharmony_ci                      "1.3",            # Protocol 1 with BINFLOAT added
597db96d56Sopenharmony_ci                      "2.0",            # Protocol 2
607db96d56Sopenharmony_ci                      "3.0",            # Protocol 3
617db96d56Sopenharmony_ci                      "4.0",            # Protocol 4
627db96d56Sopenharmony_ci                      "5.0",            # Protocol 5
637db96d56Sopenharmony_ci                      ]                 # Old format versions we can read
647db96d56Sopenharmony_ci
657db96d56Sopenharmony_ci# This is the highest protocol number we know how to read.
667db96d56Sopenharmony_ciHIGHEST_PROTOCOL = 5
677db96d56Sopenharmony_ci
687db96d56Sopenharmony_ci# The protocol we write by default.  May be less than HIGHEST_PROTOCOL.
697db96d56Sopenharmony_ci# Only bump this if the oldest still supported version of Python already
707db96d56Sopenharmony_ci# includes it.
717db96d56Sopenharmony_ciDEFAULT_PROTOCOL = 4
727db96d56Sopenharmony_ci
737db96d56Sopenharmony_ciclass PickleError(Exception):
747db96d56Sopenharmony_ci    """A common base class for the other pickling exceptions."""
757db96d56Sopenharmony_ci    pass
767db96d56Sopenharmony_ci
777db96d56Sopenharmony_ciclass PicklingError(PickleError):
787db96d56Sopenharmony_ci    """This exception is raised when an unpicklable object is passed to the
797db96d56Sopenharmony_ci    dump() method.
807db96d56Sopenharmony_ci
817db96d56Sopenharmony_ci    """
827db96d56Sopenharmony_ci    pass
837db96d56Sopenharmony_ci
847db96d56Sopenharmony_ciclass UnpicklingError(PickleError):
857db96d56Sopenharmony_ci    """This exception is raised when there is a problem unpickling an object,
867db96d56Sopenharmony_ci    such as a security violation.
877db96d56Sopenharmony_ci
887db96d56Sopenharmony_ci    Note that other exceptions may also be raised during unpickling, including
897db96d56Sopenharmony_ci    (but not necessarily limited to) AttributeError, EOFError, ImportError,
907db96d56Sopenharmony_ci    and IndexError.
917db96d56Sopenharmony_ci
927db96d56Sopenharmony_ci    """
937db96d56Sopenharmony_ci    pass
947db96d56Sopenharmony_ci
957db96d56Sopenharmony_ci# An instance of _Stop is raised by Unpickler.load_stop() in response to
967db96d56Sopenharmony_ci# the STOP opcode, passing the object that is the result of unpickling.
977db96d56Sopenharmony_ciclass _Stop(Exception):
987db96d56Sopenharmony_ci    def __init__(self, value):
997db96d56Sopenharmony_ci        self.value = value
1007db96d56Sopenharmony_ci
1017db96d56Sopenharmony_ci# Jython has PyStringMap; it's a dict subclass with string keys
1027db96d56Sopenharmony_citry:
1037db96d56Sopenharmony_ci    from org.python.core import PyStringMap
1047db96d56Sopenharmony_ciexcept ImportError:
1057db96d56Sopenharmony_ci    PyStringMap = None
1067db96d56Sopenharmony_ci
1077db96d56Sopenharmony_ci# Pickle opcodes.  See pickletools.py for extensive docs.  The listing
1087db96d56Sopenharmony_ci# here is in kind-of alphabetical order of 1-character pickle code.
1097db96d56Sopenharmony_ci# pickletools groups them by purpose.
1107db96d56Sopenharmony_ci
1117db96d56Sopenharmony_ciMARK           = b'('   # push special markobject on stack
1127db96d56Sopenharmony_ciSTOP           = b'.'   # every pickle ends with STOP
1137db96d56Sopenharmony_ciPOP            = b'0'   # discard topmost stack item
1147db96d56Sopenharmony_ciPOP_MARK       = b'1'   # discard stack top through topmost markobject
1157db96d56Sopenharmony_ciDUP            = b'2'   # duplicate top stack item
1167db96d56Sopenharmony_ciFLOAT          = b'F'   # push float object; decimal string argument
1177db96d56Sopenharmony_ciINT            = b'I'   # push integer or bool; decimal string argument
1187db96d56Sopenharmony_ciBININT         = b'J'   # push four-byte signed int
1197db96d56Sopenharmony_ciBININT1        = b'K'   # push 1-byte unsigned int
1207db96d56Sopenharmony_ciLONG           = b'L'   # push long; decimal string argument
1217db96d56Sopenharmony_ciBININT2        = b'M'   # push 2-byte unsigned int
1227db96d56Sopenharmony_ciNONE           = b'N'   # push None
1237db96d56Sopenharmony_ciPERSID         = b'P'   # push persistent object; id is taken from string arg
1247db96d56Sopenharmony_ciBINPERSID      = b'Q'   #  "       "         "  ;  "  "   "     "  stack
1257db96d56Sopenharmony_ciREDUCE         = b'R'   # apply callable to argtuple, both on stack
1267db96d56Sopenharmony_ciSTRING         = b'S'   # push string; NL-terminated string argument
1277db96d56Sopenharmony_ciBINSTRING      = b'T'   # push string; counted binary string argument
1287db96d56Sopenharmony_ciSHORT_BINSTRING= b'U'   #  "     "   ;    "      "       "      " < 256 bytes
1297db96d56Sopenharmony_ciUNICODE        = b'V'   # push Unicode string; raw-unicode-escaped'd argument
1307db96d56Sopenharmony_ciBINUNICODE     = b'X'   #   "     "       "  ; counted UTF-8 string argument
1317db96d56Sopenharmony_ciAPPEND         = b'a'   # append stack top to list below it
1327db96d56Sopenharmony_ciBUILD          = b'b'   # call __setstate__ or __dict__.update()
1337db96d56Sopenharmony_ciGLOBAL         = b'c'   # push self.find_class(modname, name); 2 string args
1347db96d56Sopenharmony_ciDICT           = b'd'   # build a dict from stack items
1357db96d56Sopenharmony_ciEMPTY_DICT     = b'}'   # push empty dict
1367db96d56Sopenharmony_ciAPPENDS        = b'e'   # extend list on stack by topmost stack slice
1377db96d56Sopenharmony_ciGET            = b'g'   # push item from memo on stack; index is string arg
1387db96d56Sopenharmony_ciBINGET         = b'h'   #   "    "    "    "   "   "  ;   "    " 1-byte arg
1397db96d56Sopenharmony_ciINST           = b'i'   # build & push class instance
1407db96d56Sopenharmony_ciLONG_BINGET    = b'j'   # push item from memo on stack; index is 4-byte arg
1417db96d56Sopenharmony_ciLIST           = b'l'   # build list from topmost stack items
1427db96d56Sopenharmony_ciEMPTY_LIST     = b']'   # push empty list
1437db96d56Sopenharmony_ciOBJ            = b'o'   # build & push class instance
1447db96d56Sopenharmony_ciPUT            = b'p'   # store stack top in memo; index is string arg
1457db96d56Sopenharmony_ciBINPUT         = b'q'   #   "     "    "   "   " ;   "    " 1-byte arg
1467db96d56Sopenharmony_ciLONG_BINPUT    = b'r'   #   "     "    "   "   " ;   "    " 4-byte arg
1477db96d56Sopenharmony_ciSETITEM        = b's'   # add key+value pair to dict
1487db96d56Sopenharmony_ciTUPLE          = b't'   # build tuple from topmost stack items
1497db96d56Sopenharmony_ciEMPTY_TUPLE    = b')'   # push empty tuple
1507db96d56Sopenharmony_ciSETITEMS       = b'u'   # modify dict by adding topmost key+value pairs
1517db96d56Sopenharmony_ciBINFLOAT       = b'G'   # push float; arg is 8-byte float encoding
1527db96d56Sopenharmony_ci
1537db96d56Sopenharmony_ciTRUE           = b'I01\n'  # not an opcode; see INT docs in pickletools.py
1547db96d56Sopenharmony_ciFALSE          = b'I00\n'  # not an opcode; see INT docs in pickletools.py
1557db96d56Sopenharmony_ci
1567db96d56Sopenharmony_ci# Protocol 2
1577db96d56Sopenharmony_ci
1587db96d56Sopenharmony_ciPROTO          = b'\x80'  # identify pickle protocol
1597db96d56Sopenharmony_ciNEWOBJ         = b'\x81'  # build object by applying cls.__new__ to argtuple
1607db96d56Sopenharmony_ciEXT1           = b'\x82'  # push object from extension registry; 1-byte index
1617db96d56Sopenharmony_ciEXT2           = b'\x83'  # ditto, but 2-byte index
1627db96d56Sopenharmony_ciEXT4           = b'\x84'  # ditto, but 4-byte index
1637db96d56Sopenharmony_ciTUPLE1         = b'\x85'  # build 1-tuple from stack top
1647db96d56Sopenharmony_ciTUPLE2         = b'\x86'  # build 2-tuple from two topmost stack items
1657db96d56Sopenharmony_ciTUPLE3         = b'\x87'  # build 3-tuple from three topmost stack items
1667db96d56Sopenharmony_ciNEWTRUE        = b'\x88'  # push True
1677db96d56Sopenharmony_ciNEWFALSE       = b'\x89'  # push False
1687db96d56Sopenharmony_ciLONG1          = b'\x8a'  # push long from < 256 bytes
1697db96d56Sopenharmony_ciLONG4          = b'\x8b'  # push really big long
1707db96d56Sopenharmony_ci
1717db96d56Sopenharmony_ci_tuplesize2code = [EMPTY_TUPLE, TUPLE1, TUPLE2, TUPLE3]
1727db96d56Sopenharmony_ci
1737db96d56Sopenharmony_ci# Protocol 3 (Python 3.x)
1747db96d56Sopenharmony_ci
1757db96d56Sopenharmony_ciBINBYTES       = b'B'   # push bytes; counted binary string argument
1767db96d56Sopenharmony_ciSHORT_BINBYTES = b'C'   #  "     "   ;    "      "       "      " < 256 bytes
1777db96d56Sopenharmony_ci
1787db96d56Sopenharmony_ci# Protocol 4
1797db96d56Sopenharmony_ci
1807db96d56Sopenharmony_ciSHORT_BINUNICODE = b'\x8c'  # push short string; UTF-8 length < 256 bytes
1817db96d56Sopenharmony_ciBINUNICODE8      = b'\x8d'  # push very long string
1827db96d56Sopenharmony_ciBINBYTES8        = b'\x8e'  # push very long bytes string
1837db96d56Sopenharmony_ciEMPTY_SET        = b'\x8f'  # push empty set on the stack
1847db96d56Sopenharmony_ciADDITEMS         = b'\x90'  # modify set by adding topmost stack items
1857db96d56Sopenharmony_ciFROZENSET        = b'\x91'  # build frozenset from topmost stack items
1867db96d56Sopenharmony_ciNEWOBJ_EX        = b'\x92'  # like NEWOBJ but work with keyword only arguments
1877db96d56Sopenharmony_ciSTACK_GLOBAL     = b'\x93'  # same as GLOBAL but using names on the stacks
1887db96d56Sopenharmony_ciMEMOIZE          = b'\x94'  # store top of the stack in memo
1897db96d56Sopenharmony_ciFRAME            = b'\x95'  # indicate the beginning of a new frame
1907db96d56Sopenharmony_ci
1917db96d56Sopenharmony_ci# Protocol 5
1927db96d56Sopenharmony_ci
1937db96d56Sopenharmony_ciBYTEARRAY8       = b'\x96'  # push bytearray
1947db96d56Sopenharmony_ciNEXT_BUFFER      = b'\x97'  # push next out-of-band buffer
1957db96d56Sopenharmony_ciREADONLY_BUFFER  = b'\x98'  # make top of stack readonly
1967db96d56Sopenharmony_ci
1977db96d56Sopenharmony_ci__all__.extend([x for x in dir() if re.match("[A-Z][A-Z0-9_]+$", x)])
1987db96d56Sopenharmony_ci
1997db96d56Sopenharmony_ci
2007db96d56Sopenharmony_ciclass _Framer:
2017db96d56Sopenharmony_ci
2027db96d56Sopenharmony_ci    _FRAME_SIZE_MIN = 4
2037db96d56Sopenharmony_ci    _FRAME_SIZE_TARGET = 64 * 1024
2047db96d56Sopenharmony_ci
2057db96d56Sopenharmony_ci    def __init__(self, file_write):
2067db96d56Sopenharmony_ci        self.file_write = file_write
2077db96d56Sopenharmony_ci        self.current_frame = None
2087db96d56Sopenharmony_ci
2097db96d56Sopenharmony_ci    def start_framing(self):
2107db96d56Sopenharmony_ci        self.current_frame = io.BytesIO()
2117db96d56Sopenharmony_ci
2127db96d56Sopenharmony_ci    def end_framing(self):
2137db96d56Sopenharmony_ci        if self.current_frame and self.current_frame.tell() > 0:
2147db96d56Sopenharmony_ci            self.commit_frame(force=True)
2157db96d56Sopenharmony_ci            self.current_frame = None
2167db96d56Sopenharmony_ci
2177db96d56Sopenharmony_ci    def commit_frame(self, force=False):
2187db96d56Sopenharmony_ci        if self.current_frame:
2197db96d56Sopenharmony_ci            f = self.current_frame
2207db96d56Sopenharmony_ci            if f.tell() >= self._FRAME_SIZE_TARGET or force:
2217db96d56Sopenharmony_ci                data = f.getbuffer()
2227db96d56Sopenharmony_ci                write = self.file_write
2237db96d56Sopenharmony_ci                if len(data) >= self._FRAME_SIZE_MIN:
2247db96d56Sopenharmony_ci                    # Issue a single call to the write method of the underlying
2257db96d56Sopenharmony_ci                    # file object for the frame opcode with the size of the
2267db96d56Sopenharmony_ci                    # frame. The concatenation is expected to be less expensive
2277db96d56Sopenharmony_ci                    # than issuing an additional call to write.
2287db96d56Sopenharmony_ci                    write(FRAME + pack("<Q", len(data)))
2297db96d56Sopenharmony_ci
2307db96d56Sopenharmony_ci                # Issue a separate call to write to append the frame
2317db96d56Sopenharmony_ci                # contents without concatenation to the above to avoid a
2327db96d56Sopenharmony_ci                # memory copy.
2337db96d56Sopenharmony_ci                write(data)
2347db96d56Sopenharmony_ci
2357db96d56Sopenharmony_ci                # Start the new frame with a new io.BytesIO instance so that
2367db96d56Sopenharmony_ci                # the file object can have delayed access to the previous frame
2377db96d56Sopenharmony_ci                # contents via an unreleased memoryview of the previous
2387db96d56Sopenharmony_ci                # io.BytesIO instance.
2397db96d56Sopenharmony_ci                self.current_frame = io.BytesIO()
2407db96d56Sopenharmony_ci
2417db96d56Sopenharmony_ci    def write(self, data):
2427db96d56Sopenharmony_ci        if self.current_frame:
2437db96d56Sopenharmony_ci            return self.current_frame.write(data)
2447db96d56Sopenharmony_ci        else:
2457db96d56Sopenharmony_ci            return self.file_write(data)
2467db96d56Sopenharmony_ci
2477db96d56Sopenharmony_ci    def write_large_bytes(self, header, payload):
2487db96d56Sopenharmony_ci        write = self.file_write
2497db96d56Sopenharmony_ci        if self.current_frame:
2507db96d56Sopenharmony_ci            # Terminate the current frame and flush it to the file.
2517db96d56Sopenharmony_ci            self.commit_frame(force=True)
2527db96d56Sopenharmony_ci
2537db96d56Sopenharmony_ci        # Perform direct write of the header and payload of the large binary
2547db96d56Sopenharmony_ci        # object. Be careful not to concatenate the header and the payload
2557db96d56Sopenharmony_ci        # prior to calling 'write' as we do not want to allocate a large
2567db96d56Sopenharmony_ci        # temporary bytes object.
2577db96d56Sopenharmony_ci        # We intentionally do not insert a protocol 4 frame opcode to make
2587db96d56Sopenharmony_ci        # it possible to optimize file.read calls in the loader.
2597db96d56Sopenharmony_ci        write(header)
2607db96d56Sopenharmony_ci        write(payload)
2617db96d56Sopenharmony_ci
2627db96d56Sopenharmony_ci
2637db96d56Sopenharmony_ciclass _Unframer:
2647db96d56Sopenharmony_ci
2657db96d56Sopenharmony_ci    def __init__(self, file_read, file_readline, file_tell=None):
2667db96d56Sopenharmony_ci        self.file_read = file_read
2677db96d56Sopenharmony_ci        self.file_readline = file_readline
2687db96d56Sopenharmony_ci        self.current_frame = None
2697db96d56Sopenharmony_ci
2707db96d56Sopenharmony_ci    def readinto(self, buf):
2717db96d56Sopenharmony_ci        if self.current_frame:
2727db96d56Sopenharmony_ci            n = self.current_frame.readinto(buf)
2737db96d56Sopenharmony_ci            if n == 0 and len(buf) != 0:
2747db96d56Sopenharmony_ci                self.current_frame = None
2757db96d56Sopenharmony_ci                n = len(buf)
2767db96d56Sopenharmony_ci                buf[:] = self.file_read(n)
2777db96d56Sopenharmony_ci                return n
2787db96d56Sopenharmony_ci            if n < len(buf):
2797db96d56Sopenharmony_ci                raise UnpicklingError(
2807db96d56Sopenharmony_ci                    "pickle exhausted before end of frame")
2817db96d56Sopenharmony_ci            return n
2827db96d56Sopenharmony_ci        else:
2837db96d56Sopenharmony_ci            n = len(buf)
2847db96d56Sopenharmony_ci            buf[:] = self.file_read(n)
2857db96d56Sopenharmony_ci            return n
2867db96d56Sopenharmony_ci
2877db96d56Sopenharmony_ci    def read(self, n):
2887db96d56Sopenharmony_ci        if self.current_frame:
2897db96d56Sopenharmony_ci            data = self.current_frame.read(n)
2907db96d56Sopenharmony_ci            if not data and n != 0:
2917db96d56Sopenharmony_ci                self.current_frame = None
2927db96d56Sopenharmony_ci                return self.file_read(n)
2937db96d56Sopenharmony_ci            if len(data) < n:
2947db96d56Sopenharmony_ci                raise UnpicklingError(
2957db96d56Sopenharmony_ci                    "pickle exhausted before end of frame")
2967db96d56Sopenharmony_ci            return data
2977db96d56Sopenharmony_ci        else:
2987db96d56Sopenharmony_ci            return self.file_read(n)
2997db96d56Sopenharmony_ci
3007db96d56Sopenharmony_ci    def readline(self):
3017db96d56Sopenharmony_ci        if self.current_frame:
3027db96d56Sopenharmony_ci            data = self.current_frame.readline()
3037db96d56Sopenharmony_ci            if not data:
3047db96d56Sopenharmony_ci                self.current_frame = None
3057db96d56Sopenharmony_ci                return self.file_readline()
3067db96d56Sopenharmony_ci            if data[-1] != b'\n'[0]:
3077db96d56Sopenharmony_ci                raise UnpicklingError(
3087db96d56Sopenharmony_ci                    "pickle exhausted before end of frame")
3097db96d56Sopenharmony_ci            return data
3107db96d56Sopenharmony_ci        else:
3117db96d56Sopenharmony_ci            return self.file_readline()
3127db96d56Sopenharmony_ci
3137db96d56Sopenharmony_ci    def load_frame(self, frame_size):
3147db96d56Sopenharmony_ci        if self.current_frame and self.current_frame.read() != b'':
3157db96d56Sopenharmony_ci            raise UnpicklingError(
3167db96d56Sopenharmony_ci                "beginning of a new frame before end of current frame")
3177db96d56Sopenharmony_ci        self.current_frame = io.BytesIO(self.file_read(frame_size))
3187db96d56Sopenharmony_ci
3197db96d56Sopenharmony_ci
3207db96d56Sopenharmony_ci# Tools used for pickling.
3217db96d56Sopenharmony_ci
3227db96d56Sopenharmony_cidef _getattribute(obj, name):
3237db96d56Sopenharmony_ci    for subpath in name.split('.'):
3247db96d56Sopenharmony_ci        if subpath == '<locals>':
3257db96d56Sopenharmony_ci            raise AttributeError("Can't get local attribute {!r} on {!r}"
3267db96d56Sopenharmony_ci                                 .format(name, obj))
3277db96d56Sopenharmony_ci        try:
3287db96d56Sopenharmony_ci            parent = obj
3297db96d56Sopenharmony_ci            obj = getattr(obj, subpath)
3307db96d56Sopenharmony_ci        except AttributeError:
3317db96d56Sopenharmony_ci            raise AttributeError("Can't get attribute {!r} on {!r}"
3327db96d56Sopenharmony_ci                                 .format(name, obj)) from None
3337db96d56Sopenharmony_ci    return obj, parent
3347db96d56Sopenharmony_ci
3357db96d56Sopenharmony_cidef whichmodule(obj, name):
3367db96d56Sopenharmony_ci    """Find the module an object belong to."""
3377db96d56Sopenharmony_ci    module_name = getattr(obj, '__module__', None)
3387db96d56Sopenharmony_ci    if module_name is not None:
3397db96d56Sopenharmony_ci        return module_name
3407db96d56Sopenharmony_ci    # Protect the iteration by using a list copy of sys.modules against dynamic
3417db96d56Sopenharmony_ci    # modules that trigger imports of other modules upon calls to getattr.
3427db96d56Sopenharmony_ci    for module_name, module in sys.modules.copy().items():
3437db96d56Sopenharmony_ci        if (module_name == '__main__'
3447db96d56Sopenharmony_ci            or module_name == '__mp_main__'  # bpo-42406
3457db96d56Sopenharmony_ci            or module is None):
3467db96d56Sopenharmony_ci            continue
3477db96d56Sopenharmony_ci        try:
3487db96d56Sopenharmony_ci            if _getattribute(module, name)[0] is obj:
3497db96d56Sopenharmony_ci                return module_name
3507db96d56Sopenharmony_ci        except AttributeError:
3517db96d56Sopenharmony_ci            pass
3527db96d56Sopenharmony_ci    return '__main__'
3537db96d56Sopenharmony_ci
3547db96d56Sopenharmony_cidef encode_long(x):
3557db96d56Sopenharmony_ci    r"""Encode a long to a two's complement little-endian binary string.
3567db96d56Sopenharmony_ci    Note that 0 is a special case, returning an empty string, to save a
3577db96d56Sopenharmony_ci    byte in the LONG1 pickling context.
3587db96d56Sopenharmony_ci
3597db96d56Sopenharmony_ci    >>> encode_long(0)
3607db96d56Sopenharmony_ci    b''
3617db96d56Sopenharmony_ci    >>> encode_long(255)
3627db96d56Sopenharmony_ci    b'\xff\x00'
3637db96d56Sopenharmony_ci    >>> encode_long(32767)
3647db96d56Sopenharmony_ci    b'\xff\x7f'
3657db96d56Sopenharmony_ci    >>> encode_long(-256)
3667db96d56Sopenharmony_ci    b'\x00\xff'
3677db96d56Sopenharmony_ci    >>> encode_long(-32768)
3687db96d56Sopenharmony_ci    b'\x00\x80'
3697db96d56Sopenharmony_ci    >>> encode_long(-128)
3707db96d56Sopenharmony_ci    b'\x80'
3717db96d56Sopenharmony_ci    >>> encode_long(127)
3727db96d56Sopenharmony_ci    b'\x7f'
3737db96d56Sopenharmony_ci    >>>
3747db96d56Sopenharmony_ci    """
3757db96d56Sopenharmony_ci    if x == 0:
3767db96d56Sopenharmony_ci        return b''
3777db96d56Sopenharmony_ci    nbytes = (x.bit_length() >> 3) + 1
3787db96d56Sopenharmony_ci    result = x.to_bytes(nbytes, byteorder='little', signed=True)
3797db96d56Sopenharmony_ci    if x < 0 and nbytes > 1:
3807db96d56Sopenharmony_ci        if result[-1] == 0xff and (result[-2] & 0x80) != 0:
3817db96d56Sopenharmony_ci            result = result[:-1]
3827db96d56Sopenharmony_ci    return result
3837db96d56Sopenharmony_ci
3847db96d56Sopenharmony_cidef decode_long(data):
3857db96d56Sopenharmony_ci    r"""Decode a long from a two's complement little-endian binary string.
3867db96d56Sopenharmony_ci
3877db96d56Sopenharmony_ci    >>> decode_long(b'')
3887db96d56Sopenharmony_ci    0
3897db96d56Sopenharmony_ci    >>> decode_long(b"\xff\x00")
3907db96d56Sopenharmony_ci    255
3917db96d56Sopenharmony_ci    >>> decode_long(b"\xff\x7f")
3927db96d56Sopenharmony_ci    32767
3937db96d56Sopenharmony_ci    >>> decode_long(b"\x00\xff")
3947db96d56Sopenharmony_ci    -256
3957db96d56Sopenharmony_ci    >>> decode_long(b"\x00\x80")
3967db96d56Sopenharmony_ci    -32768
3977db96d56Sopenharmony_ci    >>> decode_long(b"\x80")
3987db96d56Sopenharmony_ci    -128
3997db96d56Sopenharmony_ci    >>> decode_long(b"\x7f")
4007db96d56Sopenharmony_ci    127
4017db96d56Sopenharmony_ci    """
4027db96d56Sopenharmony_ci    return int.from_bytes(data, byteorder='little', signed=True)
4037db96d56Sopenharmony_ci
4047db96d56Sopenharmony_ci
4057db96d56Sopenharmony_ci# Pickling machinery
4067db96d56Sopenharmony_ci
4077db96d56Sopenharmony_ciclass _Pickler:
4087db96d56Sopenharmony_ci
4097db96d56Sopenharmony_ci    def __init__(self, file, protocol=None, *, fix_imports=True,
4107db96d56Sopenharmony_ci                 buffer_callback=None):
4117db96d56Sopenharmony_ci        """This takes a binary file for writing a pickle data stream.
4127db96d56Sopenharmony_ci
4137db96d56Sopenharmony_ci        The optional *protocol* argument tells the pickler to use the
4147db96d56Sopenharmony_ci        given protocol; supported protocols are 0, 1, 2, 3, 4 and 5.
4157db96d56Sopenharmony_ci        The default protocol is 4. It was introduced in Python 3.4, and
4167db96d56Sopenharmony_ci        is incompatible with previous versions.
4177db96d56Sopenharmony_ci
4187db96d56Sopenharmony_ci        Specifying a negative protocol version selects the highest
4197db96d56Sopenharmony_ci        protocol version supported.  The higher the protocol used, the
4207db96d56Sopenharmony_ci        more recent the version of Python needed to read the pickle
4217db96d56Sopenharmony_ci        produced.
4227db96d56Sopenharmony_ci
4237db96d56Sopenharmony_ci        The *file* argument must have a write() method that accepts a
4247db96d56Sopenharmony_ci        single bytes argument. It can thus be a file object opened for
4257db96d56Sopenharmony_ci        binary writing, an io.BytesIO instance, or any other custom
4267db96d56Sopenharmony_ci        object that meets this interface.
4277db96d56Sopenharmony_ci
4287db96d56Sopenharmony_ci        If *fix_imports* is True and *protocol* is less than 3, pickle
4297db96d56Sopenharmony_ci        will try to map the new Python 3 names to the old module names
4307db96d56Sopenharmony_ci        used in Python 2, so that the pickle data stream is readable
4317db96d56Sopenharmony_ci        with Python 2.
4327db96d56Sopenharmony_ci
4337db96d56Sopenharmony_ci        If *buffer_callback* is None (the default), buffer views are
4347db96d56Sopenharmony_ci        serialized into *file* as part of the pickle stream.
4357db96d56Sopenharmony_ci
4367db96d56Sopenharmony_ci        If *buffer_callback* is not None, then it can be called any number
4377db96d56Sopenharmony_ci        of times with a buffer view.  If the callback returns a false value
4387db96d56Sopenharmony_ci        (such as None), the given buffer is out-of-band; otherwise the
4397db96d56Sopenharmony_ci        buffer is serialized in-band, i.e. inside the pickle stream.
4407db96d56Sopenharmony_ci
4417db96d56Sopenharmony_ci        It is an error if *buffer_callback* is not None and *protocol*
4427db96d56Sopenharmony_ci        is None or smaller than 5.
4437db96d56Sopenharmony_ci        """
4447db96d56Sopenharmony_ci        if protocol is None:
4457db96d56Sopenharmony_ci            protocol = DEFAULT_PROTOCOL
4467db96d56Sopenharmony_ci        if protocol < 0:
4477db96d56Sopenharmony_ci            protocol = HIGHEST_PROTOCOL
4487db96d56Sopenharmony_ci        elif not 0 <= protocol <= HIGHEST_PROTOCOL:
4497db96d56Sopenharmony_ci            raise ValueError("pickle protocol must be <= %d" % HIGHEST_PROTOCOL)
4507db96d56Sopenharmony_ci        if buffer_callback is not None and protocol < 5:
4517db96d56Sopenharmony_ci            raise ValueError("buffer_callback needs protocol >= 5")
4527db96d56Sopenharmony_ci        self._buffer_callback = buffer_callback
4537db96d56Sopenharmony_ci        try:
4547db96d56Sopenharmony_ci            self._file_write = file.write
4557db96d56Sopenharmony_ci        except AttributeError:
4567db96d56Sopenharmony_ci            raise TypeError("file must have a 'write' attribute")
4577db96d56Sopenharmony_ci        self.framer = _Framer(self._file_write)
4587db96d56Sopenharmony_ci        self.write = self.framer.write
4597db96d56Sopenharmony_ci        self._write_large_bytes = self.framer.write_large_bytes
4607db96d56Sopenharmony_ci        self.memo = {}
4617db96d56Sopenharmony_ci        self.proto = int(protocol)
4627db96d56Sopenharmony_ci        self.bin = protocol >= 1
4637db96d56Sopenharmony_ci        self.fast = 0
4647db96d56Sopenharmony_ci        self.fix_imports = fix_imports and protocol < 3
4657db96d56Sopenharmony_ci
4667db96d56Sopenharmony_ci    def clear_memo(self):
4677db96d56Sopenharmony_ci        """Clears the pickler's "memo".
4687db96d56Sopenharmony_ci
4697db96d56Sopenharmony_ci        The memo is the data structure that remembers which objects the
4707db96d56Sopenharmony_ci        pickler has already seen, so that shared or recursive objects
4717db96d56Sopenharmony_ci        are pickled by reference and not by value.  This method is
4727db96d56Sopenharmony_ci        useful when re-using picklers.
4737db96d56Sopenharmony_ci        """
4747db96d56Sopenharmony_ci        self.memo.clear()
4757db96d56Sopenharmony_ci
4767db96d56Sopenharmony_ci    def dump(self, obj):
4777db96d56Sopenharmony_ci        """Write a pickled representation of obj to the open file."""
4787db96d56Sopenharmony_ci        # Check whether Pickler was initialized correctly. This is
4797db96d56Sopenharmony_ci        # only needed to mimic the behavior of _pickle.Pickler.dump().
4807db96d56Sopenharmony_ci        if not hasattr(self, "_file_write"):
4817db96d56Sopenharmony_ci            raise PicklingError("Pickler.__init__() was not called by "
4827db96d56Sopenharmony_ci                                "%s.__init__()" % (self.__class__.__name__,))
4837db96d56Sopenharmony_ci        if self.proto >= 2:
4847db96d56Sopenharmony_ci            self.write(PROTO + pack("<B", self.proto))
4857db96d56Sopenharmony_ci        if self.proto >= 4:
4867db96d56Sopenharmony_ci            self.framer.start_framing()
4877db96d56Sopenharmony_ci        self.save(obj)
4887db96d56Sopenharmony_ci        self.write(STOP)
4897db96d56Sopenharmony_ci        self.framer.end_framing()
4907db96d56Sopenharmony_ci
4917db96d56Sopenharmony_ci    def memoize(self, obj):
4927db96d56Sopenharmony_ci        """Store an object in the memo."""
4937db96d56Sopenharmony_ci
4947db96d56Sopenharmony_ci        # The Pickler memo is a dictionary mapping object ids to 2-tuples
4957db96d56Sopenharmony_ci        # that contain the Unpickler memo key and the object being memoized.
4967db96d56Sopenharmony_ci        # The memo key is written to the pickle and will become
4977db96d56Sopenharmony_ci        # the key in the Unpickler's memo.  The object is stored in the
4987db96d56Sopenharmony_ci        # Pickler memo so that transient objects are kept alive during
4997db96d56Sopenharmony_ci        # pickling.
5007db96d56Sopenharmony_ci
5017db96d56Sopenharmony_ci        # The use of the Unpickler memo length as the memo key is just a
5027db96d56Sopenharmony_ci        # convention.  The only requirement is that the memo values be unique.
5037db96d56Sopenharmony_ci        # But there appears no advantage to any other scheme, and this
5047db96d56Sopenharmony_ci        # scheme allows the Unpickler memo to be implemented as a plain (but
5057db96d56Sopenharmony_ci        # growable) array, indexed by memo key.
5067db96d56Sopenharmony_ci        if self.fast:
5077db96d56Sopenharmony_ci            return
5087db96d56Sopenharmony_ci        assert id(obj) not in self.memo
5097db96d56Sopenharmony_ci        idx = len(self.memo)
5107db96d56Sopenharmony_ci        self.write(self.put(idx))
5117db96d56Sopenharmony_ci        self.memo[id(obj)] = idx, obj
5127db96d56Sopenharmony_ci
5137db96d56Sopenharmony_ci    # Return a PUT (BINPUT, LONG_BINPUT) opcode string, with argument i.
5147db96d56Sopenharmony_ci    def put(self, idx):
5157db96d56Sopenharmony_ci        if self.proto >= 4:
5167db96d56Sopenharmony_ci            return MEMOIZE
5177db96d56Sopenharmony_ci        elif self.bin:
5187db96d56Sopenharmony_ci            if idx < 256:
5197db96d56Sopenharmony_ci                return BINPUT + pack("<B", idx)
5207db96d56Sopenharmony_ci            else:
5217db96d56Sopenharmony_ci                return LONG_BINPUT + pack("<I", idx)
5227db96d56Sopenharmony_ci        else:
5237db96d56Sopenharmony_ci            return PUT + repr(idx).encode("ascii") + b'\n'
5247db96d56Sopenharmony_ci
5257db96d56Sopenharmony_ci    # Return a GET (BINGET, LONG_BINGET) opcode string, with argument i.
5267db96d56Sopenharmony_ci    def get(self, i):
5277db96d56Sopenharmony_ci        if self.bin:
5287db96d56Sopenharmony_ci            if i < 256:
5297db96d56Sopenharmony_ci                return BINGET + pack("<B", i)
5307db96d56Sopenharmony_ci            else:
5317db96d56Sopenharmony_ci                return LONG_BINGET + pack("<I", i)
5327db96d56Sopenharmony_ci
5337db96d56Sopenharmony_ci        return GET + repr(i).encode("ascii") + b'\n'
5347db96d56Sopenharmony_ci
5357db96d56Sopenharmony_ci    def save(self, obj, save_persistent_id=True):
5367db96d56Sopenharmony_ci        self.framer.commit_frame()
5377db96d56Sopenharmony_ci
5387db96d56Sopenharmony_ci        # Check for persistent id (defined by a subclass)
5397db96d56Sopenharmony_ci        pid = self.persistent_id(obj)
5407db96d56Sopenharmony_ci        if pid is not None and save_persistent_id:
5417db96d56Sopenharmony_ci            self.save_pers(pid)
5427db96d56Sopenharmony_ci            return
5437db96d56Sopenharmony_ci
5447db96d56Sopenharmony_ci        # Check the memo
5457db96d56Sopenharmony_ci        x = self.memo.get(id(obj))
5467db96d56Sopenharmony_ci        if x is not None:
5477db96d56Sopenharmony_ci            self.write(self.get(x[0]))
5487db96d56Sopenharmony_ci            return
5497db96d56Sopenharmony_ci
5507db96d56Sopenharmony_ci        rv = NotImplemented
5517db96d56Sopenharmony_ci        reduce = getattr(self, "reducer_override", None)
5527db96d56Sopenharmony_ci        if reduce is not None:
5537db96d56Sopenharmony_ci            rv = reduce(obj)
5547db96d56Sopenharmony_ci
5557db96d56Sopenharmony_ci        if rv is NotImplemented:
5567db96d56Sopenharmony_ci            # Check the type dispatch table
5577db96d56Sopenharmony_ci            t = type(obj)
5587db96d56Sopenharmony_ci            f = self.dispatch.get(t)
5597db96d56Sopenharmony_ci            if f is not None:
5607db96d56Sopenharmony_ci                f(self, obj)  # Call unbound method with explicit self
5617db96d56Sopenharmony_ci                return
5627db96d56Sopenharmony_ci
5637db96d56Sopenharmony_ci            # Check private dispatch table if any, or else
5647db96d56Sopenharmony_ci            # copyreg.dispatch_table
5657db96d56Sopenharmony_ci            reduce = getattr(self, 'dispatch_table', dispatch_table).get(t)
5667db96d56Sopenharmony_ci            if reduce is not None:
5677db96d56Sopenharmony_ci                rv = reduce(obj)
5687db96d56Sopenharmony_ci            else:
5697db96d56Sopenharmony_ci                # Check for a class with a custom metaclass; treat as regular
5707db96d56Sopenharmony_ci                # class
5717db96d56Sopenharmony_ci                if issubclass(t, type):
5727db96d56Sopenharmony_ci                    self.save_global(obj)
5737db96d56Sopenharmony_ci                    return
5747db96d56Sopenharmony_ci
5757db96d56Sopenharmony_ci                # Check for a __reduce_ex__ method, fall back to __reduce__
5767db96d56Sopenharmony_ci                reduce = getattr(obj, "__reduce_ex__", None)
5777db96d56Sopenharmony_ci                if reduce is not None:
5787db96d56Sopenharmony_ci                    rv = reduce(self.proto)
5797db96d56Sopenharmony_ci                else:
5807db96d56Sopenharmony_ci                    reduce = getattr(obj, "__reduce__", None)
5817db96d56Sopenharmony_ci                    if reduce is not None:
5827db96d56Sopenharmony_ci                        rv = reduce()
5837db96d56Sopenharmony_ci                    else:
5847db96d56Sopenharmony_ci                        raise PicklingError("Can't pickle %r object: %r" %
5857db96d56Sopenharmony_ci                                            (t.__name__, obj))
5867db96d56Sopenharmony_ci
5877db96d56Sopenharmony_ci        # Check for string returned by reduce(), meaning "save as global"
5887db96d56Sopenharmony_ci        if isinstance(rv, str):
5897db96d56Sopenharmony_ci            self.save_global(obj, rv)
5907db96d56Sopenharmony_ci            return
5917db96d56Sopenharmony_ci
5927db96d56Sopenharmony_ci        # Assert that reduce() returned a tuple
5937db96d56Sopenharmony_ci        if not isinstance(rv, tuple):
5947db96d56Sopenharmony_ci            raise PicklingError("%s must return string or tuple" % reduce)
5957db96d56Sopenharmony_ci
5967db96d56Sopenharmony_ci        # Assert that it returned an appropriately sized tuple
5977db96d56Sopenharmony_ci        l = len(rv)
5987db96d56Sopenharmony_ci        if not (2 <= l <= 6):
5997db96d56Sopenharmony_ci            raise PicklingError("Tuple returned by %s must have "
6007db96d56Sopenharmony_ci                                "two to six elements" % reduce)
6017db96d56Sopenharmony_ci
6027db96d56Sopenharmony_ci        # Save the reduce() output and finally memoize the object
6037db96d56Sopenharmony_ci        self.save_reduce(obj=obj, *rv)
6047db96d56Sopenharmony_ci
6057db96d56Sopenharmony_ci    def persistent_id(self, obj):
6067db96d56Sopenharmony_ci        # This exists so a subclass can override it
6077db96d56Sopenharmony_ci        return None
6087db96d56Sopenharmony_ci
6097db96d56Sopenharmony_ci    def save_pers(self, pid):
6107db96d56Sopenharmony_ci        # Save a persistent id reference
6117db96d56Sopenharmony_ci        if self.bin:
6127db96d56Sopenharmony_ci            self.save(pid, save_persistent_id=False)
6137db96d56Sopenharmony_ci            self.write(BINPERSID)
6147db96d56Sopenharmony_ci        else:
6157db96d56Sopenharmony_ci            try:
6167db96d56Sopenharmony_ci                self.write(PERSID + str(pid).encode("ascii") + b'\n')
6177db96d56Sopenharmony_ci            except UnicodeEncodeError:
6187db96d56Sopenharmony_ci                raise PicklingError(
6197db96d56Sopenharmony_ci                    "persistent IDs in protocol 0 must be ASCII strings")
6207db96d56Sopenharmony_ci
6217db96d56Sopenharmony_ci    def save_reduce(self, func, args, state=None, listitems=None,
6227db96d56Sopenharmony_ci                    dictitems=None, state_setter=None, *, obj=None):
6237db96d56Sopenharmony_ci        # This API is called by some subclasses
6247db96d56Sopenharmony_ci
6257db96d56Sopenharmony_ci        if not isinstance(args, tuple):
6267db96d56Sopenharmony_ci            raise PicklingError("args from save_reduce() must be a tuple")
6277db96d56Sopenharmony_ci        if not callable(func):
6287db96d56Sopenharmony_ci            raise PicklingError("func from save_reduce() must be callable")
6297db96d56Sopenharmony_ci
6307db96d56Sopenharmony_ci        save = self.save
6317db96d56Sopenharmony_ci        write = self.write
6327db96d56Sopenharmony_ci
6337db96d56Sopenharmony_ci        func_name = getattr(func, "__name__", "")
6347db96d56Sopenharmony_ci        if self.proto >= 2 and func_name == "__newobj_ex__":
6357db96d56Sopenharmony_ci            cls, args, kwargs = args
6367db96d56Sopenharmony_ci            if not hasattr(cls, "__new__"):
6377db96d56Sopenharmony_ci                raise PicklingError("args[0] from {} args has no __new__"
6387db96d56Sopenharmony_ci                                    .format(func_name))
6397db96d56Sopenharmony_ci            if obj is not None and cls is not obj.__class__:
6407db96d56Sopenharmony_ci                raise PicklingError("args[0] from {} args has the wrong class"
6417db96d56Sopenharmony_ci                                    .format(func_name))
6427db96d56Sopenharmony_ci            if self.proto >= 4:
6437db96d56Sopenharmony_ci                save(cls)
6447db96d56Sopenharmony_ci                save(args)
6457db96d56Sopenharmony_ci                save(kwargs)
6467db96d56Sopenharmony_ci                write(NEWOBJ_EX)
6477db96d56Sopenharmony_ci            else:
6487db96d56Sopenharmony_ci                func = partial(cls.__new__, cls, *args, **kwargs)
6497db96d56Sopenharmony_ci                save(func)
6507db96d56Sopenharmony_ci                save(())
6517db96d56Sopenharmony_ci                write(REDUCE)
6527db96d56Sopenharmony_ci        elif self.proto >= 2 and func_name == "__newobj__":
6537db96d56Sopenharmony_ci            # A __reduce__ implementation can direct protocol 2 or newer to
6547db96d56Sopenharmony_ci            # use the more efficient NEWOBJ opcode, while still
6557db96d56Sopenharmony_ci            # allowing protocol 0 and 1 to work normally.  For this to
6567db96d56Sopenharmony_ci            # work, the function returned by __reduce__ should be
6577db96d56Sopenharmony_ci            # called __newobj__, and its first argument should be a
6587db96d56Sopenharmony_ci            # class.  The implementation for __newobj__
6597db96d56Sopenharmony_ci            # should be as follows, although pickle has no way to
6607db96d56Sopenharmony_ci            # verify this:
6617db96d56Sopenharmony_ci            #
6627db96d56Sopenharmony_ci            # def __newobj__(cls, *args):
6637db96d56Sopenharmony_ci            #     return cls.__new__(cls, *args)
6647db96d56Sopenharmony_ci            #
6657db96d56Sopenharmony_ci            # Protocols 0 and 1 will pickle a reference to __newobj__,
6667db96d56Sopenharmony_ci            # while protocol 2 (and above) will pickle a reference to
6677db96d56Sopenharmony_ci            # cls, the remaining args tuple, and the NEWOBJ code,
6687db96d56Sopenharmony_ci            # which calls cls.__new__(cls, *args) at unpickling time
6697db96d56Sopenharmony_ci            # (see load_newobj below).  If __reduce__ returns a
6707db96d56Sopenharmony_ci            # three-tuple, the state from the third tuple item will be
6717db96d56Sopenharmony_ci            # pickled regardless of the protocol, calling __setstate__
6727db96d56Sopenharmony_ci            # at unpickling time (see load_build below).
6737db96d56Sopenharmony_ci            #
6747db96d56Sopenharmony_ci            # Note that no standard __newobj__ implementation exists;
6757db96d56Sopenharmony_ci            # you have to provide your own.  This is to enforce
6767db96d56Sopenharmony_ci            # compatibility with Python 2.2 (pickles written using
6777db96d56Sopenharmony_ci            # protocol 0 or 1 in Python 2.3 should be unpicklable by
6787db96d56Sopenharmony_ci            # Python 2.2).
6797db96d56Sopenharmony_ci            cls = args[0]
6807db96d56Sopenharmony_ci            if not hasattr(cls, "__new__"):
6817db96d56Sopenharmony_ci                raise PicklingError(
6827db96d56Sopenharmony_ci                    "args[0] from __newobj__ args has no __new__")
6837db96d56Sopenharmony_ci            if obj is not None and cls is not obj.__class__:
6847db96d56Sopenharmony_ci                raise PicklingError(
6857db96d56Sopenharmony_ci                    "args[0] from __newobj__ args has the wrong class")
6867db96d56Sopenharmony_ci            args = args[1:]
6877db96d56Sopenharmony_ci            save(cls)
6887db96d56Sopenharmony_ci            save(args)
6897db96d56Sopenharmony_ci            write(NEWOBJ)
6907db96d56Sopenharmony_ci        else:
6917db96d56Sopenharmony_ci            save(func)
6927db96d56Sopenharmony_ci            save(args)
6937db96d56Sopenharmony_ci            write(REDUCE)
6947db96d56Sopenharmony_ci
6957db96d56Sopenharmony_ci        if obj is not None:
6967db96d56Sopenharmony_ci            # If the object is already in the memo, this means it is
6977db96d56Sopenharmony_ci            # recursive. In this case, throw away everything we put on the
6987db96d56Sopenharmony_ci            # stack, and fetch the object back from the memo.
6997db96d56Sopenharmony_ci            if id(obj) in self.memo:
7007db96d56Sopenharmony_ci                write(POP + self.get(self.memo[id(obj)][0]))
7017db96d56Sopenharmony_ci            else:
7027db96d56Sopenharmony_ci                self.memoize(obj)
7037db96d56Sopenharmony_ci
7047db96d56Sopenharmony_ci        # More new special cases (that work with older protocols as
7057db96d56Sopenharmony_ci        # well): when __reduce__ returns a tuple with 4 or 5 items,
7067db96d56Sopenharmony_ci        # the 4th and 5th item should be iterators that provide list
7077db96d56Sopenharmony_ci        # items and dict items (as (key, value) tuples), or None.
7087db96d56Sopenharmony_ci
7097db96d56Sopenharmony_ci        if listitems is not None:
7107db96d56Sopenharmony_ci            self._batch_appends(listitems)
7117db96d56Sopenharmony_ci
7127db96d56Sopenharmony_ci        if dictitems is not None:
7137db96d56Sopenharmony_ci            self._batch_setitems(dictitems)
7147db96d56Sopenharmony_ci
7157db96d56Sopenharmony_ci        if state is not None:
7167db96d56Sopenharmony_ci            if state_setter is None:
7177db96d56Sopenharmony_ci                save(state)
7187db96d56Sopenharmony_ci                write(BUILD)
7197db96d56Sopenharmony_ci            else:
7207db96d56Sopenharmony_ci                # If a state_setter is specified, call it instead of load_build
7217db96d56Sopenharmony_ci                # to update obj's with its previous state.
7227db96d56Sopenharmony_ci                # First, push state_setter and its tuple of expected arguments
7237db96d56Sopenharmony_ci                # (obj, state) onto the stack.
7247db96d56Sopenharmony_ci                save(state_setter)
7257db96d56Sopenharmony_ci                save(obj)  # simple BINGET opcode as obj is already memoized.
7267db96d56Sopenharmony_ci                save(state)
7277db96d56Sopenharmony_ci                write(TUPLE2)
7287db96d56Sopenharmony_ci                # Trigger a state_setter(obj, state) function call.
7297db96d56Sopenharmony_ci                write(REDUCE)
7307db96d56Sopenharmony_ci                # The purpose of state_setter is to carry-out an
7317db96d56Sopenharmony_ci                # inplace modification of obj. We do not care about what the
7327db96d56Sopenharmony_ci                # method might return, so its output is eventually removed from
7337db96d56Sopenharmony_ci                # the stack.
7347db96d56Sopenharmony_ci                write(POP)
7357db96d56Sopenharmony_ci
7367db96d56Sopenharmony_ci    # Methods below this point are dispatched through the dispatch table
7377db96d56Sopenharmony_ci
7387db96d56Sopenharmony_ci    dispatch = {}
7397db96d56Sopenharmony_ci
7407db96d56Sopenharmony_ci    def save_none(self, obj):
7417db96d56Sopenharmony_ci        self.write(NONE)
7427db96d56Sopenharmony_ci    dispatch[type(None)] = save_none
7437db96d56Sopenharmony_ci
7447db96d56Sopenharmony_ci    def save_bool(self, obj):
7457db96d56Sopenharmony_ci        if self.proto >= 2:
7467db96d56Sopenharmony_ci            self.write(NEWTRUE if obj else NEWFALSE)
7477db96d56Sopenharmony_ci        else:
7487db96d56Sopenharmony_ci            self.write(TRUE if obj else FALSE)
7497db96d56Sopenharmony_ci    dispatch[bool] = save_bool
7507db96d56Sopenharmony_ci
7517db96d56Sopenharmony_ci    def save_long(self, obj):
7527db96d56Sopenharmony_ci        if self.bin:
7537db96d56Sopenharmony_ci            # If the int is small enough to fit in a signed 4-byte 2's-comp
7547db96d56Sopenharmony_ci            # format, we can store it more efficiently than the general
7557db96d56Sopenharmony_ci            # case.
7567db96d56Sopenharmony_ci            # First one- and two-byte unsigned ints:
7577db96d56Sopenharmony_ci            if obj >= 0:
7587db96d56Sopenharmony_ci                if obj <= 0xff:
7597db96d56Sopenharmony_ci                    self.write(BININT1 + pack("<B", obj))
7607db96d56Sopenharmony_ci                    return
7617db96d56Sopenharmony_ci                if obj <= 0xffff:
7627db96d56Sopenharmony_ci                    self.write(BININT2 + pack("<H", obj))
7637db96d56Sopenharmony_ci                    return
7647db96d56Sopenharmony_ci            # Next check for 4-byte signed ints:
7657db96d56Sopenharmony_ci            if -0x80000000 <= obj <= 0x7fffffff:
7667db96d56Sopenharmony_ci                self.write(BININT + pack("<i", obj))
7677db96d56Sopenharmony_ci                return
7687db96d56Sopenharmony_ci        if self.proto >= 2:
7697db96d56Sopenharmony_ci            encoded = encode_long(obj)
7707db96d56Sopenharmony_ci            n = len(encoded)
7717db96d56Sopenharmony_ci            if n < 256:
7727db96d56Sopenharmony_ci                self.write(LONG1 + pack("<B", n) + encoded)
7737db96d56Sopenharmony_ci            else:
7747db96d56Sopenharmony_ci                self.write(LONG4 + pack("<i", n) + encoded)
7757db96d56Sopenharmony_ci            return
7767db96d56Sopenharmony_ci        if -0x80000000 <= obj <= 0x7fffffff:
7777db96d56Sopenharmony_ci            self.write(INT + repr(obj).encode("ascii") + b'\n')
7787db96d56Sopenharmony_ci        else:
7797db96d56Sopenharmony_ci            self.write(LONG + repr(obj).encode("ascii") + b'L\n')
7807db96d56Sopenharmony_ci    dispatch[int] = save_long
7817db96d56Sopenharmony_ci
7827db96d56Sopenharmony_ci    def save_float(self, obj):
7837db96d56Sopenharmony_ci        if self.bin:
7847db96d56Sopenharmony_ci            self.write(BINFLOAT + pack('>d', obj))
7857db96d56Sopenharmony_ci        else:
7867db96d56Sopenharmony_ci            self.write(FLOAT + repr(obj).encode("ascii") + b'\n')
7877db96d56Sopenharmony_ci    dispatch[float] = save_float
7887db96d56Sopenharmony_ci
7897db96d56Sopenharmony_ci    def save_bytes(self, obj):
7907db96d56Sopenharmony_ci        if self.proto < 3:
7917db96d56Sopenharmony_ci            if not obj: # bytes object is empty
7927db96d56Sopenharmony_ci                self.save_reduce(bytes, (), obj=obj)
7937db96d56Sopenharmony_ci            else:
7947db96d56Sopenharmony_ci                self.save_reduce(codecs.encode,
7957db96d56Sopenharmony_ci                                 (str(obj, 'latin1'), 'latin1'), obj=obj)
7967db96d56Sopenharmony_ci            return
7977db96d56Sopenharmony_ci        n = len(obj)
7987db96d56Sopenharmony_ci        if n <= 0xff:
7997db96d56Sopenharmony_ci            self.write(SHORT_BINBYTES + pack("<B", n) + obj)
8007db96d56Sopenharmony_ci        elif n > 0xffffffff and self.proto >= 4:
8017db96d56Sopenharmony_ci            self._write_large_bytes(BINBYTES8 + pack("<Q", n), obj)
8027db96d56Sopenharmony_ci        elif n >= self.framer._FRAME_SIZE_TARGET:
8037db96d56Sopenharmony_ci            self._write_large_bytes(BINBYTES + pack("<I", n), obj)
8047db96d56Sopenharmony_ci        else:
8057db96d56Sopenharmony_ci            self.write(BINBYTES + pack("<I", n) + obj)
8067db96d56Sopenharmony_ci        self.memoize(obj)
8077db96d56Sopenharmony_ci    dispatch[bytes] = save_bytes
8087db96d56Sopenharmony_ci
8097db96d56Sopenharmony_ci    def save_bytearray(self, obj):
8107db96d56Sopenharmony_ci        if self.proto < 5:
8117db96d56Sopenharmony_ci            if not obj:  # bytearray is empty
8127db96d56Sopenharmony_ci                self.save_reduce(bytearray, (), obj=obj)
8137db96d56Sopenharmony_ci            else:
8147db96d56Sopenharmony_ci                self.save_reduce(bytearray, (bytes(obj),), obj=obj)
8157db96d56Sopenharmony_ci            return
8167db96d56Sopenharmony_ci        n = len(obj)
8177db96d56Sopenharmony_ci        if n >= self.framer._FRAME_SIZE_TARGET:
8187db96d56Sopenharmony_ci            self._write_large_bytes(BYTEARRAY8 + pack("<Q", n), obj)
8197db96d56Sopenharmony_ci        else:
8207db96d56Sopenharmony_ci            self.write(BYTEARRAY8 + pack("<Q", n) + obj)
8217db96d56Sopenharmony_ci        self.memoize(obj)
8227db96d56Sopenharmony_ci    dispatch[bytearray] = save_bytearray
8237db96d56Sopenharmony_ci
8247db96d56Sopenharmony_ci    if _HAVE_PICKLE_BUFFER:
8257db96d56Sopenharmony_ci        def save_picklebuffer(self, obj):
8267db96d56Sopenharmony_ci            if self.proto < 5:
8277db96d56Sopenharmony_ci                raise PicklingError("PickleBuffer can only pickled with "
8287db96d56Sopenharmony_ci                                    "protocol >= 5")
8297db96d56Sopenharmony_ci            with obj.raw() as m:
8307db96d56Sopenharmony_ci                if not m.contiguous:
8317db96d56Sopenharmony_ci                    raise PicklingError("PickleBuffer can not be pickled when "
8327db96d56Sopenharmony_ci                                        "pointing to a non-contiguous buffer")
8337db96d56Sopenharmony_ci                in_band = True
8347db96d56Sopenharmony_ci                if self._buffer_callback is not None:
8357db96d56Sopenharmony_ci                    in_band = bool(self._buffer_callback(obj))
8367db96d56Sopenharmony_ci                if in_band:
8377db96d56Sopenharmony_ci                    # Write data in-band
8387db96d56Sopenharmony_ci                    # XXX The C implementation avoids a copy here
8397db96d56Sopenharmony_ci                    if m.readonly:
8407db96d56Sopenharmony_ci                        self.save_bytes(m.tobytes())
8417db96d56Sopenharmony_ci                    else:
8427db96d56Sopenharmony_ci                        self.save_bytearray(m.tobytes())
8437db96d56Sopenharmony_ci                else:
8447db96d56Sopenharmony_ci                    # Write data out-of-band
8457db96d56Sopenharmony_ci                    self.write(NEXT_BUFFER)
8467db96d56Sopenharmony_ci                    if m.readonly:
8477db96d56Sopenharmony_ci                        self.write(READONLY_BUFFER)
8487db96d56Sopenharmony_ci
8497db96d56Sopenharmony_ci        dispatch[PickleBuffer] = save_picklebuffer
8507db96d56Sopenharmony_ci
8517db96d56Sopenharmony_ci    def save_str(self, obj):
8527db96d56Sopenharmony_ci        if self.bin:
8537db96d56Sopenharmony_ci            encoded = obj.encode('utf-8', 'surrogatepass')
8547db96d56Sopenharmony_ci            n = len(encoded)
8557db96d56Sopenharmony_ci            if n <= 0xff and self.proto >= 4:
8567db96d56Sopenharmony_ci                self.write(SHORT_BINUNICODE + pack("<B", n) + encoded)
8577db96d56Sopenharmony_ci            elif n > 0xffffffff and self.proto >= 4:
8587db96d56Sopenharmony_ci                self._write_large_bytes(BINUNICODE8 + pack("<Q", n), encoded)
8597db96d56Sopenharmony_ci            elif n >= self.framer._FRAME_SIZE_TARGET:
8607db96d56Sopenharmony_ci                self._write_large_bytes(BINUNICODE + pack("<I", n), encoded)
8617db96d56Sopenharmony_ci            else:
8627db96d56Sopenharmony_ci                self.write(BINUNICODE + pack("<I", n) + encoded)
8637db96d56Sopenharmony_ci        else:
8647db96d56Sopenharmony_ci            obj = obj.replace("\\", "\\u005c")
8657db96d56Sopenharmony_ci            obj = obj.replace("\0", "\\u0000")
8667db96d56Sopenharmony_ci            obj = obj.replace("\n", "\\u000a")
8677db96d56Sopenharmony_ci            obj = obj.replace("\r", "\\u000d")
8687db96d56Sopenharmony_ci            obj = obj.replace("\x1a", "\\u001a")  # EOF on DOS
8697db96d56Sopenharmony_ci            self.write(UNICODE + obj.encode('raw-unicode-escape') +
8707db96d56Sopenharmony_ci                       b'\n')
8717db96d56Sopenharmony_ci        self.memoize(obj)
8727db96d56Sopenharmony_ci    dispatch[str] = save_str
8737db96d56Sopenharmony_ci
8747db96d56Sopenharmony_ci    def save_tuple(self, obj):
8757db96d56Sopenharmony_ci        if not obj: # tuple is empty
8767db96d56Sopenharmony_ci            if self.bin:
8777db96d56Sopenharmony_ci                self.write(EMPTY_TUPLE)
8787db96d56Sopenharmony_ci            else:
8797db96d56Sopenharmony_ci                self.write(MARK + TUPLE)
8807db96d56Sopenharmony_ci            return
8817db96d56Sopenharmony_ci
8827db96d56Sopenharmony_ci        n = len(obj)
8837db96d56Sopenharmony_ci        save = self.save
8847db96d56Sopenharmony_ci        memo = self.memo
8857db96d56Sopenharmony_ci        if n <= 3 and self.proto >= 2:
8867db96d56Sopenharmony_ci            for element in obj:
8877db96d56Sopenharmony_ci                save(element)
8887db96d56Sopenharmony_ci            # Subtle.  Same as in the big comment below.
8897db96d56Sopenharmony_ci            if id(obj) in memo:
8907db96d56Sopenharmony_ci                get = self.get(memo[id(obj)][0])
8917db96d56Sopenharmony_ci                self.write(POP * n + get)
8927db96d56Sopenharmony_ci            else:
8937db96d56Sopenharmony_ci                self.write(_tuplesize2code[n])
8947db96d56Sopenharmony_ci                self.memoize(obj)
8957db96d56Sopenharmony_ci            return
8967db96d56Sopenharmony_ci
8977db96d56Sopenharmony_ci        # proto 0 or proto 1 and tuple isn't empty, or proto > 1 and tuple
8987db96d56Sopenharmony_ci        # has more than 3 elements.
8997db96d56Sopenharmony_ci        write = self.write
9007db96d56Sopenharmony_ci        write(MARK)
9017db96d56Sopenharmony_ci        for element in obj:
9027db96d56Sopenharmony_ci            save(element)
9037db96d56Sopenharmony_ci
9047db96d56Sopenharmony_ci        if id(obj) in memo:
9057db96d56Sopenharmony_ci            # Subtle.  d was not in memo when we entered save_tuple(), so
9067db96d56Sopenharmony_ci            # the process of saving the tuple's elements must have saved
9077db96d56Sopenharmony_ci            # the tuple itself:  the tuple is recursive.  The proper action
9087db96d56Sopenharmony_ci            # now is to throw away everything we put on the stack, and
9097db96d56Sopenharmony_ci            # simply GET the tuple (it's already constructed).  This check
9107db96d56Sopenharmony_ci            # could have been done in the "for element" loop instead, but
9117db96d56Sopenharmony_ci            # recursive tuples are a rare thing.
9127db96d56Sopenharmony_ci            get = self.get(memo[id(obj)][0])
9137db96d56Sopenharmony_ci            if self.bin:
9147db96d56Sopenharmony_ci                write(POP_MARK + get)
9157db96d56Sopenharmony_ci            else:   # proto 0 -- POP_MARK not available
9167db96d56Sopenharmony_ci                write(POP * (n+1) + get)
9177db96d56Sopenharmony_ci            return
9187db96d56Sopenharmony_ci
9197db96d56Sopenharmony_ci        # No recursion.
9207db96d56Sopenharmony_ci        write(TUPLE)
9217db96d56Sopenharmony_ci        self.memoize(obj)
9227db96d56Sopenharmony_ci
9237db96d56Sopenharmony_ci    dispatch[tuple] = save_tuple
9247db96d56Sopenharmony_ci
9257db96d56Sopenharmony_ci    def save_list(self, obj):
9267db96d56Sopenharmony_ci        if self.bin:
9277db96d56Sopenharmony_ci            self.write(EMPTY_LIST)
9287db96d56Sopenharmony_ci        else:   # proto 0 -- can't use EMPTY_LIST
9297db96d56Sopenharmony_ci            self.write(MARK + LIST)
9307db96d56Sopenharmony_ci
9317db96d56Sopenharmony_ci        self.memoize(obj)
9327db96d56Sopenharmony_ci        self._batch_appends(obj)
9337db96d56Sopenharmony_ci
9347db96d56Sopenharmony_ci    dispatch[list] = save_list
9357db96d56Sopenharmony_ci
9367db96d56Sopenharmony_ci    _BATCHSIZE = 1000
9377db96d56Sopenharmony_ci
9387db96d56Sopenharmony_ci    def _batch_appends(self, items):
9397db96d56Sopenharmony_ci        # Helper to batch up APPENDS sequences
9407db96d56Sopenharmony_ci        save = self.save
9417db96d56Sopenharmony_ci        write = self.write
9427db96d56Sopenharmony_ci
9437db96d56Sopenharmony_ci        if not self.bin:
9447db96d56Sopenharmony_ci            for x in items:
9457db96d56Sopenharmony_ci                save(x)
9467db96d56Sopenharmony_ci                write(APPEND)
9477db96d56Sopenharmony_ci            return
9487db96d56Sopenharmony_ci
9497db96d56Sopenharmony_ci        it = iter(items)
9507db96d56Sopenharmony_ci        while True:
9517db96d56Sopenharmony_ci            tmp = list(islice(it, self._BATCHSIZE))
9527db96d56Sopenharmony_ci            n = len(tmp)
9537db96d56Sopenharmony_ci            if n > 1:
9547db96d56Sopenharmony_ci                write(MARK)
9557db96d56Sopenharmony_ci                for x in tmp:
9567db96d56Sopenharmony_ci                    save(x)
9577db96d56Sopenharmony_ci                write(APPENDS)
9587db96d56Sopenharmony_ci            elif n:
9597db96d56Sopenharmony_ci                save(tmp[0])
9607db96d56Sopenharmony_ci                write(APPEND)
9617db96d56Sopenharmony_ci            # else tmp is empty, and we're done
9627db96d56Sopenharmony_ci            if n < self._BATCHSIZE:
9637db96d56Sopenharmony_ci                return
9647db96d56Sopenharmony_ci
9657db96d56Sopenharmony_ci    def save_dict(self, obj):
9667db96d56Sopenharmony_ci        if self.bin:
9677db96d56Sopenharmony_ci            self.write(EMPTY_DICT)
9687db96d56Sopenharmony_ci        else:   # proto 0 -- can't use EMPTY_DICT
9697db96d56Sopenharmony_ci            self.write(MARK + DICT)
9707db96d56Sopenharmony_ci
9717db96d56Sopenharmony_ci        self.memoize(obj)
9727db96d56Sopenharmony_ci        self._batch_setitems(obj.items())
9737db96d56Sopenharmony_ci
9747db96d56Sopenharmony_ci    dispatch[dict] = save_dict
9757db96d56Sopenharmony_ci    if PyStringMap is not None:
9767db96d56Sopenharmony_ci        dispatch[PyStringMap] = save_dict
9777db96d56Sopenharmony_ci
9787db96d56Sopenharmony_ci    def _batch_setitems(self, items):
9797db96d56Sopenharmony_ci        # Helper to batch up SETITEMS sequences; proto >= 1 only
9807db96d56Sopenharmony_ci        save = self.save
9817db96d56Sopenharmony_ci        write = self.write
9827db96d56Sopenharmony_ci
9837db96d56Sopenharmony_ci        if not self.bin:
9847db96d56Sopenharmony_ci            for k, v in items:
9857db96d56Sopenharmony_ci                save(k)
9867db96d56Sopenharmony_ci                save(v)
9877db96d56Sopenharmony_ci                write(SETITEM)
9887db96d56Sopenharmony_ci            return
9897db96d56Sopenharmony_ci
9907db96d56Sopenharmony_ci        it = iter(items)
9917db96d56Sopenharmony_ci        while True:
9927db96d56Sopenharmony_ci            tmp = list(islice(it, self._BATCHSIZE))
9937db96d56Sopenharmony_ci            n = len(tmp)
9947db96d56Sopenharmony_ci            if n > 1:
9957db96d56Sopenharmony_ci                write(MARK)
9967db96d56Sopenharmony_ci                for k, v in tmp:
9977db96d56Sopenharmony_ci                    save(k)
9987db96d56Sopenharmony_ci                    save(v)
9997db96d56Sopenharmony_ci                write(SETITEMS)
10007db96d56Sopenharmony_ci            elif n:
10017db96d56Sopenharmony_ci                k, v = tmp[0]
10027db96d56Sopenharmony_ci                save(k)
10037db96d56Sopenharmony_ci                save(v)
10047db96d56Sopenharmony_ci                write(SETITEM)
10057db96d56Sopenharmony_ci            # else tmp is empty, and we're done
10067db96d56Sopenharmony_ci            if n < self._BATCHSIZE:
10077db96d56Sopenharmony_ci                return
10087db96d56Sopenharmony_ci
10097db96d56Sopenharmony_ci    def save_set(self, obj):
10107db96d56Sopenharmony_ci        save = self.save
10117db96d56Sopenharmony_ci        write = self.write
10127db96d56Sopenharmony_ci
10137db96d56Sopenharmony_ci        if self.proto < 4:
10147db96d56Sopenharmony_ci            self.save_reduce(set, (list(obj),), obj=obj)
10157db96d56Sopenharmony_ci            return
10167db96d56Sopenharmony_ci
10177db96d56Sopenharmony_ci        write(EMPTY_SET)
10187db96d56Sopenharmony_ci        self.memoize(obj)
10197db96d56Sopenharmony_ci
10207db96d56Sopenharmony_ci        it = iter(obj)
10217db96d56Sopenharmony_ci        while True:
10227db96d56Sopenharmony_ci            batch = list(islice(it, self._BATCHSIZE))
10237db96d56Sopenharmony_ci            n = len(batch)
10247db96d56Sopenharmony_ci            if n > 0:
10257db96d56Sopenharmony_ci                write(MARK)
10267db96d56Sopenharmony_ci                for item in batch:
10277db96d56Sopenharmony_ci                    save(item)
10287db96d56Sopenharmony_ci                write(ADDITEMS)
10297db96d56Sopenharmony_ci            if n < self._BATCHSIZE:
10307db96d56Sopenharmony_ci                return
10317db96d56Sopenharmony_ci    dispatch[set] = save_set
10327db96d56Sopenharmony_ci
10337db96d56Sopenharmony_ci    def save_frozenset(self, obj):
10347db96d56Sopenharmony_ci        save = self.save
10357db96d56Sopenharmony_ci        write = self.write
10367db96d56Sopenharmony_ci
10377db96d56Sopenharmony_ci        if self.proto < 4:
10387db96d56Sopenharmony_ci            self.save_reduce(frozenset, (list(obj),), obj=obj)
10397db96d56Sopenharmony_ci            return
10407db96d56Sopenharmony_ci
10417db96d56Sopenharmony_ci        write(MARK)
10427db96d56Sopenharmony_ci        for item in obj:
10437db96d56Sopenharmony_ci            save(item)
10447db96d56Sopenharmony_ci
10457db96d56Sopenharmony_ci        if id(obj) in self.memo:
10467db96d56Sopenharmony_ci            # If the object is already in the memo, this means it is
10477db96d56Sopenharmony_ci            # recursive. In this case, throw away everything we put on the
10487db96d56Sopenharmony_ci            # stack, and fetch the object back from the memo.
10497db96d56Sopenharmony_ci            write(POP_MARK + self.get(self.memo[id(obj)][0]))
10507db96d56Sopenharmony_ci            return
10517db96d56Sopenharmony_ci
10527db96d56Sopenharmony_ci        write(FROZENSET)
10537db96d56Sopenharmony_ci        self.memoize(obj)
10547db96d56Sopenharmony_ci    dispatch[frozenset] = save_frozenset
10557db96d56Sopenharmony_ci
10567db96d56Sopenharmony_ci    def save_global(self, obj, name=None):
10577db96d56Sopenharmony_ci        write = self.write
10587db96d56Sopenharmony_ci        memo = self.memo
10597db96d56Sopenharmony_ci
10607db96d56Sopenharmony_ci        if name is None:
10617db96d56Sopenharmony_ci            name = getattr(obj, '__qualname__', None)
10627db96d56Sopenharmony_ci        if name is None:
10637db96d56Sopenharmony_ci            name = obj.__name__
10647db96d56Sopenharmony_ci
10657db96d56Sopenharmony_ci        module_name = whichmodule(obj, name)
10667db96d56Sopenharmony_ci        try:
10677db96d56Sopenharmony_ci            __import__(module_name, level=0)
10687db96d56Sopenharmony_ci            module = sys.modules[module_name]
10697db96d56Sopenharmony_ci            obj2, parent = _getattribute(module, name)
10707db96d56Sopenharmony_ci        except (ImportError, KeyError, AttributeError):
10717db96d56Sopenharmony_ci            raise PicklingError(
10727db96d56Sopenharmony_ci                "Can't pickle %r: it's not found as %s.%s" %
10737db96d56Sopenharmony_ci                (obj, module_name, name)) from None
10747db96d56Sopenharmony_ci        else:
10757db96d56Sopenharmony_ci            if obj2 is not obj:
10767db96d56Sopenharmony_ci                raise PicklingError(
10777db96d56Sopenharmony_ci                    "Can't pickle %r: it's not the same object as %s.%s" %
10787db96d56Sopenharmony_ci                    (obj, module_name, name))
10797db96d56Sopenharmony_ci
10807db96d56Sopenharmony_ci        if self.proto >= 2:
10817db96d56Sopenharmony_ci            code = _extension_registry.get((module_name, name))
10827db96d56Sopenharmony_ci            if code:
10837db96d56Sopenharmony_ci                assert code > 0
10847db96d56Sopenharmony_ci                if code <= 0xff:
10857db96d56Sopenharmony_ci                    write(EXT1 + pack("<B", code))
10867db96d56Sopenharmony_ci                elif code <= 0xffff:
10877db96d56Sopenharmony_ci                    write(EXT2 + pack("<H", code))
10887db96d56Sopenharmony_ci                else:
10897db96d56Sopenharmony_ci                    write(EXT4 + pack("<i", code))
10907db96d56Sopenharmony_ci                return
10917db96d56Sopenharmony_ci        lastname = name.rpartition('.')[2]
10927db96d56Sopenharmony_ci        if parent is module:
10937db96d56Sopenharmony_ci            name = lastname
10947db96d56Sopenharmony_ci        # Non-ASCII identifiers are supported only with protocols >= 3.
10957db96d56Sopenharmony_ci        if self.proto >= 4:
10967db96d56Sopenharmony_ci            self.save(module_name)
10977db96d56Sopenharmony_ci            self.save(name)
10987db96d56Sopenharmony_ci            write(STACK_GLOBAL)
10997db96d56Sopenharmony_ci        elif parent is not module:
11007db96d56Sopenharmony_ci            self.save_reduce(getattr, (parent, lastname))
11017db96d56Sopenharmony_ci        elif self.proto >= 3:
11027db96d56Sopenharmony_ci            write(GLOBAL + bytes(module_name, "utf-8") + b'\n' +
11037db96d56Sopenharmony_ci                  bytes(name, "utf-8") + b'\n')
11047db96d56Sopenharmony_ci        else:
11057db96d56Sopenharmony_ci            if self.fix_imports:
11067db96d56Sopenharmony_ci                r_name_mapping = _compat_pickle.REVERSE_NAME_MAPPING
11077db96d56Sopenharmony_ci                r_import_mapping = _compat_pickle.REVERSE_IMPORT_MAPPING
11087db96d56Sopenharmony_ci                if (module_name, name) in r_name_mapping:
11097db96d56Sopenharmony_ci                    module_name, name = r_name_mapping[(module_name, name)]
11107db96d56Sopenharmony_ci                elif module_name in r_import_mapping:
11117db96d56Sopenharmony_ci                    module_name = r_import_mapping[module_name]
11127db96d56Sopenharmony_ci            try:
11137db96d56Sopenharmony_ci                write(GLOBAL + bytes(module_name, "ascii") + b'\n' +
11147db96d56Sopenharmony_ci                      bytes(name, "ascii") + b'\n')
11157db96d56Sopenharmony_ci            except UnicodeEncodeError:
11167db96d56Sopenharmony_ci                raise PicklingError(
11177db96d56Sopenharmony_ci                    "can't pickle global identifier '%s.%s' using "
11187db96d56Sopenharmony_ci                    "pickle protocol %i" % (module, name, self.proto)) from None
11197db96d56Sopenharmony_ci
11207db96d56Sopenharmony_ci        self.memoize(obj)
11217db96d56Sopenharmony_ci
11227db96d56Sopenharmony_ci    def save_type(self, obj):
11237db96d56Sopenharmony_ci        if obj is type(None):
11247db96d56Sopenharmony_ci            return self.save_reduce(type, (None,), obj=obj)
11257db96d56Sopenharmony_ci        elif obj is type(NotImplemented):
11267db96d56Sopenharmony_ci            return self.save_reduce(type, (NotImplemented,), obj=obj)
11277db96d56Sopenharmony_ci        elif obj is type(...):
11287db96d56Sopenharmony_ci            return self.save_reduce(type, (...,), obj=obj)
11297db96d56Sopenharmony_ci        return self.save_global(obj)
11307db96d56Sopenharmony_ci
11317db96d56Sopenharmony_ci    dispatch[FunctionType] = save_global
11327db96d56Sopenharmony_ci    dispatch[type] = save_type
11337db96d56Sopenharmony_ci
11347db96d56Sopenharmony_ci
11357db96d56Sopenharmony_ci# Unpickling machinery
11367db96d56Sopenharmony_ci
11377db96d56Sopenharmony_ciclass _Unpickler:
11387db96d56Sopenharmony_ci
11397db96d56Sopenharmony_ci    def __init__(self, file, *, fix_imports=True,
11407db96d56Sopenharmony_ci                 encoding="ASCII", errors="strict", buffers=None):
11417db96d56Sopenharmony_ci        """This takes a binary file for reading a pickle data stream.
11427db96d56Sopenharmony_ci
11437db96d56Sopenharmony_ci        The protocol version of the pickle is detected automatically, so
11447db96d56Sopenharmony_ci        no proto argument is needed.
11457db96d56Sopenharmony_ci
11467db96d56Sopenharmony_ci        The argument *file* must have two methods, a read() method that
11477db96d56Sopenharmony_ci        takes an integer argument, and a readline() method that requires
11487db96d56Sopenharmony_ci        no arguments.  Both methods should return bytes.  Thus *file*
11497db96d56Sopenharmony_ci        can be a binary file object opened for reading, an io.BytesIO
11507db96d56Sopenharmony_ci        object, or any other custom object that meets this interface.
11517db96d56Sopenharmony_ci
11527db96d56Sopenharmony_ci        The file-like object must have two methods, a read() method
11537db96d56Sopenharmony_ci        that takes an integer argument, and a readline() method that
11547db96d56Sopenharmony_ci        requires no arguments.  Both methods should return bytes.
11557db96d56Sopenharmony_ci        Thus file-like object can be a binary file object opened for
11567db96d56Sopenharmony_ci        reading, a BytesIO object, or any other custom object that
11577db96d56Sopenharmony_ci        meets this interface.
11587db96d56Sopenharmony_ci
11597db96d56Sopenharmony_ci        If *buffers* is not None, it should be an iterable of buffer-enabled
11607db96d56Sopenharmony_ci        objects that is consumed each time the pickle stream references
11617db96d56Sopenharmony_ci        an out-of-band buffer view.  Such buffers have been given in order
11627db96d56Sopenharmony_ci        to the *buffer_callback* of a Pickler object.
11637db96d56Sopenharmony_ci
11647db96d56Sopenharmony_ci        If *buffers* is None (the default), then the buffers are taken
11657db96d56Sopenharmony_ci        from the pickle stream, assuming they are serialized there.
11667db96d56Sopenharmony_ci        It is an error for *buffers* to be None if the pickle stream
11677db96d56Sopenharmony_ci        was produced with a non-None *buffer_callback*.
11687db96d56Sopenharmony_ci
11697db96d56Sopenharmony_ci        Other optional arguments are *fix_imports*, *encoding* and
11707db96d56Sopenharmony_ci        *errors*, which are used to control compatibility support for
11717db96d56Sopenharmony_ci        pickle stream generated by Python 2.  If *fix_imports* is True,
11727db96d56Sopenharmony_ci        pickle will try to map the old Python 2 names to the new names
11737db96d56Sopenharmony_ci        used in Python 3.  The *encoding* and *errors* tell pickle how
11747db96d56Sopenharmony_ci        to decode 8-bit string instances pickled by Python 2; these
11757db96d56Sopenharmony_ci        default to 'ASCII' and 'strict', respectively. *encoding* can be
11767db96d56Sopenharmony_ci        'bytes' to read these 8-bit string instances as bytes objects.
11777db96d56Sopenharmony_ci        """
11787db96d56Sopenharmony_ci        self._buffers = iter(buffers) if buffers is not None else None
11797db96d56Sopenharmony_ci        self._file_readline = file.readline
11807db96d56Sopenharmony_ci        self._file_read = file.read
11817db96d56Sopenharmony_ci        self.memo = {}
11827db96d56Sopenharmony_ci        self.encoding = encoding
11837db96d56Sopenharmony_ci        self.errors = errors
11847db96d56Sopenharmony_ci        self.proto = 0
11857db96d56Sopenharmony_ci        self.fix_imports = fix_imports
11867db96d56Sopenharmony_ci
11877db96d56Sopenharmony_ci    def load(self):
11887db96d56Sopenharmony_ci        """Read a pickled object representation from the open file.
11897db96d56Sopenharmony_ci
11907db96d56Sopenharmony_ci        Return the reconstituted object hierarchy specified in the file.
11917db96d56Sopenharmony_ci        """
11927db96d56Sopenharmony_ci        # Check whether Unpickler was initialized correctly. This is
11937db96d56Sopenharmony_ci        # only needed to mimic the behavior of _pickle.Unpickler.dump().
11947db96d56Sopenharmony_ci        if not hasattr(self, "_file_read"):
11957db96d56Sopenharmony_ci            raise UnpicklingError("Unpickler.__init__() was not called by "
11967db96d56Sopenharmony_ci                                  "%s.__init__()" % (self.__class__.__name__,))
11977db96d56Sopenharmony_ci        self._unframer = _Unframer(self._file_read, self._file_readline)
11987db96d56Sopenharmony_ci        self.read = self._unframer.read
11997db96d56Sopenharmony_ci        self.readinto = self._unframer.readinto
12007db96d56Sopenharmony_ci        self.readline = self._unframer.readline
12017db96d56Sopenharmony_ci        self.metastack = []
12027db96d56Sopenharmony_ci        self.stack = []
12037db96d56Sopenharmony_ci        self.append = self.stack.append
12047db96d56Sopenharmony_ci        self.proto = 0
12057db96d56Sopenharmony_ci        read = self.read
12067db96d56Sopenharmony_ci        dispatch = self.dispatch
12077db96d56Sopenharmony_ci        try:
12087db96d56Sopenharmony_ci            while True:
12097db96d56Sopenharmony_ci                key = read(1)
12107db96d56Sopenharmony_ci                if not key:
12117db96d56Sopenharmony_ci                    raise EOFError
12127db96d56Sopenharmony_ci                assert isinstance(key, bytes_types)
12137db96d56Sopenharmony_ci                dispatch[key[0]](self)
12147db96d56Sopenharmony_ci        except _Stop as stopinst:
12157db96d56Sopenharmony_ci            return stopinst.value
12167db96d56Sopenharmony_ci
12177db96d56Sopenharmony_ci    # Return a list of items pushed in the stack after last MARK instruction.
12187db96d56Sopenharmony_ci    def pop_mark(self):
12197db96d56Sopenharmony_ci        items = self.stack
12207db96d56Sopenharmony_ci        self.stack = self.metastack.pop()
12217db96d56Sopenharmony_ci        self.append = self.stack.append
12227db96d56Sopenharmony_ci        return items
12237db96d56Sopenharmony_ci
12247db96d56Sopenharmony_ci    def persistent_load(self, pid):
12257db96d56Sopenharmony_ci        raise UnpicklingError("unsupported persistent id encountered")
12267db96d56Sopenharmony_ci
12277db96d56Sopenharmony_ci    dispatch = {}
12287db96d56Sopenharmony_ci
12297db96d56Sopenharmony_ci    def load_proto(self):
12307db96d56Sopenharmony_ci        proto = self.read(1)[0]
12317db96d56Sopenharmony_ci        if not 0 <= proto <= HIGHEST_PROTOCOL:
12327db96d56Sopenharmony_ci            raise ValueError("unsupported pickle protocol: %d" % proto)
12337db96d56Sopenharmony_ci        self.proto = proto
12347db96d56Sopenharmony_ci    dispatch[PROTO[0]] = load_proto
12357db96d56Sopenharmony_ci
12367db96d56Sopenharmony_ci    def load_frame(self):
12377db96d56Sopenharmony_ci        frame_size, = unpack('<Q', self.read(8))
12387db96d56Sopenharmony_ci        if frame_size > sys.maxsize:
12397db96d56Sopenharmony_ci            raise ValueError("frame size > sys.maxsize: %d" % frame_size)
12407db96d56Sopenharmony_ci        self._unframer.load_frame(frame_size)
12417db96d56Sopenharmony_ci    dispatch[FRAME[0]] = load_frame
12427db96d56Sopenharmony_ci
12437db96d56Sopenharmony_ci    def load_persid(self):
12447db96d56Sopenharmony_ci        try:
12457db96d56Sopenharmony_ci            pid = self.readline()[:-1].decode("ascii")
12467db96d56Sopenharmony_ci        except UnicodeDecodeError:
12477db96d56Sopenharmony_ci            raise UnpicklingError(
12487db96d56Sopenharmony_ci                "persistent IDs in protocol 0 must be ASCII strings")
12497db96d56Sopenharmony_ci        self.append(self.persistent_load(pid))
12507db96d56Sopenharmony_ci    dispatch[PERSID[0]] = load_persid
12517db96d56Sopenharmony_ci
12527db96d56Sopenharmony_ci    def load_binpersid(self):
12537db96d56Sopenharmony_ci        pid = self.stack.pop()
12547db96d56Sopenharmony_ci        self.append(self.persistent_load(pid))
12557db96d56Sopenharmony_ci    dispatch[BINPERSID[0]] = load_binpersid
12567db96d56Sopenharmony_ci
12577db96d56Sopenharmony_ci    def load_none(self):
12587db96d56Sopenharmony_ci        self.append(None)
12597db96d56Sopenharmony_ci    dispatch[NONE[0]] = load_none
12607db96d56Sopenharmony_ci
12617db96d56Sopenharmony_ci    def load_false(self):
12627db96d56Sopenharmony_ci        self.append(False)
12637db96d56Sopenharmony_ci    dispatch[NEWFALSE[0]] = load_false
12647db96d56Sopenharmony_ci
12657db96d56Sopenharmony_ci    def load_true(self):
12667db96d56Sopenharmony_ci        self.append(True)
12677db96d56Sopenharmony_ci    dispatch[NEWTRUE[0]] = load_true
12687db96d56Sopenharmony_ci
12697db96d56Sopenharmony_ci    def load_int(self):
12707db96d56Sopenharmony_ci        data = self.readline()
12717db96d56Sopenharmony_ci        if data == FALSE[1:]:
12727db96d56Sopenharmony_ci            val = False
12737db96d56Sopenharmony_ci        elif data == TRUE[1:]:
12747db96d56Sopenharmony_ci            val = True
12757db96d56Sopenharmony_ci        else:
12767db96d56Sopenharmony_ci            val = int(data, 0)
12777db96d56Sopenharmony_ci        self.append(val)
12787db96d56Sopenharmony_ci    dispatch[INT[0]] = load_int
12797db96d56Sopenharmony_ci
12807db96d56Sopenharmony_ci    def load_binint(self):
12817db96d56Sopenharmony_ci        self.append(unpack('<i', self.read(4))[0])
12827db96d56Sopenharmony_ci    dispatch[BININT[0]] = load_binint
12837db96d56Sopenharmony_ci
12847db96d56Sopenharmony_ci    def load_binint1(self):
12857db96d56Sopenharmony_ci        self.append(self.read(1)[0])
12867db96d56Sopenharmony_ci    dispatch[BININT1[0]] = load_binint1
12877db96d56Sopenharmony_ci
12887db96d56Sopenharmony_ci    def load_binint2(self):
12897db96d56Sopenharmony_ci        self.append(unpack('<H', self.read(2))[0])
12907db96d56Sopenharmony_ci    dispatch[BININT2[0]] = load_binint2
12917db96d56Sopenharmony_ci
12927db96d56Sopenharmony_ci    def load_long(self):
12937db96d56Sopenharmony_ci        val = self.readline()[:-1]
12947db96d56Sopenharmony_ci        if val and val[-1] == b'L'[0]:
12957db96d56Sopenharmony_ci            val = val[:-1]
12967db96d56Sopenharmony_ci        self.append(int(val, 0))
12977db96d56Sopenharmony_ci    dispatch[LONG[0]] = load_long
12987db96d56Sopenharmony_ci
12997db96d56Sopenharmony_ci    def load_long1(self):
13007db96d56Sopenharmony_ci        n = self.read(1)[0]
13017db96d56Sopenharmony_ci        data = self.read(n)
13027db96d56Sopenharmony_ci        self.append(decode_long(data))
13037db96d56Sopenharmony_ci    dispatch[LONG1[0]] = load_long1
13047db96d56Sopenharmony_ci
13057db96d56Sopenharmony_ci    def load_long4(self):
13067db96d56Sopenharmony_ci        n, = unpack('<i', self.read(4))
13077db96d56Sopenharmony_ci        if n < 0:
13087db96d56Sopenharmony_ci            # Corrupt or hostile pickle -- we never write one like this
13097db96d56Sopenharmony_ci            raise UnpicklingError("LONG pickle has negative byte count")
13107db96d56Sopenharmony_ci        data = self.read(n)
13117db96d56Sopenharmony_ci        self.append(decode_long(data))
13127db96d56Sopenharmony_ci    dispatch[LONG4[0]] = load_long4
13137db96d56Sopenharmony_ci
13147db96d56Sopenharmony_ci    def load_float(self):
13157db96d56Sopenharmony_ci        self.append(float(self.readline()[:-1]))
13167db96d56Sopenharmony_ci    dispatch[FLOAT[0]] = load_float
13177db96d56Sopenharmony_ci
13187db96d56Sopenharmony_ci    def load_binfloat(self):
13197db96d56Sopenharmony_ci        self.append(unpack('>d', self.read(8))[0])
13207db96d56Sopenharmony_ci    dispatch[BINFLOAT[0]] = load_binfloat
13217db96d56Sopenharmony_ci
13227db96d56Sopenharmony_ci    def _decode_string(self, value):
13237db96d56Sopenharmony_ci        # Used to allow strings from Python 2 to be decoded either as
13247db96d56Sopenharmony_ci        # bytes or Unicode strings.  This should be used only with the
13257db96d56Sopenharmony_ci        # STRING, BINSTRING and SHORT_BINSTRING opcodes.
13267db96d56Sopenharmony_ci        if self.encoding == "bytes":
13277db96d56Sopenharmony_ci            return value
13287db96d56Sopenharmony_ci        else:
13297db96d56Sopenharmony_ci            return value.decode(self.encoding, self.errors)
13307db96d56Sopenharmony_ci
13317db96d56Sopenharmony_ci    def load_string(self):
13327db96d56Sopenharmony_ci        data = self.readline()[:-1]
13337db96d56Sopenharmony_ci        # Strip outermost quotes
13347db96d56Sopenharmony_ci        if len(data) >= 2 and data[0] == data[-1] and data[0] in b'"\'':
13357db96d56Sopenharmony_ci            data = data[1:-1]
13367db96d56Sopenharmony_ci        else:
13377db96d56Sopenharmony_ci            raise UnpicklingError("the STRING opcode argument must be quoted")
13387db96d56Sopenharmony_ci        self.append(self._decode_string(codecs.escape_decode(data)[0]))
13397db96d56Sopenharmony_ci    dispatch[STRING[0]] = load_string
13407db96d56Sopenharmony_ci
13417db96d56Sopenharmony_ci    def load_binstring(self):
13427db96d56Sopenharmony_ci        # Deprecated BINSTRING uses signed 32-bit length
13437db96d56Sopenharmony_ci        len, = unpack('<i', self.read(4))
13447db96d56Sopenharmony_ci        if len < 0:
13457db96d56Sopenharmony_ci            raise UnpicklingError("BINSTRING pickle has negative byte count")
13467db96d56Sopenharmony_ci        data = self.read(len)
13477db96d56Sopenharmony_ci        self.append(self._decode_string(data))
13487db96d56Sopenharmony_ci    dispatch[BINSTRING[0]] = load_binstring
13497db96d56Sopenharmony_ci
13507db96d56Sopenharmony_ci    def load_binbytes(self):
13517db96d56Sopenharmony_ci        len, = unpack('<I', self.read(4))
13527db96d56Sopenharmony_ci        if len > maxsize:
13537db96d56Sopenharmony_ci            raise UnpicklingError("BINBYTES exceeds system's maximum size "
13547db96d56Sopenharmony_ci                                  "of %d bytes" % maxsize)
13557db96d56Sopenharmony_ci        self.append(self.read(len))
13567db96d56Sopenharmony_ci    dispatch[BINBYTES[0]] = load_binbytes
13577db96d56Sopenharmony_ci
13587db96d56Sopenharmony_ci    def load_unicode(self):
13597db96d56Sopenharmony_ci        self.append(str(self.readline()[:-1], 'raw-unicode-escape'))
13607db96d56Sopenharmony_ci    dispatch[UNICODE[0]] = load_unicode
13617db96d56Sopenharmony_ci
13627db96d56Sopenharmony_ci    def load_binunicode(self):
13637db96d56Sopenharmony_ci        len, = unpack('<I', self.read(4))
13647db96d56Sopenharmony_ci        if len > maxsize:
13657db96d56Sopenharmony_ci            raise UnpicklingError("BINUNICODE exceeds system's maximum size "
13667db96d56Sopenharmony_ci                                  "of %d bytes" % maxsize)
13677db96d56Sopenharmony_ci        self.append(str(self.read(len), 'utf-8', 'surrogatepass'))
13687db96d56Sopenharmony_ci    dispatch[BINUNICODE[0]] = load_binunicode
13697db96d56Sopenharmony_ci
13707db96d56Sopenharmony_ci    def load_binunicode8(self):
13717db96d56Sopenharmony_ci        len, = unpack('<Q', self.read(8))
13727db96d56Sopenharmony_ci        if len > maxsize:
13737db96d56Sopenharmony_ci            raise UnpicklingError("BINUNICODE8 exceeds system's maximum size "
13747db96d56Sopenharmony_ci                                  "of %d bytes" % maxsize)
13757db96d56Sopenharmony_ci        self.append(str(self.read(len), 'utf-8', 'surrogatepass'))
13767db96d56Sopenharmony_ci    dispatch[BINUNICODE8[0]] = load_binunicode8
13777db96d56Sopenharmony_ci
13787db96d56Sopenharmony_ci    def load_binbytes8(self):
13797db96d56Sopenharmony_ci        len, = unpack('<Q', self.read(8))
13807db96d56Sopenharmony_ci        if len > maxsize:
13817db96d56Sopenharmony_ci            raise UnpicklingError("BINBYTES8 exceeds system's maximum size "
13827db96d56Sopenharmony_ci                                  "of %d bytes" % maxsize)
13837db96d56Sopenharmony_ci        self.append(self.read(len))
13847db96d56Sopenharmony_ci    dispatch[BINBYTES8[0]] = load_binbytes8
13857db96d56Sopenharmony_ci
13867db96d56Sopenharmony_ci    def load_bytearray8(self):
13877db96d56Sopenharmony_ci        len, = unpack('<Q', self.read(8))
13887db96d56Sopenharmony_ci        if len > maxsize:
13897db96d56Sopenharmony_ci            raise UnpicklingError("BYTEARRAY8 exceeds system's maximum size "
13907db96d56Sopenharmony_ci                                  "of %d bytes" % maxsize)
13917db96d56Sopenharmony_ci        b = bytearray(len)
13927db96d56Sopenharmony_ci        self.readinto(b)
13937db96d56Sopenharmony_ci        self.append(b)
13947db96d56Sopenharmony_ci    dispatch[BYTEARRAY8[0]] = load_bytearray8
13957db96d56Sopenharmony_ci
13967db96d56Sopenharmony_ci    def load_next_buffer(self):
13977db96d56Sopenharmony_ci        if self._buffers is None:
13987db96d56Sopenharmony_ci            raise UnpicklingError("pickle stream refers to out-of-band data "
13997db96d56Sopenharmony_ci                                  "but no *buffers* argument was given")
14007db96d56Sopenharmony_ci        try:
14017db96d56Sopenharmony_ci            buf = next(self._buffers)
14027db96d56Sopenharmony_ci        except StopIteration:
14037db96d56Sopenharmony_ci            raise UnpicklingError("not enough out-of-band buffers")
14047db96d56Sopenharmony_ci        self.append(buf)
14057db96d56Sopenharmony_ci    dispatch[NEXT_BUFFER[0]] = load_next_buffer
14067db96d56Sopenharmony_ci
14077db96d56Sopenharmony_ci    def load_readonly_buffer(self):
14087db96d56Sopenharmony_ci        buf = self.stack[-1]
14097db96d56Sopenharmony_ci        with memoryview(buf) as m:
14107db96d56Sopenharmony_ci            if not m.readonly:
14117db96d56Sopenharmony_ci                self.stack[-1] = m.toreadonly()
14127db96d56Sopenharmony_ci    dispatch[READONLY_BUFFER[0]] = load_readonly_buffer
14137db96d56Sopenharmony_ci
14147db96d56Sopenharmony_ci    def load_short_binstring(self):
14157db96d56Sopenharmony_ci        len = self.read(1)[0]
14167db96d56Sopenharmony_ci        data = self.read(len)
14177db96d56Sopenharmony_ci        self.append(self._decode_string(data))
14187db96d56Sopenharmony_ci    dispatch[SHORT_BINSTRING[0]] = load_short_binstring
14197db96d56Sopenharmony_ci
14207db96d56Sopenharmony_ci    def load_short_binbytes(self):
14217db96d56Sopenharmony_ci        len = self.read(1)[0]
14227db96d56Sopenharmony_ci        self.append(self.read(len))
14237db96d56Sopenharmony_ci    dispatch[SHORT_BINBYTES[0]] = load_short_binbytes
14247db96d56Sopenharmony_ci
14257db96d56Sopenharmony_ci    def load_short_binunicode(self):
14267db96d56Sopenharmony_ci        len = self.read(1)[0]
14277db96d56Sopenharmony_ci        self.append(str(self.read(len), 'utf-8', 'surrogatepass'))
14287db96d56Sopenharmony_ci    dispatch[SHORT_BINUNICODE[0]] = load_short_binunicode
14297db96d56Sopenharmony_ci
14307db96d56Sopenharmony_ci    def load_tuple(self):
14317db96d56Sopenharmony_ci        items = self.pop_mark()
14327db96d56Sopenharmony_ci        self.append(tuple(items))
14337db96d56Sopenharmony_ci    dispatch[TUPLE[0]] = load_tuple
14347db96d56Sopenharmony_ci
14357db96d56Sopenharmony_ci    def load_empty_tuple(self):
14367db96d56Sopenharmony_ci        self.append(())
14377db96d56Sopenharmony_ci    dispatch[EMPTY_TUPLE[0]] = load_empty_tuple
14387db96d56Sopenharmony_ci
14397db96d56Sopenharmony_ci    def load_tuple1(self):
14407db96d56Sopenharmony_ci        self.stack[-1] = (self.stack[-1],)
14417db96d56Sopenharmony_ci    dispatch[TUPLE1[0]] = load_tuple1
14427db96d56Sopenharmony_ci
14437db96d56Sopenharmony_ci    def load_tuple2(self):
14447db96d56Sopenharmony_ci        self.stack[-2:] = [(self.stack[-2], self.stack[-1])]
14457db96d56Sopenharmony_ci    dispatch[TUPLE2[0]] = load_tuple2
14467db96d56Sopenharmony_ci
14477db96d56Sopenharmony_ci    def load_tuple3(self):
14487db96d56Sopenharmony_ci        self.stack[-3:] = [(self.stack[-3], self.stack[-2], self.stack[-1])]
14497db96d56Sopenharmony_ci    dispatch[TUPLE3[0]] = load_tuple3
14507db96d56Sopenharmony_ci
14517db96d56Sopenharmony_ci    def load_empty_list(self):
14527db96d56Sopenharmony_ci        self.append([])
14537db96d56Sopenharmony_ci    dispatch[EMPTY_LIST[0]] = load_empty_list
14547db96d56Sopenharmony_ci
14557db96d56Sopenharmony_ci    def load_empty_dictionary(self):
14567db96d56Sopenharmony_ci        self.append({})
14577db96d56Sopenharmony_ci    dispatch[EMPTY_DICT[0]] = load_empty_dictionary
14587db96d56Sopenharmony_ci
14597db96d56Sopenharmony_ci    def load_empty_set(self):
14607db96d56Sopenharmony_ci        self.append(set())
14617db96d56Sopenharmony_ci    dispatch[EMPTY_SET[0]] = load_empty_set
14627db96d56Sopenharmony_ci
14637db96d56Sopenharmony_ci    def load_frozenset(self):
14647db96d56Sopenharmony_ci        items = self.pop_mark()
14657db96d56Sopenharmony_ci        self.append(frozenset(items))
14667db96d56Sopenharmony_ci    dispatch[FROZENSET[0]] = load_frozenset
14677db96d56Sopenharmony_ci
14687db96d56Sopenharmony_ci    def load_list(self):
14697db96d56Sopenharmony_ci        items = self.pop_mark()
14707db96d56Sopenharmony_ci        self.append(items)
14717db96d56Sopenharmony_ci    dispatch[LIST[0]] = load_list
14727db96d56Sopenharmony_ci
14737db96d56Sopenharmony_ci    def load_dict(self):
14747db96d56Sopenharmony_ci        items = self.pop_mark()
14757db96d56Sopenharmony_ci        d = {items[i]: items[i+1]
14767db96d56Sopenharmony_ci             for i in range(0, len(items), 2)}
14777db96d56Sopenharmony_ci        self.append(d)
14787db96d56Sopenharmony_ci    dispatch[DICT[0]] = load_dict
14797db96d56Sopenharmony_ci
14807db96d56Sopenharmony_ci    # INST and OBJ differ only in how they get a class object.  It's not
14817db96d56Sopenharmony_ci    # only sensible to do the rest in a common routine, the two routines
14827db96d56Sopenharmony_ci    # previously diverged and grew different bugs.
14837db96d56Sopenharmony_ci    # klass is the class to instantiate, and k points to the topmost mark
14847db96d56Sopenharmony_ci    # object, following which are the arguments for klass.__init__.
14857db96d56Sopenharmony_ci    def _instantiate(self, klass, args):
14867db96d56Sopenharmony_ci        if (args or not isinstance(klass, type) or
14877db96d56Sopenharmony_ci            hasattr(klass, "__getinitargs__")):
14887db96d56Sopenharmony_ci            try:
14897db96d56Sopenharmony_ci                value = klass(*args)
14907db96d56Sopenharmony_ci            except TypeError as err:
14917db96d56Sopenharmony_ci                raise TypeError("in constructor for %s: %s" %
14927db96d56Sopenharmony_ci                                (klass.__name__, str(err)), sys.exc_info()[2])
14937db96d56Sopenharmony_ci        else:
14947db96d56Sopenharmony_ci            value = klass.__new__(klass)
14957db96d56Sopenharmony_ci        self.append(value)
14967db96d56Sopenharmony_ci
14977db96d56Sopenharmony_ci    def load_inst(self):
14987db96d56Sopenharmony_ci        module = self.readline()[:-1].decode("ascii")
14997db96d56Sopenharmony_ci        name = self.readline()[:-1].decode("ascii")
15007db96d56Sopenharmony_ci        klass = self.find_class(module, name)
15017db96d56Sopenharmony_ci        self._instantiate(klass, self.pop_mark())
15027db96d56Sopenharmony_ci    dispatch[INST[0]] = load_inst
15037db96d56Sopenharmony_ci
15047db96d56Sopenharmony_ci    def load_obj(self):
15057db96d56Sopenharmony_ci        # Stack is ... markobject classobject arg1 arg2 ...
15067db96d56Sopenharmony_ci        args = self.pop_mark()
15077db96d56Sopenharmony_ci        cls = args.pop(0)
15087db96d56Sopenharmony_ci        self._instantiate(cls, args)
15097db96d56Sopenharmony_ci    dispatch[OBJ[0]] = load_obj
15107db96d56Sopenharmony_ci
15117db96d56Sopenharmony_ci    def load_newobj(self):
15127db96d56Sopenharmony_ci        args = self.stack.pop()
15137db96d56Sopenharmony_ci        cls = self.stack.pop()
15147db96d56Sopenharmony_ci        obj = cls.__new__(cls, *args)
15157db96d56Sopenharmony_ci        self.append(obj)
15167db96d56Sopenharmony_ci    dispatch[NEWOBJ[0]] = load_newobj
15177db96d56Sopenharmony_ci
15187db96d56Sopenharmony_ci    def load_newobj_ex(self):
15197db96d56Sopenharmony_ci        kwargs = self.stack.pop()
15207db96d56Sopenharmony_ci        args = self.stack.pop()
15217db96d56Sopenharmony_ci        cls = self.stack.pop()
15227db96d56Sopenharmony_ci        obj = cls.__new__(cls, *args, **kwargs)
15237db96d56Sopenharmony_ci        self.append(obj)
15247db96d56Sopenharmony_ci    dispatch[NEWOBJ_EX[0]] = load_newobj_ex
15257db96d56Sopenharmony_ci
15267db96d56Sopenharmony_ci    def load_global(self):
15277db96d56Sopenharmony_ci        module = self.readline()[:-1].decode("utf-8")
15287db96d56Sopenharmony_ci        name = self.readline()[:-1].decode("utf-8")
15297db96d56Sopenharmony_ci        klass = self.find_class(module, name)
15307db96d56Sopenharmony_ci        self.append(klass)
15317db96d56Sopenharmony_ci    dispatch[GLOBAL[0]] = load_global
15327db96d56Sopenharmony_ci
15337db96d56Sopenharmony_ci    def load_stack_global(self):
15347db96d56Sopenharmony_ci        name = self.stack.pop()
15357db96d56Sopenharmony_ci        module = self.stack.pop()
15367db96d56Sopenharmony_ci        if type(name) is not str or type(module) is not str:
15377db96d56Sopenharmony_ci            raise UnpicklingError("STACK_GLOBAL requires str")
15387db96d56Sopenharmony_ci        self.append(self.find_class(module, name))
15397db96d56Sopenharmony_ci    dispatch[STACK_GLOBAL[0]] = load_stack_global
15407db96d56Sopenharmony_ci
15417db96d56Sopenharmony_ci    def load_ext1(self):
15427db96d56Sopenharmony_ci        code = self.read(1)[0]
15437db96d56Sopenharmony_ci        self.get_extension(code)
15447db96d56Sopenharmony_ci    dispatch[EXT1[0]] = load_ext1
15457db96d56Sopenharmony_ci
15467db96d56Sopenharmony_ci    def load_ext2(self):
15477db96d56Sopenharmony_ci        code, = unpack('<H', self.read(2))
15487db96d56Sopenharmony_ci        self.get_extension(code)
15497db96d56Sopenharmony_ci    dispatch[EXT2[0]] = load_ext2
15507db96d56Sopenharmony_ci
15517db96d56Sopenharmony_ci    def load_ext4(self):
15527db96d56Sopenharmony_ci        code, = unpack('<i', self.read(4))
15537db96d56Sopenharmony_ci        self.get_extension(code)
15547db96d56Sopenharmony_ci    dispatch[EXT4[0]] = load_ext4
15557db96d56Sopenharmony_ci
15567db96d56Sopenharmony_ci    def get_extension(self, code):
15577db96d56Sopenharmony_ci        nil = []
15587db96d56Sopenharmony_ci        obj = _extension_cache.get(code, nil)
15597db96d56Sopenharmony_ci        if obj is not nil:
15607db96d56Sopenharmony_ci            self.append(obj)
15617db96d56Sopenharmony_ci            return
15627db96d56Sopenharmony_ci        key = _inverted_registry.get(code)
15637db96d56Sopenharmony_ci        if not key:
15647db96d56Sopenharmony_ci            if code <= 0: # note that 0 is forbidden
15657db96d56Sopenharmony_ci                # Corrupt or hostile pickle.
15667db96d56Sopenharmony_ci                raise UnpicklingError("EXT specifies code <= 0")
15677db96d56Sopenharmony_ci            raise ValueError("unregistered extension code %d" % code)
15687db96d56Sopenharmony_ci        obj = self.find_class(*key)
15697db96d56Sopenharmony_ci        _extension_cache[code] = obj
15707db96d56Sopenharmony_ci        self.append(obj)
15717db96d56Sopenharmony_ci
15727db96d56Sopenharmony_ci    def find_class(self, module, name):
15737db96d56Sopenharmony_ci        # Subclasses may override this.
15747db96d56Sopenharmony_ci        sys.audit('pickle.find_class', module, name)
15757db96d56Sopenharmony_ci        if self.proto < 3 and self.fix_imports:
15767db96d56Sopenharmony_ci            if (module, name) in _compat_pickle.NAME_MAPPING:
15777db96d56Sopenharmony_ci                module, name = _compat_pickle.NAME_MAPPING[(module, name)]
15787db96d56Sopenharmony_ci            elif module in _compat_pickle.IMPORT_MAPPING:
15797db96d56Sopenharmony_ci                module = _compat_pickle.IMPORT_MAPPING[module]
15807db96d56Sopenharmony_ci        __import__(module, level=0)
15817db96d56Sopenharmony_ci        if self.proto >= 4:
15827db96d56Sopenharmony_ci            return _getattribute(sys.modules[module], name)[0]
15837db96d56Sopenharmony_ci        else:
15847db96d56Sopenharmony_ci            return getattr(sys.modules[module], name)
15857db96d56Sopenharmony_ci
15867db96d56Sopenharmony_ci    def load_reduce(self):
15877db96d56Sopenharmony_ci        stack = self.stack
15887db96d56Sopenharmony_ci        args = stack.pop()
15897db96d56Sopenharmony_ci        func = stack[-1]
15907db96d56Sopenharmony_ci        stack[-1] = func(*args)
15917db96d56Sopenharmony_ci    dispatch[REDUCE[0]] = load_reduce
15927db96d56Sopenharmony_ci
15937db96d56Sopenharmony_ci    def load_pop(self):
15947db96d56Sopenharmony_ci        if self.stack:
15957db96d56Sopenharmony_ci            del self.stack[-1]
15967db96d56Sopenharmony_ci        else:
15977db96d56Sopenharmony_ci            self.pop_mark()
15987db96d56Sopenharmony_ci    dispatch[POP[0]] = load_pop
15997db96d56Sopenharmony_ci
16007db96d56Sopenharmony_ci    def load_pop_mark(self):
16017db96d56Sopenharmony_ci        self.pop_mark()
16027db96d56Sopenharmony_ci    dispatch[POP_MARK[0]] = load_pop_mark
16037db96d56Sopenharmony_ci
16047db96d56Sopenharmony_ci    def load_dup(self):
16057db96d56Sopenharmony_ci        self.append(self.stack[-1])
16067db96d56Sopenharmony_ci    dispatch[DUP[0]] = load_dup
16077db96d56Sopenharmony_ci
16087db96d56Sopenharmony_ci    def load_get(self):
16097db96d56Sopenharmony_ci        i = int(self.readline()[:-1])
16107db96d56Sopenharmony_ci        try:
16117db96d56Sopenharmony_ci            self.append(self.memo[i])
16127db96d56Sopenharmony_ci        except KeyError:
16137db96d56Sopenharmony_ci            msg = f'Memo value not found at index {i}'
16147db96d56Sopenharmony_ci            raise UnpicklingError(msg) from None
16157db96d56Sopenharmony_ci    dispatch[GET[0]] = load_get
16167db96d56Sopenharmony_ci
16177db96d56Sopenharmony_ci    def load_binget(self):
16187db96d56Sopenharmony_ci        i = self.read(1)[0]
16197db96d56Sopenharmony_ci        try:
16207db96d56Sopenharmony_ci            self.append(self.memo[i])
16217db96d56Sopenharmony_ci        except KeyError as exc:
16227db96d56Sopenharmony_ci            msg = f'Memo value not found at index {i}'
16237db96d56Sopenharmony_ci            raise UnpicklingError(msg) from None
16247db96d56Sopenharmony_ci    dispatch[BINGET[0]] = load_binget
16257db96d56Sopenharmony_ci
16267db96d56Sopenharmony_ci    def load_long_binget(self):
16277db96d56Sopenharmony_ci        i, = unpack('<I', self.read(4))
16287db96d56Sopenharmony_ci        try:
16297db96d56Sopenharmony_ci            self.append(self.memo[i])
16307db96d56Sopenharmony_ci        except KeyError as exc:
16317db96d56Sopenharmony_ci            msg = f'Memo value not found at index {i}'
16327db96d56Sopenharmony_ci            raise UnpicklingError(msg) from None
16337db96d56Sopenharmony_ci    dispatch[LONG_BINGET[0]] = load_long_binget
16347db96d56Sopenharmony_ci
16357db96d56Sopenharmony_ci    def load_put(self):
16367db96d56Sopenharmony_ci        i = int(self.readline()[:-1])
16377db96d56Sopenharmony_ci        if i < 0:
16387db96d56Sopenharmony_ci            raise ValueError("negative PUT argument")
16397db96d56Sopenharmony_ci        self.memo[i] = self.stack[-1]
16407db96d56Sopenharmony_ci    dispatch[PUT[0]] = load_put
16417db96d56Sopenharmony_ci
16427db96d56Sopenharmony_ci    def load_binput(self):
16437db96d56Sopenharmony_ci        i = self.read(1)[0]
16447db96d56Sopenharmony_ci        if i < 0:
16457db96d56Sopenharmony_ci            raise ValueError("negative BINPUT argument")
16467db96d56Sopenharmony_ci        self.memo[i] = self.stack[-1]
16477db96d56Sopenharmony_ci    dispatch[BINPUT[0]] = load_binput
16487db96d56Sopenharmony_ci
16497db96d56Sopenharmony_ci    def load_long_binput(self):
16507db96d56Sopenharmony_ci        i, = unpack('<I', self.read(4))
16517db96d56Sopenharmony_ci        if i > maxsize:
16527db96d56Sopenharmony_ci            raise ValueError("negative LONG_BINPUT argument")
16537db96d56Sopenharmony_ci        self.memo[i] = self.stack[-1]
16547db96d56Sopenharmony_ci    dispatch[LONG_BINPUT[0]] = load_long_binput
16557db96d56Sopenharmony_ci
16567db96d56Sopenharmony_ci    def load_memoize(self):
16577db96d56Sopenharmony_ci        memo = self.memo
16587db96d56Sopenharmony_ci        memo[len(memo)] = self.stack[-1]
16597db96d56Sopenharmony_ci    dispatch[MEMOIZE[0]] = load_memoize
16607db96d56Sopenharmony_ci
16617db96d56Sopenharmony_ci    def load_append(self):
16627db96d56Sopenharmony_ci        stack = self.stack
16637db96d56Sopenharmony_ci        value = stack.pop()
16647db96d56Sopenharmony_ci        list = stack[-1]
16657db96d56Sopenharmony_ci        list.append(value)
16667db96d56Sopenharmony_ci    dispatch[APPEND[0]] = load_append
16677db96d56Sopenharmony_ci
16687db96d56Sopenharmony_ci    def load_appends(self):
16697db96d56Sopenharmony_ci        items = self.pop_mark()
16707db96d56Sopenharmony_ci        list_obj = self.stack[-1]
16717db96d56Sopenharmony_ci        try:
16727db96d56Sopenharmony_ci            extend = list_obj.extend
16737db96d56Sopenharmony_ci        except AttributeError:
16747db96d56Sopenharmony_ci            pass
16757db96d56Sopenharmony_ci        else:
16767db96d56Sopenharmony_ci            extend(items)
16777db96d56Sopenharmony_ci            return
16787db96d56Sopenharmony_ci        # Even if the PEP 307 requires extend() and append() methods,
16797db96d56Sopenharmony_ci        # fall back on append() if the object has no extend() method
16807db96d56Sopenharmony_ci        # for backward compatibility.
16817db96d56Sopenharmony_ci        append = list_obj.append
16827db96d56Sopenharmony_ci        for item in items:
16837db96d56Sopenharmony_ci            append(item)
16847db96d56Sopenharmony_ci    dispatch[APPENDS[0]] = load_appends
16857db96d56Sopenharmony_ci
16867db96d56Sopenharmony_ci    def load_setitem(self):
16877db96d56Sopenharmony_ci        stack = self.stack
16887db96d56Sopenharmony_ci        value = stack.pop()
16897db96d56Sopenharmony_ci        key = stack.pop()
16907db96d56Sopenharmony_ci        dict = stack[-1]
16917db96d56Sopenharmony_ci        dict[key] = value
16927db96d56Sopenharmony_ci    dispatch[SETITEM[0]] = load_setitem
16937db96d56Sopenharmony_ci
16947db96d56Sopenharmony_ci    def load_setitems(self):
16957db96d56Sopenharmony_ci        items = self.pop_mark()
16967db96d56Sopenharmony_ci        dict = self.stack[-1]
16977db96d56Sopenharmony_ci        for i in range(0, len(items), 2):
16987db96d56Sopenharmony_ci            dict[items[i]] = items[i + 1]
16997db96d56Sopenharmony_ci    dispatch[SETITEMS[0]] = load_setitems
17007db96d56Sopenharmony_ci
17017db96d56Sopenharmony_ci    def load_additems(self):
17027db96d56Sopenharmony_ci        items = self.pop_mark()
17037db96d56Sopenharmony_ci        set_obj = self.stack[-1]
17047db96d56Sopenharmony_ci        if isinstance(set_obj, set):
17057db96d56Sopenharmony_ci            set_obj.update(items)
17067db96d56Sopenharmony_ci        else:
17077db96d56Sopenharmony_ci            add = set_obj.add
17087db96d56Sopenharmony_ci            for item in items:
17097db96d56Sopenharmony_ci                add(item)
17107db96d56Sopenharmony_ci    dispatch[ADDITEMS[0]] = load_additems
17117db96d56Sopenharmony_ci
17127db96d56Sopenharmony_ci    def load_build(self):
17137db96d56Sopenharmony_ci        stack = self.stack
17147db96d56Sopenharmony_ci        state = stack.pop()
17157db96d56Sopenharmony_ci        inst = stack[-1]
17167db96d56Sopenharmony_ci        setstate = getattr(inst, "__setstate__", None)
17177db96d56Sopenharmony_ci        if setstate is not None:
17187db96d56Sopenharmony_ci            setstate(state)
17197db96d56Sopenharmony_ci            return
17207db96d56Sopenharmony_ci        slotstate = None
17217db96d56Sopenharmony_ci        if isinstance(state, tuple) and len(state) == 2:
17227db96d56Sopenharmony_ci            state, slotstate = state
17237db96d56Sopenharmony_ci        if state:
17247db96d56Sopenharmony_ci            inst_dict = inst.__dict__
17257db96d56Sopenharmony_ci            intern = sys.intern
17267db96d56Sopenharmony_ci            for k, v in state.items():
17277db96d56Sopenharmony_ci                if type(k) is str:
17287db96d56Sopenharmony_ci                    inst_dict[intern(k)] = v
17297db96d56Sopenharmony_ci                else:
17307db96d56Sopenharmony_ci                    inst_dict[k] = v
17317db96d56Sopenharmony_ci        if slotstate:
17327db96d56Sopenharmony_ci            for k, v in slotstate.items():
17337db96d56Sopenharmony_ci                setattr(inst, k, v)
17347db96d56Sopenharmony_ci    dispatch[BUILD[0]] = load_build
17357db96d56Sopenharmony_ci
17367db96d56Sopenharmony_ci    def load_mark(self):
17377db96d56Sopenharmony_ci        self.metastack.append(self.stack)
17387db96d56Sopenharmony_ci        self.stack = []
17397db96d56Sopenharmony_ci        self.append = self.stack.append
17407db96d56Sopenharmony_ci    dispatch[MARK[0]] = load_mark
17417db96d56Sopenharmony_ci
17427db96d56Sopenharmony_ci    def load_stop(self):
17437db96d56Sopenharmony_ci        value = self.stack.pop()
17447db96d56Sopenharmony_ci        raise _Stop(value)
17457db96d56Sopenharmony_ci    dispatch[STOP[0]] = load_stop
17467db96d56Sopenharmony_ci
17477db96d56Sopenharmony_ci
17487db96d56Sopenharmony_ci# Shorthands
17497db96d56Sopenharmony_ci
17507db96d56Sopenharmony_cidef _dump(obj, file, protocol=None, *, fix_imports=True, buffer_callback=None):
17517db96d56Sopenharmony_ci    _Pickler(file, protocol, fix_imports=fix_imports,
17527db96d56Sopenharmony_ci             buffer_callback=buffer_callback).dump(obj)
17537db96d56Sopenharmony_ci
17547db96d56Sopenharmony_cidef _dumps(obj, protocol=None, *, fix_imports=True, buffer_callback=None):
17557db96d56Sopenharmony_ci    f = io.BytesIO()
17567db96d56Sopenharmony_ci    _Pickler(f, protocol, fix_imports=fix_imports,
17577db96d56Sopenharmony_ci             buffer_callback=buffer_callback).dump(obj)
17587db96d56Sopenharmony_ci    res = f.getvalue()
17597db96d56Sopenharmony_ci    assert isinstance(res, bytes_types)
17607db96d56Sopenharmony_ci    return res
17617db96d56Sopenharmony_ci
17627db96d56Sopenharmony_cidef _load(file, *, fix_imports=True, encoding="ASCII", errors="strict",
17637db96d56Sopenharmony_ci          buffers=None):
17647db96d56Sopenharmony_ci    return _Unpickler(file, fix_imports=fix_imports, buffers=buffers,
17657db96d56Sopenharmony_ci                     encoding=encoding, errors=errors).load()
17667db96d56Sopenharmony_ci
17677db96d56Sopenharmony_cidef _loads(s, /, *, fix_imports=True, encoding="ASCII", errors="strict",
17687db96d56Sopenharmony_ci           buffers=None):
17697db96d56Sopenharmony_ci    if isinstance(s, str):
17707db96d56Sopenharmony_ci        raise TypeError("Can't load pickle from unicode string")
17717db96d56Sopenharmony_ci    file = io.BytesIO(s)
17727db96d56Sopenharmony_ci    return _Unpickler(file, fix_imports=fix_imports, buffers=buffers,
17737db96d56Sopenharmony_ci                      encoding=encoding, errors=errors).load()
17747db96d56Sopenharmony_ci
17757db96d56Sopenharmony_ci# Use the faster _pickle if possible
17767db96d56Sopenharmony_citry:
17777db96d56Sopenharmony_ci    from _pickle import (
17787db96d56Sopenharmony_ci        PickleError,
17797db96d56Sopenharmony_ci        PicklingError,
17807db96d56Sopenharmony_ci        UnpicklingError,
17817db96d56Sopenharmony_ci        Pickler,
17827db96d56Sopenharmony_ci        Unpickler,
17837db96d56Sopenharmony_ci        dump,
17847db96d56Sopenharmony_ci        dumps,
17857db96d56Sopenharmony_ci        load,
17867db96d56Sopenharmony_ci        loads
17877db96d56Sopenharmony_ci    )
17887db96d56Sopenharmony_ciexcept ImportError:
17897db96d56Sopenharmony_ci    Pickler, Unpickler = _Pickler, _Unpickler
17907db96d56Sopenharmony_ci    dump, dumps, load, loads = _dump, _dumps, _load, _loads
17917db96d56Sopenharmony_ci
17927db96d56Sopenharmony_ci# Doctest
17937db96d56Sopenharmony_cidef _test():
17947db96d56Sopenharmony_ci    import doctest
17957db96d56Sopenharmony_ci    return doctest.testmod()
17967db96d56Sopenharmony_ci
17977db96d56Sopenharmony_ciif __name__ == "__main__":
17987db96d56Sopenharmony_ci    import argparse
17997db96d56Sopenharmony_ci    parser = argparse.ArgumentParser(
18007db96d56Sopenharmony_ci        description='display contents of the pickle files')
18017db96d56Sopenharmony_ci    parser.add_argument(
18027db96d56Sopenharmony_ci        'pickle_file', type=argparse.FileType('br'),
18037db96d56Sopenharmony_ci        nargs='*', help='the pickle file')
18047db96d56Sopenharmony_ci    parser.add_argument(
18057db96d56Sopenharmony_ci        '-t', '--test', action='store_true',
18067db96d56Sopenharmony_ci        help='run self-test suite')
18077db96d56Sopenharmony_ci    parser.add_argument(
18087db96d56Sopenharmony_ci        '-v', action='store_true',
18097db96d56Sopenharmony_ci        help='run verbosely; only affects self-test run')
18107db96d56Sopenharmony_ci    args = parser.parse_args()
18117db96d56Sopenharmony_ci    if args.test:
18127db96d56Sopenharmony_ci        _test()
18137db96d56Sopenharmony_ci    else:
18147db96d56Sopenharmony_ci        if not args.pickle_file:
18157db96d56Sopenharmony_ci            parser.print_help()
18167db96d56Sopenharmony_ci        else:
18177db96d56Sopenharmony_ci            import pprint
18187db96d56Sopenharmony_ci            for f in args.pickle_file:
18197db96d56Sopenharmony_ci                obj = load(f)
18207db96d56Sopenharmony_ci                pprint.pprint(obj)
1821