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