1*cda5da8dSAndroid Build Coastguard Worker"""Create portable serialized representations of Python objects. 2*cda5da8dSAndroid Build Coastguard Worker 3*cda5da8dSAndroid Build Coastguard WorkerSee module copyreg for a mechanism for registering custom picklers. 4*cda5da8dSAndroid Build Coastguard WorkerSee module pickletools source for extensive comments. 5*cda5da8dSAndroid Build Coastguard Worker 6*cda5da8dSAndroid Build Coastguard WorkerClasses: 7*cda5da8dSAndroid Build Coastguard Worker 8*cda5da8dSAndroid Build Coastguard Worker Pickler 9*cda5da8dSAndroid Build Coastguard Worker Unpickler 10*cda5da8dSAndroid Build Coastguard Worker 11*cda5da8dSAndroid Build Coastguard WorkerFunctions: 12*cda5da8dSAndroid Build Coastguard Worker 13*cda5da8dSAndroid Build Coastguard Worker dump(object, file) 14*cda5da8dSAndroid Build Coastguard Worker dumps(object) -> string 15*cda5da8dSAndroid Build Coastguard Worker load(file) -> object 16*cda5da8dSAndroid Build Coastguard Worker loads(bytes) -> object 17*cda5da8dSAndroid Build Coastguard Worker 18*cda5da8dSAndroid Build Coastguard WorkerMisc variables: 19*cda5da8dSAndroid Build Coastguard Worker 20*cda5da8dSAndroid Build Coastguard Worker __version__ 21*cda5da8dSAndroid Build Coastguard Worker format_version 22*cda5da8dSAndroid Build Coastguard Worker compatible_formats 23*cda5da8dSAndroid Build Coastguard Worker 24*cda5da8dSAndroid Build Coastguard Worker""" 25*cda5da8dSAndroid Build Coastguard Worker 26*cda5da8dSAndroid Build Coastguard Workerfrom types import FunctionType 27*cda5da8dSAndroid Build Coastguard Workerfrom copyreg import dispatch_table 28*cda5da8dSAndroid Build Coastguard Workerfrom copyreg import _extension_registry, _inverted_registry, _extension_cache 29*cda5da8dSAndroid Build Coastguard Workerfrom itertools import islice 30*cda5da8dSAndroid Build Coastguard Workerfrom functools import partial 31*cda5da8dSAndroid Build Coastguard Workerimport sys 32*cda5da8dSAndroid Build Coastguard Workerfrom sys import maxsize 33*cda5da8dSAndroid Build Coastguard Workerfrom struct import pack, unpack 34*cda5da8dSAndroid Build Coastguard Workerimport re 35*cda5da8dSAndroid Build Coastguard Workerimport io 36*cda5da8dSAndroid Build Coastguard Workerimport codecs 37*cda5da8dSAndroid Build Coastguard Workerimport _compat_pickle 38*cda5da8dSAndroid Build Coastguard Worker 39*cda5da8dSAndroid Build Coastguard Worker__all__ = ["PickleError", "PicklingError", "UnpicklingError", "Pickler", 40*cda5da8dSAndroid Build Coastguard Worker "Unpickler", "dump", "dumps", "load", "loads"] 41*cda5da8dSAndroid Build Coastguard Worker 42*cda5da8dSAndroid Build Coastguard Workertry: 43*cda5da8dSAndroid Build Coastguard Worker from _pickle import PickleBuffer 44*cda5da8dSAndroid Build Coastguard Worker __all__.append("PickleBuffer") 45*cda5da8dSAndroid Build Coastguard Worker _HAVE_PICKLE_BUFFER = True 46*cda5da8dSAndroid Build Coastguard Workerexcept ImportError: 47*cda5da8dSAndroid Build Coastguard Worker _HAVE_PICKLE_BUFFER = False 48*cda5da8dSAndroid Build Coastguard Worker 49*cda5da8dSAndroid Build Coastguard Worker 50*cda5da8dSAndroid Build Coastguard Worker# Shortcut for use in isinstance testing 51*cda5da8dSAndroid Build Coastguard Workerbytes_types = (bytes, bytearray) 52*cda5da8dSAndroid Build Coastguard Worker 53*cda5da8dSAndroid Build Coastguard Worker# These are purely informational; no code uses these. 54*cda5da8dSAndroid Build Coastguard Workerformat_version = "4.0" # File format version we write 55*cda5da8dSAndroid Build Coastguard Workercompatible_formats = ["1.0", # Original protocol 0 56*cda5da8dSAndroid Build Coastguard Worker "1.1", # Protocol 0 with INST added 57*cda5da8dSAndroid Build Coastguard Worker "1.2", # Original protocol 1 58*cda5da8dSAndroid Build Coastguard Worker "1.3", # Protocol 1 with BINFLOAT added 59*cda5da8dSAndroid Build Coastguard Worker "2.0", # Protocol 2 60*cda5da8dSAndroid Build Coastguard Worker "3.0", # Protocol 3 61*cda5da8dSAndroid Build Coastguard Worker "4.0", # Protocol 4 62*cda5da8dSAndroid Build Coastguard Worker "5.0", # Protocol 5 63*cda5da8dSAndroid Build Coastguard Worker ] # Old format versions we can read 64*cda5da8dSAndroid Build Coastguard Worker 65*cda5da8dSAndroid Build Coastguard Worker# This is the highest protocol number we know how to read. 66*cda5da8dSAndroid Build Coastguard WorkerHIGHEST_PROTOCOL = 5 67*cda5da8dSAndroid Build Coastguard Worker 68*cda5da8dSAndroid Build Coastguard Worker# The protocol we write by default. May be less than HIGHEST_PROTOCOL. 69*cda5da8dSAndroid Build Coastguard Worker# Only bump this if the oldest still supported version of Python already 70*cda5da8dSAndroid Build Coastguard Worker# includes it. 71*cda5da8dSAndroid Build Coastguard WorkerDEFAULT_PROTOCOL = 4 72*cda5da8dSAndroid Build Coastguard Worker 73*cda5da8dSAndroid Build Coastguard Workerclass PickleError(Exception): 74*cda5da8dSAndroid Build Coastguard Worker """A common base class for the other pickling exceptions.""" 75*cda5da8dSAndroid Build Coastguard Worker pass 76*cda5da8dSAndroid Build Coastguard Worker 77*cda5da8dSAndroid Build Coastguard Workerclass PicklingError(PickleError): 78*cda5da8dSAndroid Build Coastguard Worker """This exception is raised when an unpicklable object is passed to the 79*cda5da8dSAndroid Build Coastguard Worker dump() method. 80*cda5da8dSAndroid Build Coastguard Worker 81*cda5da8dSAndroid Build Coastguard Worker """ 82*cda5da8dSAndroid Build Coastguard Worker pass 83*cda5da8dSAndroid Build Coastguard Worker 84*cda5da8dSAndroid Build Coastguard Workerclass UnpicklingError(PickleError): 85*cda5da8dSAndroid Build Coastguard Worker """This exception is raised when there is a problem unpickling an object, 86*cda5da8dSAndroid Build Coastguard Worker such as a security violation. 87*cda5da8dSAndroid Build Coastguard Worker 88*cda5da8dSAndroid Build Coastguard Worker Note that other exceptions may also be raised during unpickling, including 89*cda5da8dSAndroid Build Coastguard Worker (but not necessarily limited to) AttributeError, EOFError, ImportError, 90*cda5da8dSAndroid Build Coastguard Worker and IndexError. 91*cda5da8dSAndroid Build Coastguard Worker 92*cda5da8dSAndroid Build Coastguard Worker """ 93*cda5da8dSAndroid Build Coastguard Worker pass 94*cda5da8dSAndroid Build Coastguard Worker 95*cda5da8dSAndroid Build Coastguard Worker# An instance of _Stop is raised by Unpickler.load_stop() in response to 96*cda5da8dSAndroid Build Coastguard Worker# the STOP opcode, passing the object that is the result of unpickling. 97*cda5da8dSAndroid Build Coastguard Workerclass _Stop(Exception): 98*cda5da8dSAndroid Build Coastguard Worker def __init__(self, value): 99*cda5da8dSAndroid Build Coastguard Worker self.value = value 100*cda5da8dSAndroid Build Coastguard Worker 101*cda5da8dSAndroid Build Coastguard Worker# Jython has PyStringMap; it's a dict subclass with string keys 102*cda5da8dSAndroid Build Coastguard Workertry: 103*cda5da8dSAndroid Build Coastguard Worker from org.python.core import PyStringMap 104*cda5da8dSAndroid Build Coastguard Workerexcept ImportError: 105*cda5da8dSAndroid Build Coastguard Worker PyStringMap = None 106*cda5da8dSAndroid Build Coastguard Worker 107*cda5da8dSAndroid Build Coastguard Worker# Pickle opcodes. See pickletools.py for extensive docs. The listing 108*cda5da8dSAndroid Build Coastguard Worker# here is in kind-of alphabetical order of 1-character pickle code. 109*cda5da8dSAndroid Build Coastguard Worker# pickletools groups them by purpose. 110*cda5da8dSAndroid Build Coastguard Worker 111*cda5da8dSAndroid Build Coastguard WorkerMARK = b'(' # push special markobject on stack 112*cda5da8dSAndroid Build Coastguard WorkerSTOP = b'.' # every pickle ends with STOP 113*cda5da8dSAndroid Build Coastguard WorkerPOP = b'0' # discard topmost stack item 114*cda5da8dSAndroid Build Coastguard WorkerPOP_MARK = b'1' # discard stack top through topmost markobject 115*cda5da8dSAndroid Build Coastguard WorkerDUP = b'2' # duplicate top stack item 116*cda5da8dSAndroid Build Coastguard WorkerFLOAT = b'F' # push float object; decimal string argument 117*cda5da8dSAndroid Build Coastguard WorkerINT = b'I' # push integer or bool; decimal string argument 118*cda5da8dSAndroid Build Coastguard WorkerBININT = b'J' # push four-byte signed int 119*cda5da8dSAndroid Build Coastguard WorkerBININT1 = b'K' # push 1-byte unsigned int 120*cda5da8dSAndroid Build Coastguard WorkerLONG = b'L' # push long; decimal string argument 121*cda5da8dSAndroid Build Coastguard WorkerBININT2 = b'M' # push 2-byte unsigned int 122*cda5da8dSAndroid Build Coastguard WorkerNONE = b'N' # push None 123*cda5da8dSAndroid Build Coastguard WorkerPERSID = b'P' # push persistent object; id is taken from string arg 124*cda5da8dSAndroid Build Coastguard WorkerBINPERSID = b'Q' # " " " ; " " " " stack 125*cda5da8dSAndroid Build Coastguard WorkerREDUCE = b'R' # apply callable to argtuple, both on stack 126*cda5da8dSAndroid Build Coastguard WorkerSTRING = b'S' # push string; NL-terminated string argument 127*cda5da8dSAndroid Build Coastguard WorkerBINSTRING = b'T' # push string; counted binary string argument 128*cda5da8dSAndroid Build Coastguard WorkerSHORT_BINSTRING= b'U' # " " ; " " " " < 256 bytes 129*cda5da8dSAndroid Build Coastguard WorkerUNICODE = b'V' # push Unicode string; raw-unicode-escaped'd argument 130*cda5da8dSAndroid Build Coastguard WorkerBINUNICODE = b'X' # " " " ; counted UTF-8 string argument 131*cda5da8dSAndroid Build Coastguard WorkerAPPEND = b'a' # append stack top to list below it 132*cda5da8dSAndroid Build Coastguard WorkerBUILD = b'b' # call __setstate__ or __dict__.update() 133*cda5da8dSAndroid Build Coastguard WorkerGLOBAL = b'c' # push self.find_class(modname, name); 2 string args 134*cda5da8dSAndroid Build Coastguard WorkerDICT = b'd' # build a dict from stack items 135*cda5da8dSAndroid Build Coastguard WorkerEMPTY_DICT = b'}' # push empty dict 136*cda5da8dSAndroid Build Coastguard WorkerAPPENDS = b'e' # extend list on stack by topmost stack slice 137*cda5da8dSAndroid Build Coastguard WorkerGET = b'g' # push item from memo on stack; index is string arg 138*cda5da8dSAndroid Build Coastguard WorkerBINGET = b'h' # " " " " " " ; " " 1-byte arg 139*cda5da8dSAndroid Build Coastguard WorkerINST = b'i' # build & push class instance 140*cda5da8dSAndroid Build Coastguard WorkerLONG_BINGET = b'j' # push item from memo on stack; index is 4-byte arg 141*cda5da8dSAndroid Build Coastguard WorkerLIST = b'l' # build list from topmost stack items 142*cda5da8dSAndroid Build Coastguard WorkerEMPTY_LIST = b']' # push empty list 143*cda5da8dSAndroid Build Coastguard WorkerOBJ = b'o' # build & push class instance 144*cda5da8dSAndroid Build Coastguard WorkerPUT = b'p' # store stack top in memo; index is string arg 145*cda5da8dSAndroid Build Coastguard WorkerBINPUT = b'q' # " " " " " ; " " 1-byte arg 146*cda5da8dSAndroid Build Coastguard WorkerLONG_BINPUT = b'r' # " " " " " ; " " 4-byte arg 147*cda5da8dSAndroid Build Coastguard WorkerSETITEM = b's' # add key+value pair to dict 148*cda5da8dSAndroid Build Coastguard WorkerTUPLE = b't' # build tuple from topmost stack items 149*cda5da8dSAndroid Build Coastguard WorkerEMPTY_TUPLE = b')' # push empty tuple 150*cda5da8dSAndroid Build Coastguard WorkerSETITEMS = b'u' # modify dict by adding topmost key+value pairs 151*cda5da8dSAndroid Build Coastguard WorkerBINFLOAT = b'G' # push float; arg is 8-byte float encoding 152*cda5da8dSAndroid Build Coastguard Worker 153*cda5da8dSAndroid Build Coastguard WorkerTRUE = b'I01\n' # not an opcode; see INT docs in pickletools.py 154*cda5da8dSAndroid Build Coastguard WorkerFALSE = b'I00\n' # not an opcode; see INT docs in pickletools.py 155*cda5da8dSAndroid Build Coastguard Worker 156*cda5da8dSAndroid Build Coastguard Worker# Protocol 2 157*cda5da8dSAndroid Build Coastguard Worker 158*cda5da8dSAndroid Build Coastguard WorkerPROTO = b'\x80' # identify pickle protocol 159*cda5da8dSAndroid Build Coastguard WorkerNEWOBJ = b'\x81' # build object by applying cls.__new__ to argtuple 160*cda5da8dSAndroid Build Coastguard WorkerEXT1 = b'\x82' # push object from extension registry; 1-byte index 161*cda5da8dSAndroid Build Coastguard WorkerEXT2 = b'\x83' # ditto, but 2-byte index 162*cda5da8dSAndroid Build Coastguard WorkerEXT4 = b'\x84' # ditto, but 4-byte index 163*cda5da8dSAndroid Build Coastguard WorkerTUPLE1 = b'\x85' # build 1-tuple from stack top 164*cda5da8dSAndroid Build Coastguard WorkerTUPLE2 = b'\x86' # build 2-tuple from two topmost stack items 165*cda5da8dSAndroid Build Coastguard WorkerTUPLE3 = b'\x87' # build 3-tuple from three topmost stack items 166*cda5da8dSAndroid Build Coastguard WorkerNEWTRUE = b'\x88' # push True 167*cda5da8dSAndroid Build Coastguard WorkerNEWFALSE = b'\x89' # push False 168*cda5da8dSAndroid Build Coastguard WorkerLONG1 = b'\x8a' # push long from < 256 bytes 169*cda5da8dSAndroid Build Coastguard WorkerLONG4 = b'\x8b' # push really big long 170*cda5da8dSAndroid Build Coastguard Worker 171*cda5da8dSAndroid Build Coastguard Worker_tuplesize2code = [EMPTY_TUPLE, TUPLE1, TUPLE2, TUPLE3] 172*cda5da8dSAndroid Build Coastguard Worker 173*cda5da8dSAndroid Build Coastguard Worker# Protocol 3 (Python 3.x) 174*cda5da8dSAndroid Build Coastguard Worker 175*cda5da8dSAndroid Build Coastguard WorkerBINBYTES = b'B' # push bytes; counted binary string argument 176*cda5da8dSAndroid Build Coastguard WorkerSHORT_BINBYTES = b'C' # " " ; " " " " < 256 bytes 177*cda5da8dSAndroid Build Coastguard Worker 178*cda5da8dSAndroid Build Coastguard Worker# Protocol 4 179*cda5da8dSAndroid Build Coastguard Worker 180*cda5da8dSAndroid Build Coastguard WorkerSHORT_BINUNICODE = b'\x8c' # push short string; UTF-8 length < 256 bytes 181*cda5da8dSAndroid Build Coastguard WorkerBINUNICODE8 = b'\x8d' # push very long string 182*cda5da8dSAndroid Build Coastguard WorkerBINBYTES8 = b'\x8e' # push very long bytes string 183*cda5da8dSAndroid Build Coastguard WorkerEMPTY_SET = b'\x8f' # push empty set on the stack 184*cda5da8dSAndroid Build Coastguard WorkerADDITEMS = b'\x90' # modify set by adding topmost stack items 185*cda5da8dSAndroid Build Coastguard WorkerFROZENSET = b'\x91' # build frozenset from topmost stack items 186*cda5da8dSAndroid Build Coastguard WorkerNEWOBJ_EX = b'\x92' # like NEWOBJ but work with keyword only arguments 187*cda5da8dSAndroid Build Coastguard WorkerSTACK_GLOBAL = b'\x93' # same as GLOBAL but using names on the stacks 188*cda5da8dSAndroid Build Coastguard WorkerMEMOIZE = b'\x94' # store top of the stack in memo 189*cda5da8dSAndroid Build Coastguard WorkerFRAME = b'\x95' # indicate the beginning of a new frame 190*cda5da8dSAndroid Build Coastguard Worker 191*cda5da8dSAndroid Build Coastguard Worker# Protocol 5 192*cda5da8dSAndroid Build Coastguard Worker 193*cda5da8dSAndroid Build Coastguard WorkerBYTEARRAY8 = b'\x96' # push bytearray 194*cda5da8dSAndroid Build Coastguard WorkerNEXT_BUFFER = b'\x97' # push next out-of-band buffer 195*cda5da8dSAndroid Build Coastguard WorkerREADONLY_BUFFER = b'\x98' # make top of stack readonly 196*cda5da8dSAndroid Build Coastguard Worker 197*cda5da8dSAndroid Build Coastguard Worker__all__.extend([x for x in dir() if re.match("[A-Z][A-Z0-9_]+$", x)]) 198*cda5da8dSAndroid Build Coastguard Worker 199*cda5da8dSAndroid Build Coastguard Worker 200*cda5da8dSAndroid Build Coastguard Workerclass _Framer: 201*cda5da8dSAndroid Build Coastguard Worker 202*cda5da8dSAndroid Build Coastguard Worker _FRAME_SIZE_MIN = 4 203*cda5da8dSAndroid Build Coastguard Worker _FRAME_SIZE_TARGET = 64 * 1024 204*cda5da8dSAndroid Build Coastguard Worker 205*cda5da8dSAndroid Build Coastguard Worker def __init__(self, file_write): 206*cda5da8dSAndroid Build Coastguard Worker self.file_write = file_write 207*cda5da8dSAndroid Build Coastguard Worker self.current_frame = None 208*cda5da8dSAndroid Build Coastguard Worker 209*cda5da8dSAndroid Build Coastguard Worker def start_framing(self): 210*cda5da8dSAndroid Build Coastguard Worker self.current_frame = io.BytesIO() 211*cda5da8dSAndroid Build Coastguard Worker 212*cda5da8dSAndroid Build Coastguard Worker def end_framing(self): 213*cda5da8dSAndroid Build Coastguard Worker if self.current_frame and self.current_frame.tell() > 0: 214*cda5da8dSAndroid Build Coastguard Worker self.commit_frame(force=True) 215*cda5da8dSAndroid Build Coastguard Worker self.current_frame = None 216*cda5da8dSAndroid Build Coastguard Worker 217*cda5da8dSAndroid Build Coastguard Worker def commit_frame(self, force=False): 218*cda5da8dSAndroid Build Coastguard Worker if self.current_frame: 219*cda5da8dSAndroid Build Coastguard Worker f = self.current_frame 220*cda5da8dSAndroid Build Coastguard Worker if f.tell() >= self._FRAME_SIZE_TARGET or force: 221*cda5da8dSAndroid Build Coastguard Worker data = f.getbuffer() 222*cda5da8dSAndroid Build Coastguard Worker write = self.file_write 223*cda5da8dSAndroid Build Coastguard Worker if len(data) >= self._FRAME_SIZE_MIN: 224*cda5da8dSAndroid Build Coastguard Worker # Issue a single call to the write method of the underlying 225*cda5da8dSAndroid Build Coastguard Worker # file object for the frame opcode with the size of the 226*cda5da8dSAndroid Build Coastguard Worker # frame. The concatenation is expected to be less expensive 227*cda5da8dSAndroid Build Coastguard Worker # than issuing an additional call to write. 228*cda5da8dSAndroid Build Coastguard Worker write(FRAME + pack("<Q", len(data))) 229*cda5da8dSAndroid Build Coastguard Worker 230*cda5da8dSAndroid Build Coastguard Worker # Issue a separate call to write to append the frame 231*cda5da8dSAndroid Build Coastguard Worker # contents without concatenation to the above to avoid a 232*cda5da8dSAndroid Build Coastguard Worker # memory copy. 233*cda5da8dSAndroid Build Coastguard Worker write(data) 234*cda5da8dSAndroid Build Coastguard Worker 235*cda5da8dSAndroid Build Coastguard Worker # Start the new frame with a new io.BytesIO instance so that 236*cda5da8dSAndroid Build Coastguard Worker # the file object can have delayed access to the previous frame 237*cda5da8dSAndroid Build Coastguard Worker # contents via an unreleased memoryview of the previous 238*cda5da8dSAndroid Build Coastguard Worker # io.BytesIO instance. 239*cda5da8dSAndroid Build Coastguard Worker self.current_frame = io.BytesIO() 240*cda5da8dSAndroid Build Coastguard Worker 241*cda5da8dSAndroid Build Coastguard Worker def write(self, data): 242*cda5da8dSAndroid Build Coastguard Worker if self.current_frame: 243*cda5da8dSAndroid Build Coastguard Worker return self.current_frame.write(data) 244*cda5da8dSAndroid Build Coastguard Worker else: 245*cda5da8dSAndroid Build Coastguard Worker return self.file_write(data) 246*cda5da8dSAndroid Build Coastguard Worker 247*cda5da8dSAndroid Build Coastguard Worker def write_large_bytes(self, header, payload): 248*cda5da8dSAndroid Build Coastguard Worker write = self.file_write 249*cda5da8dSAndroid Build Coastguard Worker if self.current_frame: 250*cda5da8dSAndroid Build Coastguard Worker # Terminate the current frame and flush it to the file. 251*cda5da8dSAndroid Build Coastguard Worker self.commit_frame(force=True) 252*cda5da8dSAndroid Build Coastguard Worker 253*cda5da8dSAndroid Build Coastguard Worker # Perform direct write of the header and payload of the large binary 254*cda5da8dSAndroid Build Coastguard Worker # object. Be careful not to concatenate the header and the payload 255*cda5da8dSAndroid Build Coastguard Worker # prior to calling 'write' as we do not want to allocate a large 256*cda5da8dSAndroid Build Coastguard Worker # temporary bytes object. 257*cda5da8dSAndroid Build Coastguard Worker # We intentionally do not insert a protocol 4 frame opcode to make 258*cda5da8dSAndroid Build Coastguard Worker # it possible to optimize file.read calls in the loader. 259*cda5da8dSAndroid Build Coastguard Worker write(header) 260*cda5da8dSAndroid Build Coastguard Worker write(payload) 261*cda5da8dSAndroid Build Coastguard Worker 262*cda5da8dSAndroid Build Coastguard Worker 263*cda5da8dSAndroid Build Coastguard Workerclass _Unframer: 264*cda5da8dSAndroid Build Coastguard Worker 265*cda5da8dSAndroid Build Coastguard Worker def __init__(self, file_read, file_readline, file_tell=None): 266*cda5da8dSAndroid Build Coastguard Worker self.file_read = file_read 267*cda5da8dSAndroid Build Coastguard Worker self.file_readline = file_readline 268*cda5da8dSAndroid Build Coastguard Worker self.current_frame = None 269*cda5da8dSAndroid Build Coastguard Worker 270*cda5da8dSAndroid Build Coastguard Worker def readinto(self, buf): 271*cda5da8dSAndroid Build Coastguard Worker if self.current_frame: 272*cda5da8dSAndroid Build Coastguard Worker n = self.current_frame.readinto(buf) 273*cda5da8dSAndroid Build Coastguard Worker if n == 0 and len(buf) != 0: 274*cda5da8dSAndroid Build Coastguard Worker self.current_frame = None 275*cda5da8dSAndroid Build Coastguard Worker n = len(buf) 276*cda5da8dSAndroid Build Coastguard Worker buf[:] = self.file_read(n) 277*cda5da8dSAndroid Build Coastguard Worker return n 278*cda5da8dSAndroid Build Coastguard Worker if n < len(buf): 279*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError( 280*cda5da8dSAndroid Build Coastguard Worker "pickle exhausted before end of frame") 281*cda5da8dSAndroid Build Coastguard Worker return n 282*cda5da8dSAndroid Build Coastguard Worker else: 283*cda5da8dSAndroid Build Coastguard Worker n = len(buf) 284*cda5da8dSAndroid Build Coastguard Worker buf[:] = self.file_read(n) 285*cda5da8dSAndroid Build Coastguard Worker return n 286*cda5da8dSAndroid Build Coastguard Worker 287*cda5da8dSAndroid Build Coastguard Worker def read(self, n): 288*cda5da8dSAndroid Build Coastguard Worker if self.current_frame: 289*cda5da8dSAndroid Build Coastguard Worker data = self.current_frame.read(n) 290*cda5da8dSAndroid Build Coastguard Worker if not data and n != 0: 291*cda5da8dSAndroid Build Coastguard Worker self.current_frame = None 292*cda5da8dSAndroid Build Coastguard Worker return self.file_read(n) 293*cda5da8dSAndroid Build Coastguard Worker if len(data) < n: 294*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError( 295*cda5da8dSAndroid Build Coastguard Worker "pickle exhausted before end of frame") 296*cda5da8dSAndroid Build Coastguard Worker return data 297*cda5da8dSAndroid Build Coastguard Worker else: 298*cda5da8dSAndroid Build Coastguard Worker return self.file_read(n) 299*cda5da8dSAndroid Build Coastguard Worker 300*cda5da8dSAndroid Build Coastguard Worker def readline(self): 301*cda5da8dSAndroid Build Coastguard Worker if self.current_frame: 302*cda5da8dSAndroid Build Coastguard Worker data = self.current_frame.readline() 303*cda5da8dSAndroid Build Coastguard Worker if not data: 304*cda5da8dSAndroid Build Coastguard Worker self.current_frame = None 305*cda5da8dSAndroid Build Coastguard Worker return self.file_readline() 306*cda5da8dSAndroid Build Coastguard Worker if data[-1] != b'\n'[0]: 307*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError( 308*cda5da8dSAndroid Build Coastguard Worker "pickle exhausted before end of frame") 309*cda5da8dSAndroid Build Coastguard Worker return data 310*cda5da8dSAndroid Build Coastguard Worker else: 311*cda5da8dSAndroid Build Coastguard Worker return self.file_readline() 312*cda5da8dSAndroid Build Coastguard Worker 313*cda5da8dSAndroid Build Coastguard Worker def load_frame(self, frame_size): 314*cda5da8dSAndroid Build Coastguard Worker if self.current_frame and self.current_frame.read() != b'': 315*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError( 316*cda5da8dSAndroid Build Coastguard Worker "beginning of a new frame before end of current frame") 317*cda5da8dSAndroid Build Coastguard Worker self.current_frame = io.BytesIO(self.file_read(frame_size)) 318*cda5da8dSAndroid Build Coastguard Worker 319*cda5da8dSAndroid Build Coastguard Worker 320*cda5da8dSAndroid Build Coastguard Worker# Tools used for pickling. 321*cda5da8dSAndroid Build Coastguard Worker 322*cda5da8dSAndroid Build Coastguard Workerdef _getattribute(obj, name): 323*cda5da8dSAndroid Build Coastguard Worker for subpath in name.split('.'): 324*cda5da8dSAndroid Build Coastguard Worker if subpath == '<locals>': 325*cda5da8dSAndroid Build Coastguard Worker raise AttributeError("Can't get local attribute {!r} on {!r}" 326*cda5da8dSAndroid Build Coastguard Worker .format(name, obj)) 327*cda5da8dSAndroid Build Coastguard Worker try: 328*cda5da8dSAndroid Build Coastguard Worker parent = obj 329*cda5da8dSAndroid Build Coastguard Worker obj = getattr(obj, subpath) 330*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 331*cda5da8dSAndroid Build Coastguard Worker raise AttributeError("Can't get attribute {!r} on {!r}" 332*cda5da8dSAndroid Build Coastguard Worker .format(name, obj)) from None 333*cda5da8dSAndroid Build Coastguard Worker return obj, parent 334*cda5da8dSAndroid Build Coastguard Worker 335*cda5da8dSAndroid Build Coastguard Workerdef whichmodule(obj, name): 336*cda5da8dSAndroid Build Coastguard Worker """Find the module an object belong to.""" 337*cda5da8dSAndroid Build Coastguard Worker module_name = getattr(obj, '__module__', None) 338*cda5da8dSAndroid Build Coastguard Worker if module_name is not None: 339*cda5da8dSAndroid Build Coastguard Worker return module_name 340*cda5da8dSAndroid Build Coastguard Worker # Protect the iteration by using a list copy of sys.modules against dynamic 341*cda5da8dSAndroid Build Coastguard Worker # modules that trigger imports of other modules upon calls to getattr. 342*cda5da8dSAndroid Build Coastguard Worker for module_name, module in sys.modules.copy().items(): 343*cda5da8dSAndroid Build Coastguard Worker if (module_name == '__main__' 344*cda5da8dSAndroid Build Coastguard Worker or module_name == '__mp_main__' # bpo-42406 345*cda5da8dSAndroid Build Coastguard Worker or module is None): 346*cda5da8dSAndroid Build Coastguard Worker continue 347*cda5da8dSAndroid Build Coastguard Worker try: 348*cda5da8dSAndroid Build Coastguard Worker if _getattribute(module, name)[0] is obj: 349*cda5da8dSAndroid Build Coastguard Worker return module_name 350*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 351*cda5da8dSAndroid Build Coastguard Worker pass 352*cda5da8dSAndroid Build Coastguard Worker return '__main__' 353*cda5da8dSAndroid Build Coastguard Worker 354*cda5da8dSAndroid Build Coastguard Workerdef encode_long(x): 355*cda5da8dSAndroid Build Coastguard Worker r"""Encode a long to a two's complement little-endian binary string. 356*cda5da8dSAndroid Build Coastguard Worker Note that 0 is a special case, returning an empty string, to save a 357*cda5da8dSAndroid Build Coastguard Worker byte in the LONG1 pickling context. 358*cda5da8dSAndroid Build Coastguard Worker 359*cda5da8dSAndroid Build Coastguard Worker >>> encode_long(0) 360*cda5da8dSAndroid Build Coastguard Worker b'' 361*cda5da8dSAndroid Build Coastguard Worker >>> encode_long(255) 362*cda5da8dSAndroid Build Coastguard Worker b'\xff\x00' 363*cda5da8dSAndroid Build Coastguard Worker >>> encode_long(32767) 364*cda5da8dSAndroid Build Coastguard Worker b'\xff\x7f' 365*cda5da8dSAndroid Build Coastguard Worker >>> encode_long(-256) 366*cda5da8dSAndroid Build Coastguard Worker b'\x00\xff' 367*cda5da8dSAndroid Build Coastguard Worker >>> encode_long(-32768) 368*cda5da8dSAndroid Build Coastguard Worker b'\x00\x80' 369*cda5da8dSAndroid Build Coastguard Worker >>> encode_long(-128) 370*cda5da8dSAndroid Build Coastguard Worker b'\x80' 371*cda5da8dSAndroid Build Coastguard Worker >>> encode_long(127) 372*cda5da8dSAndroid Build Coastguard Worker b'\x7f' 373*cda5da8dSAndroid Build Coastguard Worker >>> 374*cda5da8dSAndroid Build Coastguard Worker """ 375*cda5da8dSAndroid Build Coastguard Worker if x == 0: 376*cda5da8dSAndroid Build Coastguard Worker return b'' 377*cda5da8dSAndroid Build Coastguard Worker nbytes = (x.bit_length() >> 3) + 1 378*cda5da8dSAndroid Build Coastguard Worker result = x.to_bytes(nbytes, byteorder='little', signed=True) 379*cda5da8dSAndroid Build Coastguard Worker if x < 0 and nbytes > 1: 380*cda5da8dSAndroid Build Coastguard Worker if result[-1] == 0xff and (result[-2] & 0x80) != 0: 381*cda5da8dSAndroid Build Coastguard Worker result = result[:-1] 382*cda5da8dSAndroid Build Coastguard Worker return result 383*cda5da8dSAndroid Build Coastguard Worker 384*cda5da8dSAndroid Build Coastguard Workerdef decode_long(data): 385*cda5da8dSAndroid Build Coastguard Worker r"""Decode a long from a two's complement little-endian binary string. 386*cda5da8dSAndroid Build Coastguard Worker 387*cda5da8dSAndroid Build Coastguard Worker >>> decode_long(b'') 388*cda5da8dSAndroid Build Coastguard Worker 0 389*cda5da8dSAndroid Build Coastguard Worker >>> decode_long(b"\xff\x00") 390*cda5da8dSAndroid Build Coastguard Worker 255 391*cda5da8dSAndroid Build Coastguard Worker >>> decode_long(b"\xff\x7f") 392*cda5da8dSAndroid Build Coastguard Worker 32767 393*cda5da8dSAndroid Build Coastguard Worker >>> decode_long(b"\x00\xff") 394*cda5da8dSAndroid Build Coastguard Worker -256 395*cda5da8dSAndroid Build Coastguard Worker >>> decode_long(b"\x00\x80") 396*cda5da8dSAndroid Build Coastguard Worker -32768 397*cda5da8dSAndroid Build Coastguard Worker >>> decode_long(b"\x80") 398*cda5da8dSAndroid Build Coastguard Worker -128 399*cda5da8dSAndroid Build Coastguard Worker >>> decode_long(b"\x7f") 400*cda5da8dSAndroid Build Coastguard Worker 127 401*cda5da8dSAndroid Build Coastguard Worker """ 402*cda5da8dSAndroid Build Coastguard Worker return int.from_bytes(data, byteorder='little', signed=True) 403*cda5da8dSAndroid Build Coastguard Worker 404*cda5da8dSAndroid Build Coastguard Worker 405*cda5da8dSAndroid Build Coastguard Worker# Pickling machinery 406*cda5da8dSAndroid Build Coastguard Worker 407*cda5da8dSAndroid Build Coastguard Workerclass _Pickler: 408*cda5da8dSAndroid Build Coastguard Worker 409*cda5da8dSAndroid Build Coastguard Worker def __init__(self, file, protocol=None, *, fix_imports=True, 410*cda5da8dSAndroid Build Coastguard Worker buffer_callback=None): 411*cda5da8dSAndroid Build Coastguard Worker """This takes a binary file for writing a pickle data stream. 412*cda5da8dSAndroid Build Coastguard Worker 413*cda5da8dSAndroid Build Coastguard Worker The optional *protocol* argument tells the pickler to use the 414*cda5da8dSAndroid Build Coastguard Worker given protocol; supported protocols are 0, 1, 2, 3, 4 and 5. 415*cda5da8dSAndroid Build Coastguard Worker The default protocol is 4. It was introduced in Python 3.4, and 416*cda5da8dSAndroid Build Coastguard Worker is incompatible with previous versions. 417*cda5da8dSAndroid Build Coastguard Worker 418*cda5da8dSAndroid Build Coastguard Worker Specifying a negative protocol version selects the highest 419*cda5da8dSAndroid Build Coastguard Worker protocol version supported. The higher the protocol used, the 420*cda5da8dSAndroid Build Coastguard Worker more recent the version of Python needed to read the pickle 421*cda5da8dSAndroid Build Coastguard Worker produced. 422*cda5da8dSAndroid Build Coastguard Worker 423*cda5da8dSAndroid Build Coastguard Worker The *file* argument must have a write() method that accepts a 424*cda5da8dSAndroid Build Coastguard Worker single bytes argument. It can thus be a file object opened for 425*cda5da8dSAndroid Build Coastguard Worker binary writing, an io.BytesIO instance, or any other custom 426*cda5da8dSAndroid Build Coastguard Worker object that meets this interface. 427*cda5da8dSAndroid Build Coastguard Worker 428*cda5da8dSAndroid Build Coastguard Worker If *fix_imports* is True and *protocol* is less than 3, pickle 429*cda5da8dSAndroid Build Coastguard Worker will try to map the new Python 3 names to the old module names 430*cda5da8dSAndroid Build Coastguard Worker used in Python 2, so that the pickle data stream is readable 431*cda5da8dSAndroid Build Coastguard Worker with Python 2. 432*cda5da8dSAndroid Build Coastguard Worker 433*cda5da8dSAndroid Build Coastguard Worker If *buffer_callback* is None (the default), buffer views are 434*cda5da8dSAndroid Build Coastguard Worker serialized into *file* as part of the pickle stream. 435*cda5da8dSAndroid Build Coastguard Worker 436*cda5da8dSAndroid Build Coastguard Worker If *buffer_callback* is not None, then it can be called any number 437*cda5da8dSAndroid Build Coastguard Worker of times with a buffer view. If the callback returns a false value 438*cda5da8dSAndroid Build Coastguard Worker (such as None), the given buffer is out-of-band; otherwise the 439*cda5da8dSAndroid Build Coastguard Worker buffer is serialized in-band, i.e. inside the pickle stream. 440*cda5da8dSAndroid Build Coastguard Worker 441*cda5da8dSAndroid Build Coastguard Worker It is an error if *buffer_callback* is not None and *protocol* 442*cda5da8dSAndroid Build Coastguard Worker is None or smaller than 5. 443*cda5da8dSAndroid Build Coastguard Worker """ 444*cda5da8dSAndroid Build Coastguard Worker if protocol is None: 445*cda5da8dSAndroid Build Coastguard Worker protocol = DEFAULT_PROTOCOL 446*cda5da8dSAndroid Build Coastguard Worker if protocol < 0: 447*cda5da8dSAndroid Build Coastguard Worker protocol = HIGHEST_PROTOCOL 448*cda5da8dSAndroid Build Coastguard Worker elif not 0 <= protocol <= HIGHEST_PROTOCOL: 449*cda5da8dSAndroid Build Coastguard Worker raise ValueError("pickle protocol must be <= %d" % HIGHEST_PROTOCOL) 450*cda5da8dSAndroid Build Coastguard Worker if buffer_callback is not None and protocol < 5: 451*cda5da8dSAndroid Build Coastguard Worker raise ValueError("buffer_callback needs protocol >= 5") 452*cda5da8dSAndroid Build Coastguard Worker self._buffer_callback = buffer_callback 453*cda5da8dSAndroid Build Coastguard Worker try: 454*cda5da8dSAndroid Build Coastguard Worker self._file_write = file.write 455*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 456*cda5da8dSAndroid Build Coastguard Worker raise TypeError("file must have a 'write' attribute") 457*cda5da8dSAndroid Build Coastguard Worker self.framer = _Framer(self._file_write) 458*cda5da8dSAndroid Build Coastguard Worker self.write = self.framer.write 459*cda5da8dSAndroid Build Coastguard Worker self._write_large_bytes = self.framer.write_large_bytes 460*cda5da8dSAndroid Build Coastguard Worker self.memo = {} 461*cda5da8dSAndroid Build Coastguard Worker self.proto = int(protocol) 462*cda5da8dSAndroid Build Coastguard Worker self.bin = protocol >= 1 463*cda5da8dSAndroid Build Coastguard Worker self.fast = 0 464*cda5da8dSAndroid Build Coastguard Worker self.fix_imports = fix_imports and protocol < 3 465*cda5da8dSAndroid Build Coastguard Worker 466*cda5da8dSAndroid Build Coastguard Worker def clear_memo(self): 467*cda5da8dSAndroid Build Coastguard Worker """Clears the pickler's "memo". 468*cda5da8dSAndroid Build Coastguard Worker 469*cda5da8dSAndroid Build Coastguard Worker The memo is the data structure that remembers which objects the 470*cda5da8dSAndroid Build Coastguard Worker pickler has already seen, so that shared or recursive objects 471*cda5da8dSAndroid Build Coastguard Worker are pickled by reference and not by value. This method is 472*cda5da8dSAndroid Build Coastguard Worker useful when re-using picklers. 473*cda5da8dSAndroid Build Coastguard Worker """ 474*cda5da8dSAndroid Build Coastguard Worker self.memo.clear() 475*cda5da8dSAndroid Build Coastguard Worker 476*cda5da8dSAndroid Build Coastguard Worker def dump(self, obj): 477*cda5da8dSAndroid Build Coastguard Worker """Write a pickled representation of obj to the open file.""" 478*cda5da8dSAndroid Build Coastguard Worker # Check whether Pickler was initialized correctly. This is 479*cda5da8dSAndroid Build Coastguard Worker # only needed to mimic the behavior of _pickle.Pickler.dump(). 480*cda5da8dSAndroid Build Coastguard Worker if not hasattr(self, "_file_write"): 481*cda5da8dSAndroid Build Coastguard Worker raise PicklingError("Pickler.__init__() was not called by " 482*cda5da8dSAndroid Build Coastguard Worker "%s.__init__()" % (self.__class__.__name__,)) 483*cda5da8dSAndroid Build Coastguard Worker if self.proto >= 2: 484*cda5da8dSAndroid Build Coastguard Worker self.write(PROTO + pack("<B", self.proto)) 485*cda5da8dSAndroid Build Coastguard Worker if self.proto >= 4: 486*cda5da8dSAndroid Build Coastguard Worker self.framer.start_framing() 487*cda5da8dSAndroid Build Coastguard Worker self.save(obj) 488*cda5da8dSAndroid Build Coastguard Worker self.write(STOP) 489*cda5da8dSAndroid Build Coastguard Worker self.framer.end_framing() 490*cda5da8dSAndroid Build Coastguard Worker 491*cda5da8dSAndroid Build Coastguard Worker def memoize(self, obj): 492*cda5da8dSAndroid Build Coastguard Worker """Store an object in the memo.""" 493*cda5da8dSAndroid Build Coastguard Worker 494*cda5da8dSAndroid Build Coastguard Worker # The Pickler memo is a dictionary mapping object ids to 2-tuples 495*cda5da8dSAndroid Build Coastguard Worker # that contain the Unpickler memo key and the object being memoized. 496*cda5da8dSAndroid Build Coastguard Worker # The memo key is written to the pickle and will become 497*cda5da8dSAndroid Build Coastguard Worker # the key in the Unpickler's memo. The object is stored in the 498*cda5da8dSAndroid Build Coastguard Worker # Pickler memo so that transient objects are kept alive during 499*cda5da8dSAndroid Build Coastguard Worker # pickling. 500*cda5da8dSAndroid Build Coastguard Worker 501*cda5da8dSAndroid Build Coastguard Worker # The use of the Unpickler memo length as the memo key is just a 502*cda5da8dSAndroid Build Coastguard Worker # convention. The only requirement is that the memo values be unique. 503*cda5da8dSAndroid Build Coastguard Worker # But there appears no advantage to any other scheme, and this 504*cda5da8dSAndroid Build Coastguard Worker # scheme allows the Unpickler memo to be implemented as a plain (but 505*cda5da8dSAndroid Build Coastguard Worker # growable) array, indexed by memo key. 506*cda5da8dSAndroid Build Coastguard Worker if self.fast: 507*cda5da8dSAndroid Build Coastguard Worker return 508*cda5da8dSAndroid Build Coastguard Worker assert id(obj) not in self.memo 509*cda5da8dSAndroid Build Coastguard Worker idx = len(self.memo) 510*cda5da8dSAndroid Build Coastguard Worker self.write(self.put(idx)) 511*cda5da8dSAndroid Build Coastguard Worker self.memo[id(obj)] = idx, obj 512*cda5da8dSAndroid Build Coastguard Worker 513*cda5da8dSAndroid Build Coastguard Worker # Return a PUT (BINPUT, LONG_BINPUT) opcode string, with argument i. 514*cda5da8dSAndroid Build Coastguard Worker def put(self, idx): 515*cda5da8dSAndroid Build Coastguard Worker if self.proto >= 4: 516*cda5da8dSAndroid Build Coastguard Worker return MEMOIZE 517*cda5da8dSAndroid Build Coastguard Worker elif self.bin: 518*cda5da8dSAndroid Build Coastguard Worker if idx < 256: 519*cda5da8dSAndroid Build Coastguard Worker return BINPUT + pack("<B", idx) 520*cda5da8dSAndroid Build Coastguard Worker else: 521*cda5da8dSAndroid Build Coastguard Worker return LONG_BINPUT + pack("<I", idx) 522*cda5da8dSAndroid Build Coastguard Worker else: 523*cda5da8dSAndroid Build Coastguard Worker return PUT + repr(idx).encode("ascii") + b'\n' 524*cda5da8dSAndroid Build Coastguard Worker 525*cda5da8dSAndroid Build Coastguard Worker # Return a GET (BINGET, LONG_BINGET) opcode string, with argument i. 526*cda5da8dSAndroid Build Coastguard Worker def get(self, i): 527*cda5da8dSAndroid Build Coastguard Worker if self.bin: 528*cda5da8dSAndroid Build Coastguard Worker if i < 256: 529*cda5da8dSAndroid Build Coastguard Worker return BINGET + pack("<B", i) 530*cda5da8dSAndroid Build Coastguard Worker else: 531*cda5da8dSAndroid Build Coastguard Worker return LONG_BINGET + pack("<I", i) 532*cda5da8dSAndroid Build Coastguard Worker 533*cda5da8dSAndroid Build Coastguard Worker return GET + repr(i).encode("ascii") + b'\n' 534*cda5da8dSAndroid Build Coastguard Worker 535*cda5da8dSAndroid Build Coastguard Worker def save(self, obj, save_persistent_id=True): 536*cda5da8dSAndroid Build Coastguard Worker self.framer.commit_frame() 537*cda5da8dSAndroid Build Coastguard Worker 538*cda5da8dSAndroid Build Coastguard Worker # Check for persistent id (defined by a subclass) 539*cda5da8dSAndroid Build Coastguard Worker pid = self.persistent_id(obj) 540*cda5da8dSAndroid Build Coastguard Worker if pid is not None and save_persistent_id: 541*cda5da8dSAndroid Build Coastguard Worker self.save_pers(pid) 542*cda5da8dSAndroid Build Coastguard Worker return 543*cda5da8dSAndroid Build Coastguard Worker 544*cda5da8dSAndroid Build Coastguard Worker # Check the memo 545*cda5da8dSAndroid Build Coastguard Worker x = self.memo.get(id(obj)) 546*cda5da8dSAndroid Build Coastguard Worker if x is not None: 547*cda5da8dSAndroid Build Coastguard Worker self.write(self.get(x[0])) 548*cda5da8dSAndroid Build Coastguard Worker return 549*cda5da8dSAndroid Build Coastguard Worker 550*cda5da8dSAndroid Build Coastguard Worker rv = NotImplemented 551*cda5da8dSAndroid Build Coastguard Worker reduce = getattr(self, "reducer_override", None) 552*cda5da8dSAndroid Build Coastguard Worker if reduce is not None: 553*cda5da8dSAndroid Build Coastguard Worker rv = reduce(obj) 554*cda5da8dSAndroid Build Coastguard Worker 555*cda5da8dSAndroid Build Coastguard Worker if rv is NotImplemented: 556*cda5da8dSAndroid Build Coastguard Worker # Check the type dispatch table 557*cda5da8dSAndroid Build Coastguard Worker t = type(obj) 558*cda5da8dSAndroid Build Coastguard Worker f = self.dispatch.get(t) 559*cda5da8dSAndroid Build Coastguard Worker if f is not None: 560*cda5da8dSAndroid Build Coastguard Worker f(self, obj) # Call unbound method with explicit self 561*cda5da8dSAndroid Build Coastguard Worker return 562*cda5da8dSAndroid Build Coastguard Worker 563*cda5da8dSAndroid Build Coastguard Worker # Check private dispatch table if any, or else 564*cda5da8dSAndroid Build Coastguard Worker # copyreg.dispatch_table 565*cda5da8dSAndroid Build Coastguard Worker reduce = getattr(self, 'dispatch_table', dispatch_table).get(t) 566*cda5da8dSAndroid Build Coastguard Worker if reduce is not None: 567*cda5da8dSAndroid Build Coastguard Worker rv = reduce(obj) 568*cda5da8dSAndroid Build Coastguard Worker else: 569*cda5da8dSAndroid Build Coastguard Worker # Check for a class with a custom metaclass; treat as regular 570*cda5da8dSAndroid Build Coastguard Worker # class 571*cda5da8dSAndroid Build Coastguard Worker if issubclass(t, type): 572*cda5da8dSAndroid Build Coastguard Worker self.save_global(obj) 573*cda5da8dSAndroid Build Coastguard Worker return 574*cda5da8dSAndroid Build Coastguard Worker 575*cda5da8dSAndroid Build Coastguard Worker # Check for a __reduce_ex__ method, fall back to __reduce__ 576*cda5da8dSAndroid Build Coastguard Worker reduce = getattr(obj, "__reduce_ex__", None) 577*cda5da8dSAndroid Build Coastguard Worker if reduce is not None: 578*cda5da8dSAndroid Build Coastguard Worker rv = reduce(self.proto) 579*cda5da8dSAndroid Build Coastguard Worker else: 580*cda5da8dSAndroid Build Coastguard Worker reduce = getattr(obj, "__reduce__", None) 581*cda5da8dSAndroid Build Coastguard Worker if reduce is not None: 582*cda5da8dSAndroid Build Coastguard Worker rv = reduce() 583*cda5da8dSAndroid Build Coastguard Worker else: 584*cda5da8dSAndroid Build Coastguard Worker raise PicklingError("Can't pickle %r object: %r" % 585*cda5da8dSAndroid Build Coastguard Worker (t.__name__, obj)) 586*cda5da8dSAndroid Build Coastguard Worker 587*cda5da8dSAndroid Build Coastguard Worker # Check for string returned by reduce(), meaning "save as global" 588*cda5da8dSAndroid Build Coastguard Worker if isinstance(rv, str): 589*cda5da8dSAndroid Build Coastguard Worker self.save_global(obj, rv) 590*cda5da8dSAndroid Build Coastguard Worker return 591*cda5da8dSAndroid Build Coastguard Worker 592*cda5da8dSAndroid Build Coastguard Worker # Assert that reduce() returned a tuple 593*cda5da8dSAndroid Build Coastguard Worker if not isinstance(rv, tuple): 594*cda5da8dSAndroid Build Coastguard Worker raise PicklingError("%s must return string or tuple" % reduce) 595*cda5da8dSAndroid Build Coastguard Worker 596*cda5da8dSAndroid Build Coastguard Worker # Assert that it returned an appropriately sized tuple 597*cda5da8dSAndroid Build Coastguard Worker l = len(rv) 598*cda5da8dSAndroid Build Coastguard Worker if not (2 <= l <= 6): 599*cda5da8dSAndroid Build Coastguard Worker raise PicklingError("Tuple returned by %s must have " 600*cda5da8dSAndroid Build Coastguard Worker "two to six elements" % reduce) 601*cda5da8dSAndroid Build Coastguard Worker 602*cda5da8dSAndroid Build Coastguard Worker # Save the reduce() output and finally memoize the object 603*cda5da8dSAndroid Build Coastguard Worker self.save_reduce(obj=obj, *rv) 604*cda5da8dSAndroid Build Coastguard Worker 605*cda5da8dSAndroid Build Coastguard Worker def persistent_id(self, obj): 606*cda5da8dSAndroid Build Coastguard Worker # This exists so a subclass can override it 607*cda5da8dSAndroid Build Coastguard Worker return None 608*cda5da8dSAndroid Build Coastguard Worker 609*cda5da8dSAndroid Build Coastguard Worker def save_pers(self, pid): 610*cda5da8dSAndroid Build Coastguard Worker # Save a persistent id reference 611*cda5da8dSAndroid Build Coastguard Worker if self.bin: 612*cda5da8dSAndroid Build Coastguard Worker self.save(pid, save_persistent_id=False) 613*cda5da8dSAndroid Build Coastguard Worker self.write(BINPERSID) 614*cda5da8dSAndroid Build Coastguard Worker else: 615*cda5da8dSAndroid Build Coastguard Worker try: 616*cda5da8dSAndroid Build Coastguard Worker self.write(PERSID + str(pid).encode("ascii") + b'\n') 617*cda5da8dSAndroid Build Coastguard Worker except UnicodeEncodeError: 618*cda5da8dSAndroid Build Coastguard Worker raise PicklingError( 619*cda5da8dSAndroid Build Coastguard Worker "persistent IDs in protocol 0 must be ASCII strings") 620*cda5da8dSAndroid Build Coastguard Worker 621*cda5da8dSAndroid Build Coastguard Worker def save_reduce(self, func, args, state=None, listitems=None, 622*cda5da8dSAndroid Build Coastguard Worker dictitems=None, state_setter=None, *, obj=None): 623*cda5da8dSAndroid Build Coastguard Worker # This API is called by some subclasses 624*cda5da8dSAndroid Build Coastguard Worker 625*cda5da8dSAndroid Build Coastguard Worker if not isinstance(args, tuple): 626*cda5da8dSAndroid Build Coastguard Worker raise PicklingError("args from save_reduce() must be a tuple") 627*cda5da8dSAndroid Build Coastguard Worker if not callable(func): 628*cda5da8dSAndroid Build Coastguard Worker raise PicklingError("func from save_reduce() must be callable") 629*cda5da8dSAndroid Build Coastguard Worker 630*cda5da8dSAndroid Build Coastguard Worker save = self.save 631*cda5da8dSAndroid Build Coastguard Worker write = self.write 632*cda5da8dSAndroid Build Coastguard Worker 633*cda5da8dSAndroid Build Coastguard Worker func_name = getattr(func, "__name__", "") 634*cda5da8dSAndroid Build Coastguard Worker if self.proto >= 2 and func_name == "__newobj_ex__": 635*cda5da8dSAndroid Build Coastguard Worker cls, args, kwargs = args 636*cda5da8dSAndroid Build Coastguard Worker if not hasattr(cls, "__new__"): 637*cda5da8dSAndroid Build Coastguard Worker raise PicklingError("args[0] from {} args has no __new__" 638*cda5da8dSAndroid Build Coastguard Worker .format(func_name)) 639*cda5da8dSAndroid Build Coastguard Worker if obj is not None and cls is not obj.__class__: 640*cda5da8dSAndroid Build Coastguard Worker raise PicklingError("args[0] from {} args has the wrong class" 641*cda5da8dSAndroid Build Coastguard Worker .format(func_name)) 642*cda5da8dSAndroid Build Coastguard Worker if self.proto >= 4: 643*cda5da8dSAndroid Build Coastguard Worker save(cls) 644*cda5da8dSAndroid Build Coastguard Worker save(args) 645*cda5da8dSAndroid Build Coastguard Worker save(kwargs) 646*cda5da8dSAndroid Build Coastguard Worker write(NEWOBJ_EX) 647*cda5da8dSAndroid Build Coastguard Worker else: 648*cda5da8dSAndroid Build Coastguard Worker func = partial(cls.__new__, cls, *args, **kwargs) 649*cda5da8dSAndroid Build Coastguard Worker save(func) 650*cda5da8dSAndroid Build Coastguard Worker save(()) 651*cda5da8dSAndroid Build Coastguard Worker write(REDUCE) 652*cda5da8dSAndroid Build Coastguard Worker elif self.proto >= 2 and func_name == "__newobj__": 653*cda5da8dSAndroid Build Coastguard Worker # A __reduce__ implementation can direct protocol 2 or newer to 654*cda5da8dSAndroid Build Coastguard Worker # use the more efficient NEWOBJ opcode, while still 655*cda5da8dSAndroid Build Coastguard Worker # allowing protocol 0 and 1 to work normally. For this to 656*cda5da8dSAndroid Build Coastguard Worker # work, the function returned by __reduce__ should be 657*cda5da8dSAndroid Build Coastguard Worker # called __newobj__, and its first argument should be a 658*cda5da8dSAndroid Build Coastguard Worker # class. The implementation for __newobj__ 659*cda5da8dSAndroid Build Coastguard Worker # should be as follows, although pickle has no way to 660*cda5da8dSAndroid Build Coastguard Worker # verify this: 661*cda5da8dSAndroid Build Coastguard Worker # 662*cda5da8dSAndroid Build Coastguard Worker # def __newobj__(cls, *args): 663*cda5da8dSAndroid Build Coastguard Worker # return cls.__new__(cls, *args) 664*cda5da8dSAndroid Build Coastguard Worker # 665*cda5da8dSAndroid Build Coastguard Worker # Protocols 0 and 1 will pickle a reference to __newobj__, 666*cda5da8dSAndroid Build Coastguard Worker # while protocol 2 (and above) will pickle a reference to 667*cda5da8dSAndroid Build Coastguard Worker # cls, the remaining args tuple, and the NEWOBJ code, 668*cda5da8dSAndroid Build Coastguard Worker # which calls cls.__new__(cls, *args) at unpickling time 669*cda5da8dSAndroid Build Coastguard Worker # (see load_newobj below). If __reduce__ returns a 670*cda5da8dSAndroid Build Coastguard Worker # three-tuple, the state from the third tuple item will be 671*cda5da8dSAndroid Build Coastguard Worker # pickled regardless of the protocol, calling __setstate__ 672*cda5da8dSAndroid Build Coastguard Worker # at unpickling time (see load_build below). 673*cda5da8dSAndroid Build Coastguard Worker # 674*cda5da8dSAndroid Build Coastguard Worker # Note that no standard __newobj__ implementation exists; 675*cda5da8dSAndroid Build Coastguard Worker # you have to provide your own. This is to enforce 676*cda5da8dSAndroid Build Coastguard Worker # compatibility with Python 2.2 (pickles written using 677*cda5da8dSAndroid Build Coastguard Worker # protocol 0 or 1 in Python 2.3 should be unpicklable by 678*cda5da8dSAndroid Build Coastguard Worker # Python 2.2). 679*cda5da8dSAndroid Build Coastguard Worker cls = args[0] 680*cda5da8dSAndroid Build Coastguard Worker if not hasattr(cls, "__new__"): 681*cda5da8dSAndroid Build Coastguard Worker raise PicklingError( 682*cda5da8dSAndroid Build Coastguard Worker "args[0] from __newobj__ args has no __new__") 683*cda5da8dSAndroid Build Coastguard Worker if obj is not None and cls is not obj.__class__: 684*cda5da8dSAndroid Build Coastguard Worker raise PicklingError( 685*cda5da8dSAndroid Build Coastguard Worker "args[0] from __newobj__ args has the wrong class") 686*cda5da8dSAndroid Build Coastguard Worker args = args[1:] 687*cda5da8dSAndroid Build Coastguard Worker save(cls) 688*cda5da8dSAndroid Build Coastguard Worker save(args) 689*cda5da8dSAndroid Build Coastguard Worker write(NEWOBJ) 690*cda5da8dSAndroid Build Coastguard Worker else: 691*cda5da8dSAndroid Build Coastguard Worker save(func) 692*cda5da8dSAndroid Build Coastguard Worker save(args) 693*cda5da8dSAndroid Build Coastguard Worker write(REDUCE) 694*cda5da8dSAndroid Build Coastguard Worker 695*cda5da8dSAndroid Build Coastguard Worker if obj is not None: 696*cda5da8dSAndroid Build Coastguard Worker # If the object is already in the memo, this means it is 697*cda5da8dSAndroid Build Coastguard Worker # recursive. In this case, throw away everything we put on the 698*cda5da8dSAndroid Build Coastguard Worker # stack, and fetch the object back from the memo. 699*cda5da8dSAndroid Build Coastguard Worker if id(obj) in self.memo: 700*cda5da8dSAndroid Build Coastguard Worker write(POP + self.get(self.memo[id(obj)][0])) 701*cda5da8dSAndroid Build Coastguard Worker else: 702*cda5da8dSAndroid Build Coastguard Worker self.memoize(obj) 703*cda5da8dSAndroid Build Coastguard Worker 704*cda5da8dSAndroid Build Coastguard Worker # More new special cases (that work with older protocols as 705*cda5da8dSAndroid Build Coastguard Worker # well): when __reduce__ returns a tuple with 4 or 5 items, 706*cda5da8dSAndroid Build Coastguard Worker # the 4th and 5th item should be iterators that provide list 707*cda5da8dSAndroid Build Coastguard Worker # items and dict items (as (key, value) tuples), or None. 708*cda5da8dSAndroid Build Coastguard Worker 709*cda5da8dSAndroid Build Coastguard Worker if listitems is not None: 710*cda5da8dSAndroid Build Coastguard Worker self._batch_appends(listitems) 711*cda5da8dSAndroid Build Coastguard Worker 712*cda5da8dSAndroid Build Coastguard Worker if dictitems is not None: 713*cda5da8dSAndroid Build Coastguard Worker self._batch_setitems(dictitems) 714*cda5da8dSAndroid Build Coastguard Worker 715*cda5da8dSAndroid Build Coastguard Worker if state is not None: 716*cda5da8dSAndroid Build Coastguard Worker if state_setter is None: 717*cda5da8dSAndroid Build Coastguard Worker save(state) 718*cda5da8dSAndroid Build Coastguard Worker write(BUILD) 719*cda5da8dSAndroid Build Coastguard Worker else: 720*cda5da8dSAndroid Build Coastguard Worker # If a state_setter is specified, call it instead of load_build 721*cda5da8dSAndroid Build Coastguard Worker # to update obj's with its previous state. 722*cda5da8dSAndroid Build Coastguard Worker # First, push state_setter and its tuple of expected arguments 723*cda5da8dSAndroid Build Coastguard Worker # (obj, state) onto the stack. 724*cda5da8dSAndroid Build Coastguard Worker save(state_setter) 725*cda5da8dSAndroid Build Coastguard Worker save(obj) # simple BINGET opcode as obj is already memoized. 726*cda5da8dSAndroid Build Coastguard Worker save(state) 727*cda5da8dSAndroid Build Coastguard Worker write(TUPLE2) 728*cda5da8dSAndroid Build Coastguard Worker # Trigger a state_setter(obj, state) function call. 729*cda5da8dSAndroid Build Coastguard Worker write(REDUCE) 730*cda5da8dSAndroid Build Coastguard Worker # The purpose of state_setter is to carry-out an 731*cda5da8dSAndroid Build Coastguard Worker # inplace modification of obj. We do not care about what the 732*cda5da8dSAndroid Build Coastguard Worker # method might return, so its output is eventually removed from 733*cda5da8dSAndroid Build Coastguard Worker # the stack. 734*cda5da8dSAndroid Build Coastguard Worker write(POP) 735*cda5da8dSAndroid Build Coastguard Worker 736*cda5da8dSAndroid Build Coastguard Worker # Methods below this point are dispatched through the dispatch table 737*cda5da8dSAndroid Build Coastguard Worker 738*cda5da8dSAndroid Build Coastguard Worker dispatch = {} 739*cda5da8dSAndroid Build Coastguard Worker 740*cda5da8dSAndroid Build Coastguard Worker def save_none(self, obj): 741*cda5da8dSAndroid Build Coastguard Worker self.write(NONE) 742*cda5da8dSAndroid Build Coastguard Worker dispatch[type(None)] = save_none 743*cda5da8dSAndroid Build Coastguard Worker 744*cda5da8dSAndroid Build Coastguard Worker def save_bool(self, obj): 745*cda5da8dSAndroid Build Coastguard Worker if self.proto >= 2: 746*cda5da8dSAndroid Build Coastguard Worker self.write(NEWTRUE if obj else NEWFALSE) 747*cda5da8dSAndroid Build Coastguard Worker else: 748*cda5da8dSAndroid Build Coastguard Worker self.write(TRUE if obj else FALSE) 749*cda5da8dSAndroid Build Coastguard Worker dispatch[bool] = save_bool 750*cda5da8dSAndroid Build Coastguard Worker 751*cda5da8dSAndroid Build Coastguard Worker def save_long(self, obj): 752*cda5da8dSAndroid Build Coastguard Worker if self.bin: 753*cda5da8dSAndroid Build Coastguard Worker # If the int is small enough to fit in a signed 4-byte 2's-comp 754*cda5da8dSAndroid Build Coastguard Worker # format, we can store it more efficiently than the general 755*cda5da8dSAndroid Build Coastguard Worker # case. 756*cda5da8dSAndroid Build Coastguard Worker # First one- and two-byte unsigned ints: 757*cda5da8dSAndroid Build Coastguard Worker if obj >= 0: 758*cda5da8dSAndroid Build Coastguard Worker if obj <= 0xff: 759*cda5da8dSAndroid Build Coastguard Worker self.write(BININT1 + pack("<B", obj)) 760*cda5da8dSAndroid Build Coastguard Worker return 761*cda5da8dSAndroid Build Coastguard Worker if obj <= 0xffff: 762*cda5da8dSAndroid Build Coastguard Worker self.write(BININT2 + pack("<H", obj)) 763*cda5da8dSAndroid Build Coastguard Worker return 764*cda5da8dSAndroid Build Coastguard Worker # Next check for 4-byte signed ints: 765*cda5da8dSAndroid Build Coastguard Worker if -0x80000000 <= obj <= 0x7fffffff: 766*cda5da8dSAndroid Build Coastguard Worker self.write(BININT + pack("<i", obj)) 767*cda5da8dSAndroid Build Coastguard Worker return 768*cda5da8dSAndroid Build Coastguard Worker if self.proto >= 2: 769*cda5da8dSAndroid Build Coastguard Worker encoded = encode_long(obj) 770*cda5da8dSAndroid Build Coastguard Worker n = len(encoded) 771*cda5da8dSAndroid Build Coastguard Worker if n < 256: 772*cda5da8dSAndroid Build Coastguard Worker self.write(LONG1 + pack("<B", n) + encoded) 773*cda5da8dSAndroid Build Coastguard Worker else: 774*cda5da8dSAndroid Build Coastguard Worker self.write(LONG4 + pack("<i", n) + encoded) 775*cda5da8dSAndroid Build Coastguard Worker return 776*cda5da8dSAndroid Build Coastguard Worker if -0x80000000 <= obj <= 0x7fffffff: 777*cda5da8dSAndroid Build Coastguard Worker self.write(INT + repr(obj).encode("ascii") + b'\n') 778*cda5da8dSAndroid Build Coastguard Worker else: 779*cda5da8dSAndroid Build Coastguard Worker self.write(LONG + repr(obj).encode("ascii") + b'L\n') 780*cda5da8dSAndroid Build Coastguard Worker dispatch[int] = save_long 781*cda5da8dSAndroid Build Coastguard Worker 782*cda5da8dSAndroid Build Coastguard Worker def save_float(self, obj): 783*cda5da8dSAndroid Build Coastguard Worker if self.bin: 784*cda5da8dSAndroid Build Coastguard Worker self.write(BINFLOAT + pack('>d', obj)) 785*cda5da8dSAndroid Build Coastguard Worker else: 786*cda5da8dSAndroid Build Coastguard Worker self.write(FLOAT + repr(obj).encode("ascii") + b'\n') 787*cda5da8dSAndroid Build Coastguard Worker dispatch[float] = save_float 788*cda5da8dSAndroid Build Coastguard Worker 789*cda5da8dSAndroid Build Coastguard Worker def save_bytes(self, obj): 790*cda5da8dSAndroid Build Coastguard Worker if self.proto < 3: 791*cda5da8dSAndroid Build Coastguard Worker if not obj: # bytes object is empty 792*cda5da8dSAndroid Build Coastguard Worker self.save_reduce(bytes, (), obj=obj) 793*cda5da8dSAndroid Build Coastguard Worker else: 794*cda5da8dSAndroid Build Coastguard Worker self.save_reduce(codecs.encode, 795*cda5da8dSAndroid Build Coastguard Worker (str(obj, 'latin1'), 'latin1'), obj=obj) 796*cda5da8dSAndroid Build Coastguard Worker return 797*cda5da8dSAndroid Build Coastguard Worker n = len(obj) 798*cda5da8dSAndroid Build Coastguard Worker if n <= 0xff: 799*cda5da8dSAndroid Build Coastguard Worker self.write(SHORT_BINBYTES + pack("<B", n) + obj) 800*cda5da8dSAndroid Build Coastguard Worker elif n > 0xffffffff and self.proto >= 4: 801*cda5da8dSAndroid Build Coastguard Worker self._write_large_bytes(BINBYTES8 + pack("<Q", n), obj) 802*cda5da8dSAndroid Build Coastguard Worker elif n >= self.framer._FRAME_SIZE_TARGET: 803*cda5da8dSAndroid Build Coastguard Worker self._write_large_bytes(BINBYTES + pack("<I", n), obj) 804*cda5da8dSAndroid Build Coastguard Worker else: 805*cda5da8dSAndroid Build Coastguard Worker self.write(BINBYTES + pack("<I", n) + obj) 806*cda5da8dSAndroid Build Coastguard Worker self.memoize(obj) 807*cda5da8dSAndroid Build Coastguard Worker dispatch[bytes] = save_bytes 808*cda5da8dSAndroid Build Coastguard Worker 809*cda5da8dSAndroid Build Coastguard Worker def save_bytearray(self, obj): 810*cda5da8dSAndroid Build Coastguard Worker if self.proto < 5: 811*cda5da8dSAndroid Build Coastguard Worker if not obj: # bytearray is empty 812*cda5da8dSAndroid Build Coastguard Worker self.save_reduce(bytearray, (), obj=obj) 813*cda5da8dSAndroid Build Coastguard Worker else: 814*cda5da8dSAndroid Build Coastguard Worker self.save_reduce(bytearray, (bytes(obj),), obj=obj) 815*cda5da8dSAndroid Build Coastguard Worker return 816*cda5da8dSAndroid Build Coastguard Worker n = len(obj) 817*cda5da8dSAndroid Build Coastguard Worker if n >= self.framer._FRAME_SIZE_TARGET: 818*cda5da8dSAndroid Build Coastguard Worker self._write_large_bytes(BYTEARRAY8 + pack("<Q", n), obj) 819*cda5da8dSAndroid Build Coastguard Worker else: 820*cda5da8dSAndroid Build Coastguard Worker self.write(BYTEARRAY8 + pack("<Q", n) + obj) 821*cda5da8dSAndroid Build Coastguard Worker self.memoize(obj) 822*cda5da8dSAndroid Build Coastguard Worker dispatch[bytearray] = save_bytearray 823*cda5da8dSAndroid Build Coastguard Worker 824*cda5da8dSAndroid Build Coastguard Worker if _HAVE_PICKLE_BUFFER: 825*cda5da8dSAndroid Build Coastguard Worker def save_picklebuffer(self, obj): 826*cda5da8dSAndroid Build Coastguard Worker if self.proto < 5: 827*cda5da8dSAndroid Build Coastguard Worker raise PicklingError("PickleBuffer can only pickled with " 828*cda5da8dSAndroid Build Coastguard Worker "protocol >= 5") 829*cda5da8dSAndroid Build Coastguard Worker with obj.raw() as m: 830*cda5da8dSAndroid Build Coastguard Worker if not m.contiguous: 831*cda5da8dSAndroid Build Coastguard Worker raise PicklingError("PickleBuffer can not be pickled when " 832*cda5da8dSAndroid Build Coastguard Worker "pointing to a non-contiguous buffer") 833*cda5da8dSAndroid Build Coastguard Worker in_band = True 834*cda5da8dSAndroid Build Coastguard Worker if self._buffer_callback is not None: 835*cda5da8dSAndroid Build Coastguard Worker in_band = bool(self._buffer_callback(obj)) 836*cda5da8dSAndroid Build Coastguard Worker if in_band: 837*cda5da8dSAndroid Build Coastguard Worker # Write data in-band 838*cda5da8dSAndroid Build Coastguard Worker # XXX The C implementation avoids a copy here 839*cda5da8dSAndroid Build Coastguard Worker if m.readonly: 840*cda5da8dSAndroid Build Coastguard Worker self.save_bytes(m.tobytes()) 841*cda5da8dSAndroid Build Coastguard Worker else: 842*cda5da8dSAndroid Build Coastguard Worker self.save_bytearray(m.tobytes()) 843*cda5da8dSAndroid Build Coastguard Worker else: 844*cda5da8dSAndroid Build Coastguard Worker # Write data out-of-band 845*cda5da8dSAndroid Build Coastguard Worker self.write(NEXT_BUFFER) 846*cda5da8dSAndroid Build Coastguard Worker if m.readonly: 847*cda5da8dSAndroid Build Coastguard Worker self.write(READONLY_BUFFER) 848*cda5da8dSAndroid Build Coastguard Worker 849*cda5da8dSAndroid Build Coastguard Worker dispatch[PickleBuffer] = save_picklebuffer 850*cda5da8dSAndroid Build Coastguard Worker 851*cda5da8dSAndroid Build Coastguard Worker def save_str(self, obj): 852*cda5da8dSAndroid Build Coastguard Worker if self.bin: 853*cda5da8dSAndroid Build Coastguard Worker encoded = obj.encode('utf-8', 'surrogatepass') 854*cda5da8dSAndroid Build Coastguard Worker n = len(encoded) 855*cda5da8dSAndroid Build Coastguard Worker if n <= 0xff and self.proto >= 4: 856*cda5da8dSAndroid Build Coastguard Worker self.write(SHORT_BINUNICODE + pack("<B", n) + encoded) 857*cda5da8dSAndroid Build Coastguard Worker elif n > 0xffffffff and self.proto >= 4: 858*cda5da8dSAndroid Build Coastguard Worker self._write_large_bytes(BINUNICODE8 + pack("<Q", n), encoded) 859*cda5da8dSAndroid Build Coastguard Worker elif n >= self.framer._FRAME_SIZE_TARGET: 860*cda5da8dSAndroid Build Coastguard Worker self._write_large_bytes(BINUNICODE + pack("<I", n), encoded) 861*cda5da8dSAndroid Build Coastguard Worker else: 862*cda5da8dSAndroid Build Coastguard Worker self.write(BINUNICODE + pack("<I", n) + encoded) 863*cda5da8dSAndroid Build Coastguard Worker else: 864*cda5da8dSAndroid Build Coastguard Worker obj = obj.replace("\\", "\\u005c") 865*cda5da8dSAndroid Build Coastguard Worker obj = obj.replace("\0", "\\u0000") 866*cda5da8dSAndroid Build Coastguard Worker obj = obj.replace("\n", "\\u000a") 867*cda5da8dSAndroid Build Coastguard Worker obj = obj.replace("\r", "\\u000d") 868*cda5da8dSAndroid Build Coastguard Worker obj = obj.replace("\x1a", "\\u001a") # EOF on DOS 869*cda5da8dSAndroid Build Coastguard Worker self.write(UNICODE + obj.encode('raw-unicode-escape') + 870*cda5da8dSAndroid Build Coastguard Worker b'\n') 871*cda5da8dSAndroid Build Coastguard Worker self.memoize(obj) 872*cda5da8dSAndroid Build Coastguard Worker dispatch[str] = save_str 873*cda5da8dSAndroid Build Coastguard Worker 874*cda5da8dSAndroid Build Coastguard Worker def save_tuple(self, obj): 875*cda5da8dSAndroid Build Coastguard Worker if not obj: # tuple is empty 876*cda5da8dSAndroid Build Coastguard Worker if self.bin: 877*cda5da8dSAndroid Build Coastguard Worker self.write(EMPTY_TUPLE) 878*cda5da8dSAndroid Build Coastguard Worker else: 879*cda5da8dSAndroid Build Coastguard Worker self.write(MARK + TUPLE) 880*cda5da8dSAndroid Build Coastguard Worker return 881*cda5da8dSAndroid Build Coastguard Worker 882*cda5da8dSAndroid Build Coastguard Worker n = len(obj) 883*cda5da8dSAndroid Build Coastguard Worker save = self.save 884*cda5da8dSAndroid Build Coastguard Worker memo = self.memo 885*cda5da8dSAndroid Build Coastguard Worker if n <= 3 and self.proto >= 2: 886*cda5da8dSAndroid Build Coastguard Worker for element in obj: 887*cda5da8dSAndroid Build Coastguard Worker save(element) 888*cda5da8dSAndroid Build Coastguard Worker # Subtle. Same as in the big comment below. 889*cda5da8dSAndroid Build Coastguard Worker if id(obj) in memo: 890*cda5da8dSAndroid Build Coastguard Worker get = self.get(memo[id(obj)][0]) 891*cda5da8dSAndroid Build Coastguard Worker self.write(POP * n + get) 892*cda5da8dSAndroid Build Coastguard Worker else: 893*cda5da8dSAndroid Build Coastguard Worker self.write(_tuplesize2code[n]) 894*cda5da8dSAndroid Build Coastguard Worker self.memoize(obj) 895*cda5da8dSAndroid Build Coastguard Worker return 896*cda5da8dSAndroid Build Coastguard Worker 897*cda5da8dSAndroid Build Coastguard Worker # proto 0 or proto 1 and tuple isn't empty, or proto > 1 and tuple 898*cda5da8dSAndroid Build Coastguard Worker # has more than 3 elements. 899*cda5da8dSAndroid Build Coastguard Worker write = self.write 900*cda5da8dSAndroid Build Coastguard Worker write(MARK) 901*cda5da8dSAndroid Build Coastguard Worker for element in obj: 902*cda5da8dSAndroid Build Coastguard Worker save(element) 903*cda5da8dSAndroid Build Coastguard Worker 904*cda5da8dSAndroid Build Coastguard Worker if id(obj) in memo: 905*cda5da8dSAndroid Build Coastguard Worker # Subtle. d was not in memo when we entered save_tuple(), so 906*cda5da8dSAndroid Build Coastguard Worker # the process of saving the tuple's elements must have saved 907*cda5da8dSAndroid Build Coastguard Worker # the tuple itself: the tuple is recursive. The proper action 908*cda5da8dSAndroid Build Coastguard Worker # now is to throw away everything we put on the stack, and 909*cda5da8dSAndroid Build Coastguard Worker # simply GET the tuple (it's already constructed). This check 910*cda5da8dSAndroid Build Coastguard Worker # could have been done in the "for element" loop instead, but 911*cda5da8dSAndroid Build Coastguard Worker # recursive tuples are a rare thing. 912*cda5da8dSAndroid Build Coastguard Worker get = self.get(memo[id(obj)][0]) 913*cda5da8dSAndroid Build Coastguard Worker if self.bin: 914*cda5da8dSAndroid Build Coastguard Worker write(POP_MARK + get) 915*cda5da8dSAndroid Build Coastguard Worker else: # proto 0 -- POP_MARK not available 916*cda5da8dSAndroid Build Coastguard Worker write(POP * (n+1) + get) 917*cda5da8dSAndroid Build Coastguard Worker return 918*cda5da8dSAndroid Build Coastguard Worker 919*cda5da8dSAndroid Build Coastguard Worker # No recursion. 920*cda5da8dSAndroid Build Coastguard Worker write(TUPLE) 921*cda5da8dSAndroid Build Coastguard Worker self.memoize(obj) 922*cda5da8dSAndroid Build Coastguard Worker 923*cda5da8dSAndroid Build Coastguard Worker dispatch[tuple] = save_tuple 924*cda5da8dSAndroid Build Coastguard Worker 925*cda5da8dSAndroid Build Coastguard Worker def save_list(self, obj): 926*cda5da8dSAndroid Build Coastguard Worker if self.bin: 927*cda5da8dSAndroid Build Coastguard Worker self.write(EMPTY_LIST) 928*cda5da8dSAndroid Build Coastguard Worker else: # proto 0 -- can't use EMPTY_LIST 929*cda5da8dSAndroid Build Coastguard Worker self.write(MARK + LIST) 930*cda5da8dSAndroid Build Coastguard Worker 931*cda5da8dSAndroid Build Coastguard Worker self.memoize(obj) 932*cda5da8dSAndroid Build Coastguard Worker self._batch_appends(obj) 933*cda5da8dSAndroid Build Coastguard Worker 934*cda5da8dSAndroid Build Coastguard Worker dispatch[list] = save_list 935*cda5da8dSAndroid Build Coastguard Worker 936*cda5da8dSAndroid Build Coastguard Worker _BATCHSIZE = 1000 937*cda5da8dSAndroid Build Coastguard Worker 938*cda5da8dSAndroid Build Coastguard Worker def _batch_appends(self, items): 939*cda5da8dSAndroid Build Coastguard Worker # Helper to batch up APPENDS sequences 940*cda5da8dSAndroid Build Coastguard Worker save = self.save 941*cda5da8dSAndroid Build Coastguard Worker write = self.write 942*cda5da8dSAndroid Build Coastguard Worker 943*cda5da8dSAndroid Build Coastguard Worker if not self.bin: 944*cda5da8dSAndroid Build Coastguard Worker for x in items: 945*cda5da8dSAndroid Build Coastguard Worker save(x) 946*cda5da8dSAndroid Build Coastguard Worker write(APPEND) 947*cda5da8dSAndroid Build Coastguard Worker return 948*cda5da8dSAndroid Build Coastguard Worker 949*cda5da8dSAndroid Build Coastguard Worker it = iter(items) 950*cda5da8dSAndroid Build Coastguard Worker while True: 951*cda5da8dSAndroid Build Coastguard Worker tmp = list(islice(it, self._BATCHSIZE)) 952*cda5da8dSAndroid Build Coastguard Worker n = len(tmp) 953*cda5da8dSAndroid Build Coastguard Worker if n > 1: 954*cda5da8dSAndroid Build Coastguard Worker write(MARK) 955*cda5da8dSAndroid Build Coastguard Worker for x in tmp: 956*cda5da8dSAndroid Build Coastguard Worker save(x) 957*cda5da8dSAndroid Build Coastguard Worker write(APPENDS) 958*cda5da8dSAndroid Build Coastguard Worker elif n: 959*cda5da8dSAndroid Build Coastguard Worker save(tmp[0]) 960*cda5da8dSAndroid Build Coastguard Worker write(APPEND) 961*cda5da8dSAndroid Build Coastguard Worker # else tmp is empty, and we're done 962*cda5da8dSAndroid Build Coastguard Worker if n < self._BATCHSIZE: 963*cda5da8dSAndroid Build Coastguard Worker return 964*cda5da8dSAndroid Build Coastguard Worker 965*cda5da8dSAndroid Build Coastguard Worker def save_dict(self, obj): 966*cda5da8dSAndroid Build Coastguard Worker if self.bin: 967*cda5da8dSAndroid Build Coastguard Worker self.write(EMPTY_DICT) 968*cda5da8dSAndroid Build Coastguard Worker else: # proto 0 -- can't use EMPTY_DICT 969*cda5da8dSAndroid Build Coastguard Worker self.write(MARK + DICT) 970*cda5da8dSAndroid Build Coastguard Worker 971*cda5da8dSAndroid Build Coastguard Worker self.memoize(obj) 972*cda5da8dSAndroid Build Coastguard Worker self._batch_setitems(obj.items()) 973*cda5da8dSAndroid Build Coastguard Worker 974*cda5da8dSAndroid Build Coastguard Worker dispatch[dict] = save_dict 975*cda5da8dSAndroid Build Coastguard Worker if PyStringMap is not None: 976*cda5da8dSAndroid Build Coastguard Worker dispatch[PyStringMap] = save_dict 977*cda5da8dSAndroid Build Coastguard Worker 978*cda5da8dSAndroid Build Coastguard Worker def _batch_setitems(self, items): 979*cda5da8dSAndroid Build Coastguard Worker # Helper to batch up SETITEMS sequences; proto >= 1 only 980*cda5da8dSAndroid Build Coastguard Worker save = self.save 981*cda5da8dSAndroid Build Coastguard Worker write = self.write 982*cda5da8dSAndroid Build Coastguard Worker 983*cda5da8dSAndroid Build Coastguard Worker if not self.bin: 984*cda5da8dSAndroid Build Coastguard Worker for k, v in items: 985*cda5da8dSAndroid Build Coastguard Worker save(k) 986*cda5da8dSAndroid Build Coastguard Worker save(v) 987*cda5da8dSAndroid Build Coastguard Worker write(SETITEM) 988*cda5da8dSAndroid Build Coastguard Worker return 989*cda5da8dSAndroid Build Coastguard Worker 990*cda5da8dSAndroid Build Coastguard Worker it = iter(items) 991*cda5da8dSAndroid Build Coastguard Worker while True: 992*cda5da8dSAndroid Build Coastguard Worker tmp = list(islice(it, self._BATCHSIZE)) 993*cda5da8dSAndroid Build Coastguard Worker n = len(tmp) 994*cda5da8dSAndroid Build Coastguard Worker if n > 1: 995*cda5da8dSAndroid Build Coastguard Worker write(MARK) 996*cda5da8dSAndroid Build Coastguard Worker for k, v in tmp: 997*cda5da8dSAndroid Build Coastguard Worker save(k) 998*cda5da8dSAndroid Build Coastguard Worker save(v) 999*cda5da8dSAndroid Build Coastguard Worker write(SETITEMS) 1000*cda5da8dSAndroid Build Coastguard Worker elif n: 1001*cda5da8dSAndroid Build Coastguard Worker k, v = tmp[0] 1002*cda5da8dSAndroid Build Coastguard Worker save(k) 1003*cda5da8dSAndroid Build Coastguard Worker save(v) 1004*cda5da8dSAndroid Build Coastguard Worker write(SETITEM) 1005*cda5da8dSAndroid Build Coastguard Worker # else tmp is empty, and we're done 1006*cda5da8dSAndroid Build Coastguard Worker if n < self._BATCHSIZE: 1007*cda5da8dSAndroid Build Coastguard Worker return 1008*cda5da8dSAndroid Build Coastguard Worker 1009*cda5da8dSAndroid Build Coastguard Worker def save_set(self, obj): 1010*cda5da8dSAndroid Build Coastguard Worker save = self.save 1011*cda5da8dSAndroid Build Coastguard Worker write = self.write 1012*cda5da8dSAndroid Build Coastguard Worker 1013*cda5da8dSAndroid Build Coastguard Worker if self.proto < 4: 1014*cda5da8dSAndroid Build Coastguard Worker self.save_reduce(set, (list(obj),), obj=obj) 1015*cda5da8dSAndroid Build Coastguard Worker return 1016*cda5da8dSAndroid Build Coastguard Worker 1017*cda5da8dSAndroid Build Coastguard Worker write(EMPTY_SET) 1018*cda5da8dSAndroid Build Coastguard Worker self.memoize(obj) 1019*cda5da8dSAndroid Build Coastguard Worker 1020*cda5da8dSAndroid Build Coastguard Worker it = iter(obj) 1021*cda5da8dSAndroid Build Coastguard Worker while True: 1022*cda5da8dSAndroid Build Coastguard Worker batch = list(islice(it, self._BATCHSIZE)) 1023*cda5da8dSAndroid Build Coastguard Worker n = len(batch) 1024*cda5da8dSAndroid Build Coastguard Worker if n > 0: 1025*cda5da8dSAndroid Build Coastguard Worker write(MARK) 1026*cda5da8dSAndroid Build Coastguard Worker for item in batch: 1027*cda5da8dSAndroid Build Coastguard Worker save(item) 1028*cda5da8dSAndroid Build Coastguard Worker write(ADDITEMS) 1029*cda5da8dSAndroid Build Coastguard Worker if n < self._BATCHSIZE: 1030*cda5da8dSAndroid Build Coastguard Worker return 1031*cda5da8dSAndroid Build Coastguard Worker dispatch[set] = save_set 1032*cda5da8dSAndroid Build Coastguard Worker 1033*cda5da8dSAndroid Build Coastguard Worker def save_frozenset(self, obj): 1034*cda5da8dSAndroid Build Coastguard Worker save = self.save 1035*cda5da8dSAndroid Build Coastguard Worker write = self.write 1036*cda5da8dSAndroid Build Coastguard Worker 1037*cda5da8dSAndroid Build Coastguard Worker if self.proto < 4: 1038*cda5da8dSAndroid Build Coastguard Worker self.save_reduce(frozenset, (list(obj),), obj=obj) 1039*cda5da8dSAndroid Build Coastguard Worker return 1040*cda5da8dSAndroid Build Coastguard Worker 1041*cda5da8dSAndroid Build Coastguard Worker write(MARK) 1042*cda5da8dSAndroid Build Coastguard Worker for item in obj: 1043*cda5da8dSAndroid Build Coastguard Worker save(item) 1044*cda5da8dSAndroid Build Coastguard Worker 1045*cda5da8dSAndroid Build Coastguard Worker if id(obj) in self.memo: 1046*cda5da8dSAndroid Build Coastguard Worker # If the object is already in the memo, this means it is 1047*cda5da8dSAndroid Build Coastguard Worker # recursive. In this case, throw away everything we put on the 1048*cda5da8dSAndroid Build Coastguard Worker # stack, and fetch the object back from the memo. 1049*cda5da8dSAndroid Build Coastguard Worker write(POP_MARK + self.get(self.memo[id(obj)][0])) 1050*cda5da8dSAndroid Build Coastguard Worker return 1051*cda5da8dSAndroid Build Coastguard Worker 1052*cda5da8dSAndroid Build Coastguard Worker write(FROZENSET) 1053*cda5da8dSAndroid Build Coastguard Worker self.memoize(obj) 1054*cda5da8dSAndroid Build Coastguard Worker dispatch[frozenset] = save_frozenset 1055*cda5da8dSAndroid Build Coastguard Worker 1056*cda5da8dSAndroid Build Coastguard Worker def save_global(self, obj, name=None): 1057*cda5da8dSAndroid Build Coastguard Worker write = self.write 1058*cda5da8dSAndroid Build Coastguard Worker memo = self.memo 1059*cda5da8dSAndroid Build Coastguard Worker 1060*cda5da8dSAndroid Build Coastguard Worker if name is None: 1061*cda5da8dSAndroid Build Coastguard Worker name = getattr(obj, '__qualname__', None) 1062*cda5da8dSAndroid Build Coastguard Worker if name is None: 1063*cda5da8dSAndroid Build Coastguard Worker name = obj.__name__ 1064*cda5da8dSAndroid Build Coastguard Worker 1065*cda5da8dSAndroid Build Coastguard Worker module_name = whichmodule(obj, name) 1066*cda5da8dSAndroid Build Coastguard Worker try: 1067*cda5da8dSAndroid Build Coastguard Worker __import__(module_name, level=0) 1068*cda5da8dSAndroid Build Coastguard Worker module = sys.modules[module_name] 1069*cda5da8dSAndroid Build Coastguard Worker obj2, parent = _getattribute(module, name) 1070*cda5da8dSAndroid Build Coastguard Worker except (ImportError, KeyError, AttributeError): 1071*cda5da8dSAndroid Build Coastguard Worker raise PicklingError( 1072*cda5da8dSAndroid Build Coastguard Worker "Can't pickle %r: it's not found as %s.%s" % 1073*cda5da8dSAndroid Build Coastguard Worker (obj, module_name, name)) from None 1074*cda5da8dSAndroid Build Coastguard Worker else: 1075*cda5da8dSAndroid Build Coastguard Worker if obj2 is not obj: 1076*cda5da8dSAndroid Build Coastguard Worker raise PicklingError( 1077*cda5da8dSAndroid Build Coastguard Worker "Can't pickle %r: it's not the same object as %s.%s" % 1078*cda5da8dSAndroid Build Coastguard Worker (obj, module_name, name)) 1079*cda5da8dSAndroid Build Coastguard Worker 1080*cda5da8dSAndroid Build Coastguard Worker if self.proto >= 2: 1081*cda5da8dSAndroid Build Coastguard Worker code = _extension_registry.get((module_name, name)) 1082*cda5da8dSAndroid Build Coastguard Worker if code: 1083*cda5da8dSAndroid Build Coastguard Worker assert code > 0 1084*cda5da8dSAndroid Build Coastguard Worker if code <= 0xff: 1085*cda5da8dSAndroid Build Coastguard Worker write(EXT1 + pack("<B", code)) 1086*cda5da8dSAndroid Build Coastguard Worker elif code <= 0xffff: 1087*cda5da8dSAndroid Build Coastguard Worker write(EXT2 + pack("<H", code)) 1088*cda5da8dSAndroid Build Coastguard Worker else: 1089*cda5da8dSAndroid Build Coastguard Worker write(EXT4 + pack("<i", code)) 1090*cda5da8dSAndroid Build Coastguard Worker return 1091*cda5da8dSAndroid Build Coastguard Worker lastname = name.rpartition('.')[2] 1092*cda5da8dSAndroid Build Coastguard Worker if parent is module: 1093*cda5da8dSAndroid Build Coastguard Worker name = lastname 1094*cda5da8dSAndroid Build Coastguard Worker # Non-ASCII identifiers are supported only with protocols >= 3. 1095*cda5da8dSAndroid Build Coastguard Worker if self.proto >= 4: 1096*cda5da8dSAndroid Build Coastguard Worker self.save(module_name) 1097*cda5da8dSAndroid Build Coastguard Worker self.save(name) 1098*cda5da8dSAndroid Build Coastguard Worker write(STACK_GLOBAL) 1099*cda5da8dSAndroid Build Coastguard Worker elif parent is not module: 1100*cda5da8dSAndroid Build Coastguard Worker self.save_reduce(getattr, (parent, lastname)) 1101*cda5da8dSAndroid Build Coastguard Worker elif self.proto >= 3: 1102*cda5da8dSAndroid Build Coastguard Worker write(GLOBAL + bytes(module_name, "utf-8") + b'\n' + 1103*cda5da8dSAndroid Build Coastguard Worker bytes(name, "utf-8") + b'\n') 1104*cda5da8dSAndroid Build Coastguard Worker else: 1105*cda5da8dSAndroid Build Coastguard Worker if self.fix_imports: 1106*cda5da8dSAndroid Build Coastguard Worker r_name_mapping = _compat_pickle.REVERSE_NAME_MAPPING 1107*cda5da8dSAndroid Build Coastguard Worker r_import_mapping = _compat_pickle.REVERSE_IMPORT_MAPPING 1108*cda5da8dSAndroid Build Coastguard Worker if (module_name, name) in r_name_mapping: 1109*cda5da8dSAndroid Build Coastguard Worker module_name, name = r_name_mapping[(module_name, name)] 1110*cda5da8dSAndroid Build Coastguard Worker elif module_name in r_import_mapping: 1111*cda5da8dSAndroid Build Coastguard Worker module_name = r_import_mapping[module_name] 1112*cda5da8dSAndroid Build Coastguard Worker try: 1113*cda5da8dSAndroid Build Coastguard Worker write(GLOBAL + bytes(module_name, "ascii") + b'\n' + 1114*cda5da8dSAndroid Build Coastguard Worker bytes(name, "ascii") + b'\n') 1115*cda5da8dSAndroid Build Coastguard Worker except UnicodeEncodeError: 1116*cda5da8dSAndroid Build Coastguard Worker raise PicklingError( 1117*cda5da8dSAndroid Build Coastguard Worker "can't pickle global identifier '%s.%s' using " 1118*cda5da8dSAndroid Build Coastguard Worker "pickle protocol %i" % (module, name, self.proto)) from None 1119*cda5da8dSAndroid Build Coastguard Worker 1120*cda5da8dSAndroid Build Coastguard Worker self.memoize(obj) 1121*cda5da8dSAndroid Build Coastguard Worker 1122*cda5da8dSAndroid Build Coastguard Worker def save_type(self, obj): 1123*cda5da8dSAndroid Build Coastguard Worker if obj is type(None): 1124*cda5da8dSAndroid Build Coastguard Worker return self.save_reduce(type, (None,), obj=obj) 1125*cda5da8dSAndroid Build Coastguard Worker elif obj is type(NotImplemented): 1126*cda5da8dSAndroid Build Coastguard Worker return self.save_reduce(type, (NotImplemented,), obj=obj) 1127*cda5da8dSAndroid Build Coastguard Worker elif obj is type(...): 1128*cda5da8dSAndroid Build Coastguard Worker return self.save_reduce(type, (...,), obj=obj) 1129*cda5da8dSAndroid Build Coastguard Worker return self.save_global(obj) 1130*cda5da8dSAndroid Build Coastguard Worker 1131*cda5da8dSAndroid Build Coastguard Worker dispatch[FunctionType] = save_global 1132*cda5da8dSAndroid Build Coastguard Worker dispatch[type] = save_type 1133*cda5da8dSAndroid Build Coastguard Worker 1134*cda5da8dSAndroid Build Coastguard Worker 1135*cda5da8dSAndroid Build Coastguard Worker# Unpickling machinery 1136*cda5da8dSAndroid Build Coastguard Worker 1137*cda5da8dSAndroid Build Coastguard Workerclass _Unpickler: 1138*cda5da8dSAndroid Build Coastguard Worker 1139*cda5da8dSAndroid Build Coastguard Worker def __init__(self, file, *, fix_imports=True, 1140*cda5da8dSAndroid Build Coastguard Worker encoding="ASCII", errors="strict", buffers=None): 1141*cda5da8dSAndroid Build Coastguard Worker """This takes a binary file for reading a pickle data stream. 1142*cda5da8dSAndroid Build Coastguard Worker 1143*cda5da8dSAndroid Build Coastguard Worker The protocol version of the pickle is detected automatically, so 1144*cda5da8dSAndroid Build Coastguard Worker no proto argument is needed. 1145*cda5da8dSAndroid Build Coastguard Worker 1146*cda5da8dSAndroid Build Coastguard Worker The argument *file* must have two methods, a read() method that 1147*cda5da8dSAndroid Build Coastguard Worker takes an integer argument, and a readline() method that requires 1148*cda5da8dSAndroid Build Coastguard Worker no arguments. Both methods should return bytes. Thus *file* 1149*cda5da8dSAndroid Build Coastguard Worker can be a binary file object opened for reading, an io.BytesIO 1150*cda5da8dSAndroid Build Coastguard Worker object, or any other custom object that meets this interface. 1151*cda5da8dSAndroid Build Coastguard Worker 1152*cda5da8dSAndroid Build Coastguard Worker The file-like object must have two methods, a read() method 1153*cda5da8dSAndroid Build Coastguard Worker that takes an integer argument, and a readline() method that 1154*cda5da8dSAndroid Build Coastguard Worker requires no arguments. Both methods should return bytes. 1155*cda5da8dSAndroid Build Coastguard Worker Thus file-like object can be a binary file object opened for 1156*cda5da8dSAndroid Build Coastguard Worker reading, a BytesIO object, or any other custom object that 1157*cda5da8dSAndroid Build Coastguard Worker meets this interface. 1158*cda5da8dSAndroid Build Coastguard Worker 1159*cda5da8dSAndroid Build Coastguard Worker If *buffers* is not None, it should be an iterable of buffer-enabled 1160*cda5da8dSAndroid Build Coastguard Worker objects that is consumed each time the pickle stream references 1161*cda5da8dSAndroid Build Coastguard Worker an out-of-band buffer view. Such buffers have been given in order 1162*cda5da8dSAndroid Build Coastguard Worker to the *buffer_callback* of a Pickler object. 1163*cda5da8dSAndroid Build Coastguard Worker 1164*cda5da8dSAndroid Build Coastguard Worker If *buffers* is None (the default), then the buffers are taken 1165*cda5da8dSAndroid Build Coastguard Worker from the pickle stream, assuming they are serialized there. 1166*cda5da8dSAndroid Build Coastguard Worker It is an error for *buffers* to be None if the pickle stream 1167*cda5da8dSAndroid Build Coastguard Worker was produced with a non-None *buffer_callback*. 1168*cda5da8dSAndroid Build Coastguard Worker 1169*cda5da8dSAndroid Build Coastguard Worker Other optional arguments are *fix_imports*, *encoding* and 1170*cda5da8dSAndroid Build Coastguard Worker *errors*, which are used to control compatibility support for 1171*cda5da8dSAndroid Build Coastguard Worker pickle stream generated by Python 2. If *fix_imports* is True, 1172*cda5da8dSAndroid Build Coastguard Worker pickle will try to map the old Python 2 names to the new names 1173*cda5da8dSAndroid Build Coastguard Worker used in Python 3. The *encoding* and *errors* tell pickle how 1174*cda5da8dSAndroid Build Coastguard Worker to decode 8-bit string instances pickled by Python 2; these 1175*cda5da8dSAndroid Build Coastguard Worker default to 'ASCII' and 'strict', respectively. *encoding* can be 1176*cda5da8dSAndroid Build Coastguard Worker 'bytes' to read these 8-bit string instances as bytes objects. 1177*cda5da8dSAndroid Build Coastguard Worker """ 1178*cda5da8dSAndroid Build Coastguard Worker self._buffers = iter(buffers) if buffers is not None else None 1179*cda5da8dSAndroid Build Coastguard Worker self._file_readline = file.readline 1180*cda5da8dSAndroid Build Coastguard Worker self._file_read = file.read 1181*cda5da8dSAndroid Build Coastguard Worker self.memo = {} 1182*cda5da8dSAndroid Build Coastguard Worker self.encoding = encoding 1183*cda5da8dSAndroid Build Coastguard Worker self.errors = errors 1184*cda5da8dSAndroid Build Coastguard Worker self.proto = 0 1185*cda5da8dSAndroid Build Coastguard Worker self.fix_imports = fix_imports 1186*cda5da8dSAndroid Build Coastguard Worker 1187*cda5da8dSAndroid Build Coastguard Worker def load(self): 1188*cda5da8dSAndroid Build Coastguard Worker """Read a pickled object representation from the open file. 1189*cda5da8dSAndroid Build Coastguard Worker 1190*cda5da8dSAndroid Build Coastguard Worker Return the reconstituted object hierarchy specified in the file. 1191*cda5da8dSAndroid Build Coastguard Worker """ 1192*cda5da8dSAndroid Build Coastguard Worker # Check whether Unpickler was initialized correctly. This is 1193*cda5da8dSAndroid Build Coastguard Worker # only needed to mimic the behavior of _pickle.Unpickler.dump(). 1194*cda5da8dSAndroid Build Coastguard Worker if not hasattr(self, "_file_read"): 1195*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError("Unpickler.__init__() was not called by " 1196*cda5da8dSAndroid Build Coastguard Worker "%s.__init__()" % (self.__class__.__name__,)) 1197*cda5da8dSAndroid Build Coastguard Worker self._unframer = _Unframer(self._file_read, self._file_readline) 1198*cda5da8dSAndroid Build Coastguard Worker self.read = self._unframer.read 1199*cda5da8dSAndroid Build Coastguard Worker self.readinto = self._unframer.readinto 1200*cda5da8dSAndroid Build Coastguard Worker self.readline = self._unframer.readline 1201*cda5da8dSAndroid Build Coastguard Worker self.metastack = [] 1202*cda5da8dSAndroid Build Coastguard Worker self.stack = [] 1203*cda5da8dSAndroid Build Coastguard Worker self.append = self.stack.append 1204*cda5da8dSAndroid Build Coastguard Worker self.proto = 0 1205*cda5da8dSAndroid Build Coastguard Worker read = self.read 1206*cda5da8dSAndroid Build Coastguard Worker dispatch = self.dispatch 1207*cda5da8dSAndroid Build Coastguard Worker try: 1208*cda5da8dSAndroid Build Coastguard Worker while True: 1209*cda5da8dSAndroid Build Coastguard Worker key = read(1) 1210*cda5da8dSAndroid Build Coastguard Worker if not key: 1211*cda5da8dSAndroid Build Coastguard Worker raise EOFError 1212*cda5da8dSAndroid Build Coastguard Worker assert isinstance(key, bytes_types) 1213*cda5da8dSAndroid Build Coastguard Worker dispatch[key[0]](self) 1214*cda5da8dSAndroid Build Coastguard Worker except _Stop as stopinst: 1215*cda5da8dSAndroid Build Coastguard Worker return stopinst.value 1216*cda5da8dSAndroid Build Coastguard Worker 1217*cda5da8dSAndroid Build Coastguard Worker # Return a list of items pushed in the stack after last MARK instruction. 1218*cda5da8dSAndroid Build Coastguard Worker def pop_mark(self): 1219*cda5da8dSAndroid Build Coastguard Worker items = self.stack 1220*cda5da8dSAndroid Build Coastguard Worker self.stack = self.metastack.pop() 1221*cda5da8dSAndroid Build Coastguard Worker self.append = self.stack.append 1222*cda5da8dSAndroid Build Coastguard Worker return items 1223*cda5da8dSAndroid Build Coastguard Worker 1224*cda5da8dSAndroid Build Coastguard Worker def persistent_load(self, pid): 1225*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError("unsupported persistent id encountered") 1226*cda5da8dSAndroid Build Coastguard Worker 1227*cda5da8dSAndroid Build Coastguard Worker dispatch = {} 1228*cda5da8dSAndroid Build Coastguard Worker 1229*cda5da8dSAndroid Build Coastguard Worker def load_proto(self): 1230*cda5da8dSAndroid Build Coastguard Worker proto = self.read(1)[0] 1231*cda5da8dSAndroid Build Coastguard Worker if not 0 <= proto <= HIGHEST_PROTOCOL: 1232*cda5da8dSAndroid Build Coastguard Worker raise ValueError("unsupported pickle protocol: %d" % proto) 1233*cda5da8dSAndroid Build Coastguard Worker self.proto = proto 1234*cda5da8dSAndroid Build Coastguard Worker dispatch[PROTO[0]] = load_proto 1235*cda5da8dSAndroid Build Coastguard Worker 1236*cda5da8dSAndroid Build Coastguard Worker def load_frame(self): 1237*cda5da8dSAndroid Build Coastguard Worker frame_size, = unpack('<Q', self.read(8)) 1238*cda5da8dSAndroid Build Coastguard Worker if frame_size > sys.maxsize: 1239*cda5da8dSAndroid Build Coastguard Worker raise ValueError("frame size > sys.maxsize: %d" % frame_size) 1240*cda5da8dSAndroid Build Coastguard Worker self._unframer.load_frame(frame_size) 1241*cda5da8dSAndroid Build Coastguard Worker dispatch[FRAME[0]] = load_frame 1242*cda5da8dSAndroid Build Coastguard Worker 1243*cda5da8dSAndroid Build Coastguard Worker def load_persid(self): 1244*cda5da8dSAndroid Build Coastguard Worker try: 1245*cda5da8dSAndroid Build Coastguard Worker pid = self.readline()[:-1].decode("ascii") 1246*cda5da8dSAndroid Build Coastguard Worker except UnicodeDecodeError: 1247*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError( 1248*cda5da8dSAndroid Build Coastguard Worker "persistent IDs in protocol 0 must be ASCII strings") 1249*cda5da8dSAndroid Build Coastguard Worker self.append(self.persistent_load(pid)) 1250*cda5da8dSAndroid Build Coastguard Worker dispatch[PERSID[0]] = load_persid 1251*cda5da8dSAndroid Build Coastguard Worker 1252*cda5da8dSAndroid Build Coastguard Worker def load_binpersid(self): 1253*cda5da8dSAndroid Build Coastguard Worker pid = self.stack.pop() 1254*cda5da8dSAndroid Build Coastguard Worker self.append(self.persistent_load(pid)) 1255*cda5da8dSAndroid Build Coastguard Worker dispatch[BINPERSID[0]] = load_binpersid 1256*cda5da8dSAndroid Build Coastguard Worker 1257*cda5da8dSAndroid Build Coastguard Worker def load_none(self): 1258*cda5da8dSAndroid Build Coastguard Worker self.append(None) 1259*cda5da8dSAndroid Build Coastguard Worker dispatch[NONE[0]] = load_none 1260*cda5da8dSAndroid Build Coastguard Worker 1261*cda5da8dSAndroid Build Coastguard Worker def load_false(self): 1262*cda5da8dSAndroid Build Coastguard Worker self.append(False) 1263*cda5da8dSAndroid Build Coastguard Worker dispatch[NEWFALSE[0]] = load_false 1264*cda5da8dSAndroid Build Coastguard Worker 1265*cda5da8dSAndroid Build Coastguard Worker def load_true(self): 1266*cda5da8dSAndroid Build Coastguard Worker self.append(True) 1267*cda5da8dSAndroid Build Coastguard Worker dispatch[NEWTRUE[0]] = load_true 1268*cda5da8dSAndroid Build Coastguard Worker 1269*cda5da8dSAndroid Build Coastguard Worker def load_int(self): 1270*cda5da8dSAndroid Build Coastguard Worker data = self.readline() 1271*cda5da8dSAndroid Build Coastguard Worker if data == FALSE[1:]: 1272*cda5da8dSAndroid Build Coastguard Worker val = False 1273*cda5da8dSAndroid Build Coastguard Worker elif data == TRUE[1:]: 1274*cda5da8dSAndroid Build Coastguard Worker val = True 1275*cda5da8dSAndroid Build Coastguard Worker else: 1276*cda5da8dSAndroid Build Coastguard Worker val = int(data, 0) 1277*cda5da8dSAndroid Build Coastguard Worker self.append(val) 1278*cda5da8dSAndroid Build Coastguard Worker dispatch[INT[0]] = load_int 1279*cda5da8dSAndroid Build Coastguard Worker 1280*cda5da8dSAndroid Build Coastguard Worker def load_binint(self): 1281*cda5da8dSAndroid Build Coastguard Worker self.append(unpack('<i', self.read(4))[0]) 1282*cda5da8dSAndroid Build Coastguard Worker dispatch[BININT[0]] = load_binint 1283*cda5da8dSAndroid Build Coastguard Worker 1284*cda5da8dSAndroid Build Coastguard Worker def load_binint1(self): 1285*cda5da8dSAndroid Build Coastguard Worker self.append(self.read(1)[0]) 1286*cda5da8dSAndroid Build Coastguard Worker dispatch[BININT1[0]] = load_binint1 1287*cda5da8dSAndroid Build Coastguard Worker 1288*cda5da8dSAndroid Build Coastguard Worker def load_binint2(self): 1289*cda5da8dSAndroid Build Coastguard Worker self.append(unpack('<H', self.read(2))[0]) 1290*cda5da8dSAndroid Build Coastguard Worker dispatch[BININT2[0]] = load_binint2 1291*cda5da8dSAndroid Build Coastguard Worker 1292*cda5da8dSAndroid Build Coastguard Worker def load_long(self): 1293*cda5da8dSAndroid Build Coastguard Worker val = self.readline()[:-1] 1294*cda5da8dSAndroid Build Coastguard Worker if val and val[-1] == b'L'[0]: 1295*cda5da8dSAndroid Build Coastguard Worker val = val[:-1] 1296*cda5da8dSAndroid Build Coastguard Worker self.append(int(val, 0)) 1297*cda5da8dSAndroid Build Coastguard Worker dispatch[LONG[0]] = load_long 1298*cda5da8dSAndroid Build Coastguard Worker 1299*cda5da8dSAndroid Build Coastguard Worker def load_long1(self): 1300*cda5da8dSAndroid Build Coastguard Worker n = self.read(1)[0] 1301*cda5da8dSAndroid Build Coastguard Worker data = self.read(n) 1302*cda5da8dSAndroid Build Coastguard Worker self.append(decode_long(data)) 1303*cda5da8dSAndroid Build Coastguard Worker dispatch[LONG1[0]] = load_long1 1304*cda5da8dSAndroid Build Coastguard Worker 1305*cda5da8dSAndroid Build Coastguard Worker def load_long4(self): 1306*cda5da8dSAndroid Build Coastguard Worker n, = unpack('<i', self.read(4)) 1307*cda5da8dSAndroid Build Coastguard Worker if n < 0: 1308*cda5da8dSAndroid Build Coastguard Worker # Corrupt or hostile pickle -- we never write one like this 1309*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError("LONG pickle has negative byte count") 1310*cda5da8dSAndroid Build Coastguard Worker data = self.read(n) 1311*cda5da8dSAndroid Build Coastguard Worker self.append(decode_long(data)) 1312*cda5da8dSAndroid Build Coastguard Worker dispatch[LONG4[0]] = load_long4 1313*cda5da8dSAndroid Build Coastguard Worker 1314*cda5da8dSAndroid Build Coastguard Worker def load_float(self): 1315*cda5da8dSAndroid Build Coastguard Worker self.append(float(self.readline()[:-1])) 1316*cda5da8dSAndroid Build Coastguard Worker dispatch[FLOAT[0]] = load_float 1317*cda5da8dSAndroid Build Coastguard Worker 1318*cda5da8dSAndroid Build Coastguard Worker def load_binfloat(self): 1319*cda5da8dSAndroid Build Coastguard Worker self.append(unpack('>d', self.read(8))[0]) 1320*cda5da8dSAndroid Build Coastguard Worker dispatch[BINFLOAT[0]] = load_binfloat 1321*cda5da8dSAndroid Build Coastguard Worker 1322*cda5da8dSAndroid Build Coastguard Worker def _decode_string(self, value): 1323*cda5da8dSAndroid Build Coastguard Worker # Used to allow strings from Python 2 to be decoded either as 1324*cda5da8dSAndroid Build Coastguard Worker # bytes or Unicode strings. This should be used only with the 1325*cda5da8dSAndroid Build Coastguard Worker # STRING, BINSTRING and SHORT_BINSTRING opcodes. 1326*cda5da8dSAndroid Build Coastguard Worker if self.encoding == "bytes": 1327*cda5da8dSAndroid Build Coastguard Worker return value 1328*cda5da8dSAndroid Build Coastguard Worker else: 1329*cda5da8dSAndroid Build Coastguard Worker return value.decode(self.encoding, self.errors) 1330*cda5da8dSAndroid Build Coastguard Worker 1331*cda5da8dSAndroid Build Coastguard Worker def load_string(self): 1332*cda5da8dSAndroid Build Coastguard Worker data = self.readline()[:-1] 1333*cda5da8dSAndroid Build Coastguard Worker # Strip outermost quotes 1334*cda5da8dSAndroid Build Coastguard Worker if len(data) >= 2 and data[0] == data[-1] and data[0] in b'"\'': 1335*cda5da8dSAndroid Build Coastguard Worker data = data[1:-1] 1336*cda5da8dSAndroid Build Coastguard Worker else: 1337*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError("the STRING opcode argument must be quoted") 1338*cda5da8dSAndroid Build Coastguard Worker self.append(self._decode_string(codecs.escape_decode(data)[0])) 1339*cda5da8dSAndroid Build Coastguard Worker dispatch[STRING[0]] = load_string 1340*cda5da8dSAndroid Build Coastguard Worker 1341*cda5da8dSAndroid Build Coastguard Worker def load_binstring(self): 1342*cda5da8dSAndroid Build Coastguard Worker # Deprecated BINSTRING uses signed 32-bit length 1343*cda5da8dSAndroid Build Coastguard Worker len, = unpack('<i', self.read(4)) 1344*cda5da8dSAndroid Build Coastguard Worker if len < 0: 1345*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError("BINSTRING pickle has negative byte count") 1346*cda5da8dSAndroid Build Coastguard Worker data = self.read(len) 1347*cda5da8dSAndroid Build Coastguard Worker self.append(self._decode_string(data)) 1348*cda5da8dSAndroid Build Coastguard Worker dispatch[BINSTRING[0]] = load_binstring 1349*cda5da8dSAndroid Build Coastguard Worker 1350*cda5da8dSAndroid Build Coastguard Worker def load_binbytes(self): 1351*cda5da8dSAndroid Build Coastguard Worker len, = unpack('<I', self.read(4)) 1352*cda5da8dSAndroid Build Coastguard Worker if len > maxsize: 1353*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError("BINBYTES exceeds system's maximum size " 1354*cda5da8dSAndroid Build Coastguard Worker "of %d bytes" % maxsize) 1355*cda5da8dSAndroid Build Coastguard Worker self.append(self.read(len)) 1356*cda5da8dSAndroid Build Coastguard Worker dispatch[BINBYTES[0]] = load_binbytes 1357*cda5da8dSAndroid Build Coastguard Worker 1358*cda5da8dSAndroid Build Coastguard Worker def load_unicode(self): 1359*cda5da8dSAndroid Build Coastguard Worker self.append(str(self.readline()[:-1], 'raw-unicode-escape')) 1360*cda5da8dSAndroid Build Coastguard Worker dispatch[UNICODE[0]] = load_unicode 1361*cda5da8dSAndroid Build Coastguard Worker 1362*cda5da8dSAndroid Build Coastguard Worker def load_binunicode(self): 1363*cda5da8dSAndroid Build Coastguard Worker len, = unpack('<I', self.read(4)) 1364*cda5da8dSAndroid Build Coastguard Worker if len > maxsize: 1365*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError("BINUNICODE exceeds system's maximum size " 1366*cda5da8dSAndroid Build Coastguard Worker "of %d bytes" % maxsize) 1367*cda5da8dSAndroid Build Coastguard Worker self.append(str(self.read(len), 'utf-8', 'surrogatepass')) 1368*cda5da8dSAndroid Build Coastguard Worker dispatch[BINUNICODE[0]] = load_binunicode 1369*cda5da8dSAndroid Build Coastguard Worker 1370*cda5da8dSAndroid Build Coastguard Worker def load_binunicode8(self): 1371*cda5da8dSAndroid Build Coastguard Worker len, = unpack('<Q', self.read(8)) 1372*cda5da8dSAndroid Build Coastguard Worker if len > maxsize: 1373*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError("BINUNICODE8 exceeds system's maximum size " 1374*cda5da8dSAndroid Build Coastguard Worker "of %d bytes" % maxsize) 1375*cda5da8dSAndroid Build Coastguard Worker self.append(str(self.read(len), 'utf-8', 'surrogatepass')) 1376*cda5da8dSAndroid Build Coastguard Worker dispatch[BINUNICODE8[0]] = load_binunicode8 1377*cda5da8dSAndroid Build Coastguard Worker 1378*cda5da8dSAndroid Build Coastguard Worker def load_binbytes8(self): 1379*cda5da8dSAndroid Build Coastguard Worker len, = unpack('<Q', self.read(8)) 1380*cda5da8dSAndroid Build Coastguard Worker if len > maxsize: 1381*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError("BINBYTES8 exceeds system's maximum size " 1382*cda5da8dSAndroid Build Coastguard Worker "of %d bytes" % maxsize) 1383*cda5da8dSAndroid Build Coastguard Worker self.append(self.read(len)) 1384*cda5da8dSAndroid Build Coastguard Worker dispatch[BINBYTES8[0]] = load_binbytes8 1385*cda5da8dSAndroid Build Coastguard Worker 1386*cda5da8dSAndroid Build Coastguard Worker def load_bytearray8(self): 1387*cda5da8dSAndroid Build Coastguard Worker len, = unpack('<Q', self.read(8)) 1388*cda5da8dSAndroid Build Coastguard Worker if len > maxsize: 1389*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError("BYTEARRAY8 exceeds system's maximum size " 1390*cda5da8dSAndroid Build Coastguard Worker "of %d bytes" % maxsize) 1391*cda5da8dSAndroid Build Coastguard Worker b = bytearray(len) 1392*cda5da8dSAndroid Build Coastguard Worker self.readinto(b) 1393*cda5da8dSAndroid Build Coastguard Worker self.append(b) 1394*cda5da8dSAndroid Build Coastguard Worker dispatch[BYTEARRAY8[0]] = load_bytearray8 1395*cda5da8dSAndroid Build Coastguard Worker 1396*cda5da8dSAndroid Build Coastguard Worker def load_next_buffer(self): 1397*cda5da8dSAndroid Build Coastguard Worker if self._buffers is None: 1398*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError("pickle stream refers to out-of-band data " 1399*cda5da8dSAndroid Build Coastguard Worker "but no *buffers* argument was given") 1400*cda5da8dSAndroid Build Coastguard Worker try: 1401*cda5da8dSAndroid Build Coastguard Worker buf = next(self._buffers) 1402*cda5da8dSAndroid Build Coastguard Worker except StopIteration: 1403*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError("not enough out-of-band buffers") 1404*cda5da8dSAndroid Build Coastguard Worker self.append(buf) 1405*cda5da8dSAndroid Build Coastguard Worker dispatch[NEXT_BUFFER[0]] = load_next_buffer 1406*cda5da8dSAndroid Build Coastguard Worker 1407*cda5da8dSAndroid Build Coastguard Worker def load_readonly_buffer(self): 1408*cda5da8dSAndroid Build Coastguard Worker buf = self.stack[-1] 1409*cda5da8dSAndroid Build Coastguard Worker with memoryview(buf) as m: 1410*cda5da8dSAndroid Build Coastguard Worker if not m.readonly: 1411*cda5da8dSAndroid Build Coastguard Worker self.stack[-1] = m.toreadonly() 1412*cda5da8dSAndroid Build Coastguard Worker dispatch[READONLY_BUFFER[0]] = load_readonly_buffer 1413*cda5da8dSAndroid Build Coastguard Worker 1414*cda5da8dSAndroid Build Coastguard Worker def load_short_binstring(self): 1415*cda5da8dSAndroid Build Coastguard Worker len = self.read(1)[0] 1416*cda5da8dSAndroid Build Coastguard Worker data = self.read(len) 1417*cda5da8dSAndroid Build Coastguard Worker self.append(self._decode_string(data)) 1418*cda5da8dSAndroid Build Coastguard Worker dispatch[SHORT_BINSTRING[0]] = load_short_binstring 1419*cda5da8dSAndroid Build Coastguard Worker 1420*cda5da8dSAndroid Build Coastguard Worker def load_short_binbytes(self): 1421*cda5da8dSAndroid Build Coastguard Worker len = self.read(1)[0] 1422*cda5da8dSAndroid Build Coastguard Worker self.append(self.read(len)) 1423*cda5da8dSAndroid Build Coastguard Worker dispatch[SHORT_BINBYTES[0]] = load_short_binbytes 1424*cda5da8dSAndroid Build Coastguard Worker 1425*cda5da8dSAndroid Build Coastguard Worker def load_short_binunicode(self): 1426*cda5da8dSAndroid Build Coastguard Worker len = self.read(1)[0] 1427*cda5da8dSAndroid Build Coastguard Worker self.append(str(self.read(len), 'utf-8', 'surrogatepass')) 1428*cda5da8dSAndroid Build Coastguard Worker dispatch[SHORT_BINUNICODE[0]] = load_short_binunicode 1429*cda5da8dSAndroid Build Coastguard Worker 1430*cda5da8dSAndroid Build Coastguard Worker def load_tuple(self): 1431*cda5da8dSAndroid Build Coastguard Worker items = self.pop_mark() 1432*cda5da8dSAndroid Build Coastguard Worker self.append(tuple(items)) 1433*cda5da8dSAndroid Build Coastguard Worker dispatch[TUPLE[0]] = load_tuple 1434*cda5da8dSAndroid Build Coastguard Worker 1435*cda5da8dSAndroid Build Coastguard Worker def load_empty_tuple(self): 1436*cda5da8dSAndroid Build Coastguard Worker self.append(()) 1437*cda5da8dSAndroid Build Coastguard Worker dispatch[EMPTY_TUPLE[0]] = load_empty_tuple 1438*cda5da8dSAndroid Build Coastguard Worker 1439*cda5da8dSAndroid Build Coastguard Worker def load_tuple1(self): 1440*cda5da8dSAndroid Build Coastguard Worker self.stack[-1] = (self.stack[-1],) 1441*cda5da8dSAndroid Build Coastguard Worker dispatch[TUPLE1[0]] = load_tuple1 1442*cda5da8dSAndroid Build Coastguard Worker 1443*cda5da8dSAndroid Build Coastguard Worker def load_tuple2(self): 1444*cda5da8dSAndroid Build Coastguard Worker self.stack[-2:] = [(self.stack[-2], self.stack[-1])] 1445*cda5da8dSAndroid Build Coastguard Worker dispatch[TUPLE2[0]] = load_tuple2 1446*cda5da8dSAndroid Build Coastguard Worker 1447*cda5da8dSAndroid Build Coastguard Worker def load_tuple3(self): 1448*cda5da8dSAndroid Build Coastguard Worker self.stack[-3:] = [(self.stack[-3], self.stack[-2], self.stack[-1])] 1449*cda5da8dSAndroid Build Coastguard Worker dispatch[TUPLE3[0]] = load_tuple3 1450*cda5da8dSAndroid Build Coastguard Worker 1451*cda5da8dSAndroid Build Coastguard Worker def load_empty_list(self): 1452*cda5da8dSAndroid Build Coastguard Worker self.append([]) 1453*cda5da8dSAndroid Build Coastguard Worker dispatch[EMPTY_LIST[0]] = load_empty_list 1454*cda5da8dSAndroid Build Coastguard Worker 1455*cda5da8dSAndroid Build Coastguard Worker def load_empty_dictionary(self): 1456*cda5da8dSAndroid Build Coastguard Worker self.append({}) 1457*cda5da8dSAndroid Build Coastguard Worker dispatch[EMPTY_DICT[0]] = load_empty_dictionary 1458*cda5da8dSAndroid Build Coastguard Worker 1459*cda5da8dSAndroid Build Coastguard Worker def load_empty_set(self): 1460*cda5da8dSAndroid Build Coastguard Worker self.append(set()) 1461*cda5da8dSAndroid Build Coastguard Worker dispatch[EMPTY_SET[0]] = load_empty_set 1462*cda5da8dSAndroid Build Coastguard Worker 1463*cda5da8dSAndroid Build Coastguard Worker def load_frozenset(self): 1464*cda5da8dSAndroid Build Coastguard Worker items = self.pop_mark() 1465*cda5da8dSAndroid Build Coastguard Worker self.append(frozenset(items)) 1466*cda5da8dSAndroid Build Coastguard Worker dispatch[FROZENSET[0]] = load_frozenset 1467*cda5da8dSAndroid Build Coastguard Worker 1468*cda5da8dSAndroid Build Coastguard Worker def load_list(self): 1469*cda5da8dSAndroid Build Coastguard Worker items = self.pop_mark() 1470*cda5da8dSAndroid Build Coastguard Worker self.append(items) 1471*cda5da8dSAndroid Build Coastguard Worker dispatch[LIST[0]] = load_list 1472*cda5da8dSAndroid Build Coastguard Worker 1473*cda5da8dSAndroid Build Coastguard Worker def load_dict(self): 1474*cda5da8dSAndroid Build Coastguard Worker items = self.pop_mark() 1475*cda5da8dSAndroid Build Coastguard Worker d = {items[i]: items[i+1] 1476*cda5da8dSAndroid Build Coastguard Worker for i in range(0, len(items), 2)} 1477*cda5da8dSAndroid Build Coastguard Worker self.append(d) 1478*cda5da8dSAndroid Build Coastguard Worker dispatch[DICT[0]] = load_dict 1479*cda5da8dSAndroid Build Coastguard Worker 1480*cda5da8dSAndroid Build Coastguard Worker # INST and OBJ differ only in how they get a class object. It's not 1481*cda5da8dSAndroid Build Coastguard Worker # only sensible to do the rest in a common routine, the two routines 1482*cda5da8dSAndroid Build Coastguard Worker # previously diverged and grew different bugs. 1483*cda5da8dSAndroid Build Coastguard Worker # klass is the class to instantiate, and k points to the topmost mark 1484*cda5da8dSAndroid Build Coastguard Worker # object, following which are the arguments for klass.__init__. 1485*cda5da8dSAndroid Build Coastguard Worker def _instantiate(self, klass, args): 1486*cda5da8dSAndroid Build Coastguard Worker if (args or not isinstance(klass, type) or 1487*cda5da8dSAndroid Build Coastguard Worker hasattr(klass, "__getinitargs__")): 1488*cda5da8dSAndroid Build Coastguard Worker try: 1489*cda5da8dSAndroid Build Coastguard Worker value = klass(*args) 1490*cda5da8dSAndroid Build Coastguard Worker except TypeError as err: 1491*cda5da8dSAndroid Build Coastguard Worker raise TypeError("in constructor for %s: %s" % 1492*cda5da8dSAndroid Build Coastguard Worker (klass.__name__, str(err)), sys.exc_info()[2]) 1493*cda5da8dSAndroid Build Coastguard Worker else: 1494*cda5da8dSAndroid Build Coastguard Worker value = klass.__new__(klass) 1495*cda5da8dSAndroid Build Coastguard Worker self.append(value) 1496*cda5da8dSAndroid Build Coastguard Worker 1497*cda5da8dSAndroid Build Coastguard Worker def load_inst(self): 1498*cda5da8dSAndroid Build Coastguard Worker module = self.readline()[:-1].decode("ascii") 1499*cda5da8dSAndroid Build Coastguard Worker name = self.readline()[:-1].decode("ascii") 1500*cda5da8dSAndroid Build Coastguard Worker klass = self.find_class(module, name) 1501*cda5da8dSAndroid Build Coastguard Worker self._instantiate(klass, self.pop_mark()) 1502*cda5da8dSAndroid Build Coastguard Worker dispatch[INST[0]] = load_inst 1503*cda5da8dSAndroid Build Coastguard Worker 1504*cda5da8dSAndroid Build Coastguard Worker def load_obj(self): 1505*cda5da8dSAndroid Build Coastguard Worker # Stack is ... markobject classobject arg1 arg2 ... 1506*cda5da8dSAndroid Build Coastguard Worker args = self.pop_mark() 1507*cda5da8dSAndroid Build Coastguard Worker cls = args.pop(0) 1508*cda5da8dSAndroid Build Coastguard Worker self._instantiate(cls, args) 1509*cda5da8dSAndroid Build Coastguard Worker dispatch[OBJ[0]] = load_obj 1510*cda5da8dSAndroid Build Coastguard Worker 1511*cda5da8dSAndroid Build Coastguard Worker def load_newobj(self): 1512*cda5da8dSAndroid Build Coastguard Worker args = self.stack.pop() 1513*cda5da8dSAndroid Build Coastguard Worker cls = self.stack.pop() 1514*cda5da8dSAndroid Build Coastguard Worker obj = cls.__new__(cls, *args) 1515*cda5da8dSAndroid Build Coastguard Worker self.append(obj) 1516*cda5da8dSAndroid Build Coastguard Worker dispatch[NEWOBJ[0]] = load_newobj 1517*cda5da8dSAndroid Build Coastguard Worker 1518*cda5da8dSAndroid Build Coastguard Worker def load_newobj_ex(self): 1519*cda5da8dSAndroid Build Coastguard Worker kwargs = self.stack.pop() 1520*cda5da8dSAndroid Build Coastguard Worker args = self.stack.pop() 1521*cda5da8dSAndroid Build Coastguard Worker cls = self.stack.pop() 1522*cda5da8dSAndroid Build Coastguard Worker obj = cls.__new__(cls, *args, **kwargs) 1523*cda5da8dSAndroid Build Coastguard Worker self.append(obj) 1524*cda5da8dSAndroid Build Coastguard Worker dispatch[NEWOBJ_EX[0]] = load_newobj_ex 1525*cda5da8dSAndroid Build Coastguard Worker 1526*cda5da8dSAndroid Build Coastguard Worker def load_global(self): 1527*cda5da8dSAndroid Build Coastguard Worker module = self.readline()[:-1].decode("utf-8") 1528*cda5da8dSAndroid Build Coastguard Worker name = self.readline()[:-1].decode("utf-8") 1529*cda5da8dSAndroid Build Coastguard Worker klass = self.find_class(module, name) 1530*cda5da8dSAndroid Build Coastguard Worker self.append(klass) 1531*cda5da8dSAndroid Build Coastguard Worker dispatch[GLOBAL[0]] = load_global 1532*cda5da8dSAndroid Build Coastguard Worker 1533*cda5da8dSAndroid Build Coastguard Worker def load_stack_global(self): 1534*cda5da8dSAndroid Build Coastguard Worker name = self.stack.pop() 1535*cda5da8dSAndroid Build Coastguard Worker module = self.stack.pop() 1536*cda5da8dSAndroid Build Coastguard Worker if type(name) is not str or type(module) is not str: 1537*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError("STACK_GLOBAL requires str") 1538*cda5da8dSAndroid Build Coastguard Worker self.append(self.find_class(module, name)) 1539*cda5da8dSAndroid Build Coastguard Worker dispatch[STACK_GLOBAL[0]] = load_stack_global 1540*cda5da8dSAndroid Build Coastguard Worker 1541*cda5da8dSAndroid Build Coastguard Worker def load_ext1(self): 1542*cda5da8dSAndroid Build Coastguard Worker code = self.read(1)[0] 1543*cda5da8dSAndroid Build Coastguard Worker self.get_extension(code) 1544*cda5da8dSAndroid Build Coastguard Worker dispatch[EXT1[0]] = load_ext1 1545*cda5da8dSAndroid Build Coastguard Worker 1546*cda5da8dSAndroid Build Coastguard Worker def load_ext2(self): 1547*cda5da8dSAndroid Build Coastguard Worker code, = unpack('<H', self.read(2)) 1548*cda5da8dSAndroid Build Coastguard Worker self.get_extension(code) 1549*cda5da8dSAndroid Build Coastguard Worker dispatch[EXT2[0]] = load_ext2 1550*cda5da8dSAndroid Build Coastguard Worker 1551*cda5da8dSAndroid Build Coastguard Worker def load_ext4(self): 1552*cda5da8dSAndroid Build Coastguard Worker code, = unpack('<i', self.read(4)) 1553*cda5da8dSAndroid Build Coastguard Worker self.get_extension(code) 1554*cda5da8dSAndroid Build Coastguard Worker dispatch[EXT4[0]] = load_ext4 1555*cda5da8dSAndroid Build Coastguard Worker 1556*cda5da8dSAndroid Build Coastguard Worker def get_extension(self, code): 1557*cda5da8dSAndroid Build Coastguard Worker nil = [] 1558*cda5da8dSAndroid Build Coastguard Worker obj = _extension_cache.get(code, nil) 1559*cda5da8dSAndroid Build Coastguard Worker if obj is not nil: 1560*cda5da8dSAndroid Build Coastguard Worker self.append(obj) 1561*cda5da8dSAndroid Build Coastguard Worker return 1562*cda5da8dSAndroid Build Coastguard Worker key = _inverted_registry.get(code) 1563*cda5da8dSAndroid Build Coastguard Worker if not key: 1564*cda5da8dSAndroid Build Coastguard Worker if code <= 0: # note that 0 is forbidden 1565*cda5da8dSAndroid Build Coastguard Worker # Corrupt or hostile pickle. 1566*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError("EXT specifies code <= 0") 1567*cda5da8dSAndroid Build Coastguard Worker raise ValueError("unregistered extension code %d" % code) 1568*cda5da8dSAndroid Build Coastguard Worker obj = self.find_class(*key) 1569*cda5da8dSAndroid Build Coastguard Worker _extension_cache[code] = obj 1570*cda5da8dSAndroid Build Coastguard Worker self.append(obj) 1571*cda5da8dSAndroid Build Coastguard Worker 1572*cda5da8dSAndroid Build Coastguard Worker def find_class(self, module, name): 1573*cda5da8dSAndroid Build Coastguard Worker # Subclasses may override this. 1574*cda5da8dSAndroid Build Coastguard Worker sys.audit('pickle.find_class', module, name) 1575*cda5da8dSAndroid Build Coastguard Worker if self.proto < 3 and self.fix_imports: 1576*cda5da8dSAndroid Build Coastguard Worker if (module, name) in _compat_pickle.NAME_MAPPING: 1577*cda5da8dSAndroid Build Coastguard Worker module, name = _compat_pickle.NAME_MAPPING[(module, name)] 1578*cda5da8dSAndroid Build Coastguard Worker elif module in _compat_pickle.IMPORT_MAPPING: 1579*cda5da8dSAndroid Build Coastguard Worker module = _compat_pickle.IMPORT_MAPPING[module] 1580*cda5da8dSAndroid Build Coastguard Worker __import__(module, level=0) 1581*cda5da8dSAndroid Build Coastguard Worker if self.proto >= 4: 1582*cda5da8dSAndroid Build Coastguard Worker return _getattribute(sys.modules[module], name)[0] 1583*cda5da8dSAndroid Build Coastguard Worker else: 1584*cda5da8dSAndroid Build Coastguard Worker return getattr(sys.modules[module], name) 1585*cda5da8dSAndroid Build Coastguard Worker 1586*cda5da8dSAndroid Build Coastguard Worker def load_reduce(self): 1587*cda5da8dSAndroid Build Coastguard Worker stack = self.stack 1588*cda5da8dSAndroid Build Coastguard Worker args = stack.pop() 1589*cda5da8dSAndroid Build Coastguard Worker func = stack[-1] 1590*cda5da8dSAndroid Build Coastguard Worker stack[-1] = func(*args) 1591*cda5da8dSAndroid Build Coastguard Worker dispatch[REDUCE[0]] = load_reduce 1592*cda5da8dSAndroid Build Coastguard Worker 1593*cda5da8dSAndroid Build Coastguard Worker def load_pop(self): 1594*cda5da8dSAndroid Build Coastguard Worker if self.stack: 1595*cda5da8dSAndroid Build Coastguard Worker del self.stack[-1] 1596*cda5da8dSAndroid Build Coastguard Worker else: 1597*cda5da8dSAndroid Build Coastguard Worker self.pop_mark() 1598*cda5da8dSAndroid Build Coastguard Worker dispatch[POP[0]] = load_pop 1599*cda5da8dSAndroid Build Coastguard Worker 1600*cda5da8dSAndroid Build Coastguard Worker def load_pop_mark(self): 1601*cda5da8dSAndroid Build Coastguard Worker self.pop_mark() 1602*cda5da8dSAndroid Build Coastguard Worker dispatch[POP_MARK[0]] = load_pop_mark 1603*cda5da8dSAndroid Build Coastguard Worker 1604*cda5da8dSAndroid Build Coastguard Worker def load_dup(self): 1605*cda5da8dSAndroid Build Coastguard Worker self.append(self.stack[-1]) 1606*cda5da8dSAndroid Build Coastguard Worker dispatch[DUP[0]] = load_dup 1607*cda5da8dSAndroid Build Coastguard Worker 1608*cda5da8dSAndroid Build Coastguard Worker def load_get(self): 1609*cda5da8dSAndroid Build Coastguard Worker i = int(self.readline()[:-1]) 1610*cda5da8dSAndroid Build Coastguard Worker try: 1611*cda5da8dSAndroid Build Coastguard Worker self.append(self.memo[i]) 1612*cda5da8dSAndroid Build Coastguard Worker except KeyError: 1613*cda5da8dSAndroid Build Coastguard Worker msg = f'Memo value not found at index {i}' 1614*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError(msg) from None 1615*cda5da8dSAndroid Build Coastguard Worker dispatch[GET[0]] = load_get 1616*cda5da8dSAndroid Build Coastguard Worker 1617*cda5da8dSAndroid Build Coastguard Worker def load_binget(self): 1618*cda5da8dSAndroid Build Coastguard Worker i = self.read(1)[0] 1619*cda5da8dSAndroid Build Coastguard Worker try: 1620*cda5da8dSAndroid Build Coastguard Worker self.append(self.memo[i]) 1621*cda5da8dSAndroid Build Coastguard Worker except KeyError as exc: 1622*cda5da8dSAndroid Build Coastguard Worker msg = f'Memo value not found at index {i}' 1623*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError(msg) from None 1624*cda5da8dSAndroid Build Coastguard Worker dispatch[BINGET[0]] = load_binget 1625*cda5da8dSAndroid Build Coastguard Worker 1626*cda5da8dSAndroid Build Coastguard Worker def load_long_binget(self): 1627*cda5da8dSAndroid Build Coastguard Worker i, = unpack('<I', self.read(4)) 1628*cda5da8dSAndroid Build Coastguard Worker try: 1629*cda5da8dSAndroid Build Coastguard Worker self.append(self.memo[i]) 1630*cda5da8dSAndroid Build Coastguard Worker except KeyError as exc: 1631*cda5da8dSAndroid Build Coastguard Worker msg = f'Memo value not found at index {i}' 1632*cda5da8dSAndroid Build Coastguard Worker raise UnpicklingError(msg) from None 1633*cda5da8dSAndroid Build Coastguard Worker dispatch[LONG_BINGET[0]] = load_long_binget 1634*cda5da8dSAndroid Build Coastguard Worker 1635*cda5da8dSAndroid Build Coastguard Worker def load_put(self): 1636*cda5da8dSAndroid Build Coastguard Worker i = int(self.readline()[:-1]) 1637*cda5da8dSAndroid Build Coastguard Worker if i < 0: 1638*cda5da8dSAndroid Build Coastguard Worker raise ValueError("negative PUT argument") 1639*cda5da8dSAndroid Build Coastguard Worker self.memo[i] = self.stack[-1] 1640*cda5da8dSAndroid Build Coastguard Worker dispatch[PUT[0]] = load_put 1641*cda5da8dSAndroid Build Coastguard Worker 1642*cda5da8dSAndroid Build Coastguard Worker def load_binput(self): 1643*cda5da8dSAndroid Build Coastguard Worker i = self.read(1)[0] 1644*cda5da8dSAndroid Build Coastguard Worker if i < 0: 1645*cda5da8dSAndroid Build Coastguard Worker raise ValueError("negative BINPUT argument") 1646*cda5da8dSAndroid Build Coastguard Worker self.memo[i] = self.stack[-1] 1647*cda5da8dSAndroid Build Coastguard Worker dispatch[BINPUT[0]] = load_binput 1648*cda5da8dSAndroid Build Coastguard Worker 1649*cda5da8dSAndroid Build Coastguard Worker def load_long_binput(self): 1650*cda5da8dSAndroid Build Coastguard Worker i, = unpack('<I', self.read(4)) 1651*cda5da8dSAndroid Build Coastguard Worker if i > maxsize: 1652*cda5da8dSAndroid Build Coastguard Worker raise ValueError("negative LONG_BINPUT argument") 1653*cda5da8dSAndroid Build Coastguard Worker self.memo[i] = self.stack[-1] 1654*cda5da8dSAndroid Build Coastguard Worker dispatch[LONG_BINPUT[0]] = load_long_binput 1655*cda5da8dSAndroid Build Coastguard Worker 1656*cda5da8dSAndroid Build Coastguard Worker def load_memoize(self): 1657*cda5da8dSAndroid Build Coastguard Worker memo = self.memo 1658*cda5da8dSAndroid Build Coastguard Worker memo[len(memo)] = self.stack[-1] 1659*cda5da8dSAndroid Build Coastguard Worker dispatch[MEMOIZE[0]] = load_memoize 1660*cda5da8dSAndroid Build Coastguard Worker 1661*cda5da8dSAndroid Build Coastguard Worker def load_append(self): 1662*cda5da8dSAndroid Build Coastguard Worker stack = self.stack 1663*cda5da8dSAndroid Build Coastguard Worker value = stack.pop() 1664*cda5da8dSAndroid Build Coastguard Worker list = stack[-1] 1665*cda5da8dSAndroid Build Coastguard Worker list.append(value) 1666*cda5da8dSAndroid Build Coastguard Worker dispatch[APPEND[0]] = load_append 1667*cda5da8dSAndroid Build Coastguard Worker 1668*cda5da8dSAndroid Build Coastguard Worker def load_appends(self): 1669*cda5da8dSAndroid Build Coastguard Worker items = self.pop_mark() 1670*cda5da8dSAndroid Build Coastguard Worker list_obj = self.stack[-1] 1671*cda5da8dSAndroid Build Coastguard Worker try: 1672*cda5da8dSAndroid Build Coastguard Worker extend = list_obj.extend 1673*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 1674*cda5da8dSAndroid Build Coastguard Worker pass 1675*cda5da8dSAndroid Build Coastguard Worker else: 1676*cda5da8dSAndroid Build Coastguard Worker extend(items) 1677*cda5da8dSAndroid Build Coastguard Worker return 1678*cda5da8dSAndroid Build Coastguard Worker # Even if the PEP 307 requires extend() and append() methods, 1679*cda5da8dSAndroid Build Coastguard Worker # fall back on append() if the object has no extend() method 1680*cda5da8dSAndroid Build Coastguard Worker # for backward compatibility. 1681*cda5da8dSAndroid Build Coastguard Worker append = list_obj.append 1682*cda5da8dSAndroid Build Coastguard Worker for item in items: 1683*cda5da8dSAndroid Build Coastguard Worker append(item) 1684*cda5da8dSAndroid Build Coastguard Worker dispatch[APPENDS[0]] = load_appends 1685*cda5da8dSAndroid Build Coastguard Worker 1686*cda5da8dSAndroid Build Coastguard Worker def load_setitem(self): 1687*cda5da8dSAndroid Build Coastguard Worker stack = self.stack 1688*cda5da8dSAndroid Build Coastguard Worker value = stack.pop() 1689*cda5da8dSAndroid Build Coastguard Worker key = stack.pop() 1690*cda5da8dSAndroid Build Coastguard Worker dict = stack[-1] 1691*cda5da8dSAndroid Build Coastguard Worker dict[key] = value 1692*cda5da8dSAndroid Build Coastguard Worker dispatch[SETITEM[0]] = load_setitem 1693*cda5da8dSAndroid Build Coastguard Worker 1694*cda5da8dSAndroid Build Coastguard Worker def load_setitems(self): 1695*cda5da8dSAndroid Build Coastguard Worker items = self.pop_mark() 1696*cda5da8dSAndroid Build Coastguard Worker dict = self.stack[-1] 1697*cda5da8dSAndroid Build Coastguard Worker for i in range(0, len(items), 2): 1698*cda5da8dSAndroid Build Coastguard Worker dict[items[i]] = items[i + 1] 1699*cda5da8dSAndroid Build Coastguard Worker dispatch[SETITEMS[0]] = load_setitems 1700*cda5da8dSAndroid Build Coastguard Worker 1701*cda5da8dSAndroid Build Coastguard Worker def load_additems(self): 1702*cda5da8dSAndroid Build Coastguard Worker items = self.pop_mark() 1703*cda5da8dSAndroid Build Coastguard Worker set_obj = self.stack[-1] 1704*cda5da8dSAndroid Build Coastguard Worker if isinstance(set_obj, set): 1705*cda5da8dSAndroid Build Coastguard Worker set_obj.update(items) 1706*cda5da8dSAndroid Build Coastguard Worker else: 1707*cda5da8dSAndroid Build Coastguard Worker add = set_obj.add 1708*cda5da8dSAndroid Build Coastguard Worker for item in items: 1709*cda5da8dSAndroid Build Coastguard Worker add(item) 1710*cda5da8dSAndroid Build Coastguard Worker dispatch[ADDITEMS[0]] = load_additems 1711*cda5da8dSAndroid Build Coastguard Worker 1712*cda5da8dSAndroid Build Coastguard Worker def load_build(self): 1713*cda5da8dSAndroid Build Coastguard Worker stack = self.stack 1714*cda5da8dSAndroid Build Coastguard Worker state = stack.pop() 1715*cda5da8dSAndroid Build Coastguard Worker inst = stack[-1] 1716*cda5da8dSAndroid Build Coastguard Worker setstate = getattr(inst, "__setstate__", None) 1717*cda5da8dSAndroid Build Coastguard Worker if setstate is not None: 1718*cda5da8dSAndroid Build Coastguard Worker setstate(state) 1719*cda5da8dSAndroid Build Coastguard Worker return 1720*cda5da8dSAndroid Build Coastguard Worker slotstate = None 1721*cda5da8dSAndroid Build Coastguard Worker if isinstance(state, tuple) and len(state) == 2: 1722*cda5da8dSAndroid Build Coastguard Worker state, slotstate = state 1723*cda5da8dSAndroid Build Coastguard Worker if state: 1724*cda5da8dSAndroid Build Coastguard Worker inst_dict = inst.__dict__ 1725*cda5da8dSAndroid Build Coastguard Worker intern = sys.intern 1726*cda5da8dSAndroid Build Coastguard Worker for k, v in state.items(): 1727*cda5da8dSAndroid Build Coastguard Worker if type(k) is str: 1728*cda5da8dSAndroid Build Coastguard Worker inst_dict[intern(k)] = v 1729*cda5da8dSAndroid Build Coastguard Worker else: 1730*cda5da8dSAndroid Build Coastguard Worker inst_dict[k] = v 1731*cda5da8dSAndroid Build Coastguard Worker if slotstate: 1732*cda5da8dSAndroid Build Coastguard Worker for k, v in slotstate.items(): 1733*cda5da8dSAndroid Build Coastguard Worker setattr(inst, k, v) 1734*cda5da8dSAndroid Build Coastguard Worker dispatch[BUILD[0]] = load_build 1735*cda5da8dSAndroid Build Coastguard Worker 1736*cda5da8dSAndroid Build Coastguard Worker def load_mark(self): 1737*cda5da8dSAndroid Build Coastguard Worker self.metastack.append(self.stack) 1738*cda5da8dSAndroid Build Coastguard Worker self.stack = [] 1739*cda5da8dSAndroid Build Coastguard Worker self.append = self.stack.append 1740*cda5da8dSAndroid Build Coastguard Worker dispatch[MARK[0]] = load_mark 1741*cda5da8dSAndroid Build Coastguard Worker 1742*cda5da8dSAndroid Build Coastguard Worker def load_stop(self): 1743*cda5da8dSAndroid Build Coastguard Worker value = self.stack.pop() 1744*cda5da8dSAndroid Build Coastguard Worker raise _Stop(value) 1745*cda5da8dSAndroid Build Coastguard Worker dispatch[STOP[0]] = load_stop 1746*cda5da8dSAndroid Build Coastguard Worker 1747*cda5da8dSAndroid Build Coastguard Worker 1748*cda5da8dSAndroid Build Coastguard Worker# Shorthands 1749*cda5da8dSAndroid Build Coastguard Worker 1750*cda5da8dSAndroid Build Coastguard Workerdef _dump(obj, file, protocol=None, *, fix_imports=True, buffer_callback=None): 1751*cda5da8dSAndroid Build Coastguard Worker _Pickler(file, protocol, fix_imports=fix_imports, 1752*cda5da8dSAndroid Build Coastguard Worker buffer_callback=buffer_callback).dump(obj) 1753*cda5da8dSAndroid Build Coastguard Worker 1754*cda5da8dSAndroid Build Coastguard Workerdef _dumps(obj, protocol=None, *, fix_imports=True, buffer_callback=None): 1755*cda5da8dSAndroid Build Coastguard Worker f = io.BytesIO() 1756*cda5da8dSAndroid Build Coastguard Worker _Pickler(f, protocol, fix_imports=fix_imports, 1757*cda5da8dSAndroid Build Coastguard Worker buffer_callback=buffer_callback).dump(obj) 1758*cda5da8dSAndroid Build Coastguard Worker res = f.getvalue() 1759*cda5da8dSAndroid Build Coastguard Worker assert isinstance(res, bytes_types) 1760*cda5da8dSAndroid Build Coastguard Worker return res 1761*cda5da8dSAndroid Build Coastguard Worker 1762*cda5da8dSAndroid Build Coastguard Workerdef _load(file, *, fix_imports=True, encoding="ASCII", errors="strict", 1763*cda5da8dSAndroid Build Coastguard Worker buffers=None): 1764*cda5da8dSAndroid Build Coastguard Worker return _Unpickler(file, fix_imports=fix_imports, buffers=buffers, 1765*cda5da8dSAndroid Build Coastguard Worker encoding=encoding, errors=errors).load() 1766*cda5da8dSAndroid Build Coastguard Worker 1767*cda5da8dSAndroid Build Coastguard Workerdef _loads(s, /, *, fix_imports=True, encoding="ASCII", errors="strict", 1768*cda5da8dSAndroid Build Coastguard Worker buffers=None): 1769*cda5da8dSAndroid Build Coastguard Worker if isinstance(s, str): 1770*cda5da8dSAndroid Build Coastguard Worker raise TypeError("Can't load pickle from unicode string") 1771*cda5da8dSAndroid Build Coastguard Worker file = io.BytesIO(s) 1772*cda5da8dSAndroid Build Coastguard Worker return _Unpickler(file, fix_imports=fix_imports, buffers=buffers, 1773*cda5da8dSAndroid Build Coastguard Worker encoding=encoding, errors=errors).load() 1774*cda5da8dSAndroid Build Coastguard Worker 1775*cda5da8dSAndroid Build Coastguard Worker# Use the faster _pickle if possible 1776*cda5da8dSAndroid Build Coastguard Workertry: 1777*cda5da8dSAndroid Build Coastguard Worker from _pickle import ( 1778*cda5da8dSAndroid Build Coastguard Worker PickleError, 1779*cda5da8dSAndroid Build Coastguard Worker PicklingError, 1780*cda5da8dSAndroid Build Coastguard Worker UnpicklingError, 1781*cda5da8dSAndroid Build Coastguard Worker Pickler, 1782*cda5da8dSAndroid Build Coastguard Worker Unpickler, 1783*cda5da8dSAndroid Build Coastguard Worker dump, 1784*cda5da8dSAndroid Build Coastguard Worker dumps, 1785*cda5da8dSAndroid Build Coastguard Worker load, 1786*cda5da8dSAndroid Build Coastguard Worker loads 1787*cda5da8dSAndroid Build Coastguard Worker ) 1788*cda5da8dSAndroid Build Coastguard Workerexcept ImportError: 1789*cda5da8dSAndroid Build Coastguard Worker Pickler, Unpickler = _Pickler, _Unpickler 1790*cda5da8dSAndroid Build Coastguard Worker dump, dumps, load, loads = _dump, _dumps, _load, _loads 1791*cda5da8dSAndroid Build Coastguard Worker 1792*cda5da8dSAndroid Build Coastguard Worker# Doctest 1793*cda5da8dSAndroid Build Coastguard Workerdef _test(): 1794*cda5da8dSAndroid Build Coastguard Worker import doctest 1795*cda5da8dSAndroid Build Coastguard Worker return doctest.testmod() 1796*cda5da8dSAndroid Build Coastguard Worker 1797*cda5da8dSAndroid Build Coastguard Workerif __name__ == "__main__": 1798*cda5da8dSAndroid Build Coastguard Worker import argparse 1799*cda5da8dSAndroid Build Coastguard Worker parser = argparse.ArgumentParser( 1800*cda5da8dSAndroid Build Coastguard Worker description='display contents of the pickle files') 1801*cda5da8dSAndroid Build Coastguard Worker parser.add_argument( 1802*cda5da8dSAndroid Build Coastguard Worker 'pickle_file', type=argparse.FileType('br'), 1803*cda5da8dSAndroid Build Coastguard Worker nargs='*', help='the pickle file') 1804*cda5da8dSAndroid Build Coastguard Worker parser.add_argument( 1805*cda5da8dSAndroid Build Coastguard Worker '-t', '--test', action='store_true', 1806*cda5da8dSAndroid Build Coastguard Worker help='run self-test suite') 1807*cda5da8dSAndroid Build Coastguard Worker parser.add_argument( 1808*cda5da8dSAndroid Build Coastguard Worker '-v', action='store_true', 1809*cda5da8dSAndroid Build Coastguard Worker help='run verbosely; only affects self-test run') 1810*cda5da8dSAndroid Build Coastguard Worker args = parser.parse_args() 1811*cda5da8dSAndroid Build Coastguard Worker if args.test: 1812*cda5da8dSAndroid Build Coastguard Worker _test() 1813*cda5da8dSAndroid Build Coastguard Worker else: 1814*cda5da8dSAndroid Build Coastguard Worker if not args.pickle_file: 1815*cda5da8dSAndroid Build Coastguard Worker parser.print_help() 1816*cda5da8dSAndroid Build Coastguard Worker else: 1817*cda5da8dSAndroid Build Coastguard Worker import pprint 1818*cda5da8dSAndroid Build Coastguard Worker for f in args.pickle_file: 1819*cda5da8dSAndroid Build Coastguard Worker obj = load(f) 1820*cda5da8dSAndroid Build Coastguard Worker pprint.pprint(obj) 1821