1*cda5da8dSAndroid Build Coastguard Worker'''"Executable documentation" for the pickle module. 2*cda5da8dSAndroid Build Coastguard Worker 3*cda5da8dSAndroid Build Coastguard WorkerExtensive comments about the pickle protocols and pickle-machine opcodes 4*cda5da8dSAndroid Build Coastguard Workercan be found here. Some functions meant for external use: 5*cda5da8dSAndroid Build Coastguard Worker 6*cda5da8dSAndroid Build Coastguard Workergenops(pickle) 7*cda5da8dSAndroid Build Coastguard Worker Generate all the opcodes in a pickle, as (opcode, arg, position) triples. 8*cda5da8dSAndroid Build Coastguard Worker 9*cda5da8dSAndroid Build Coastguard Workerdis(pickle, out=None, memo=None, indentlevel=4) 10*cda5da8dSAndroid Build Coastguard Worker Print a symbolic disassembly of a pickle. 11*cda5da8dSAndroid Build Coastguard Worker''' 12*cda5da8dSAndroid Build Coastguard Worker 13*cda5da8dSAndroid Build Coastguard Workerimport codecs 14*cda5da8dSAndroid Build Coastguard Workerimport io 15*cda5da8dSAndroid Build Coastguard Workerimport pickle 16*cda5da8dSAndroid Build Coastguard Workerimport re 17*cda5da8dSAndroid Build Coastguard Workerimport sys 18*cda5da8dSAndroid Build Coastguard Worker 19*cda5da8dSAndroid Build Coastguard Worker__all__ = ['dis', 'genops', 'optimize'] 20*cda5da8dSAndroid Build Coastguard Worker 21*cda5da8dSAndroid Build Coastguard Workerbytes_types = pickle.bytes_types 22*cda5da8dSAndroid Build Coastguard Worker 23*cda5da8dSAndroid Build Coastguard Worker# Other ideas: 24*cda5da8dSAndroid Build Coastguard Worker# 25*cda5da8dSAndroid Build Coastguard Worker# - A pickle verifier: read a pickle and check it exhaustively for 26*cda5da8dSAndroid Build Coastguard Worker# well-formedness. dis() does a lot of this already. 27*cda5da8dSAndroid Build Coastguard Worker# 28*cda5da8dSAndroid Build Coastguard Worker# - A protocol identifier: examine a pickle and return its protocol number 29*cda5da8dSAndroid Build Coastguard Worker# (== the highest .proto attr value among all the opcodes in the pickle). 30*cda5da8dSAndroid Build Coastguard Worker# dis() already prints this info at the end. 31*cda5da8dSAndroid Build Coastguard Worker# 32*cda5da8dSAndroid Build Coastguard Worker# - A pickle optimizer: for example, tuple-building code is sometimes more 33*cda5da8dSAndroid Build Coastguard Worker# elaborate than necessary, catering for the possibility that the tuple 34*cda5da8dSAndroid Build Coastguard Worker# is recursive. Or lots of times a PUT is generated that's never accessed 35*cda5da8dSAndroid Build Coastguard Worker# by a later GET. 36*cda5da8dSAndroid Build Coastguard Worker 37*cda5da8dSAndroid Build Coastguard Worker 38*cda5da8dSAndroid Build Coastguard Worker# "A pickle" is a program for a virtual pickle machine (PM, but more accurately 39*cda5da8dSAndroid Build Coastguard Worker# called an unpickling machine). It's a sequence of opcodes, interpreted by the 40*cda5da8dSAndroid Build Coastguard Worker# PM, building an arbitrarily complex Python object. 41*cda5da8dSAndroid Build Coastguard Worker# 42*cda5da8dSAndroid Build Coastguard Worker# For the most part, the PM is very simple: there are no looping, testing, or 43*cda5da8dSAndroid Build Coastguard Worker# conditional instructions, no arithmetic and no function calls. Opcodes are 44*cda5da8dSAndroid Build Coastguard Worker# executed once each, from first to last, until a STOP opcode is reached. 45*cda5da8dSAndroid Build Coastguard Worker# 46*cda5da8dSAndroid Build Coastguard Worker# The PM has two data areas, "the stack" and "the memo". 47*cda5da8dSAndroid Build Coastguard Worker# 48*cda5da8dSAndroid Build Coastguard Worker# Many opcodes push Python objects onto the stack; e.g., INT pushes a Python 49*cda5da8dSAndroid Build Coastguard Worker# integer object on the stack, whose value is gotten from a decimal string 50*cda5da8dSAndroid Build Coastguard Worker# literal immediately following the INT opcode in the pickle bytestream. Other 51*cda5da8dSAndroid Build Coastguard Worker# opcodes take Python objects off the stack. The result of unpickling is 52*cda5da8dSAndroid Build Coastguard Worker# whatever object is left on the stack when the final STOP opcode is executed. 53*cda5da8dSAndroid Build Coastguard Worker# 54*cda5da8dSAndroid Build Coastguard Worker# The memo is simply an array of objects, or it can be implemented as a dict 55*cda5da8dSAndroid Build Coastguard Worker# mapping little integers to objects. The memo serves as the PM's "long term 56*cda5da8dSAndroid Build Coastguard Worker# memory", and the little integers indexing the memo are akin to variable 57*cda5da8dSAndroid Build Coastguard Worker# names. Some opcodes pop a stack object into the memo at a given index, 58*cda5da8dSAndroid Build Coastguard Worker# and others push a memo object at a given index onto the stack again. 59*cda5da8dSAndroid Build Coastguard Worker# 60*cda5da8dSAndroid Build Coastguard Worker# At heart, that's all the PM has. Subtleties arise for these reasons: 61*cda5da8dSAndroid Build Coastguard Worker# 62*cda5da8dSAndroid Build Coastguard Worker# + Object identity. Objects can be arbitrarily complex, and subobjects 63*cda5da8dSAndroid Build Coastguard Worker# may be shared (for example, the list [a, a] refers to the same object a 64*cda5da8dSAndroid Build Coastguard Worker# twice). It can be vital that unpickling recreate an isomorphic object 65*cda5da8dSAndroid Build Coastguard Worker# graph, faithfully reproducing sharing. 66*cda5da8dSAndroid Build Coastguard Worker# 67*cda5da8dSAndroid Build Coastguard Worker# + Recursive objects. For example, after "L = []; L.append(L)", L is a 68*cda5da8dSAndroid Build Coastguard Worker# list, and L[0] is the same list. This is related to the object identity 69*cda5da8dSAndroid Build Coastguard Worker# point, and some sequences of pickle opcodes are subtle in order to 70*cda5da8dSAndroid Build Coastguard Worker# get the right result in all cases. 71*cda5da8dSAndroid Build Coastguard Worker# 72*cda5da8dSAndroid Build Coastguard Worker# + Things pickle doesn't know everything about. Examples of things pickle 73*cda5da8dSAndroid Build Coastguard Worker# does know everything about are Python's builtin scalar and container 74*cda5da8dSAndroid Build Coastguard Worker# types, like ints and tuples. They generally have opcodes dedicated to 75*cda5da8dSAndroid Build Coastguard Worker# them. For things like module references and instances of user-defined 76*cda5da8dSAndroid Build Coastguard Worker# classes, pickle's knowledge is limited. Historically, many enhancements 77*cda5da8dSAndroid Build Coastguard Worker# have been made to the pickle protocol in order to do a better (faster, 78*cda5da8dSAndroid Build Coastguard Worker# and/or more compact) job on those. 79*cda5da8dSAndroid Build Coastguard Worker# 80*cda5da8dSAndroid Build Coastguard Worker# + Backward compatibility and micro-optimization. As explained below, 81*cda5da8dSAndroid Build Coastguard Worker# pickle opcodes never go away, not even when better ways to do a thing 82*cda5da8dSAndroid Build Coastguard Worker# get invented. The repertoire of the PM just keeps growing over time. 83*cda5da8dSAndroid Build Coastguard Worker# For example, protocol 0 had two opcodes for building Python integers (INT 84*cda5da8dSAndroid Build Coastguard Worker# and LONG), protocol 1 added three more for more-efficient pickling of short 85*cda5da8dSAndroid Build Coastguard Worker# integers, and protocol 2 added two more for more-efficient pickling of 86*cda5da8dSAndroid Build Coastguard Worker# long integers (before protocol 2, the only ways to pickle a Python long 87*cda5da8dSAndroid Build Coastguard Worker# took time quadratic in the number of digits, for both pickling and 88*cda5da8dSAndroid Build Coastguard Worker# unpickling). "Opcode bloat" isn't so much a subtlety as a source of 89*cda5da8dSAndroid Build Coastguard Worker# wearying complication. 90*cda5da8dSAndroid Build Coastguard Worker# 91*cda5da8dSAndroid Build Coastguard Worker# 92*cda5da8dSAndroid Build Coastguard Worker# Pickle protocols: 93*cda5da8dSAndroid Build Coastguard Worker# 94*cda5da8dSAndroid Build Coastguard Worker# For compatibility, the meaning of a pickle opcode never changes. Instead new 95*cda5da8dSAndroid Build Coastguard Worker# pickle opcodes get added, and each version's unpickler can handle all the 96*cda5da8dSAndroid Build Coastguard Worker# pickle opcodes in all protocol versions to date. So old pickles continue to 97*cda5da8dSAndroid Build Coastguard Worker# be readable forever. The pickler can generally be told to restrict itself to 98*cda5da8dSAndroid Build Coastguard Worker# the subset of opcodes available under previous protocol versions too, so that 99*cda5da8dSAndroid Build Coastguard Worker# users can create pickles under the current version readable by older 100*cda5da8dSAndroid Build Coastguard Worker# versions. However, a pickle does not contain its version number embedded 101*cda5da8dSAndroid Build Coastguard Worker# within it. If an older unpickler tries to read a pickle using a later 102*cda5da8dSAndroid Build Coastguard Worker# protocol, the result is most likely an exception due to seeing an unknown (in 103*cda5da8dSAndroid Build Coastguard Worker# the older unpickler) opcode. 104*cda5da8dSAndroid Build Coastguard Worker# 105*cda5da8dSAndroid Build Coastguard Worker# The original pickle used what's now called "protocol 0", and what was called 106*cda5da8dSAndroid Build Coastguard Worker# "text mode" before Python 2.3. The entire pickle bytestream is made up of 107*cda5da8dSAndroid Build Coastguard Worker# printable 7-bit ASCII characters, plus the newline character, in protocol 0. 108*cda5da8dSAndroid Build Coastguard Worker# That's why it was called text mode. Protocol 0 is small and elegant, but 109*cda5da8dSAndroid Build Coastguard Worker# sometimes painfully inefficient. 110*cda5da8dSAndroid Build Coastguard Worker# 111*cda5da8dSAndroid Build Coastguard Worker# The second major set of additions is now called "protocol 1", and was called 112*cda5da8dSAndroid Build Coastguard Worker# "binary mode" before Python 2.3. This added many opcodes with arguments 113*cda5da8dSAndroid Build Coastguard Worker# consisting of arbitrary bytes, including NUL bytes and unprintable "high bit" 114*cda5da8dSAndroid Build Coastguard Worker# bytes. Binary mode pickles can be substantially smaller than equivalent 115*cda5da8dSAndroid Build Coastguard Worker# text mode pickles, and sometimes faster too; e.g., BININT represents a 4-byte 116*cda5da8dSAndroid Build Coastguard Worker# int as 4 bytes following the opcode, which is cheaper to unpickle than the 117*cda5da8dSAndroid Build Coastguard Worker# (perhaps) 11-character decimal string attached to INT. Protocol 1 also added 118*cda5da8dSAndroid Build Coastguard Worker# a number of opcodes that operate on many stack elements at once (like APPENDS 119*cda5da8dSAndroid Build Coastguard Worker# and SETITEMS), and "shortcut" opcodes (like EMPTY_DICT and EMPTY_TUPLE). 120*cda5da8dSAndroid Build Coastguard Worker# 121*cda5da8dSAndroid Build Coastguard Worker# The third major set of additions came in Python 2.3, and is called "protocol 122*cda5da8dSAndroid Build Coastguard Worker# 2". This added: 123*cda5da8dSAndroid Build Coastguard Worker# 124*cda5da8dSAndroid Build Coastguard Worker# - A better way to pickle instances of new-style classes (NEWOBJ). 125*cda5da8dSAndroid Build Coastguard Worker# 126*cda5da8dSAndroid Build Coastguard Worker# - A way for a pickle to identify its protocol (PROTO). 127*cda5da8dSAndroid Build Coastguard Worker# 128*cda5da8dSAndroid Build Coastguard Worker# - Time- and space- efficient pickling of long ints (LONG{1,4}). 129*cda5da8dSAndroid Build Coastguard Worker# 130*cda5da8dSAndroid Build Coastguard Worker# - Shortcuts for small tuples (TUPLE{1,2,3}}. 131*cda5da8dSAndroid Build Coastguard Worker# 132*cda5da8dSAndroid Build Coastguard Worker# - Dedicated opcodes for bools (NEWTRUE, NEWFALSE). 133*cda5da8dSAndroid Build Coastguard Worker# 134*cda5da8dSAndroid Build Coastguard Worker# - The "extension registry", a vector of popular objects that can be pushed 135*cda5da8dSAndroid Build Coastguard Worker# efficiently by index (EXT{1,2,4}). This is akin to the memo and GET, but 136*cda5da8dSAndroid Build Coastguard Worker# the registry contents are predefined (there's nothing akin to the memo's 137*cda5da8dSAndroid Build Coastguard Worker# PUT). 138*cda5da8dSAndroid Build Coastguard Worker# 139*cda5da8dSAndroid Build Coastguard Worker# Another independent change with Python 2.3 is the abandonment of any 140*cda5da8dSAndroid Build Coastguard Worker# pretense that it might be safe to load pickles received from untrusted 141*cda5da8dSAndroid Build Coastguard Worker# parties -- no sufficient security analysis has been done to guarantee 142*cda5da8dSAndroid Build Coastguard Worker# this and there isn't a use case that warrants the expense of such an 143*cda5da8dSAndroid Build Coastguard Worker# analysis. 144*cda5da8dSAndroid Build Coastguard Worker# 145*cda5da8dSAndroid Build Coastguard Worker# To this end, all tests for __safe_for_unpickling__ or for 146*cda5da8dSAndroid Build Coastguard Worker# copyreg.safe_constructors are removed from the unpickling code. 147*cda5da8dSAndroid Build Coastguard Worker# References to these variables in the descriptions below are to be seen 148*cda5da8dSAndroid Build Coastguard Worker# as describing unpickling in Python 2.2 and before. 149*cda5da8dSAndroid Build Coastguard Worker 150*cda5da8dSAndroid Build Coastguard Worker 151*cda5da8dSAndroid Build Coastguard Worker# Meta-rule: Descriptions are stored in instances of descriptor objects, 152*cda5da8dSAndroid Build Coastguard Worker# with plain constructors. No meta-language is defined from which 153*cda5da8dSAndroid Build Coastguard Worker# descriptors could be constructed. If you want, e.g., XML, write a little 154*cda5da8dSAndroid Build Coastguard Worker# program to generate XML from the objects. 155*cda5da8dSAndroid Build Coastguard Worker 156*cda5da8dSAndroid Build Coastguard Worker############################################################################## 157*cda5da8dSAndroid Build Coastguard Worker# Some pickle opcodes have an argument, following the opcode in the 158*cda5da8dSAndroid Build Coastguard Worker# bytestream. An argument is of a specific type, described by an instance 159*cda5da8dSAndroid Build Coastguard Worker# of ArgumentDescriptor. These are not to be confused with arguments taken 160*cda5da8dSAndroid Build Coastguard Worker# off the stack -- ArgumentDescriptor applies only to arguments embedded in 161*cda5da8dSAndroid Build Coastguard Worker# the opcode stream, immediately following an opcode. 162*cda5da8dSAndroid Build Coastguard Worker 163*cda5da8dSAndroid Build Coastguard Worker# Represents the number of bytes consumed by an argument delimited by the 164*cda5da8dSAndroid Build Coastguard Worker# next newline character. 165*cda5da8dSAndroid Build Coastguard WorkerUP_TO_NEWLINE = -1 166*cda5da8dSAndroid Build Coastguard Worker 167*cda5da8dSAndroid Build Coastguard Worker# Represents the number of bytes consumed by a two-argument opcode where 168*cda5da8dSAndroid Build Coastguard Worker# the first argument gives the number of bytes in the second argument. 169*cda5da8dSAndroid Build Coastguard WorkerTAKEN_FROM_ARGUMENT1 = -2 # num bytes is 1-byte unsigned int 170*cda5da8dSAndroid Build Coastguard WorkerTAKEN_FROM_ARGUMENT4 = -3 # num bytes is 4-byte signed little-endian int 171*cda5da8dSAndroid Build Coastguard WorkerTAKEN_FROM_ARGUMENT4U = -4 # num bytes is 4-byte unsigned little-endian int 172*cda5da8dSAndroid Build Coastguard WorkerTAKEN_FROM_ARGUMENT8U = -5 # num bytes is 8-byte unsigned little-endian int 173*cda5da8dSAndroid Build Coastguard Worker 174*cda5da8dSAndroid Build Coastguard Workerclass ArgumentDescriptor(object): 175*cda5da8dSAndroid Build Coastguard Worker __slots__ = ( 176*cda5da8dSAndroid Build Coastguard Worker # name of descriptor record, also a module global name; a string 177*cda5da8dSAndroid Build Coastguard Worker 'name', 178*cda5da8dSAndroid Build Coastguard Worker 179*cda5da8dSAndroid Build Coastguard Worker # length of argument, in bytes; an int; UP_TO_NEWLINE and 180*cda5da8dSAndroid Build Coastguard Worker # TAKEN_FROM_ARGUMENT{1,4,8} are negative values for variable-length 181*cda5da8dSAndroid Build Coastguard Worker # cases 182*cda5da8dSAndroid Build Coastguard Worker 'n', 183*cda5da8dSAndroid Build Coastguard Worker 184*cda5da8dSAndroid Build Coastguard Worker # a function taking a file-like object, reading this kind of argument 185*cda5da8dSAndroid Build Coastguard Worker # from the object at the current position, advancing the current 186*cda5da8dSAndroid Build Coastguard Worker # position by n bytes, and returning the value of the argument 187*cda5da8dSAndroid Build Coastguard Worker 'reader', 188*cda5da8dSAndroid Build Coastguard Worker 189*cda5da8dSAndroid Build Coastguard Worker # human-readable docs for this arg descriptor; a string 190*cda5da8dSAndroid Build Coastguard Worker 'doc', 191*cda5da8dSAndroid Build Coastguard Worker ) 192*cda5da8dSAndroid Build Coastguard Worker 193*cda5da8dSAndroid Build Coastguard Worker def __init__(self, name, n, reader, doc): 194*cda5da8dSAndroid Build Coastguard Worker assert isinstance(name, str) 195*cda5da8dSAndroid Build Coastguard Worker self.name = name 196*cda5da8dSAndroid Build Coastguard Worker 197*cda5da8dSAndroid Build Coastguard Worker assert isinstance(n, int) and (n >= 0 or 198*cda5da8dSAndroid Build Coastguard Worker n in (UP_TO_NEWLINE, 199*cda5da8dSAndroid Build Coastguard Worker TAKEN_FROM_ARGUMENT1, 200*cda5da8dSAndroid Build Coastguard Worker TAKEN_FROM_ARGUMENT4, 201*cda5da8dSAndroid Build Coastguard Worker TAKEN_FROM_ARGUMENT4U, 202*cda5da8dSAndroid Build Coastguard Worker TAKEN_FROM_ARGUMENT8U)) 203*cda5da8dSAndroid Build Coastguard Worker self.n = n 204*cda5da8dSAndroid Build Coastguard Worker 205*cda5da8dSAndroid Build Coastguard Worker self.reader = reader 206*cda5da8dSAndroid Build Coastguard Worker 207*cda5da8dSAndroid Build Coastguard Worker assert isinstance(doc, str) 208*cda5da8dSAndroid Build Coastguard Worker self.doc = doc 209*cda5da8dSAndroid Build Coastguard Worker 210*cda5da8dSAndroid Build Coastguard Workerfrom struct import unpack as _unpack 211*cda5da8dSAndroid Build Coastguard Worker 212*cda5da8dSAndroid Build Coastguard Workerdef read_uint1(f): 213*cda5da8dSAndroid Build Coastguard Worker r""" 214*cda5da8dSAndroid Build Coastguard Worker >>> import io 215*cda5da8dSAndroid Build Coastguard Worker >>> read_uint1(io.BytesIO(b'\xff')) 216*cda5da8dSAndroid Build Coastguard Worker 255 217*cda5da8dSAndroid Build Coastguard Worker """ 218*cda5da8dSAndroid Build Coastguard Worker 219*cda5da8dSAndroid Build Coastguard Worker data = f.read(1) 220*cda5da8dSAndroid Build Coastguard Worker if data: 221*cda5da8dSAndroid Build Coastguard Worker return data[0] 222*cda5da8dSAndroid Build Coastguard Worker raise ValueError("not enough data in stream to read uint1") 223*cda5da8dSAndroid Build Coastguard Worker 224*cda5da8dSAndroid Build Coastguard Workeruint1 = ArgumentDescriptor( 225*cda5da8dSAndroid Build Coastguard Worker name='uint1', 226*cda5da8dSAndroid Build Coastguard Worker n=1, 227*cda5da8dSAndroid Build Coastguard Worker reader=read_uint1, 228*cda5da8dSAndroid Build Coastguard Worker doc="One-byte unsigned integer.") 229*cda5da8dSAndroid Build Coastguard Worker 230*cda5da8dSAndroid Build Coastguard Worker 231*cda5da8dSAndroid Build Coastguard Workerdef read_uint2(f): 232*cda5da8dSAndroid Build Coastguard Worker r""" 233*cda5da8dSAndroid Build Coastguard Worker >>> import io 234*cda5da8dSAndroid Build Coastguard Worker >>> read_uint2(io.BytesIO(b'\xff\x00')) 235*cda5da8dSAndroid Build Coastguard Worker 255 236*cda5da8dSAndroid Build Coastguard Worker >>> read_uint2(io.BytesIO(b'\xff\xff')) 237*cda5da8dSAndroid Build Coastguard Worker 65535 238*cda5da8dSAndroid Build Coastguard Worker """ 239*cda5da8dSAndroid Build Coastguard Worker 240*cda5da8dSAndroid Build Coastguard Worker data = f.read(2) 241*cda5da8dSAndroid Build Coastguard Worker if len(data) == 2: 242*cda5da8dSAndroid Build Coastguard Worker return _unpack("<H", data)[0] 243*cda5da8dSAndroid Build Coastguard Worker raise ValueError("not enough data in stream to read uint2") 244*cda5da8dSAndroid Build Coastguard Worker 245*cda5da8dSAndroid Build Coastguard Workeruint2 = ArgumentDescriptor( 246*cda5da8dSAndroid Build Coastguard Worker name='uint2', 247*cda5da8dSAndroid Build Coastguard Worker n=2, 248*cda5da8dSAndroid Build Coastguard Worker reader=read_uint2, 249*cda5da8dSAndroid Build Coastguard Worker doc="Two-byte unsigned integer, little-endian.") 250*cda5da8dSAndroid Build Coastguard Worker 251*cda5da8dSAndroid Build Coastguard Worker 252*cda5da8dSAndroid Build Coastguard Workerdef read_int4(f): 253*cda5da8dSAndroid Build Coastguard Worker r""" 254*cda5da8dSAndroid Build Coastguard Worker >>> import io 255*cda5da8dSAndroid Build Coastguard Worker >>> read_int4(io.BytesIO(b'\xff\x00\x00\x00')) 256*cda5da8dSAndroid Build Coastguard Worker 255 257*cda5da8dSAndroid Build Coastguard Worker >>> read_int4(io.BytesIO(b'\x00\x00\x00\x80')) == -(2**31) 258*cda5da8dSAndroid Build Coastguard Worker True 259*cda5da8dSAndroid Build Coastguard Worker """ 260*cda5da8dSAndroid Build Coastguard Worker 261*cda5da8dSAndroid Build Coastguard Worker data = f.read(4) 262*cda5da8dSAndroid Build Coastguard Worker if len(data) == 4: 263*cda5da8dSAndroid Build Coastguard Worker return _unpack("<i", data)[0] 264*cda5da8dSAndroid Build Coastguard Worker raise ValueError("not enough data in stream to read int4") 265*cda5da8dSAndroid Build Coastguard Worker 266*cda5da8dSAndroid Build Coastguard Workerint4 = ArgumentDescriptor( 267*cda5da8dSAndroid Build Coastguard Worker name='int4', 268*cda5da8dSAndroid Build Coastguard Worker n=4, 269*cda5da8dSAndroid Build Coastguard Worker reader=read_int4, 270*cda5da8dSAndroid Build Coastguard Worker doc="Four-byte signed integer, little-endian, 2's complement.") 271*cda5da8dSAndroid Build Coastguard Worker 272*cda5da8dSAndroid Build Coastguard Worker 273*cda5da8dSAndroid Build Coastguard Workerdef read_uint4(f): 274*cda5da8dSAndroid Build Coastguard Worker r""" 275*cda5da8dSAndroid Build Coastguard Worker >>> import io 276*cda5da8dSAndroid Build Coastguard Worker >>> read_uint4(io.BytesIO(b'\xff\x00\x00\x00')) 277*cda5da8dSAndroid Build Coastguard Worker 255 278*cda5da8dSAndroid Build Coastguard Worker >>> read_uint4(io.BytesIO(b'\x00\x00\x00\x80')) == 2**31 279*cda5da8dSAndroid Build Coastguard Worker True 280*cda5da8dSAndroid Build Coastguard Worker """ 281*cda5da8dSAndroid Build Coastguard Worker 282*cda5da8dSAndroid Build Coastguard Worker data = f.read(4) 283*cda5da8dSAndroid Build Coastguard Worker if len(data) == 4: 284*cda5da8dSAndroid Build Coastguard Worker return _unpack("<I", data)[0] 285*cda5da8dSAndroid Build Coastguard Worker raise ValueError("not enough data in stream to read uint4") 286*cda5da8dSAndroid Build Coastguard Worker 287*cda5da8dSAndroid Build Coastguard Workeruint4 = ArgumentDescriptor( 288*cda5da8dSAndroid Build Coastguard Worker name='uint4', 289*cda5da8dSAndroid Build Coastguard Worker n=4, 290*cda5da8dSAndroid Build Coastguard Worker reader=read_uint4, 291*cda5da8dSAndroid Build Coastguard Worker doc="Four-byte unsigned integer, little-endian.") 292*cda5da8dSAndroid Build Coastguard Worker 293*cda5da8dSAndroid Build Coastguard Worker 294*cda5da8dSAndroid Build Coastguard Workerdef read_uint8(f): 295*cda5da8dSAndroid Build Coastguard Worker r""" 296*cda5da8dSAndroid Build Coastguard Worker >>> import io 297*cda5da8dSAndroid Build Coastguard Worker >>> read_uint8(io.BytesIO(b'\xff\x00\x00\x00\x00\x00\x00\x00')) 298*cda5da8dSAndroid Build Coastguard Worker 255 299*cda5da8dSAndroid Build Coastguard Worker >>> read_uint8(io.BytesIO(b'\xff' * 8)) == 2**64-1 300*cda5da8dSAndroid Build Coastguard Worker True 301*cda5da8dSAndroid Build Coastguard Worker """ 302*cda5da8dSAndroid Build Coastguard Worker 303*cda5da8dSAndroid Build Coastguard Worker data = f.read(8) 304*cda5da8dSAndroid Build Coastguard Worker if len(data) == 8: 305*cda5da8dSAndroid Build Coastguard Worker return _unpack("<Q", data)[0] 306*cda5da8dSAndroid Build Coastguard Worker raise ValueError("not enough data in stream to read uint8") 307*cda5da8dSAndroid Build Coastguard Worker 308*cda5da8dSAndroid Build Coastguard Workeruint8 = ArgumentDescriptor( 309*cda5da8dSAndroid Build Coastguard Worker name='uint8', 310*cda5da8dSAndroid Build Coastguard Worker n=8, 311*cda5da8dSAndroid Build Coastguard Worker reader=read_uint8, 312*cda5da8dSAndroid Build Coastguard Worker doc="Eight-byte unsigned integer, little-endian.") 313*cda5da8dSAndroid Build Coastguard Worker 314*cda5da8dSAndroid Build Coastguard Worker 315*cda5da8dSAndroid Build Coastguard Workerdef read_stringnl(f, decode=True, stripquotes=True): 316*cda5da8dSAndroid Build Coastguard Worker r""" 317*cda5da8dSAndroid Build Coastguard Worker >>> import io 318*cda5da8dSAndroid Build Coastguard Worker >>> read_stringnl(io.BytesIO(b"'abcd'\nefg\n")) 319*cda5da8dSAndroid Build Coastguard Worker 'abcd' 320*cda5da8dSAndroid Build Coastguard Worker 321*cda5da8dSAndroid Build Coastguard Worker >>> read_stringnl(io.BytesIO(b"\n")) 322*cda5da8dSAndroid Build Coastguard Worker Traceback (most recent call last): 323*cda5da8dSAndroid Build Coastguard Worker ... 324*cda5da8dSAndroid Build Coastguard Worker ValueError: no string quotes around b'' 325*cda5da8dSAndroid Build Coastguard Worker 326*cda5da8dSAndroid Build Coastguard Worker >>> read_stringnl(io.BytesIO(b"\n"), stripquotes=False) 327*cda5da8dSAndroid Build Coastguard Worker '' 328*cda5da8dSAndroid Build Coastguard Worker 329*cda5da8dSAndroid Build Coastguard Worker >>> read_stringnl(io.BytesIO(b"''\n")) 330*cda5da8dSAndroid Build Coastguard Worker '' 331*cda5da8dSAndroid Build Coastguard Worker 332*cda5da8dSAndroid Build Coastguard Worker >>> read_stringnl(io.BytesIO(b'"abcd"')) 333*cda5da8dSAndroid Build Coastguard Worker Traceback (most recent call last): 334*cda5da8dSAndroid Build Coastguard Worker ... 335*cda5da8dSAndroid Build Coastguard Worker ValueError: no newline found when trying to read stringnl 336*cda5da8dSAndroid Build Coastguard Worker 337*cda5da8dSAndroid Build Coastguard Worker Embedded escapes are undone in the result. 338*cda5da8dSAndroid Build Coastguard Worker >>> read_stringnl(io.BytesIO(br"'a\n\\b\x00c\td'" + b"\n'e'")) 339*cda5da8dSAndroid Build Coastguard Worker 'a\n\\b\x00c\td' 340*cda5da8dSAndroid Build Coastguard Worker """ 341*cda5da8dSAndroid Build Coastguard Worker 342*cda5da8dSAndroid Build Coastguard Worker data = f.readline() 343*cda5da8dSAndroid Build Coastguard Worker if not data.endswith(b'\n'): 344*cda5da8dSAndroid Build Coastguard Worker raise ValueError("no newline found when trying to read stringnl") 345*cda5da8dSAndroid Build Coastguard Worker data = data[:-1] # lose the newline 346*cda5da8dSAndroid Build Coastguard Worker 347*cda5da8dSAndroid Build Coastguard Worker if stripquotes: 348*cda5da8dSAndroid Build Coastguard Worker for q in (b'"', b"'"): 349*cda5da8dSAndroid Build Coastguard Worker if data.startswith(q): 350*cda5da8dSAndroid Build Coastguard Worker if not data.endswith(q): 351*cda5da8dSAndroid Build Coastguard Worker raise ValueError("strinq quote %r not found at both " 352*cda5da8dSAndroid Build Coastguard Worker "ends of %r" % (q, data)) 353*cda5da8dSAndroid Build Coastguard Worker data = data[1:-1] 354*cda5da8dSAndroid Build Coastguard Worker break 355*cda5da8dSAndroid Build Coastguard Worker else: 356*cda5da8dSAndroid Build Coastguard Worker raise ValueError("no string quotes around %r" % data) 357*cda5da8dSAndroid Build Coastguard Worker 358*cda5da8dSAndroid Build Coastguard Worker if decode: 359*cda5da8dSAndroid Build Coastguard Worker data = codecs.escape_decode(data)[0].decode("ascii") 360*cda5da8dSAndroid Build Coastguard Worker return data 361*cda5da8dSAndroid Build Coastguard Worker 362*cda5da8dSAndroid Build Coastguard Workerstringnl = ArgumentDescriptor( 363*cda5da8dSAndroid Build Coastguard Worker name='stringnl', 364*cda5da8dSAndroid Build Coastguard Worker n=UP_TO_NEWLINE, 365*cda5da8dSAndroid Build Coastguard Worker reader=read_stringnl, 366*cda5da8dSAndroid Build Coastguard Worker doc="""A newline-terminated string. 367*cda5da8dSAndroid Build Coastguard Worker 368*cda5da8dSAndroid Build Coastguard Worker This is a repr-style string, with embedded escapes, and 369*cda5da8dSAndroid Build Coastguard Worker bracketing quotes. 370*cda5da8dSAndroid Build Coastguard Worker """) 371*cda5da8dSAndroid Build Coastguard Worker 372*cda5da8dSAndroid Build Coastguard Workerdef read_stringnl_noescape(f): 373*cda5da8dSAndroid Build Coastguard Worker return read_stringnl(f, stripquotes=False) 374*cda5da8dSAndroid Build Coastguard Worker 375*cda5da8dSAndroid Build Coastguard Workerstringnl_noescape = ArgumentDescriptor( 376*cda5da8dSAndroid Build Coastguard Worker name='stringnl_noescape', 377*cda5da8dSAndroid Build Coastguard Worker n=UP_TO_NEWLINE, 378*cda5da8dSAndroid Build Coastguard Worker reader=read_stringnl_noescape, 379*cda5da8dSAndroid Build Coastguard Worker doc="""A newline-terminated string. 380*cda5da8dSAndroid Build Coastguard Worker 381*cda5da8dSAndroid Build Coastguard Worker This is a str-style string, without embedded escapes, 382*cda5da8dSAndroid Build Coastguard Worker or bracketing quotes. It should consist solely of 383*cda5da8dSAndroid Build Coastguard Worker printable ASCII characters. 384*cda5da8dSAndroid Build Coastguard Worker """) 385*cda5da8dSAndroid Build Coastguard Worker 386*cda5da8dSAndroid Build Coastguard Workerdef read_stringnl_noescape_pair(f): 387*cda5da8dSAndroid Build Coastguard Worker r""" 388*cda5da8dSAndroid Build Coastguard Worker >>> import io 389*cda5da8dSAndroid Build Coastguard Worker >>> read_stringnl_noescape_pair(io.BytesIO(b"Queue\nEmpty\njunk")) 390*cda5da8dSAndroid Build Coastguard Worker 'Queue Empty' 391*cda5da8dSAndroid Build Coastguard Worker """ 392*cda5da8dSAndroid Build Coastguard Worker 393*cda5da8dSAndroid Build Coastguard Worker return "%s %s" % (read_stringnl_noescape(f), read_stringnl_noescape(f)) 394*cda5da8dSAndroid Build Coastguard Worker 395*cda5da8dSAndroid Build Coastguard Workerstringnl_noescape_pair = ArgumentDescriptor( 396*cda5da8dSAndroid Build Coastguard Worker name='stringnl_noescape_pair', 397*cda5da8dSAndroid Build Coastguard Worker n=UP_TO_NEWLINE, 398*cda5da8dSAndroid Build Coastguard Worker reader=read_stringnl_noescape_pair, 399*cda5da8dSAndroid Build Coastguard Worker doc="""A pair of newline-terminated strings. 400*cda5da8dSAndroid Build Coastguard Worker 401*cda5da8dSAndroid Build Coastguard Worker These are str-style strings, without embedded 402*cda5da8dSAndroid Build Coastguard Worker escapes, or bracketing quotes. They should 403*cda5da8dSAndroid Build Coastguard Worker consist solely of printable ASCII characters. 404*cda5da8dSAndroid Build Coastguard Worker The pair is returned as a single string, with 405*cda5da8dSAndroid Build Coastguard Worker a single blank separating the two strings. 406*cda5da8dSAndroid Build Coastguard Worker """) 407*cda5da8dSAndroid Build Coastguard Worker 408*cda5da8dSAndroid Build Coastguard Worker 409*cda5da8dSAndroid Build Coastguard Workerdef read_string1(f): 410*cda5da8dSAndroid Build Coastguard Worker r""" 411*cda5da8dSAndroid Build Coastguard Worker >>> import io 412*cda5da8dSAndroid Build Coastguard Worker >>> read_string1(io.BytesIO(b"\x00")) 413*cda5da8dSAndroid Build Coastguard Worker '' 414*cda5da8dSAndroid Build Coastguard Worker >>> read_string1(io.BytesIO(b"\x03abcdef")) 415*cda5da8dSAndroid Build Coastguard Worker 'abc' 416*cda5da8dSAndroid Build Coastguard Worker """ 417*cda5da8dSAndroid Build Coastguard Worker 418*cda5da8dSAndroid Build Coastguard Worker n = read_uint1(f) 419*cda5da8dSAndroid Build Coastguard Worker assert n >= 0 420*cda5da8dSAndroid Build Coastguard Worker data = f.read(n) 421*cda5da8dSAndroid Build Coastguard Worker if len(data) == n: 422*cda5da8dSAndroid Build Coastguard Worker return data.decode("latin-1") 423*cda5da8dSAndroid Build Coastguard Worker raise ValueError("expected %d bytes in a string1, but only %d remain" % 424*cda5da8dSAndroid Build Coastguard Worker (n, len(data))) 425*cda5da8dSAndroid Build Coastguard Worker 426*cda5da8dSAndroid Build Coastguard Workerstring1 = ArgumentDescriptor( 427*cda5da8dSAndroid Build Coastguard Worker name="string1", 428*cda5da8dSAndroid Build Coastguard Worker n=TAKEN_FROM_ARGUMENT1, 429*cda5da8dSAndroid Build Coastguard Worker reader=read_string1, 430*cda5da8dSAndroid Build Coastguard Worker doc="""A counted string. 431*cda5da8dSAndroid Build Coastguard Worker 432*cda5da8dSAndroid Build Coastguard Worker The first argument is a 1-byte unsigned int giving the number 433*cda5da8dSAndroid Build Coastguard Worker of bytes in the string, and the second argument is that many 434*cda5da8dSAndroid Build Coastguard Worker bytes. 435*cda5da8dSAndroid Build Coastguard Worker """) 436*cda5da8dSAndroid Build Coastguard Worker 437*cda5da8dSAndroid Build Coastguard Worker 438*cda5da8dSAndroid Build Coastguard Workerdef read_string4(f): 439*cda5da8dSAndroid Build Coastguard Worker r""" 440*cda5da8dSAndroid Build Coastguard Worker >>> import io 441*cda5da8dSAndroid Build Coastguard Worker >>> read_string4(io.BytesIO(b"\x00\x00\x00\x00abc")) 442*cda5da8dSAndroid Build Coastguard Worker '' 443*cda5da8dSAndroid Build Coastguard Worker >>> read_string4(io.BytesIO(b"\x03\x00\x00\x00abcdef")) 444*cda5da8dSAndroid Build Coastguard Worker 'abc' 445*cda5da8dSAndroid Build Coastguard Worker >>> read_string4(io.BytesIO(b"\x00\x00\x00\x03abcdef")) 446*cda5da8dSAndroid Build Coastguard Worker Traceback (most recent call last): 447*cda5da8dSAndroid Build Coastguard Worker ... 448*cda5da8dSAndroid Build Coastguard Worker ValueError: expected 50331648 bytes in a string4, but only 6 remain 449*cda5da8dSAndroid Build Coastguard Worker """ 450*cda5da8dSAndroid Build Coastguard Worker 451*cda5da8dSAndroid Build Coastguard Worker n = read_int4(f) 452*cda5da8dSAndroid Build Coastguard Worker if n < 0: 453*cda5da8dSAndroid Build Coastguard Worker raise ValueError("string4 byte count < 0: %d" % n) 454*cda5da8dSAndroid Build Coastguard Worker data = f.read(n) 455*cda5da8dSAndroid Build Coastguard Worker if len(data) == n: 456*cda5da8dSAndroid Build Coastguard Worker return data.decode("latin-1") 457*cda5da8dSAndroid Build Coastguard Worker raise ValueError("expected %d bytes in a string4, but only %d remain" % 458*cda5da8dSAndroid Build Coastguard Worker (n, len(data))) 459*cda5da8dSAndroid Build Coastguard Worker 460*cda5da8dSAndroid Build Coastguard Workerstring4 = ArgumentDescriptor( 461*cda5da8dSAndroid Build Coastguard Worker name="string4", 462*cda5da8dSAndroid Build Coastguard Worker n=TAKEN_FROM_ARGUMENT4, 463*cda5da8dSAndroid Build Coastguard Worker reader=read_string4, 464*cda5da8dSAndroid Build Coastguard Worker doc="""A counted string. 465*cda5da8dSAndroid Build Coastguard Worker 466*cda5da8dSAndroid Build Coastguard Worker The first argument is a 4-byte little-endian signed int giving 467*cda5da8dSAndroid Build Coastguard Worker the number of bytes in the string, and the second argument is 468*cda5da8dSAndroid Build Coastguard Worker that many bytes. 469*cda5da8dSAndroid Build Coastguard Worker """) 470*cda5da8dSAndroid Build Coastguard Worker 471*cda5da8dSAndroid Build Coastguard Worker 472*cda5da8dSAndroid Build Coastguard Workerdef read_bytes1(f): 473*cda5da8dSAndroid Build Coastguard Worker r""" 474*cda5da8dSAndroid Build Coastguard Worker >>> import io 475*cda5da8dSAndroid Build Coastguard Worker >>> read_bytes1(io.BytesIO(b"\x00")) 476*cda5da8dSAndroid Build Coastguard Worker b'' 477*cda5da8dSAndroid Build Coastguard Worker >>> read_bytes1(io.BytesIO(b"\x03abcdef")) 478*cda5da8dSAndroid Build Coastguard Worker b'abc' 479*cda5da8dSAndroid Build Coastguard Worker """ 480*cda5da8dSAndroid Build Coastguard Worker 481*cda5da8dSAndroid Build Coastguard Worker n = read_uint1(f) 482*cda5da8dSAndroid Build Coastguard Worker assert n >= 0 483*cda5da8dSAndroid Build Coastguard Worker data = f.read(n) 484*cda5da8dSAndroid Build Coastguard Worker if len(data) == n: 485*cda5da8dSAndroid Build Coastguard Worker return data 486*cda5da8dSAndroid Build Coastguard Worker raise ValueError("expected %d bytes in a bytes1, but only %d remain" % 487*cda5da8dSAndroid Build Coastguard Worker (n, len(data))) 488*cda5da8dSAndroid Build Coastguard Worker 489*cda5da8dSAndroid Build Coastguard Workerbytes1 = ArgumentDescriptor( 490*cda5da8dSAndroid Build Coastguard Worker name="bytes1", 491*cda5da8dSAndroid Build Coastguard Worker n=TAKEN_FROM_ARGUMENT1, 492*cda5da8dSAndroid Build Coastguard Worker reader=read_bytes1, 493*cda5da8dSAndroid Build Coastguard Worker doc="""A counted bytes string. 494*cda5da8dSAndroid Build Coastguard Worker 495*cda5da8dSAndroid Build Coastguard Worker The first argument is a 1-byte unsigned int giving the number 496*cda5da8dSAndroid Build Coastguard Worker of bytes, and the second argument is that many bytes. 497*cda5da8dSAndroid Build Coastguard Worker """) 498*cda5da8dSAndroid Build Coastguard Worker 499*cda5da8dSAndroid Build Coastguard Worker 500*cda5da8dSAndroid Build Coastguard Workerdef read_bytes4(f): 501*cda5da8dSAndroid Build Coastguard Worker r""" 502*cda5da8dSAndroid Build Coastguard Worker >>> import io 503*cda5da8dSAndroid Build Coastguard Worker >>> read_bytes4(io.BytesIO(b"\x00\x00\x00\x00abc")) 504*cda5da8dSAndroid Build Coastguard Worker b'' 505*cda5da8dSAndroid Build Coastguard Worker >>> read_bytes4(io.BytesIO(b"\x03\x00\x00\x00abcdef")) 506*cda5da8dSAndroid Build Coastguard Worker b'abc' 507*cda5da8dSAndroid Build Coastguard Worker >>> read_bytes4(io.BytesIO(b"\x00\x00\x00\x03abcdef")) 508*cda5da8dSAndroid Build Coastguard Worker Traceback (most recent call last): 509*cda5da8dSAndroid Build Coastguard Worker ... 510*cda5da8dSAndroid Build Coastguard Worker ValueError: expected 50331648 bytes in a bytes4, but only 6 remain 511*cda5da8dSAndroid Build Coastguard Worker """ 512*cda5da8dSAndroid Build Coastguard Worker 513*cda5da8dSAndroid Build Coastguard Worker n = read_uint4(f) 514*cda5da8dSAndroid Build Coastguard Worker assert n >= 0 515*cda5da8dSAndroid Build Coastguard Worker if n > sys.maxsize: 516*cda5da8dSAndroid Build Coastguard Worker raise ValueError("bytes4 byte count > sys.maxsize: %d" % n) 517*cda5da8dSAndroid Build Coastguard Worker data = f.read(n) 518*cda5da8dSAndroid Build Coastguard Worker if len(data) == n: 519*cda5da8dSAndroid Build Coastguard Worker return data 520*cda5da8dSAndroid Build Coastguard Worker raise ValueError("expected %d bytes in a bytes4, but only %d remain" % 521*cda5da8dSAndroid Build Coastguard Worker (n, len(data))) 522*cda5da8dSAndroid Build Coastguard Worker 523*cda5da8dSAndroid Build Coastguard Workerbytes4 = ArgumentDescriptor( 524*cda5da8dSAndroid Build Coastguard Worker name="bytes4", 525*cda5da8dSAndroid Build Coastguard Worker n=TAKEN_FROM_ARGUMENT4U, 526*cda5da8dSAndroid Build Coastguard Worker reader=read_bytes4, 527*cda5da8dSAndroid Build Coastguard Worker doc="""A counted bytes string. 528*cda5da8dSAndroid Build Coastguard Worker 529*cda5da8dSAndroid Build Coastguard Worker The first argument is a 4-byte little-endian unsigned int giving 530*cda5da8dSAndroid Build Coastguard Worker the number of bytes, and the second argument is that many bytes. 531*cda5da8dSAndroid Build Coastguard Worker """) 532*cda5da8dSAndroid Build Coastguard Worker 533*cda5da8dSAndroid Build Coastguard Worker 534*cda5da8dSAndroid Build Coastguard Workerdef read_bytes8(f): 535*cda5da8dSAndroid Build Coastguard Worker r""" 536*cda5da8dSAndroid Build Coastguard Worker >>> import io, struct, sys 537*cda5da8dSAndroid Build Coastguard Worker >>> read_bytes8(io.BytesIO(b"\x00\x00\x00\x00\x00\x00\x00\x00abc")) 538*cda5da8dSAndroid Build Coastguard Worker b'' 539*cda5da8dSAndroid Build Coastguard Worker >>> read_bytes8(io.BytesIO(b"\x03\x00\x00\x00\x00\x00\x00\x00abcdef")) 540*cda5da8dSAndroid Build Coastguard Worker b'abc' 541*cda5da8dSAndroid Build Coastguard Worker >>> bigsize8 = struct.pack("<Q", sys.maxsize//3) 542*cda5da8dSAndroid Build Coastguard Worker >>> read_bytes8(io.BytesIO(bigsize8 + b"abcdef")) #doctest: +ELLIPSIS 543*cda5da8dSAndroid Build Coastguard Worker Traceback (most recent call last): 544*cda5da8dSAndroid Build Coastguard Worker ... 545*cda5da8dSAndroid Build Coastguard Worker ValueError: expected ... bytes in a bytes8, but only 6 remain 546*cda5da8dSAndroid Build Coastguard Worker """ 547*cda5da8dSAndroid Build Coastguard Worker 548*cda5da8dSAndroid Build Coastguard Worker n = read_uint8(f) 549*cda5da8dSAndroid Build Coastguard Worker assert n >= 0 550*cda5da8dSAndroid Build Coastguard Worker if n > sys.maxsize: 551*cda5da8dSAndroid Build Coastguard Worker raise ValueError("bytes8 byte count > sys.maxsize: %d" % n) 552*cda5da8dSAndroid Build Coastguard Worker data = f.read(n) 553*cda5da8dSAndroid Build Coastguard Worker if len(data) == n: 554*cda5da8dSAndroid Build Coastguard Worker return data 555*cda5da8dSAndroid Build Coastguard Worker raise ValueError("expected %d bytes in a bytes8, but only %d remain" % 556*cda5da8dSAndroid Build Coastguard Worker (n, len(data))) 557*cda5da8dSAndroid Build Coastguard Worker 558*cda5da8dSAndroid Build Coastguard Workerbytes8 = ArgumentDescriptor( 559*cda5da8dSAndroid Build Coastguard Worker name="bytes8", 560*cda5da8dSAndroid Build Coastguard Worker n=TAKEN_FROM_ARGUMENT8U, 561*cda5da8dSAndroid Build Coastguard Worker reader=read_bytes8, 562*cda5da8dSAndroid Build Coastguard Worker doc="""A counted bytes string. 563*cda5da8dSAndroid Build Coastguard Worker 564*cda5da8dSAndroid Build Coastguard Worker The first argument is an 8-byte little-endian unsigned int giving 565*cda5da8dSAndroid Build Coastguard Worker the number of bytes, and the second argument is that many bytes. 566*cda5da8dSAndroid Build Coastguard Worker """) 567*cda5da8dSAndroid Build Coastguard Worker 568*cda5da8dSAndroid Build Coastguard Worker 569*cda5da8dSAndroid Build Coastguard Workerdef read_bytearray8(f): 570*cda5da8dSAndroid Build Coastguard Worker r""" 571*cda5da8dSAndroid Build Coastguard Worker >>> import io, struct, sys 572*cda5da8dSAndroid Build Coastguard Worker >>> read_bytearray8(io.BytesIO(b"\x00\x00\x00\x00\x00\x00\x00\x00abc")) 573*cda5da8dSAndroid Build Coastguard Worker bytearray(b'') 574*cda5da8dSAndroid Build Coastguard Worker >>> read_bytearray8(io.BytesIO(b"\x03\x00\x00\x00\x00\x00\x00\x00abcdef")) 575*cda5da8dSAndroid Build Coastguard Worker bytearray(b'abc') 576*cda5da8dSAndroid Build Coastguard Worker >>> bigsize8 = struct.pack("<Q", sys.maxsize//3) 577*cda5da8dSAndroid Build Coastguard Worker >>> read_bytearray8(io.BytesIO(bigsize8 + b"abcdef")) #doctest: +ELLIPSIS 578*cda5da8dSAndroid Build Coastguard Worker Traceback (most recent call last): 579*cda5da8dSAndroid Build Coastguard Worker ... 580*cda5da8dSAndroid Build Coastguard Worker ValueError: expected ... bytes in a bytearray8, but only 6 remain 581*cda5da8dSAndroid Build Coastguard Worker """ 582*cda5da8dSAndroid Build Coastguard Worker 583*cda5da8dSAndroid Build Coastguard Worker n = read_uint8(f) 584*cda5da8dSAndroid Build Coastguard Worker assert n >= 0 585*cda5da8dSAndroid Build Coastguard Worker if n > sys.maxsize: 586*cda5da8dSAndroid Build Coastguard Worker raise ValueError("bytearray8 byte count > sys.maxsize: %d" % n) 587*cda5da8dSAndroid Build Coastguard Worker data = f.read(n) 588*cda5da8dSAndroid Build Coastguard Worker if len(data) == n: 589*cda5da8dSAndroid Build Coastguard Worker return bytearray(data) 590*cda5da8dSAndroid Build Coastguard Worker raise ValueError("expected %d bytes in a bytearray8, but only %d remain" % 591*cda5da8dSAndroid Build Coastguard Worker (n, len(data))) 592*cda5da8dSAndroid Build Coastguard Worker 593*cda5da8dSAndroid Build Coastguard Workerbytearray8 = ArgumentDescriptor( 594*cda5da8dSAndroid Build Coastguard Worker name="bytearray8", 595*cda5da8dSAndroid Build Coastguard Worker n=TAKEN_FROM_ARGUMENT8U, 596*cda5da8dSAndroid Build Coastguard Worker reader=read_bytearray8, 597*cda5da8dSAndroid Build Coastguard Worker doc="""A counted bytearray. 598*cda5da8dSAndroid Build Coastguard Worker 599*cda5da8dSAndroid Build Coastguard Worker The first argument is an 8-byte little-endian unsigned int giving 600*cda5da8dSAndroid Build Coastguard Worker the number of bytes, and the second argument is that many bytes. 601*cda5da8dSAndroid Build Coastguard Worker """) 602*cda5da8dSAndroid Build Coastguard Worker 603*cda5da8dSAndroid Build Coastguard Workerdef read_unicodestringnl(f): 604*cda5da8dSAndroid Build Coastguard Worker r""" 605*cda5da8dSAndroid Build Coastguard Worker >>> import io 606*cda5da8dSAndroid Build Coastguard Worker >>> read_unicodestringnl(io.BytesIO(b"abc\\uabcd\njunk")) == 'abc\uabcd' 607*cda5da8dSAndroid Build Coastguard Worker True 608*cda5da8dSAndroid Build Coastguard Worker """ 609*cda5da8dSAndroid Build Coastguard Worker 610*cda5da8dSAndroid Build Coastguard Worker data = f.readline() 611*cda5da8dSAndroid Build Coastguard Worker if not data.endswith(b'\n'): 612*cda5da8dSAndroid Build Coastguard Worker raise ValueError("no newline found when trying to read " 613*cda5da8dSAndroid Build Coastguard Worker "unicodestringnl") 614*cda5da8dSAndroid Build Coastguard Worker data = data[:-1] # lose the newline 615*cda5da8dSAndroid Build Coastguard Worker return str(data, 'raw-unicode-escape') 616*cda5da8dSAndroid Build Coastguard Worker 617*cda5da8dSAndroid Build Coastguard Workerunicodestringnl = ArgumentDescriptor( 618*cda5da8dSAndroid Build Coastguard Worker name='unicodestringnl', 619*cda5da8dSAndroid Build Coastguard Worker n=UP_TO_NEWLINE, 620*cda5da8dSAndroid Build Coastguard Worker reader=read_unicodestringnl, 621*cda5da8dSAndroid Build Coastguard Worker doc="""A newline-terminated Unicode string. 622*cda5da8dSAndroid Build Coastguard Worker 623*cda5da8dSAndroid Build Coastguard Worker This is raw-unicode-escape encoded, so consists of 624*cda5da8dSAndroid Build Coastguard Worker printable ASCII characters, and may contain embedded 625*cda5da8dSAndroid Build Coastguard Worker escape sequences. 626*cda5da8dSAndroid Build Coastguard Worker """) 627*cda5da8dSAndroid Build Coastguard Worker 628*cda5da8dSAndroid Build Coastguard Worker 629*cda5da8dSAndroid Build Coastguard Workerdef read_unicodestring1(f): 630*cda5da8dSAndroid Build Coastguard Worker r""" 631*cda5da8dSAndroid Build Coastguard Worker >>> import io 632*cda5da8dSAndroid Build Coastguard Worker >>> s = 'abcd\uabcd' 633*cda5da8dSAndroid Build Coastguard Worker >>> enc = s.encode('utf-8') 634*cda5da8dSAndroid Build Coastguard Worker >>> enc 635*cda5da8dSAndroid Build Coastguard Worker b'abcd\xea\xaf\x8d' 636*cda5da8dSAndroid Build Coastguard Worker >>> n = bytes([len(enc)]) # little-endian 1-byte length 637*cda5da8dSAndroid Build Coastguard Worker >>> t = read_unicodestring1(io.BytesIO(n + enc + b'junk')) 638*cda5da8dSAndroid Build Coastguard Worker >>> s == t 639*cda5da8dSAndroid Build Coastguard Worker True 640*cda5da8dSAndroid Build Coastguard Worker 641*cda5da8dSAndroid Build Coastguard Worker >>> read_unicodestring1(io.BytesIO(n + enc[:-1])) 642*cda5da8dSAndroid Build Coastguard Worker Traceback (most recent call last): 643*cda5da8dSAndroid Build Coastguard Worker ... 644*cda5da8dSAndroid Build Coastguard Worker ValueError: expected 7 bytes in a unicodestring1, but only 6 remain 645*cda5da8dSAndroid Build Coastguard Worker """ 646*cda5da8dSAndroid Build Coastguard Worker 647*cda5da8dSAndroid Build Coastguard Worker n = read_uint1(f) 648*cda5da8dSAndroid Build Coastguard Worker assert n >= 0 649*cda5da8dSAndroid Build Coastguard Worker data = f.read(n) 650*cda5da8dSAndroid Build Coastguard Worker if len(data) == n: 651*cda5da8dSAndroid Build Coastguard Worker return str(data, 'utf-8', 'surrogatepass') 652*cda5da8dSAndroid Build Coastguard Worker raise ValueError("expected %d bytes in a unicodestring1, but only %d " 653*cda5da8dSAndroid Build Coastguard Worker "remain" % (n, len(data))) 654*cda5da8dSAndroid Build Coastguard Worker 655*cda5da8dSAndroid Build Coastguard Workerunicodestring1 = ArgumentDescriptor( 656*cda5da8dSAndroid Build Coastguard Worker name="unicodestring1", 657*cda5da8dSAndroid Build Coastguard Worker n=TAKEN_FROM_ARGUMENT1, 658*cda5da8dSAndroid Build Coastguard Worker reader=read_unicodestring1, 659*cda5da8dSAndroid Build Coastguard Worker doc="""A counted Unicode string. 660*cda5da8dSAndroid Build Coastguard Worker 661*cda5da8dSAndroid Build Coastguard Worker The first argument is a 1-byte little-endian signed int 662*cda5da8dSAndroid Build Coastguard Worker giving the number of bytes in the string, and the second 663*cda5da8dSAndroid Build Coastguard Worker argument-- the UTF-8 encoding of the Unicode string -- 664*cda5da8dSAndroid Build Coastguard Worker contains that many bytes. 665*cda5da8dSAndroid Build Coastguard Worker """) 666*cda5da8dSAndroid Build Coastguard Worker 667*cda5da8dSAndroid Build Coastguard Worker 668*cda5da8dSAndroid Build Coastguard Workerdef read_unicodestring4(f): 669*cda5da8dSAndroid Build Coastguard Worker r""" 670*cda5da8dSAndroid Build Coastguard Worker >>> import io 671*cda5da8dSAndroid Build Coastguard Worker >>> s = 'abcd\uabcd' 672*cda5da8dSAndroid Build Coastguard Worker >>> enc = s.encode('utf-8') 673*cda5da8dSAndroid Build Coastguard Worker >>> enc 674*cda5da8dSAndroid Build Coastguard Worker b'abcd\xea\xaf\x8d' 675*cda5da8dSAndroid Build Coastguard Worker >>> n = bytes([len(enc), 0, 0, 0]) # little-endian 4-byte length 676*cda5da8dSAndroid Build Coastguard Worker >>> t = read_unicodestring4(io.BytesIO(n + enc + b'junk')) 677*cda5da8dSAndroid Build Coastguard Worker >>> s == t 678*cda5da8dSAndroid Build Coastguard Worker True 679*cda5da8dSAndroid Build Coastguard Worker 680*cda5da8dSAndroid Build Coastguard Worker >>> read_unicodestring4(io.BytesIO(n + enc[:-1])) 681*cda5da8dSAndroid Build Coastguard Worker Traceback (most recent call last): 682*cda5da8dSAndroid Build Coastguard Worker ... 683*cda5da8dSAndroid Build Coastguard Worker ValueError: expected 7 bytes in a unicodestring4, but only 6 remain 684*cda5da8dSAndroid Build Coastguard Worker """ 685*cda5da8dSAndroid Build Coastguard Worker 686*cda5da8dSAndroid Build Coastguard Worker n = read_uint4(f) 687*cda5da8dSAndroid Build Coastguard Worker assert n >= 0 688*cda5da8dSAndroid Build Coastguard Worker if n > sys.maxsize: 689*cda5da8dSAndroid Build Coastguard Worker raise ValueError("unicodestring4 byte count > sys.maxsize: %d" % n) 690*cda5da8dSAndroid Build Coastguard Worker data = f.read(n) 691*cda5da8dSAndroid Build Coastguard Worker if len(data) == n: 692*cda5da8dSAndroid Build Coastguard Worker return str(data, 'utf-8', 'surrogatepass') 693*cda5da8dSAndroid Build Coastguard Worker raise ValueError("expected %d bytes in a unicodestring4, but only %d " 694*cda5da8dSAndroid Build Coastguard Worker "remain" % (n, len(data))) 695*cda5da8dSAndroid Build Coastguard Worker 696*cda5da8dSAndroid Build Coastguard Workerunicodestring4 = ArgumentDescriptor( 697*cda5da8dSAndroid Build Coastguard Worker name="unicodestring4", 698*cda5da8dSAndroid Build Coastguard Worker n=TAKEN_FROM_ARGUMENT4U, 699*cda5da8dSAndroid Build Coastguard Worker reader=read_unicodestring4, 700*cda5da8dSAndroid Build Coastguard Worker doc="""A counted Unicode string. 701*cda5da8dSAndroid Build Coastguard Worker 702*cda5da8dSAndroid Build Coastguard Worker The first argument is a 4-byte little-endian signed int 703*cda5da8dSAndroid Build Coastguard Worker giving the number of bytes in the string, and the second 704*cda5da8dSAndroid Build Coastguard Worker argument-- the UTF-8 encoding of the Unicode string -- 705*cda5da8dSAndroid Build Coastguard Worker contains that many bytes. 706*cda5da8dSAndroid Build Coastguard Worker """) 707*cda5da8dSAndroid Build Coastguard Worker 708*cda5da8dSAndroid Build Coastguard Worker 709*cda5da8dSAndroid Build Coastguard Workerdef read_unicodestring8(f): 710*cda5da8dSAndroid Build Coastguard Worker r""" 711*cda5da8dSAndroid Build Coastguard Worker >>> import io 712*cda5da8dSAndroid Build Coastguard Worker >>> s = 'abcd\uabcd' 713*cda5da8dSAndroid Build Coastguard Worker >>> enc = s.encode('utf-8') 714*cda5da8dSAndroid Build Coastguard Worker >>> enc 715*cda5da8dSAndroid Build Coastguard Worker b'abcd\xea\xaf\x8d' 716*cda5da8dSAndroid Build Coastguard Worker >>> n = bytes([len(enc)]) + b'\0' * 7 # little-endian 8-byte length 717*cda5da8dSAndroid Build Coastguard Worker >>> t = read_unicodestring8(io.BytesIO(n + enc + b'junk')) 718*cda5da8dSAndroid Build Coastguard Worker >>> s == t 719*cda5da8dSAndroid Build Coastguard Worker True 720*cda5da8dSAndroid Build Coastguard Worker 721*cda5da8dSAndroid Build Coastguard Worker >>> read_unicodestring8(io.BytesIO(n + enc[:-1])) 722*cda5da8dSAndroid Build Coastguard Worker Traceback (most recent call last): 723*cda5da8dSAndroid Build Coastguard Worker ... 724*cda5da8dSAndroid Build Coastguard Worker ValueError: expected 7 bytes in a unicodestring8, but only 6 remain 725*cda5da8dSAndroid Build Coastguard Worker """ 726*cda5da8dSAndroid Build Coastguard Worker 727*cda5da8dSAndroid Build Coastguard Worker n = read_uint8(f) 728*cda5da8dSAndroid Build Coastguard Worker assert n >= 0 729*cda5da8dSAndroid Build Coastguard Worker if n > sys.maxsize: 730*cda5da8dSAndroid Build Coastguard Worker raise ValueError("unicodestring8 byte count > sys.maxsize: %d" % n) 731*cda5da8dSAndroid Build Coastguard Worker data = f.read(n) 732*cda5da8dSAndroid Build Coastguard Worker if len(data) == n: 733*cda5da8dSAndroid Build Coastguard Worker return str(data, 'utf-8', 'surrogatepass') 734*cda5da8dSAndroid Build Coastguard Worker raise ValueError("expected %d bytes in a unicodestring8, but only %d " 735*cda5da8dSAndroid Build Coastguard Worker "remain" % (n, len(data))) 736*cda5da8dSAndroid Build Coastguard Worker 737*cda5da8dSAndroid Build Coastguard Workerunicodestring8 = ArgumentDescriptor( 738*cda5da8dSAndroid Build Coastguard Worker name="unicodestring8", 739*cda5da8dSAndroid Build Coastguard Worker n=TAKEN_FROM_ARGUMENT8U, 740*cda5da8dSAndroid Build Coastguard Worker reader=read_unicodestring8, 741*cda5da8dSAndroid Build Coastguard Worker doc="""A counted Unicode string. 742*cda5da8dSAndroid Build Coastguard Worker 743*cda5da8dSAndroid Build Coastguard Worker The first argument is an 8-byte little-endian signed int 744*cda5da8dSAndroid Build Coastguard Worker giving the number of bytes in the string, and the second 745*cda5da8dSAndroid Build Coastguard Worker argument-- the UTF-8 encoding of the Unicode string -- 746*cda5da8dSAndroid Build Coastguard Worker contains that many bytes. 747*cda5da8dSAndroid Build Coastguard Worker """) 748*cda5da8dSAndroid Build Coastguard Worker 749*cda5da8dSAndroid Build Coastguard Worker 750*cda5da8dSAndroid Build Coastguard Workerdef read_decimalnl_short(f): 751*cda5da8dSAndroid Build Coastguard Worker r""" 752*cda5da8dSAndroid Build Coastguard Worker >>> import io 753*cda5da8dSAndroid Build Coastguard Worker >>> read_decimalnl_short(io.BytesIO(b"1234\n56")) 754*cda5da8dSAndroid Build Coastguard Worker 1234 755*cda5da8dSAndroid Build Coastguard Worker 756*cda5da8dSAndroid Build Coastguard Worker >>> read_decimalnl_short(io.BytesIO(b"1234L\n56")) 757*cda5da8dSAndroid Build Coastguard Worker Traceback (most recent call last): 758*cda5da8dSAndroid Build Coastguard Worker ... 759*cda5da8dSAndroid Build Coastguard Worker ValueError: invalid literal for int() with base 10: b'1234L' 760*cda5da8dSAndroid Build Coastguard Worker """ 761*cda5da8dSAndroid Build Coastguard Worker 762*cda5da8dSAndroid Build Coastguard Worker s = read_stringnl(f, decode=False, stripquotes=False) 763*cda5da8dSAndroid Build Coastguard Worker 764*cda5da8dSAndroid Build Coastguard Worker # There's a hack for True and False here. 765*cda5da8dSAndroid Build Coastguard Worker if s == b"00": 766*cda5da8dSAndroid Build Coastguard Worker return False 767*cda5da8dSAndroid Build Coastguard Worker elif s == b"01": 768*cda5da8dSAndroid Build Coastguard Worker return True 769*cda5da8dSAndroid Build Coastguard Worker 770*cda5da8dSAndroid Build Coastguard Worker return int(s) 771*cda5da8dSAndroid Build Coastguard Worker 772*cda5da8dSAndroid Build Coastguard Workerdef read_decimalnl_long(f): 773*cda5da8dSAndroid Build Coastguard Worker r""" 774*cda5da8dSAndroid Build Coastguard Worker >>> import io 775*cda5da8dSAndroid Build Coastguard Worker 776*cda5da8dSAndroid Build Coastguard Worker >>> read_decimalnl_long(io.BytesIO(b"1234L\n56")) 777*cda5da8dSAndroid Build Coastguard Worker 1234 778*cda5da8dSAndroid Build Coastguard Worker 779*cda5da8dSAndroid Build Coastguard Worker >>> read_decimalnl_long(io.BytesIO(b"123456789012345678901234L\n6")) 780*cda5da8dSAndroid Build Coastguard Worker 123456789012345678901234 781*cda5da8dSAndroid Build Coastguard Worker """ 782*cda5da8dSAndroid Build Coastguard Worker 783*cda5da8dSAndroid Build Coastguard Worker s = read_stringnl(f, decode=False, stripquotes=False) 784*cda5da8dSAndroid Build Coastguard Worker if s[-1:] == b'L': 785*cda5da8dSAndroid Build Coastguard Worker s = s[:-1] 786*cda5da8dSAndroid Build Coastguard Worker return int(s) 787*cda5da8dSAndroid Build Coastguard Worker 788*cda5da8dSAndroid Build Coastguard Worker 789*cda5da8dSAndroid Build Coastguard Workerdecimalnl_short = ArgumentDescriptor( 790*cda5da8dSAndroid Build Coastguard Worker name='decimalnl_short', 791*cda5da8dSAndroid Build Coastguard Worker n=UP_TO_NEWLINE, 792*cda5da8dSAndroid Build Coastguard Worker reader=read_decimalnl_short, 793*cda5da8dSAndroid Build Coastguard Worker doc="""A newline-terminated decimal integer literal. 794*cda5da8dSAndroid Build Coastguard Worker 795*cda5da8dSAndroid Build Coastguard Worker This never has a trailing 'L', and the integer fit 796*cda5da8dSAndroid Build Coastguard Worker in a short Python int on the box where the pickle 797*cda5da8dSAndroid Build Coastguard Worker was written -- but there's no guarantee it will fit 798*cda5da8dSAndroid Build Coastguard Worker in a short Python int on the box where the pickle 799*cda5da8dSAndroid Build Coastguard Worker is read. 800*cda5da8dSAndroid Build Coastguard Worker """) 801*cda5da8dSAndroid Build Coastguard Worker 802*cda5da8dSAndroid Build Coastguard Workerdecimalnl_long = ArgumentDescriptor( 803*cda5da8dSAndroid Build Coastguard Worker name='decimalnl_long', 804*cda5da8dSAndroid Build Coastguard Worker n=UP_TO_NEWLINE, 805*cda5da8dSAndroid Build Coastguard Worker reader=read_decimalnl_long, 806*cda5da8dSAndroid Build Coastguard Worker doc="""A newline-terminated decimal integer literal. 807*cda5da8dSAndroid Build Coastguard Worker 808*cda5da8dSAndroid Build Coastguard Worker This has a trailing 'L', and can represent integers 809*cda5da8dSAndroid Build Coastguard Worker of any size. 810*cda5da8dSAndroid Build Coastguard Worker """) 811*cda5da8dSAndroid Build Coastguard Worker 812*cda5da8dSAndroid Build Coastguard Worker 813*cda5da8dSAndroid Build Coastguard Workerdef read_floatnl(f): 814*cda5da8dSAndroid Build Coastguard Worker r""" 815*cda5da8dSAndroid Build Coastguard Worker >>> import io 816*cda5da8dSAndroid Build Coastguard Worker >>> read_floatnl(io.BytesIO(b"-1.25\n6")) 817*cda5da8dSAndroid Build Coastguard Worker -1.25 818*cda5da8dSAndroid Build Coastguard Worker """ 819*cda5da8dSAndroid Build Coastguard Worker s = read_stringnl(f, decode=False, stripquotes=False) 820*cda5da8dSAndroid Build Coastguard Worker return float(s) 821*cda5da8dSAndroid Build Coastguard Worker 822*cda5da8dSAndroid Build Coastguard Workerfloatnl = ArgumentDescriptor( 823*cda5da8dSAndroid Build Coastguard Worker name='floatnl', 824*cda5da8dSAndroid Build Coastguard Worker n=UP_TO_NEWLINE, 825*cda5da8dSAndroid Build Coastguard Worker reader=read_floatnl, 826*cda5da8dSAndroid Build Coastguard Worker doc="""A newline-terminated decimal floating literal. 827*cda5da8dSAndroid Build Coastguard Worker 828*cda5da8dSAndroid Build Coastguard Worker In general this requires 17 significant digits for roundtrip 829*cda5da8dSAndroid Build Coastguard Worker identity, and pickling then unpickling infinities, NaNs, and 830*cda5da8dSAndroid Build Coastguard Worker minus zero doesn't work across boxes, or on some boxes even 831*cda5da8dSAndroid Build Coastguard Worker on itself (e.g., Windows can't read the strings it produces 832*cda5da8dSAndroid Build Coastguard Worker for infinities or NaNs). 833*cda5da8dSAndroid Build Coastguard Worker """) 834*cda5da8dSAndroid Build Coastguard Worker 835*cda5da8dSAndroid Build Coastguard Workerdef read_float8(f): 836*cda5da8dSAndroid Build Coastguard Worker r""" 837*cda5da8dSAndroid Build Coastguard Worker >>> import io, struct 838*cda5da8dSAndroid Build Coastguard Worker >>> raw = struct.pack(">d", -1.25) 839*cda5da8dSAndroid Build Coastguard Worker >>> raw 840*cda5da8dSAndroid Build Coastguard Worker b'\xbf\xf4\x00\x00\x00\x00\x00\x00' 841*cda5da8dSAndroid Build Coastguard Worker >>> read_float8(io.BytesIO(raw + b"\n")) 842*cda5da8dSAndroid Build Coastguard Worker -1.25 843*cda5da8dSAndroid Build Coastguard Worker """ 844*cda5da8dSAndroid Build Coastguard Worker 845*cda5da8dSAndroid Build Coastguard Worker data = f.read(8) 846*cda5da8dSAndroid Build Coastguard Worker if len(data) == 8: 847*cda5da8dSAndroid Build Coastguard Worker return _unpack(">d", data)[0] 848*cda5da8dSAndroid Build Coastguard Worker raise ValueError("not enough data in stream to read float8") 849*cda5da8dSAndroid Build Coastguard Worker 850*cda5da8dSAndroid Build Coastguard Worker 851*cda5da8dSAndroid Build Coastguard Workerfloat8 = ArgumentDescriptor( 852*cda5da8dSAndroid Build Coastguard Worker name='float8', 853*cda5da8dSAndroid Build Coastguard Worker n=8, 854*cda5da8dSAndroid Build Coastguard Worker reader=read_float8, 855*cda5da8dSAndroid Build Coastguard Worker doc="""An 8-byte binary representation of a float, big-endian. 856*cda5da8dSAndroid Build Coastguard Worker 857*cda5da8dSAndroid Build Coastguard Worker The format is unique to Python, and shared with the struct 858*cda5da8dSAndroid Build Coastguard Worker module (format string '>d') "in theory" (the struct and pickle 859*cda5da8dSAndroid Build Coastguard Worker implementations don't share the code -- they should). It's 860*cda5da8dSAndroid Build Coastguard Worker strongly related to the IEEE-754 double format, and, in normal 861*cda5da8dSAndroid Build Coastguard Worker cases, is in fact identical to the big-endian 754 double format. 862*cda5da8dSAndroid Build Coastguard Worker On other boxes the dynamic range is limited to that of a 754 863*cda5da8dSAndroid Build Coastguard Worker double, and "add a half and chop" rounding is used to reduce 864*cda5da8dSAndroid Build Coastguard Worker the precision to 53 bits. However, even on a 754 box, 865*cda5da8dSAndroid Build Coastguard Worker infinities, NaNs, and minus zero may not be handled correctly 866*cda5da8dSAndroid Build Coastguard Worker (may not survive roundtrip pickling intact). 867*cda5da8dSAndroid Build Coastguard Worker """) 868*cda5da8dSAndroid Build Coastguard Worker 869*cda5da8dSAndroid Build Coastguard Worker# Protocol 2 formats 870*cda5da8dSAndroid Build Coastguard Worker 871*cda5da8dSAndroid Build Coastguard Workerfrom pickle import decode_long 872*cda5da8dSAndroid Build Coastguard Worker 873*cda5da8dSAndroid Build Coastguard Workerdef read_long1(f): 874*cda5da8dSAndroid Build Coastguard Worker r""" 875*cda5da8dSAndroid Build Coastguard Worker >>> import io 876*cda5da8dSAndroid Build Coastguard Worker >>> read_long1(io.BytesIO(b"\x00")) 877*cda5da8dSAndroid Build Coastguard Worker 0 878*cda5da8dSAndroid Build Coastguard Worker >>> read_long1(io.BytesIO(b"\x02\xff\x00")) 879*cda5da8dSAndroid Build Coastguard Worker 255 880*cda5da8dSAndroid Build Coastguard Worker >>> read_long1(io.BytesIO(b"\x02\xff\x7f")) 881*cda5da8dSAndroid Build Coastguard Worker 32767 882*cda5da8dSAndroid Build Coastguard Worker >>> read_long1(io.BytesIO(b"\x02\x00\xff")) 883*cda5da8dSAndroid Build Coastguard Worker -256 884*cda5da8dSAndroid Build Coastguard Worker >>> read_long1(io.BytesIO(b"\x02\x00\x80")) 885*cda5da8dSAndroid Build Coastguard Worker -32768 886*cda5da8dSAndroid Build Coastguard Worker """ 887*cda5da8dSAndroid Build Coastguard Worker 888*cda5da8dSAndroid Build Coastguard Worker n = read_uint1(f) 889*cda5da8dSAndroid Build Coastguard Worker data = f.read(n) 890*cda5da8dSAndroid Build Coastguard Worker if len(data) != n: 891*cda5da8dSAndroid Build Coastguard Worker raise ValueError("not enough data in stream to read long1") 892*cda5da8dSAndroid Build Coastguard Worker return decode_long(data) 893*cda5da8dSAndroid Build Coastguard Worker 894*cda5da8dSAndroid Build Coastguard Workerlong1 = ArgumentDescriptor( 895*cda5da8dSAndroid Build Coastguard Worker name="long1", 896*cda5da8dSAndroid Build Coastguard Worker n=TAKEN_FROM_ARGUMENT1, 897*cda5da8dSAndroid Build Coastguard Worker reader=read_long1, 898*cda5da8dSAndroid Build Coastguard Worker doc="""A binary long, little-endian, using 1-byte size. 899*cda5da8dSAndroid Build Coastguard Worker 900*cda5da8dSAndroid Build Coastguard Worker This first reads one byte as an unsigned size, then reads that 901*cda5da8dSAndroid Build Coastguard Worker many bytes and interprets them as a little-endian 2's-complement long. 902*cda5da8dSAndroid Build Coastguard Worker If the size is 0, that's taken as a shortcut for the long 0L. 903*cda5da8dSAndroid Build Coastguard Worker """) 904*cda5da8dSAndroid Build Coastguard Worker 905*cda5da8dSAndroid Build Coastguard Workerdef read_long4(f): 906*cda5da8dSAndroid Build Coastguard Worker r""" 907*cda5da8dSAndroid Build Coastguard Worker >>> import io 908*cda5da8dSAndroid Build Coastguard Worker >>> read_long4(io.BytesIO(b"\x02\x00\x00\x00\xff\x00")) 909*cda5da8dSAndroid Build Coastguard Worker 255 910*cda5da8dSAndroid Build Coastguard Worker >>> read_long4(io.BytesIO(b"\x02\x00\x00\x00\xff\x7f")) 911*cda5da8dSAndroid Build Coastguard Worker 32767 912*cda5da8dSAndroid Build Coastguard Worker >>> read_long4(io.BytesIO(b"\x02\x00\x00\x00\x00\xff")) 913*cda5da8dSAndroid Build Coastguard Worker -256 914*cda5da8dSAndroid Build Coastguard Worker >>> read_long4(io.BytesIO(b"\x02\x00\x00\x00\x00\x80")) 915*cda5da8dSAndroid Build Coastguard Worker -32768 916*cda5da8dSAndroid Build Coastguard Worker >>> read_long1(io.BytesIO(b"\x00\x00\x00\x00")) 917*cda5da8dSAndroid Build Coastguard Worker 0 918*cda5da8dSAndroid Build Coastguard Worker """ 919*cda5da8dSAndroid Build Coastguard Worker 920*cda5da8dSAndroid Build Coastguard Worker n = read_int4(f) 921*cda5da8dSAndroid Build Coastguard Worker if n < 0: 922*cda5da8dSAndroid Build Coastguard Worker raise ValueError("long4 byte count < 0: %d" % n) 923*cda5da8dSAndroid Build Coastguard Worker data = f.read(n) 924*cda5da8dSAndroid Build Coastguard Worker if len(data) != n: 925*cda5da8dSAndroid Build Coastguard Worker raise ValueError("not enough data in stream to read long4") 926*cda5da8dSAndroid Build Coastguard Worker return decode_long(data) 927*cda5da8dSAndroid Build Coastguard Worker 928*cda5da8dSAndroid Build Coastguard Workerlong4 = ArgumentDescriptor( 929*cda5da8dSAndroid Build Coastguard Worker name="long4", 930*cda5da8dSAndroid Build Coastguard Worker n=TAKEN_FROM_ARGUMENT4, 931*cda5da8dSAndroid Build Coastguard Worker reader=read_long4, 932*cda5da8dSAndroid Build Coastguard Worker doc="""A binary representation of a long, little-endian. 933*cda5da8dSAndroid Build Coastguard Worker 934*cda5da8dSAndroid Build Coastguard Worker This first reads four bytes as a signed size (but requires the 935*cda5da8dSAndroid Build Coastguard Worker size to be >= 0), then reads that many bytes and interprets them 936*cda5da8dSAndroid Build Coastguard Worker as a little-endian 2's-complement long. If the size is 0, that's taken 937*cda5da8dSAndroid Build Coastguard Worker as a shortcut for the int 0, although LONG1 should really be used 938*cda5da8dSAndroid Build Coastguard Worker then instead (and in any case where # of bytes < 256). 939*cda5da8dSAndroid Build Coastguard Worker """) 940*cda5da8dSAndroid Build Coastguard Worker 941*cda5da8dSAndroid Build Coastguard Worker 942*cda5da8dSAndroid Build Coastguard Worker############################################################################## 943*cda5da8dSAndroid Build Coastguard Worker# Object descriptors. The stack used by the pickle machine holds objects, 944*cda5da8dSAndroid Build Coastguard Worker# and in the stack_before and stack_after attributes of OpcodeInfo 945*cda5da8dSAndroid Build Coastguard Worker# descriptors we need names to describe the various types of objects that can 946*cda5da8dSAndroid Build Coastguard Worker# appear on the stack. 947*cda5da8dSAndroid Build Coastguard Worker 948*cda5da8dSAndroid Build Coastguard Workerclass StackObject(object): 949*cda5da8dSAndroid Build Coastguard Worker __slots__ = ( 950*cda5da8dSAndroid Build Coastguard Worker # name of descriptor record, for info only 951*cda5da8dSAndroid Build Coastguard Worker 'name', 952*cda5da8dSAndroid Build Coastguard Worker 953*cda5da8dSAndroid Build Coastguard Worker # type of object, or tuple of type objects (meaning the object can 954*cda5da8dSAndroid Build Coastguard Worker # be of any type in the tuple) 955*cda5da8dSAndroid Build Coastguard Worker 'obtype', 956*cda5da8dSAndroid Build Coastguard Worker 957*cda5da8dSAndroid Build Coastguard Worker # human-readable docs for this kind of stack object; a string 958*cda5da8dSAndroid Build Coastguard Worker 'doc', 959*cda5da8dSAndroid Build Coastguard Worker ) 960*cda5da8dSAndroid Build Coastguard Worker 961*cda5da8dSAndroid Build Coastguard Worker def __init__(self, name, obtype, doc): 962*cda5da8dSAndroid Build Coastguard Worker assert isinstance(name, str) 963*cda5da8dSAndroid Build Coastguard Worker self.name = name 964*cda5da8dSAndroid Build Coastguard Worker 965*cda5da8dSAndroid Build Coastguard Worker assert isinstance(obtype, type) or isinstance(obtype, tuple) 966*cda5da8dSAndroid Build Coastguard Worker if isinstance(obtype, tuple): 967*cda5da8dSAndroid Build Coastguard Worker for contained in obtype: 968*cda5da8dSAndroid Build Coastguard Worker assert isinstance(contained, type) 969*cda5da8dSAndroid Build Coastguard Worker self.obtype = obtype 970*cda5da8dSAndroid Build Coastguard Worker 971*cda5da8dSAndroid Build Coastguard Worker assert isinstance(doc, str) 972*cda5da8dSAndroid Build Coastguard Worker self.doc = doc 973*cda5da8dSAndroid Build Coastguard Worker 974*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 975*cda5da8dSAndroid Build Coastguard Worker return self.name 976*cda5da8dSAndroid Build Coastguard Worker 977*cda5da8dSAndroid Build Coastguard Worker 978*cda5da8dSAndroid Build Coastguard Workerpyint = pylong = StackObject( 979*cda5da8dSAndroid Build Coastguard Worker name='int', 980*cda5da8dSAndroid Build Coastguard Worker obtype=int, 981*cda5da8dSAndroid Build Coastguard Worker doc="A Python integer object.") 982*cda5da8dSAndroid Build Coastguard Worker 983*cda5da8dSAndroid Build Coastguard Workerpyinteger_or_bool = StackObject( 984*cda5da8dSAndroid Build Coastguard Worker name='int_or_bool', 985*cda5da8dSAndroid Build Coastguard Worker obtype=(int, bool), 986*cda5da8dSAndroid Build Coastguard Worker doc="A Python integer or boolean object.") 987*cda5da8dSAndroid Build Coastguard Worker 988*cda5da8dSAndroid Build Coastguard Workerpybool = StackObject( 989*cda5da8dSAndroid Build Coastguard Worker name='bool', 990*cda5da8dSAndroid Build Coastguard Worker obtype=bool, 991*cda5da8dSAndroid Build Coastguard Worker doc="A Python boolean object.") 992*cda5da8dSAndroid Build Coastguard Worker 993*cda5da8dSAndroid Build Coastguard Workerpyfloat = StackObject( 994*cda5da8dSAndroid Build Coastguard Worker name='float', 995*cda5da8dSAndroid Build Coastguard Worker obtype=float, 996*cda5da8dSAndroid Build Coastguard Worker doc="A Python float object.") 997*cda5da8dSAndroid Build Coastguard Worker 998*cda5da8dSAndroid Build Coastguard Workerpybytes_or_str = pystring = StackObject( 999*cda5da8dSAndroid Build Coastguard Worker name='bytes_or_str', 1000*cda5da8dSAndroid Build Coastguard Worker obtype=(bytes, str), 1001*cda5da8dSAndroid Build Coastguard Worker doc="A Python bytes or (Unicode) string object.") 1002*cda5da8dSAndroid Build Coastguard Worker 1003*cda5da8dSAndroid Build Coastguard Workerpybytes = StackObject( 1004*cda5da8dSAndroid Build Coastguard Worker name='bytes', 1005*cda5da8dSAndroid Build Coastguard Worker obtype=bytes, 1006*cda5da8dSAndroid Build Coastguard Worker doc="A Python bytes object.") 1007*cda5da8dSAndroid Build Coastguard Worker 1008*cda5da8dSAndroid Build Coastguard Workerpybytearray = StackObject( 1009*cda5da8dSAndroid Build Coastguard Worker name='bytearray', 1010*cda5da8dSAndroid Build Coastguard Worker obtype=bytearray, 1011*cda5da8dSAndroid Build Coastguard Worker doc="A Python bytearray object.") 1012*cda5da8dSAndroid Build Coastguard Worker 1013*cda5da8dSAndroid Build Coastguard Workerpyunicode = StackObject( 1014*cda5da8dSAndroid Build Coastguard Worker name='str', 1015*cda5da8dSAndroid Build Coastguard Worker obtype=str, 1016*cda5da8dSAndroid Build Coastguard Worker doc="A Python (Unicode) string object.") 1017*cda5da8dSAndroid Build Coastguard Worker 1018*cda5da8dSAndroid Build Coastguard Workerpynone = StackObject( 1019*cda5da8dSAndroid Build Coastguard Worker name="None", 1020*cda5da8dSAndroid Build Coastguard Worker obtype=type(None), 1021*cda5da8dSAndroid Build Coastguard Worker doc="The Python None object.") 1022*cda5da8dSAndroid Build Coastguard Worker 1023*cda5da8dSAndroid Build Coastguard Workerpytuple = StackObject( 1024*cda5da8dSAndroid Build Coastguard Worker name="tuple", 1025*cda5da8dSAndroid Build Coastguard Worker obtype=tuple, 1026*cda5da8dSAndroid Build Coastguard Worker doc="A Python tuple object.") 1027*cda5da8dSAndroid Build Coastguard Worker 1028*cda5da8dSAndroid Build Coastguard Workerpylist = StackObject( 1029*cda5da8dSAndroid Build Coastguard Worker name="list", 1030*cda5da8dSAndroid Build Coastguard Worker obtype=list, 1031*cda5da8dSAndroid Build Coastguard Worker doc="A Python list object.") 1032*cda5da8dSAndroid Build Coastguard Worker 1033*cda5da8dSAndroid Build Coastguard Workerpydict = StackObject( 1034*cda5da8dSAndroid Build Coastguard Worker name="dict", 1035*cda5da8dSAndroid Build Coastguard Worker obtype=dict, 1036*cda5da8dSAndroid Build Coastguard Worker doc="A Python dict object.") 1037*cda5da8dSAndroid Build Coastguard Worker 1038*cda5da8dSAndroid Build Coastguard Workerpyset = StackObject( 1039*cda5da8dSAndroid Build Coastguard Worker name="set", 1040*cda5da8dSAndroid Build Coastguard Worker obtype=set, 1041*cda5da8dSAndroid Build Coastguard Worker doc="A Python set object.") 1042*cda5da8dSAndroid Build Coastguard Worker 1043*cda5da8dSAndroid Build Coastguard Workerpyfrozenset = StackObject( 1044*cda5da8dSAndroid Build Coastguard Worker name="frozenset", 1045*cda5da8dSAndroid Build Coastguard Worker obtype=set, 1046*cda5da8dSAndroid Build Coastguard Worker doc="A Python frozenset object.") 1047*cda5da8dSAndroid Build Coastguard Worker 1048*cda5da8dSAndroid Build Coastguard Workerpybuffer = StackObject( 1049*cda5da8dSAndroid Build Coastguard Worker name='buffer', 1050*cda5da8dSAndroid Build Coastguard Worker obtype=object, 1051*cda5da8dSAndroid Build Coastguard Worker doc="A Python buffer-like object.") 1052*cda5da8dSAndroid Build Coastguard Worker 1053*cda5da8dSAndroid Build Coastguard Workeranyobject = StackObject( 1054*cda5da8dSAndroid Build Coastguard Worker name='any', 1055*cda5da8dSAndroid Build Coastguard Worker obtype=object, 1056*cda5da8dSAndroid Build Coastguard Worker doc="Any kind of object whatsoever.") 1057*cda5da8dSAndroid Build Coastguard Worker 1058*cda5da8dSAndroid Build Coastguard Workermarkobject = StackObject( 1059*cda5da8dSAndroid Build Coastguard Worker name="mark", 1060*cda5da8dSAndroid Build Coastguard Worker obtype=StackObject, 1061*cda5da8dSAndroid Build Coastguard Worker doc="""'The mark' is a unique object. 1062*cda5da8dSAndroid Build Coastguard Worker 1063*cda5da8dSAndroid Build Coastguard WorkerOpcodes that operate on a variable number of objects 1064*cda5da8dSAndroid Build Coastguard Workergenerally don't embed the count of objects in the opcode, 1065*cda5da8dSAndroid Build Coastguard Workeror pull it off the stack. Instead the MARK opcode is used 1066*cda5da8dSAndroid Build Coastguard Workerto push a special marker object on the stack, and then 1067*cda5da8dSAndroid Build Coastguard Workersome other opcodes grab all the objects from the top of 1068*cda5da8dSAndroid Build Coastguard Workerthe stack down to (but not including) the topmost marker 1069*cda5da8dSAndroid Build Coastguard Workerobject. 1070*cda5da8dSAndroid Build Coastguard Worker""") 1071*cda5da8dSAndroid Build Coastguard Worker 1072*cda5da8dSAndroid Build Coastguard Workerstackslice = StackObject( 1073*cda5da8dSAndroid Build Coastguard Worker name="stackslice", 1074*cda5da8dSAndroid Build Coastguard Worker obtype=StackObject, 1075*cda5da8dSAndroid Build Coastguard Worker doc="""An object representing a contiguous slice of the stack. 1076*cda5da8dSAndroid Build Coastguard Worker 1077*cda5da8dSAndroid Build Coastguard WorkerThis is used in conjunction with markobject, to represent all 1078*cda5da8dSAndroid Build Coastguard Workerof the stack following the topmost markobject. For example, 1079*cda5da8dSAndroid Build Coastguard Workerthe POP_MARK opcode changes the stack from 1080*cda5da8dSAndroid Build Coastguard Worker 1081*cda5da8dSAndroid Build Coastguard Worker [..., markobject, stackslice] 1082*cda5da8dSAndroid Build Coastguard Workerto 1083*cda5da8dSAndroid Build Coastguard Worker [...] 1084*cda5da8dSAndroid Build Coastguard Worker 1085*cda5da8dSAndroid Build Coastguard WorkerNo matter how many object are on the stack after the topmost 1086*cda5da8dSAndroid Build Coastguard Workermarkobject, POP_MARK gets rid of all of them (including the 1087*cda5da8dSAndroid Build Coastguard Workertopmost markobject too). 1088*cda5da8dSAndroid Build Coastguard Worker""") 1089*cda5da8dSAndroid Build Coastguard Worker 1090*cda5da8dSAndroid Build Coastguard Worker############################################################################## 1091*cda5da8dSAndroid Build Coastguard Worker# Descriptors for pickle opcodes. 1092*cda5da8dSAndroid Build Coastguard Worker 1093*cda5da8dSAndroid Build Coastguard Workerclass OpcodeInfo(object): 1094*cda5da8dSAndroid Build Coastguard Worker 1095*cda5da8dSAndroid Build Coastguard Worker __slots__ = ( 1096*cda5da8dSAndroid Build Coastguard Worker # symbolic name of opcode; a string 1097*cda5da8dSAndroid Build Coastguard Worker 'name', 1098*cda5da8dSAndroid Build Coastguard Worker 1099*cda5da8dSAndroid Build Coastguard Worker # the code used in a bytestream to represent the opcode; a 1100*cda5da8dSAndroid Build Coastguard Worker # one-character string 1101*cda5da8dSAndroid Build Coastguard Worker 'code', 1102*cda5da8dSAndroid Build Coastguard Worker 1103*cda5da8dSAndroid Build Coastguard Worker # If the opcode has an argument embedded in the byte string, an 1104*cda5da8dSAndroid Build Coastguard Worker # instance of ArgumentDescriptor specifying its type. Note that 1105*cda5da8dSAndroid Build Coastguard Worker # arg.reader(s) can be used to read and decode the argument from 1106*cda5da8dSAndroid Build Coastguard Worker # the bytestream s, and arg.doc documents the format of the raw 1107*cda5da8dSAndroid Build Coastguard Worker # argument bytes. If the opcode doesn't have an argument embedded 1108*cda5da8dSAndroid Build Coastguard Worker # in the bytestream, arg should be None. 1109*cda5da8dSAndroid Build Coastguard Worker 'arg', 1110*cda5da8dSAndroid Build Coastguard Worker 1111*cda5da8dSAndroid Build Coastguard Worker # what the stack looks like before this opcode runs; a list 1112*cda5da8dSAndroid Build Coastguard Worker 'stack_before', 1113*cda5da8dSAndroid Build Coastguard Worker 1114*cda5da8dSAndroid Build Coastguard Worker # what the stack looks like after this opcode runs; a list 1115*cda5da8dSAndroid Build Coastguard Worker 'stack_after', 1116*cda5da8dSAndroid Build Coastguard Worker 1117*cda5da8dSAndroid Build Coastguard Worker # the protocol number in which this opcode was introduced; an int 1118*cda5da8dSAndroid Build Coastguard Worker 'proto', 1119*cda5da8dSAndroid Build Coastguard Worker 1120*cda5da8dSAndroid Build Coastguard Worker # human-readable docs for this opcode; a string 1121*cda5da8dSAndroid Build Coastguard Worker 'doc', 1122*cda5da8dSAndroid Build Coastguard Worker ) 1123*cda5da8dSAndroid Build Coastguard Worker 1124*cda5da8dSAndroid Build Coastguard Worker def __init__(self, name, code, arg, 1125*cda5da8dSAndroid Build Coastguard Worker stack_before, stack_after, proto, doc): 1126*cda5da8dSAndroid Build Coastguard Worker assert isinstance(name, str) 1127*cda5da8dSAndroid Build Coastguard Worker self.name = name 1128*cda5da8dSAndroid Build Coastguard Worker 1129*cda5da8dSAndroid Build Coastguard Worker assert isinstance(code, str) 1130*cda5da8dSAndroid Build Coastguard Worker assert len(code) == 1 1131*cda5da8dSAndroid Build Coastguard Worker self.code = code 1132*cda5da8dSAndroid Build Coastguard Worker 1133*cda5da8dSAndroid Build Coastguard Worker assert arg is None or isinstance(arg, ArgumentDescriptor) 1134*cda5da8dSAndroid Build Coastguard Worker self.arg = arg 1135*cda5da8dSAndroid Build Coastguard Worker 1136*cda5da8dSAndroid Build Coastguard Worker assert isinstance(stack_before, list) 1137*cda5da8dSAndroid Build Coastguard Worker for x in stack_before: 1138*cda5da8dSAndroid Build Coastguard Worker assert isinstance(x, StackObject) 1139*cda5da8dSAndroid Build Coastguard Worker self.stack_before = stack_before 1140*cda5da8dSAndroid Build Coastguard Worker 1141*cda5da8dSAndroid Build Coastguard Worker assert isinstance(stack_after, list) 1142*cda5da8dSAndroid Build Coastguard Worker for x in stack_after: 1143*cda5da8dSAndroid Build Coastguard Worker assert isinstance(x, StackObject) 1144*cda5da8dSAndroid Build Coastguard Worker self.stack_after = stack_after 1145*cda5da8dSAndroid Build Coastguard Worker 1146*cda5da8dSAndroid Build Coastguard Worker assert isinstance(proto, int) and 0 <= proto <= pickle.HIGHEST_PROTOCOL 1147*cda5da8dSAndroid Build Coastguard Worker self.proto = proto 1148*cda5da8dSAndroid Build Coastguard Worker 1149*cda5da8dSAndroid Build Coastguard Worker assert isinstance(doc, str) 1150*cda5da8dSAndroid Build Coastguard Worker self.doc = doc 1151*cda5da8dSAndroid Build Coastguard Worker 1152*cda5da8dSAndroid Build Coastguard WorkerI = OpcodeInfo 1153*cda5da8dSAndroid Build Coastguard Workeropcodes = [ 1154*cda5da8dSAndroid Build Coastguard Worker 1155*cda5da8dSAndroid Build Coastguard Worker # Ways to spell integers. 1156*cda5da8dSAndroid Build Coastguard Worker 1157*cda5da8dSAndroid Build Coastguard Worker I(name='INT', 1158*cda5da8dSAndroid Build Coastguard Worker code='I', 1159*cda5da8dSAndroid Build Coastguard Worker arg=decimalnl_short, 1160*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1161*cda5da8dSAndroid Build Coastguard Worker stack_after=[pyinteger_or_bool], 1162*cda5da8dSAndroid Build Coastguard Worker proto=0, 1163*cda5da8dSAndroid Build Coastguard Worker doc="""Push an integer or bool. 1164*cda5da8dSAndroid Build Coastguard Worker 1165*cda5da8dSAndroid Build Coastguard Worker The argument is a newline-terminated decimal literal string. 1166*cda5da8dSAndroid Build Coastguard Worker 1167*cda5da8dSAndroid Build Coastguard Worker The intent may have been that this always fit in a short Python int, 1168*cda5da8dSAndroid Build Coastguard Worker but INT can be generated in pickles written on a 64-bit box that 1169*cda5da8dSAndroid Build Coastguard Worker require a Python long on a 32-bit box. The difference between this 1170*cda5da8dSAndroid Build Coastguard Worker and LONG then is that INT skips a trailing 'L', and produces a short 1171*cda5da8dSAndroid Build Coastguard Worker int whenever possible. 1172*cda5da8dSAndroid Build Coastguard Worker 1173*cda5da8dSAndroid Build Coastguard Worker Another difference is due to that, when bool was introduced as a 1174*cda5da8dSAndroid Build Coastguard Worker distinct type in 2.3, builtin names True and False were also added to 1175*cda5da8dSAndroid Build Coastguard Worker 2.2.2, mapping to ints 1 and 0. For compatibility in both directions, 1176*cda5da8dSAndroid Build Coastguard Worker True gets pickled as INT + "I01\\n", and False as INT + "I00\\n". 1177*cda5da8dSAndroid Build Coastguard Worker Leading zeroes are never produced for a genuine integer. The 2.3 1178*cda5da8dSAndroid Build Coastguard Worker (and later) unpicklers special-case these and return bool instead; 1179*cda5da8dSAndroid Build Coastguard Worker earlier unpicklers ignore the leading "0" and return the int. 1180*cda5da8dSAndroid Build Coastguard Worker """), 1181*cda5da8dSAndroid Build Coastguard Worker 1182*cda5da8dSAndroid Build Coastguard Worker I(name='BININT', 1183*cda5da8dSAndroid Build Coastguard Worker code='J', 1184*cda5da8dSAndroid Build Coastguard Worker arg=int4, 1185*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1186*cda5da8dSAndroid Build Coastguard Worker stack_after=[pyint], 1187*cda5da8dSAndroid Build Coastguard Worker proto=1, 1188*cda5da8dSAndroid Build Coastguard Worker doc="""Push a four-byte signed integer. 1189*cda5da8dSAndroid Build Coastguard Worker 1190*cda5da8dSAndroid Build Coastguard Worker This handles the full range of Python (short) integers on a 32-bit 1191*cda5da8dSAndroid Build Coastguard Worker box, directly as binary bytes (1 for the opcode and 4 for the integer). 1192*cda5da8dSAndroid Build Coastguard Worker If the integer is non-negative and fits in 1 or 2 bytes, pickling via 1193*cda5da8dSAndroid Build Coastguard Worker BININT1 or BININT2 saves space. 1194*cda5da8dSAndroid Build Coastguard Worker """), 1195*cda5da8dSAndroid Build Coastguard Worker 1196*cda5da8dSAndroid Build Coastguard Worker I(name='BININT1', 1197*cda5da8dSAndroid Build Coastguard Worker code='K', 1198*cda5da8dSAndroid Build Coastguard Worker arg=uint1, 1199*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1200*cda5da8dSAndroid Build Coastguard Worker stack_after=[pyint], 1201*cda5da8dSAndroid Build Coastguard Worker proto=1, 1202*cda5da8dSAndroid Build Coastguard Worker doc="""Push a one-byte unsigned integer. 1203*cda5da8dSAndroid Build Coastguard Worker 1204*cda5da8dSAndroid Build Coastguard Worker This is a space optimization for pickling very small non-negative ints, 1205*cda5da8dSAndroid Build Coastguard Worker in range(256). 1206*cda5da8dSAndroid Build Coastguard Worker """), 1207*cda5da8dSAndroid Build Coastguard Worker 1208*cda5da8dSAndroid Build Coastguard Worker I(name='BININT2', 1209*cda5da8dSAndroid Build Coastguard Worker code='M', 1210*cda5da8dSAndroid Build Coastguard Worker arg=uint2, 1211*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1212*cda5da8dSAndroid Build Coastguard Worker stack_after=[pyint], 1213*cda5da8dSAndroid Build Coastguard Worker proto=1, 1214*cda5da8dSAndroid Build Coastguard Worker doc="""Push a two-byte unsigned integer. 1215*cda5da8dSAndroid Build Coastguard Worker 1216*cda5da8dSAndroid Build Coastguard Worker This is a space optimization for pickling small positive ints, in 1217*cda5da8dSAndroid Build Coastguard Worker range(256, 2**16). Integers in range(256) can also be pickled via 1218*cda5da8dSAndroid Build Coastguard Worker BININT2, but BININT1 instead saves a byte. 1219*cda5da8dSAndroid Build Coastguard Worker """), 1220*cda5da8dSAndroid Build Coastguard Worker 1221*cda5da8dSAndroid Build Coastguard Worker I(name='LONG', 1222*cda5da8dSAndroid Build Coastguard Worker code='L', 1223*cda5da8dSAndroid Build Coastguard Worker arg=decimalnl_long, 1224*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1225*cda5da8dSAndroid Build Coastguard Worker stack_after=[pyint], 1226*cda5da8dSAndroid Build Coastguard Worker proto=0, 1227*cda5da8dSAndroid Build Coastguard Worker doc="""Push a long integer. 1228*cda5da8dSAndroid Build Coastguard Worker 1229*cda5da8dSAndroid Build Coastguard Worker The same as INT, except that the literal ends with 'L', and always 1230*cda5da8dSAndroid Build Coastguard Worker unpickles to a Python long. There doesn't seem a real purpose to the 1231*cda5da8dSAndroid Build Coastguard Worker trailing 'L'. 1232*cda5da8dSAndroid Build Coastguard Worker 1233*cda5da8dSAndroid Build Coastguard Worker Note that LONG takes time quadratic in the number of digits when 1234*cda5da8dSAndroid Build Coastguard Worker unpickling (this is simply due to the nature of decimal->binary 1235*cda5da8dSAndroid Build Coastguard Worker conversion). Proto 2 added linear-time (in C; still quadratic-time 1236*cda5da8dSAndroid Build Coastguard Worker in Python) LONG1 and LONG4 opcodes. 1237*cda5da8dSAndroid Build Coastguard Worker """), 1238*cda5da8dSAndroid Build Coastguard Worker 1239*cda5da8dSAndroid Build Coastguard Worker I(name="LONG1", 1240*cda5da8dSAndroid Build Coastguard Worker code='\x8a', 1241*cda5da8dSAndroid Build Coastguard Worker arg=long1, 1242*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1243*cda5da8dSAndroid Build Coastguard Worker stack_after=[pyint], 1244*cda5da8dSAndroid Build Coastguard Worker proto=2, 1245*cda5da8dSAndroid Build Coastguard Worker doc="""Long integer using one-byte length. 1246*cda5da8dSAndroid Build Coastguard Worker 1247*cda5da8dSAndroid Build Coastguard Worker A more efficient encoding of a Python long; the long1 encoding 1248*cda5da8dSAndroid Build Coastguard Worker says it all."""), 1249*cda5da8dSAndroid Build Coastguard Worker 1250*cda5da8dSAndroid Build Coastguard Worker I(name="LONG4", 1251*cda5da8dSAndroid Build Coastguard Worker code='\x8b', 1252*cda5da8dSAndroid Build Coastguard Worker arg=long4, 1253*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1254*cda5da8dSAndroid Build Coastguard Worker stack_after=[pyint], 1255*cda5da8dSAndroid Build Coastguard Worker proto=2, 1256*cda5da8dSAndroid Build Coastguard Worker doc="""Long integer using found-byte length. 1257*cda5da8dSAndroid Build Coastguard Worker 1258*cda5da8dSAndroid Build Coastguard Worker A more efficient encoding of a Python long; the long4 encoding 1259*cda5da8dSAndroid Build Coastguard Worker says it all."""), 1260*cda5da8dSAndroid Build Coastguard Worker 1261*cda5da8dSAndroid Build Coastguard Worker # Ways to spell strings (8-bit, not Unicode). 1262*cda5da8dSAndroid Build Coastguard Worker 1263*cda5da8dSAndroid Build Coastguard Worker I(name='STRING', 1264*cda5da8dSAndroid Build Coastguard Worker code='S', 1265*cda5da8dSAndroid Build Coastguard Worker arg=stringnl, 1266*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1267*cda5da8dSAndroid Build Coastguard Worker stack_after=[pybytes_or_str], 1268*cda5da8dSAndroid Build Coastguard Worker proto=0, 1269*cda5da8dSAndroid Build Coastguard Worker doc="""Push a Python string object. 1270*cda5da8dSAndroid Build Coastguard Worker 1271*cda5da8dSAndroid Build Coastguard Worker The argument is a repr-style string, with bracketing quote characters, 1272*cda5da8dSAndroid Build Coastguard Worker and perhaps embedded escapes. The argument extends until the next 1273*cda5da8dSAndroid Build Coastguard Worker newline character. These are usually decoded into a str instance 1274*cda5da8dSAndroid Build Coastguard Worker using the encoding given to the Unpickler constructor. or the default, 1275*cda5da8dSAndroid Build Coastguard Worker 'ASCII'. If the encoding given was 'bytes' however, they will be 1276*cda5da8dSAndroid Build Coastguard Worker decoded as bytes object instead. 1277*cda5da8dSAndroid Build Coastguard Worker """), 1278*cda5da8dSAndroid Build Coastguard Worker 1279*cda5da8dSAndroid Build Coastguard Worker I(name='BINSTRING', 1280*cda5da8dSAndroid Build Coastguard Worker code='T', 1281*cda5da8dSAndroid Build Coastguard Worker arg=string4, 1282*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1283*cda5da8dSAndroid Build Coastguard Worker stack_after=[pybytes_or_str], 1284*cda5da8dSAndroid Build Coastguard Worker proto=1, 1285*cda5da8dSAndroid Build Coastguard Worker doc="""Push a Python string object. 1286*cda5da8dSAndroid Build Coastguard Worker 1287*cda5da8dSAndroid Build Coastguard Worker There are two arguments: the first is a 4-byte little-endian 1288*cda5da8dSAndroid Build Coastguard Worker signed int giving the number of bytes in the string, and the 1289*cda5da8dSAndroid Build Coastguard Worker second is that many bytes, which are taken literally as the string 1290*cda5da8dSAndroid Build Coastguard Worker content. These are usually decoded into a str instance using the 1291*cda5da8dSAndroid Build Coastguard Worker encoding given to the Unpickler constructor. or the default, 1292*cda5da8dSAndroid Build Coastguard Worker 'ASCII'. If the encoding given was 'bytes' however, they will be 1293*cda5da8dSAndroid Build Coastguard Worker decoded as bytes object instead. 1294*cda5da8dSAndroid Build Coastguard Worker """), 1295*cda5da8dSAndroid Build Coastguard Worker 1296*cda5da8dSAndroid Build Coastguard Worker I(name='SHORT_BINSTRING', 1297*cda5da8dSAndroid Build Coastguard Worker code='U', 1298*cda5da8dSAndroid Build Coastguard Worker arg=string1, 1299*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1300*cda5da8dSAndroid Build Coastguard Worker stack_after=[pybytes_or_str], 1301*cda5da8dSAndroid Build Coastguard Worker proto=1, 1302*cda5da8dSAndroid Build Coastguard Worker doc="""Push a Python string object. 1303*cda5da8dSAndroid Build Coastguard Worker 1304*cda5da8dSAndroid Build Coastguard Worker There are two arguments: the first is a 1-byte unsigned int giving 1305*cda5da8dSAndroid Build Coastguard Worker the number of bytes in the string, and the second is that many 1306*cda5da8dSAndroid Build Coastguard Worker bytes, which are taken literally as the string content. These are 1307*cda5da8dSAndroid Build Coastguard Worker usually decoded into a str instance using the encoding given to 1308*cda5da8dSAndroid Build Coastguard Worker the Unpickler constructor. or the default, 'ASCII'. If the 1309*cda5da8dSAndroid Build Coastguard Worker encoding given was 'bytes' however, they will be decoded as bytes 1310*cda5da8dSAndroid Build Coastguard Worker object instead. 1311*cda5da8dSAndroid Build Coastguard Worker """), 1312*cda5da8dSAndroid Build Coastguard Worker 1313*cda5da8dSAndroid Build Coastguard Worker # Bytes (protocol 3 and higher) 1314*cda5da8dSAndroid Build Coastguard Worker 1315*cda5da8dSAndroid Build Coastguard Worker I(name='BINBYTES', 1316*cda5da8dSAndroid Build Coastguard Worker code='B', 1317*cda5da8dSAndroid Build Coastguard Worker arg=bytes4, 1318*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1319*cda5da8dSAndroid Build Coastguard Worker stack_after=[pybytes], 1320*cda5da8dSAndroid Build Coastguard Worker proto=3, 1321*cda5da8dSAndroid Build Coastguard Worker doc="""Push a Python bytes object. 1322*cda5da8dSAndroid Build Coastguard Worker 1323*cda5da8dSAndroid Build Coastguard Worker There are two arguments: the first is a 4-byte little-endian unsigned int 1324*cda5da8dSAndroid Build Coastguard Worker giving the number of bytes, and the second is that many bytes, which are 1325*cda5da8dSAndroid Build Coastguard Worker taken literally as the bytes content. 1326*cda5da8dSAndroid Build Coastguard Worker """), 1327*cda5da8dSAndroid Build Coastguard Worker 1328*cda5da8dSAndroid Build Coastguard Worker I(name='SHORT_BINBYTES', 1329*cda5da8dSAndroid Build Coastguard Worker code='C', 1330*cda5da8dSAndroid Build Coastguard Worker arg=bytes1, 1331*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1332*cda5da8dSAndroid Build Coastguard Worker stack_after=[pybytes], 1333*cda5da8dSAndroid Build Coastguard Worker proto=3, 1334*cda5da8dSAndroid Build Coastguard Worker doc="""Push a Python bytes object. 1335*cda5da8dSAndroid Build Coastguard Worker 1336*cda5da8dSAndroid Build Coastguard Worker There are two arguments: the first is a 1-byte unsigned int giving 1337*cda5da8dSAndroid Build Coastguard Worker the number of bytes, and the second is that many bytes, which are taken 1338*cda5da8dSAndroid Build Coastguard Worker literally as the string content. 1339*cda5da8dSAndroid Build Coastguard Worker """), 1340*cda5da8dSAndroid Build Coastguard Worker 1341*cda5da8dSAndroid Build Coastguard Worker I(name='BINBYTES8', 1342*cda5da8dSAndroid Build Coastguard Worker code='\x8e', 1343*cda5da8dSAndroid Build Coastguard Worker arg=bytes8, 1344*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1345*cda5da8dSAndroid Build Coastguard Worker stack_after=[pybytes], 1346*cda5da8dSAndroid Build Coastguard Worker proto=4, 1347*cda5da8dSAndroid Build Coastguard Worker doc="""Push a Python bytes object. 1348*cda5da8dSAndroid Build Coastguard Worker 1349*cda5da8dSAndroid Build Coastguard Worker There are two arguments: the first is an 8-byte unsigned int giving 1350*cda5da8dSAndroid Build Coastguard Worker the number of bytes in the string, and the second is that many bytes, 1351*cda5da8dSAndroid Build Coastguard Worker which are taken literally as the string content. 1352*cda5da8dSAndroid Build Coastguard Worker """), 1353*cda5da8dSAndroid Build Coastguard Worker 1354*cda5da8dSAndroid Build Coastguard Worker # Bytearray (protocol 5 and higher) 1355*cda5da8dSAndroid Build Coastguard Worker 1356*cda5da8dSAndroid Build Coastguard Worker I(name='BYTEARRAY8', 1357*cda5da8dSAndroid Build Coastguard Worker code='\x96', 1358*cda5da8dSAndroid Build Coastguard Worker arg=bytearray8, 1359*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1360*cda5da8dSAndroid Build Coastguard Worker stack_after=[pybytearray], 1361*cda5da8dSAndroid Build Coastguard Worker proto=5, 1362*cda5da8dSAndroid Build Coastguard Worker doc="""Push a Python bytearray object. 1363*cda5da8dSAndroid Build Coastguard Worker 1364*cda5da8dSAndroid Build Coastguard Worker There are two arguments: the first is an 8-byte unsigned int giving 1365*cda5da8dSAndroid Build Coastguard Worker the number of bytes in the bytearray, and the second is that many bytes, 1366*cda5da8dSAndroid Build Coastguard Worker which are taken literally as the bytearray content. 1367*cda5da8dSAndroid Build Coastguard Worker """), 1368*cda5da8dSAndroid Build Coastguard Worker 1369*cda5da8dSAndroid Build Coastguard Worker # Out-of-band buffer (protocol 5 and higher) 1370*cda5da8dSAndroid Build Coastguard Worker 1371*cda5da8dSAndroid Build Coastguard Worker I(name='NEXT_BUFFER', 1372*cda5da8dSAndroid Build Coastguard Worker code='\x97', 1373*cda5da8dSAndroid Build Coastguard Worker arg=None, 1374*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1375*cda5da8dSAndroid Build Coastguard Worker stack_after=[pybuffer], 1376*cda5da8dSAndroid Build Coastguard Worker proto=5, 1377*cda5da8dSAndroid Build Coastguard Worker doc="Push an out-of-band buffer object."), 1378*cda5da8dSAndroid Build Coastguard Worker 1379*cda5da8dSAndroid Build Coastguard Worker I(name='READONLY_BUFFER', 1380*cda5da8dSAndroid Build Coastguard Worker code='\x98', 1381*cda5da8dSAndroid Build Coastguard Worker arg=None, 1382*cda5da8dSAndroid Build Coastguard Worker stack_before=[pybuffer], 1383*cda5da8dSAndroid Build Coastguard Worker stack_after=[pybuffer], 1384*cda5da8dSAndroid Build Coastguard Worker proto=5, 1385*cda5da8dSAndroid Build Coastguard Worker doc="Make an out-of-band buffer object read-only."), 1386*cda5da8dSAndroid Build Coastguard Worker 1387*cda5da8dSAndroid Build Coastguard Worker # Ways to spell None. 1388*cda5da8dSAndroid Build Coastguard Worker 1389*cda5da8dSAndroid Build Coastguard Worker I(name='NONE', 1390*cda5da8dSAndroid Build Coastguard Worker code='N', 1391*cda5da8dSAndroid Build Coastguard Worker arg=None, 1392*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1393*cda5da8dSAndroid Build Coastguard Worker stack_after=[pynone], 1394*cda5da8dSAndroid Build Coastguard Worker proto=0, 1395*cda5da8dSAndroid Build Coastguard Worker doc="Push None on the stack."), 1396*cda5da8dSAndroid Build Coastguard Worker 1397*cda5da8dSAndroid Build Coastguard Worker # Ways to spell bools, starting with proto 2. See INT for how this was 1398*cda5da8dSAndroid Build Coastguard Worker # done before proto 2. 1399*cda5da8dSAndroid Build Coastguard Worker 1400*cda5da8dSAndroid Build Coastguard Worker I(name='NEWTRUE', 1401*cda5da8dSAndroid Build Coastguard Worker code='\x88', 1402*cda5da8dSAndroid Build Coastguard Worker arg=None, 1403*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1404*cda5da8dSAndroid Build Coastguard Worker stack_after=[pybool], 1405*cda5da8dSAndroid Build Coastguard Worker proto=2, 1406*cda5da8dSAndroid Build Coastguard Worker doc="Push True onto the stack."), 1407*cda5da8dSAndroid Build Coastguard Worker 1408*cda5da8dSAndroid Build Coastguard Worker I(name='NEWFALSE', 1409*cda5da8dSAndroid Build Coastguard Worker code='\x89', 1410*cda5da8dSAndroid Build Coastguard Worker arg=None, 1411*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1412*cda5da8dSAndroid Build Coastguard Worker stack_after=[pybool], 1413*cda5da8dSAndroid Build Coastguard Worker proto=2, 1414*cda5da8dSAndroid Build Coastguard Worker doc="Push False onto the stack."), 1415*cda5da8dSAndroid Build Coastguard Worker 1416*cda5da8dSAndroid Build Coastguard Worker # Ways to spell Unicode strings. 1417*cda5da8dSAndroid Build Coastguard Worker 1418*cda5da8dSAndroid Build Coastguard Worker I(name='UNICODE', 1419*cda5da8dSAndroid Build Coastguard Worker code='V', 1420*cda5da8dSAndroid Build Coastguard Worker arg=unicodestringnl, 1421*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1422*cda5da8dSAndroid Build Coastguard Worker stack_after=[pyunicode], 1423*cda5da8dSAndroid Build Coastguard Worker proto=0, # this may be pure-text, but it's a later addition 1424*cda5da8dSAndroid Build Coastguard Worker doc="""Push a Python Unicode string object. 1425*cda5da8dSAndroid Build Coastguard Worker 1426*cda5da8dSAndroid Build Coastguard Worker The argument is a raw-unicode-escape encoding of a Unicode string, 1427*cda5da8dSAndroid Build Coastguard Worker and so may contain embedded escape sequences. The argument extends 1428*cda5da8dSAndroid Build Coastguard Worker until the next newline character. 1429*cda5da8dSAndroid Build Coastguard Worker """), 1430*cda5da8dSAndroid Build Coastguard Worker 1431*cda5da8dSAndroid Build Coastguard Worker I(name='SHORT_BINUNICODE', 1432*cda5da8dSAndroid Build Coastguard Worker code='\x8c', 1433*cda5da8dSAndroid Build Coastguard Worker arg=unicodestring1, 1434*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1435*cda5da8dSAndroid Build Coastguard Worker stack_after=[pyunicode], 1436*cda5da8dSAndroid Build Coastguard Worker proto=4, 1437*cda5da8dSAndroid Build Coastguard Worker doc="""Push a Python Unicode string object. 1438*cda5da8dSAndroid Build Coastguard Worker 1439*cda5da8dSAndroid Build Coastguard Worker There are two arguments: the first is a 1-byte little-endian signed int 1440*cda5da8dSAndroid Build Coastguard Worker giving the number of bytes in the string. The second is that many 1441*cda5da8dSAndroid Build Coastguard Worker bytes, and is the UTF-8 encoding of the Unicode string. 1442*cda5da8dSAndroid Build Coastguard Worker """), 1443*cda5da8dSAndroid Build Coastguard Worker 1444*cda5da8dSAndroid Build Coastguard Worker I(name='BINUNICODE', 1445*cda5da8dSAndroid Build Coastguard Worker code='X', 1446*cda5da8dSAndroid Build Coastguard Worker arg=unicodestring4, 1447*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1448*cda5da8dSAndroid Build Coastguard Worker stack_after=[pyunicode], 1449*cda5da8dSAndroid Build Coastguard Worker proto=1, 1450*cda5da8dSAndroid Build Coastguard Worker doc="""Push a Python Unicode string object. 1451*cda5da8dSAndroid Build Coastguard Worker 1452*cda5da8dSAndroid Build Coastguard Worker There are two arguments: the first is a 4-byte little-endian unsigned int 1453*cda5da8dSAndroid Build Coastguard Worker giving the number of bytes in the string. The second is that many 1454*cda5da8dSAndroid Build Coastguard Worker bytes, and is the UTF-8 encoding of the Unicode string. 1455*cda5da8dSAndroid Build Coastguard Worker """), 1456*cda5da8dSAndroid Build Coastguard Worker 1457*cda5da8dSAndroid Build Coastguard Worker I(name='BINUNICODE8', 1458*cda5da8dSAndroid Build Coastguard Worker code='\x8d', 1459*cda5da8dSAndroid Build Coastguard Worker arg=unicodestring8, 1460*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1461*cda5da8dSAndroid Build Coastguard Worker stack_after=[pyunicode], 1462*cda5da8dSAndroid Build Coastguard Worker proto=4, 1463*cda5da8dSAndroid Build Coastguard Worker doc="""Push a Python Unicode string object. 1464*cda5da8dSAndroid Build Coastguard Worker 1465*cda5da8dSAndroid Build Coastguard Worker There are two arguments: the first is an 8-byte little-endian signed int 1466*cda5da8dSAndroid Build Coastguard Worker giving the number of bytes in the string. The second is that many 1467*cda5da8dSAndroid Build Coastguard Worker bytes, and is the UTF-8 encoding of the Unicode string. 1468*cda5da8dSAndroid Build Coastguard Worker """), 1469*cda5da8dSAndroid Build Coastguard Worker 1470*cda5da8dSAndroid Build Coastguard Worker # Ways to spell floats. 1471*cda5da8dSAndroid Build Coastguard Worker 1472*cda5da8dSAndroid Build Coastguard Worker I(name='FLOAT', 1473*cda5da8dSAndroid Build Coastguard Worker code='F', 1474*cda5da8dSAndroid Build Coastguard Worker arg=floatnl, 1475*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1476*cda5da8dSAndroid Build Coastguard Worker stack_after=[pyfloat], 1477*cda5da8dSAndroid Build Coastguard Worker proto=0, 1478*cda5da8dSAndroid Build Coastguard Worker doc="""Newline-terminated decimal float literal. 1479*cda5da8dSAndroid Build Coastguard Worker 1480*cda5da8dSAndroid Build Coastguard Worker The argument is repr(a_float), and in general requires 17 significant 1481*cda5da8dSAndroid Build Coastguard Worker digits for roundtrip conversion to be an identity (this is so for 1482*cda5da8dSAndroid Build Coastguard Worker IEEE-754 double precision values, which is what Python float maps to 1483*cda5da8dSAndroid Build Coastguard Worker on most boxes). 1484*cda5da8dSAndroid Build Coastguard Worker 1485*cda5da8dSAndroid Build Coastguard Worker In general, FLOAT cannot be used to transport infinities, NaNs, or 1486*cda5da8dSAndroid Build Coastguard Worker minus zero across boxes (or even on a single box, if the platform C 1487*cda5da8dSAndroid Build Coastguard Worker library can't read the strings it produces for such things -- Windows 1488*cda5da8dSAndroid Build Coastguard Worker is like that), but may do less damage than BINFLOAT on boxes with 1489*cda5da8dSAndroid Build Coastguard Worker greater precision or dynamic range than IEEE-754 double. 1490*cda5da8dSAndroid Build Coastguard Worker """), 1491*cda5da8dSAndroid Build Coastguard Worker 1492*cda5da8dSAndroid Build Coastguard Worker I(name='BINFLOAT', 1493*cda5da8dSAndroid Build Coastguard Worker code='G', 1494*cda5da8dSAndroid Build Coastguard Worker arg=float8, 1495*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1496*cda5da8dSAndroid Build Coastguard Worker stack_after=[pyfloat], 1497*cda5da8dSAndroid Build Coastguard Worker proto=1, 1498*cda5da8dSAndroid Build Coastguard Worker doc="""Float stored in binary form, with 8 bytes of data. 1499*cda5da8dSAndroid Build Coastguard Worker 1500*cda5da8dSAndroid Build Coastguard Worker This generally requires less than half the space of FLOAT encoding. 1501*cda5da8dSAndroid Build Coastguard Worker In general, BINFLOAT cannot be used to transport infinities, NaNs, or 1502*cda5da8dSAndroid Build Coastguard Worker minus zero, raises an exception if the exponent exceeds the range of 1503*cda5da8dSAndroid Build Coastguard Worker an IEEE-754 double, and retains no more than 53 bits of precision (if 1504*cda5da8dSAndroid Build Coastguard Worker there are more than that, "add a half and chop" rounding is used to 1505*cda5da8dSAndroid Build Coastguard Worker cut it back to 53 significant bits). 1506*cda5da8dSAndroid Build Coastguard Worker """), 1507*cda5da8dSAndroid Build Coastguard Worker 1508*cda5da8dSAndroid Build Coastguard Worker # Ways to build lists. 1509*cda5da8dSAndroid Build Coastguard Worker 1510*cda5da8dSAndroid Build Coastguard Worker I(name='EMPTY_LIST', 1511*cda5da8dSAndroid Build Coastguard Worker code=']', 1512*cda5da8dSAndroid Build Coastguard Worker arg=None, 1513*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1514*cda5da8dSAndroid Build Coastguard Worker stack_after=[pylist], 1515*cda5da8dSAndroid Build Coastguard Worker proto=1, 1516*cda5da8dSAndroid Build Coastguard Worker doc="Push an empty list."), 1517*cda5da8dSAndroid Build Coastguard Worker 1518*cda5da8dSAndroid Build Coastguard Worker I(name='APPEND', 1519*cda5da8dSAndroid Build Coastguard Worker code='a', 1520*cda5da8dSAndroid Build Coastguard Worker arg=None, 1521*cda5da8dSAndroid Build Coastguard Worker stack_before=[pylist, anyobject], 1522*cda5da8dSAndroid Build Coastguard Worker stack_after=[pylist], 1523*cda5da8dSAndroid Build Coastguard Worker proto=0, 1524*cda5da8dSAndroid Build Coastguard Worker doc="""Append an object to a list. 1525*cda5da8dSAndroid Build Coastguard Worker 1526*cda5da8dSAndroid Build Coastguard Worker Stack before: ... pylist anyobject 1527*cda5da8dSAndroid Build Coastguard Worker Stack after: ... pylist+[anyobject] 1528*cda5da8dSAndroid Build Coastguard Worker 1529*cda5da8dSAndroid Build Coastguard Worker although pylist is really extended in-place. 1530*cda5da8dSAndroid Build Coastguard Worker """), 1531*cda5da8dSAndroid Build Coastguard Worker 1532*cda5da8dSAndroid Build Coastguard Worker I(name='APPENDS', 1533*cda5da8dSAndroid Build Coastguard Worker code='e', 1534*cda5da8dSAndroid Build Coastguard Worker arg=None, 1535*cda5da8dSAndroid Build Coastguard Worker stack_before=[pylist, markobject, stackslice], 1536*cda5da8dSAndroid Build Coastguard Worker stack_after=[pylist], 1537*cda5da8dSAndroid Build Coastguard Worker proto=1, 1538*cda5da8dSAndroid Build Coastguard Worker doc="""Extend a list by a slice of stack objects. 1539*cda5da8dSAndroid Build Coastguard Worker 1540*cda5da8dSAndroid Build Coastguard Worker Stack before: ... pylist markobject stackslice 1541*cda5da8dSAndroid Build Coastguard Worker Stack after: ... pylist+stackslice 1542*cda5da8dSAndroid Build Coastguard Worker 1543*cda5da8dSAndroid Build Coastguard Worker although pylist is really extended in-place. 1544*cda5da8dSAndroid Build Coastguard Worker """), 1545*cda5da8dSAndroid Build Coastguard Worker 1546*cda5da8dSAndroid Build Coastguard Worker I(name='LIST', 1547*cda5da8dSAndroid Build Coastguard Worker code='l', 1548*cda5da8dSAndroid Build Coastguard Worker arg=None, 1549*cda5da8dSAndroid Build Coastguard Worker stack_before=[markobject, stackslice], 1550*cda5da8dSAndroid Build Coastguard Worker stack_after=[pylist], 1551*cda5da8dSAndroid Build Coastguard Worker proto=0, 1552*cda5da8dSAndroid Build Coastguard Worker doc="""Build a list out of the topmost stack slice, after markobject. 1553*cda5da8dSAndroid Build Coastguard Worker 1554*cda5da8dSAndroid Build Coastguard Worker All the stack entries following the topmost markobject are placed into 1555*cda5da8dSAndroid Build Coastguard Worker a single Python list, which single list object replaces all of the 1556*cda5da8dSAndroid Build Coastguard Worker stack from the topmost markobject onward. For example, 1557*cda5da8dSAndroid Build Coastguard Worker 1558*cda5da8dSAndroid Build Coastguard Worker Stack before: ... markobject 1 2 3 'abc' 1559*cda5da8dSAndroid Build Coastguard Worker Stack after: ... [1, 2, 3, 'abc'] 1560*cda5da8dSAndroid Build Coastguard Worker """), 1561*cda5da8dSAndroid Build Coastguard Worker 1562*cda5da8dSAndroid Build Coastguard Worker # Ways to build tuples. 1563*cda5da8dSAndroid Build Coastguard Worker 1564*cda5da8dSAndroid Build Coastguard Worker I(name='EMPTY_TUPLE', 1565*cda5da8dSAndroid Build Coastguard Worker code=')', 1566*cda5da8dSAndroid Build Coastguard Worker arg=None, 1567*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1568*cda5da8dSAndroid Build Coastguard Worker stack_after=[pytuple], 1569*cda5da8dSAndroid Build Coastguard Worker proto=1, 1570*cda5da8dSAndroid Build Coastguard Worker doc="Push an empty tuple."), 1571*cda5da8dSAndroid Build Coastguard Worker 1572*cda5da8dSAndroid Build Coastguard Worker I(name='TUPLE', 1573*cda5da8dSAndroid Build Coastguard Worker code='t', 1574*cda5da8dSAndroid Build Coastguard Worker arg=None, 1575*cda5da8dSAndroid Build Coastguard Worker stack_before=[markobject, stackslice], 1576*cda5da8dSAndroid Build Coastguard Worker stack_after=[pytuple], 1577*cda5da8dSAndroid Build Coastguard Worker proto=0, 1578*cda5da8dSAndroid Build Coastguard Worker doc="""Build a tuple out of the topmost stack slice, after markobject. 1579*cda5da8dSAndroid Build Coastguard Worker 1580*cda5da8dSAndroid Build Coastguard Worker All the stack entries following the topmost markobject are placed into 1581*cda5da8dSAndroid Build Coastguard Worker a single Python tuple, which single tuple object replaces all of the 1582*cda5da8dSAndroid Build Coastguard Worker stack from the topmost markobject onward. For example, 1583*cda5da8dSAndroid Build Coastguard Worker 1584*cda5da8dSAndroid Build Coastguard Worker Stack before: ... markobject 1 2 3 'abc' 1585*cda5da8dSAndroid Build Coastguard Worker Stack after: ... (1, 2, 3, 'abc') 1586*cda5da8dSAndroid Build Coastguard Worker """), 1587*cda5da8dSAndroid Build Coastguard Worker 1588*cda5da8dSAndroid Build Coastguard Worker I(name='TUPLE1', 1589*cda5da8dSAndroid Build Coastguard Worker code='\x85', 1590*cda5da8dSAndroid Build Coastguard Worker arg=None, 1591*cda5da8dSAndroid Build Coastguard Worker stack_before=[anyobject], 1592*cda5da8dSAndroid Build Coastguard Worker stack_after=[pytuple], 1593*cda5da8dSAndroid Build Coastguard Worker proto=2, 1594*cda5da8dSAndroid Build Coastguard Worker doc="""Build a one-tuple out of the topmost item on the stack. 1595*cda5da8dSAndroid Build Coastguard Worker 1596*cda5da8dSAndroid Build Coastguard Worker This code pops one value off the stack and pushes a tuple of 1597*cda5da8dSAndroid Build Coastguard Worker length 1 whose one item is that value back onto it. In other 1598*cda5da8dSAndroid Build Coastguard Worker words: 1599*cda5da8dSAndroid Build Coastguard Worker 1600*cda5da8dSAndroid Build Coastguard Worker stack[-1] = tuple(stack[-1:]) 1601*cda5da8dSAndroid Build Coastguard Worker """), 1602*cda5da8dSAndroid Build Coastguard Worker 1603*cda5da8dSAndroid Build Coastguard Worker I(name='TUPLE2', 1604*cda5da8dSAndroid Build Coastguard Worker code='\x86', 1605*cda5da8dSAndroid Build Coastguard Worker arg=None, 1606*cda5da8dSAndroid Build Coastguard Worker stack_before=[anyobject, anyobject], 1607*cda5da8dSAndroid Build Coastguard Worker stack_after=[pytuple], 1608*cda5da8dSAndroid Build Coastguard Worker proto=2, 1609*cda5da8dSAndroid Build Coastguard Worker doc="""Build a two-tuple out of the top two items on the stack. 1610*cda5da8dSAndroid Build Coastguard Worker 1611*cda5da8dSAndroid Build Coastguard Worker This code pops two values off the stack and pushes a tuple of 1612*cda5da8dSAndroid Build Coastguard Worker length 2 whose items are those values back onto it. In other 1613*cda5da8dSAndroid Build Coastguard Worker words: 1614*cda5da8dSAndroid Build Coastguard Worker 1615*cda5da8dSAndroid Build Coastguard Worker stack[-2:] = [tuple(stack[-2:])] 1616*cda5da8dSAndroid Build Coastguard Worker """), 1617*cda5da8dSAndroid Build Coastguard Worker 1618*cda5da8dSAndroid Build Coastguard Worker I(name='TUPLE3', 1619*cda5da8dSAndroid Build Coastguard Worker code='\x87', 1620*cda5da8dSAndroid Build Coastguard Worker arg=None, 1621*cda5da8dSAndroid Build Coastguard Worker stack_before=[anyobject, anyobject, anyobject], 1622*cda5da8dSAndroid Build Coastguard Worker stack_after=[pytuple], 1623*cda5da8dSAndroid Build Coastguard Worker proto=2, 1624*cda5da8dSAndroid Build Coastguard Worker doc="""Build a three-tuple out of the top three items on the stack. 1625*cda5da8dSAndroid Build Coastguard Worker 1626*cda5da8dSAndroid Build Coastguard Worker This code pops three values off the stack and pushes a tuple of 1627*cda5da8dSAndroid Build Coastguard Worker length 3 whose items are those values back onto it. In other 1628*cda5da8dSAndroid Build Coastguard Worker words: 1629*cda5da8dSAndroid Build Coastguard Worker 1630*cda5da8dSAndroid Build Coastguard Worker stack[-3:] = [tuple(stack[-3:])] 1631*cda5da8dSAndroid Build Coastguard Worker """), 1632*cda5da8dSAndroid Build Coastguard Worker 1633*cda5da8dSAndroid Build Coastguard Worker # Ways to build dicts. 1634*cda5da8dSAndroid Build Coastguard Worker 1635*cda5da8dSAndroid Build Coastguard Worker I(name='EMPTY_DICT', 1636*cda5da8dSAndroid Build Coastguard Worker code='}', 1637*cda5da8dSAndroid Build Coastguard Worker arg=None, 1638*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1639*cda5da8dSAndroid Build Coastguard Worker stack_after=[pydict], 1640*cda5da8dSAndroid Build Coastguard Worker proto=1, 1641*cda5da8dSAndroid Build Coastguard Worker doc="Push an empty dict."), 1642*cda5da8dSAndroid Build Coastguard Worker 1643*cda5da8dSAndroid Build Coastguard Worker I(name='DICT', 1644*cda5da8dSAndroid Build Coastguard Worker code='d', 1645*cda5da8dSAndroid Build Coastguard Worker arg=None, 1646*cda5da8dSAndroid Build Coastguard Worker stack_before=[markobject, stackslice], 1647*cda5da8dSAndroid Build Coastguard Worker stack_after=[pydict], 1648*cda5da8dSAndroid Build Coastguard Worker proto=0, 1649*cda5da8dSAndroid Build Coastguard Worker doc="""Build a dict out of the topmost stack slice, after markobject. 1650*cda5da8dSAndroid Build Coastguard Worker 1651*cda5da8dSAndroid Build Coastguard Worker All the stack entries following the topmost markobject are placed into 1652*cda5da8dSAndroid Build Coastguard Worker a single Python dict, which single dict object replaces all of the 1653*cda5da8dSAndroid Build Coastguard Worker stack from the topmost markobject onward. The stack slice alternates 1654*cda5da8dSAndroid Build Coastguard Worker key, value, key, value, .... For example, 1655*cda5da8dSAndroid Build Coastguard Worker 1656*cda5da8dSAndroid Build Coastguard Worker Stack before: ... markobject 1 2 3 'abc' 1657*cda5da8dSAndroid Build Coastguard Worker Stack after: ... {1: 2, 3: 'abc'} 1658*cda5da8dSAndroid Build Coastguard Worker """), 1659*cda5da8dSAndroid Build Coastguard Worker 1660*cda5da8dSAndroid Build Coastguard Worker I(name='SETITEM', 1661*cda5da8dSAndroid Build Coastguard Worker code='s', 1662*cda5da8dSAndroid Build Coastguard Worker arg=None, 1663*cda5da8dSAndroid Build Coastguard Worker stack_before=[pydict, anyobject, anyobject], 1664*cda5da8dSAndroid Build Coastguard Worker stack_after=[pydict], 1665*cda5da8dSAndroid Build Coastguard Worker proto=0, 1666*cda5da8dSAndroid Build Coastguard Worker doc="""Add a key+value pair to an existing dict. 1667*cda5da8dSAndroid Build Coastguard Worker 1668*cda5da8dSAndroid Build Coastguard Worker Stack before: ... pydict key value 1669*cda5da8dSAndroid Build Coastguard Worker Stack after: ... pydict 1670*cda5da8dSAndroid Build Coastguard Worker 1671*cda5da8dSAndroid Build Coastguard Worker where pydict has been modified via pydict[key] = value. 1672*cda5da8dSAndroid Build Coastguard Worker """), 1673*cda5da8dSAndroid Build Coastguard Worker 1674*cda5da8dSAndroid Build Coastguard Worker I(name='SETITEMS', 1675*cda5da8dSAndroid Build Coastguard Worker code='u', 1676*cda5da8dSAndroid Build Coastguard Worker arg=None, 1677*cda5da8dSAndroid Build Coastguard Worker stack_before=[pydict, markobject, stackslice], 1678*cda5da8dSAndroid Build Coastguard Worker stack_after=[pydict], 1679*cda5da8dSAndroid Build Coastguard Worker proto=1, 1680*cda5da8dSAndroid Build Coastguard Worker doc="""Add an arbitrary number of key+value pairs to an existing dict. 1681*cda5da8dSAndroid Build Coastguard Worker 1682*cda5da8dSAndroid Build Coastguard Worker The slice of the stack following the topmost markobject is taken as 1683*cda5da8dSAndroid Build Coastguard Worker an alternating sequence of keys and values, added to the dict 1684*cda5da8dSAndroid Build Coastguard Worker immediately under the topmost markobject. Everything at and after the 1685*cda5da8dSAndroid Build Coastguard Worker topmost markobject is popped, leaving the mutated dict at the top 1686*cda5da8dSAndroid Build Coastguard Worker of the stack. 1687*cda5da8dSAndroid Build Coastguard Worker 1688*cda5da8dSAndroid Build Coastguard Worker Stack before: ... pydict markobject key_1 value_1 ... key_n value_n 1689*cda5da8dSAndroid Build Coastguard Worker Stack after: ... pydict 1690*cda5da8dSAndroid Build Coastguard Worker 1691*cda5da8dSAndroid Build Coastguard Worker where pydict has been modified via pydict[key_i] = value_i for i in 1692*cda5da8dSAndroid Build Coastguard Worker 1, 2, ..., n, and in that order. 1693*cda5da8dSAndroid Build Coastguard Worker """), 1694*cda5da8dSAndroid Build Coastguard Worker 1695*cda5da8dSAndroid Build Coastguard Worker # Ways to build sets 1696*cda5da8dSAndroid Build Coastguard Worker 1697*cda5da8dSAndroid Build Coastguard Worker I(name='EMPTY_SET', 1698*cda5da8dSAndroid Build Coastguard Worker code='\x8f', 1699*cda5da8dSAndroid Build Coastguard Worker arg=None, 1700*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1701*cda5da8dSAndroid Build Coastguard Worker stack_after=[pyset], 1702*cda5da8dSAndroid Build Coastguard Worker proto=4, 1703*cda5da8dSAndroid Build Coastguard Worker doc="Push an empty set."), 1704*cda5da8dSAndroid Build Coastguard Worker 1705*cda5da8dSAndroid Build Coastguard Worker I(name='ADDITEMS', 1706*cda5da8dSAndroid Build Coastguard Worker code='\x90', 1707*cda5da8dSAndroid Build Coastguard Worker arg=None, 1708*cda5da8dSAndroid Build Coastguard Worker stack_before=[pyset, markobject, stackslice], 1709*cda5da8dSAndroid Build Coastguard Worker stack_after=[pyset], 1710*cda5da8dSAndroid Build Coastguard Worker proto=4, 1711*cda5da8dSAndroid Build Coastguard Worker doc="""Add an arbitrary number of items to an existing set. 1712*cda5da8dSAndroid Build Coastguard Worker 1713*cda5da8dSAndroid Build Coastguard Worker The slice of the stack following the topmost markobject is taken as 1714*cda5da8dSAndroid Build Coastguard Worker a sequence of items, added to the set immediately under the topmost 1715*cda5da8dSAndroid Build Coastguard Worker markobject. Everything at and after the topmost markobject is popped, 1716*cda5da8dSAndroid Build Coastguard Worker leaving the mutated set at the top of the stack. 1717*cda5da8dSAndroid Build Coastguard Worker 1718*cda5da8dSAndroid Build Coastguard Worker Stack before: ... pyset markobject item_1 ... item_n 1719*cda5da8dSAndroid Build Coastguard Worker Stack after: ... pyset 1720*cda5da8dSAndroid Build Coastguard Worker 1721*cda5da8dSAndroid Build Coastguard Worker where pyset has been modified via pyset.add(item_i) = item_i for i in 1722*cda5da8dSAndroid Build Coastguard Worker 1, 2, ..., n, and in that order. 1723*cda5da8dSAndroid Build Coastguard Worker """), 1724*cda5da8dSAndroid Build Coastguard Worker 1725*cda5da8dSAndroid Build Coastguard Worker # Way to build frozensets 1726*cda5da8dSAndroid Build Coastguard Worker 1727*cda5da8dSAndroid Build Coastguard Worker I(name='FROZENSET', 1728*cda5da8dSAndroid Build Coastguard Worker code='\x91', 1729*cda5da8dSAndroid Build Coastguard Worker arg=None, 1730*cda5da8dSAndroid Build Coastguard Worker stack_before=[markobject, stackslice], 1731*cda5da8dSAndroid Build Coastguard Worker stack_after=[pyfrozenset], 1732*cda5da8dSAndroid Build Coastguard Worker proto=4, 1733*cda5da8dSAndroid Build Coastguard Worker doc="""Build a frozenset out of the topmost slice, after markobject. 1734*cda5da8dSAndroid Build Coastguard Worker 1735*cda5da8dSAndroid Build Coastguard Worker All the stack entries following the topmost markobject are placed into 1736*cda5da8dSAndroid Build Coastguard Worker a single Python frozenset, which single frozenset object replaces all 1737*cda5da8dSAndroid Build Coastguard Worker of the stack from the topmost markobject onward. For example, 1738*cda5da8dSAndroid Build Coastguard Worker 1739*cda5da8dSAndroid Build Coastguard Worker Stack before: ... markobject 1 2 3 1740*cda5da8dSAndroid Build Coastguard Worker Stack after: ... frozenset({1, 2, 3}) 1741*cda5da8dSAndroid Build Coastguard Worker """), 1742*cda5da8dSAndroid Build Coastguard Worker 1743*cda5da8dSAndroid Build Coastguard Worker # Stack manipulation. 1744*cda5da8dSAndroid Build Coastguard Worker 1745*cda5da8dSAndroid Build Coastguard Worker I(name='POP', 1746*cda5da8dSAndroid Build Coastguard Worker code='0', 1747*cda5da8dSAndroid Build Coastguard Worker arg=None, 1748*cda5da8dSAndroid Build Coastguard Worker stack_before=[anyobject], 1749*cda5da8dSAndroid Build Coastguard Worker stack_after=[], 1750*cda5da8dSAndroid Build Coastguard Worker proto=0, 1751*cda5da8dSAndroid Build Coastguard Worker doc="Discard the top stack item, shrinking the stack by one item."), 1752*cda5da8dSAndroid Build Coastguard Worker 1753*cda5da8dSAndroid Build Coastguard Worker I(name='DUP', 1754*cda5da8dSAndroid Build Coastguard Worker code='2', 1755*cda5da8dSAndroid Build Coastguard Worker arg=None, 1756*cda5da8dSAndroid Build Coastguard Worker stack_before=[anyobject], 1757*cda5da8dSAndroid Build Coastguard Worker stack_after=[anyobject, anyobject], 1758*cda5da8dSAndroid Build Coastguard Worker proto=0, 1759*cda5da8dSAndroid Build Coastguard Worker doc="Push the top stack item onto the stack again, duplicating it."), 1760*cda5da8dSAndroid Build Coastguard Worker 1761*cda5da8dSAndroid Build Coastguard Worker I(name='MARK', 1762*cda5da8dSAndroid Build Coastguard Worker code='(', 1763*cda5da8dSAndroid Build Coastguard Worker arg=None, 1764*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1765*cda5da8dSAndroid Build Coastguard Worker stack_after=[markobject], 1766*cda5da8dSAndroid Build Coastguard Worker proto=0, 1767*cda5da8dSAndroid Build Coastguard Worker doc="""Push markobject onto the stack. 1768*cda5da8dSAndroid Build Coastguard Worker 1769*cda5da8dSAndroid Build Coastguard Worker markobject is a unique object, used by other opcodes to identify a 1770*cda5da8dSAndroid Build Coastguard Worker region of the stack containing a variable number of objects for them 1771*cda5da8dSAndroid Build Coastguard Worker to work on. See markobject.doc for more detail. 1772*cda5da8dSAndroid Build Coastguard Worker """), 1773*cda5da8dSAndroid Build Coastguard Worker 1774*cda5da8dSAndroid Build Coastguard Worker I(name='POP_MARK', 1775*cda5da8dSAndroid Build Coastguard Worker code='1', 1776*cda5da8dSAndroid Build Coastguard Worker arg=None, 1777*cda5da8dSAndroid Build Coastguard Worker stack_before=[markobject, stackslice], 1778*cda5da8dSAndroid Build Coastguard Worker stack_after=[], 1779*cda5da8dSAndroid Build Coastguard Worker proto=1, 1780*cda5da8dSAndroid Build Coastguard Worker doc="""Pop all the stack objects at and above the topmost markobject. 1781*cda5da8dSAndroid Build Coastguard Worker 1782*cda5da8dSAndroid Build Coastguard Worker When an opcode using a variable number of stack objects is done, 1783*cda5da8dSAndroid Build Coastguard Worker POP_MARK is used to remove those objects, and to remove the markobject 1784*cda5da8dSAndroid Build Coastguard Worker that delimited their starting position on the stack. 1785*cda5da8dSAndroid Build Coastguard Worker """), 1786*cda5da8dSAndroid Build Coastguard Worker 1787*cda5da8dSAndroid Build Coastguard Worker # Memo manipulation. There are really only two operations (get and put), 1788*cda5da8dSAndroid Build Coastguard Worker # each in all-text, "short binary", and "long binary" flavors. 1789*cda5da8dSAndroid Build Coastguard Worker 1790*cda5da8dSAndroid Build Coastguard Worker I(name='GET', 1791*cda5da8dSAndroid Build Coastguard Worker code='g', 1792*cda5da8dSAndroid Build Coastguard Worker arg=decimalnl_short, 1793*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1794*cda5da8dSAndroid Build Coastguard Worker stack_after=[anyobject], 1795*cda5da8dSAndroid Build Coastguard Worker proto=0, 1796*cda5da8dSAndroid Build Coastguard Worker doc="""Read an object from the memo and push it on the stack. 1797*cda5da8dSAndroid Build Coastguard Worker 1798*cda5da8dSAndroid Build Coastguard Worker The index of the memo object to push is given by the newline-terminated 1799*cda5da8dSAndroid Build Coastguard Worker decimal string following. BINGET and LONG_BINGET are space-optimized 1800*cda5da8dSAndroid Build Coastguard Worker versions. 1801*cda5da8dSAndroid Build Coastguard Worker """), 1802*cda5da8dSAndroid Build Coastguard Worker 1803*cda5da8dSAndroid Build Coastguard Worker I(name='BINGET', 1804*cda5da8dSAndroid Build Coastguard Worker code='h', 1805*cda5da8dSAndroid Build Coastguard Worker arg=uint1, 1806*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1807*cda5da8dSAndroid Build Coastguard Worker stack_after=[anyobject], 1808*cda5da8dSAndroid Build Coastguard Worker proto=1, 1809*cda5da8dSAndroid Build Coastguard Worker doc="""Read an object from the memo and push it on the stack. 1810*cda5da8dSAndroid Build Coastguard Worker 1811*cda5da8dSAndroid Build Coastguard Worker The index of the memo object to push is given by the 1-byte unsigned 1812*cda5da8dSAndroid Build Coastguard Worker integer following. 1813*cda5da8dSAndroid Build Coastguard Worker """), 1814*cda5da8dSAndroid Build Coastguard Worker 1815*cda5da8dSAndroid Build Coastguard Worker I(name='LONG_BINGET', 1816*cda5da8dSAndroid Build Coastguard Worker code='j', 1817*cda5da8dSAndroid Build Coastguard Worker arg=uint4, 1818*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1819*cda5da8dSAndroid Build Coastguard Worker stack_after=[anyobject], 1820*cda5da8dSAndroid Build Coastguard Worker proto=1, 1821*cda5da8dSAndroid Build Coastguard Worker doc="""Read an object from the memo and push it on the stack. 1822*cda5da8dSAndroid Build Coastguard Worker 1823*cda5da8dSAndroid Build Coastguard Worker The index of the memo object to push is given by the 4-byte unsigned 1824*cda5da8dSAndroid Build Coastguard Worker little-endian integer following. 1825*cda5da8dSAndroid Build Coastguard Worker """), 1826*cda5da8dSAndroid Build Coastguard Worker 1827*cda5da8dSAndroid Build Coastguard Worker I(name='PUT', 1828*cda5da8dSAndroid Build Coastguard Worker code='p', 1829*cda5da8dSAndroid Build Coastguard Worker arg=decimalnl_short, 1830*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1831*cda5da8dSAndroid Build Coastguard Worker stack_after=[], 1832*cda5da8dSAndroid Build Coastguard Worker proto=0, 1833*cda5da8dSAndroid Build Coastguard Worker doc="""Store the stack top into the memo. The stack is not popped. 1834*cda5da8dSAndroid Build Coastguard Worker 1835*cda5da8dSAndroid Build Coastguard Worker The index of the memo location to write into is given by the newline- 1836*cda5da8dSAndroid Build Coastguard Worker terminated decimal string following. BINPUT and LONG_BINPUT are 1837*cda5da8dSAndroid Build Coastguard Worker space-optimized versions. 1838*cda5da8dSAndroid Build Coastguard Worker """), 1839*cda5da8dSAndroid Build Coastguard Worker 1840*cda5da8dSAndroid Build Coastguard Worker I(name='BINPUT', 1841*cda5da8dSAndroid Build Coastguard Worker code='q', 1842*cda5da8dSAndroid Build Coastguard Worker arg=uint1, 1843*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1844*cda5da8dSAndroid Build Coastguard Worker stack_after=[], 1845*cda5da8dSAndroid Build Coastguard Worker proto=1, 1846*cda5da8dSAndroid Build Coastguard Worker doc="""Store the stack top into the memo. The stack is not popped. 1847*cda5da8dSAndroid Build Coastguard Worker 1848*cda5da8dSAndroid Build Coastguard Worker The index of the memo location to write into is given by the 1-byte 1849*cda5da8dSAndroid Build Coastguard Worker unsigned integer following. 1850*cda5da8dSAndroid Build Coastguard Worker """), 1851*cda5da8dSAndroid Build Coastguard Worker 1852*cda5da8dSAndroid Build Coastguard Worker I(name='LONG_BINPUT', 1853*cda5da8dSAndroid Build Coastguard Worker code='r', 1854*cda5da8dSAndroid Build Coastguard Worker arg=uint4, 1855*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1856*cda5da8dSAndroid Build Coastguard Worker stack_after=[], 1857*cda5da8dSAndroid Build Coastguard Worker proto=1, 1858*cda5da8dSAndroid Build Coastguard Worker doc="""Store the stack top into the memo. The stack is not popped. 1859*cda5da8dSAndroid Build Coastguard Worker 1860*cda5da8dSAndroid Build Coastguard Worker The index of the memo location to write into is given by the 4-byte 1861*cda5da8dSAndroid Build Coastguard Worker unsigned little-endian integer following. 1862*cda5da8dSAndroid Build Coastguard Worker """), 1863*cda5da8dSAndroid Build Coastguard Worker 1864*cda5da8dSAndroid Build Coastguard Worker I(name='MEMOIZE', 1865*cda5da8dSAndroid Build Coastguard Worker code='\x94', 1866*cda5da8dSAndroid Build Coastguard Worker arg=None, 1867*cda5da8dSAndroid Build Coastguard Worker stack_before=[anyobject], 1868*cda5da8dSAndroid Build Coastguard Worker stack_after=[anyobject], 1869*cda5da8dSAndroid Build Coastguard Worker proto=4, 1870*cda5da8dSAndroid Build Coastguard Worker doc="""Store the stack top into the memo. The stack is not popped. 1871*cda5da8dSAndroid Build Coastguard Worker 1872*cda5da8dSAndroid Build Coastguard Worker The index of the memo location to write is the number of 1873*cda5da8dSAndroid Build Coastguard Worker elements currently present in the memo. 1874*cda5da8dSAndroid Build Coastguard Worker """), 1875*cda5da8dSAndroid Build Coastguard Worker 1876*cda5da8dSAndroid Build Coastguard Worker # Access the extension registry (predefined objects). Akin to the GET 1877*cda5da8dSAndroid Build Coastguard Worker # family. 1878*cda5da8dSAndroid Build Coastguard Worker 1879*cda5da8dSAndroid Build Coastguard Worker I(name='EXT1', 1880*cda5da8dSAndroid Build Coastguard Worker code='\x82', 1881*cda5da8dSAndroid Build Coastguard Worker arg=uint1, 1882*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1883*cda5da8dSAndroid Build Coastguard Worker stack_after=[anyobject], 1884*cda5da8dSAndroid Build Coastguard Worker proto=2, 1885*cda5da8dSAndroid Build Coastguard Worker doc="""Extension code. 1886*cda5da8dSAndroid Build Coastguard Worker 1887*cda5da8dSAndroid Build Coastguard Worker This code and the similar EXT2 and EXT4 allow using a registry 1888*cda5da8dSAndroid Build Coastguard Worker of popular objects that are pickled by name, typically classes. 1889*cda5da8dSAndroid Build Coastguard Worker It is envisioned that through a global negotiation and 1890*cda5da8dSAndroid Build Coastguard Worker registration process, third parties can set up a mapping between 1891*cda5da8dSAndroid Build Coastguard Worker ints and object names. 1892*cda5da8dSAndroid Build Coastguard Worker 1893*cda5da8dSAndroid Build Coastguard Worker In order to guarantee pickle interchangeability, the extension 1894*cda5da8dSAndroid Build Coastguard Worker code registry ought to be global, although a range of codes may 1895*cda5da8dSAndroid Build Coastguard Worker be reserved for private use. 1896*cda5da8dSAndroid Build Coastguard Worker 1897*cda5da8dSAndroid Build Coastguard Worker EXT1 has a 1-byte integer argument. This is used to index into the 1898*cda5da8dSAndroid Build Coastguard Worker extension registry, and the object at that index is pushed on the stack. 1899*cda5da8dSAndroid Build Coastguard Worker """), 1900*cda5da8dSAndroid Build Coastguard Worker 1901*cda5da8dSAndroid Build Coastguard Worker I(name='EXT2', 1902*cda5da8dSAndroid Build Coastguard Worker code='\x83', 1903*cda5da8dSAndroid Build Coastguard Worker arg=uint2, 1904*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1905*cda5da8dSAndroid Build Coastguard Worker stack_after=[anyobject], 1906*cda5da8dSAndroid Build Coastguard Worker proto=2, 1907*cda5da8dSAndroid Build Coastguard Worker doc="""Extension code. 1908*cda5da8dSAndroid Build Coastguard Worker 1909*cda5da8dSAndroid Build Coastguard Worker See EXT1. EXT2 has a two-byte integer argument. 1910*cda5da8dSAndroid Build Coastguard Worker """), 1911*cda5da8dSAndroid Build Coastguard Worker 1912*cda5da8dSAndroid Build Coastguard Worker I(name='EXT4', 1913*cda5da8dSAndroid Build Coastguard Worker code='\x84', 1914*cda5da8dSAndroid Build Coastguard Worker arg=int4, 1915*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1916*cda5da8dSAndroid Build Coastguard Worker stack_after=[anyobject], 1917*cda5da8dSAndroid Build Coastguard Worker proto=2, 1918*cda5da8dSAndroid Build Coastguard Worker doc="""Extension code. 1919*cda5da8dSAndroid Build Coastguard Worker 1920*cda5da8dSAndroid Build Coastguard Worker See EXT1. EXT4 has a four-byte integer argument. 1921*cda5da8dSAndroid Build Coastguard Worker """), 1922*cda5da8dSAndroid Build Coastguard Worker 1923*cda5da8dSAndroid Build Coastguard Worker # Push a class object, or module function, on the stack, via its module 1924*cda5da8dSAndroid Build Coastguard Worker # and name. 1925*cda5da8dSAndroid Build Coastguard Worker 1926*cda5da8dSAndroid Build Coastguard Worker I(name='GLOBAL', 1927*cda5da8dSAndroid Build Coastguard Worker code='c', 1928*cda5da8dSAndroid Build Coastguard Worker arg=stringnl_noescape_pair, 1929*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 1930*cda5da8dSAndroid Build Coastguard Worker stack_after=[anyobject], 1931*cda5da8dSAndroid Build Coastguard Worker proto=0, 1932*cda5da8dSAndroid Build Coastguard Worker doc="""Push a global object (module.attr) on the stack. 1933*cda5da8dSAndroid Build Coastguard Worker 1934*cda5da8dSAndroid Build Coastguard Worker Two newline-terminated strings follow the GLOBAL opcode. The first is 1935*cda5da8dSAndroid Build Coastguard Worker taken as a module name, and the second as a class name. The class 1936*cda5da8dSAndroid Build Coastguard Worker object module.class is pushed on the stack. More accurately, the 1937*cda5da8dSAndroid Build Coastguard Worker object returned by self.find_class(module, class) is pushed on the 1938*cda5da8dSAndroid Build Coastguard Worker stack, so unpickling subclasses can override this form of lookup. 1939*cda5da8dSAndroid Build Coastguard Worker """), 1940*cda5da8dSAndroid Build Coastguard Worker 1941*cda5da8dSAndroid Build Coastguard Worker I(name='STACK_GLOBAL', 1942*cda5da8dSAndroid Build Coastguard Worker code='\x93', 1943*cda5da8dSAndroid Build Coastguard Worker arg=None, 1944*cda5da8dSAndroid Build Coastguard Worker stack_before=[pyunicode, pyunicode], 1945*cda5da8dSAndroid Build Coastguard Worker stack_after=[anyobject], 1946*cda5da8dSAndroid Build Coastguard Worker proto=4, 1947*cda5da8dSAndroid Build Coastguard Worker doc="""Push a global object (module.attr) on the stack. 1948*cda5da8dSAndroid Build Coastguard Worker """), 1949*cda5da8dSAndroid Build Coastguard Worker 1950*cda5da8dSAndroid Build Coastguard Worker # Ways to build objects of classes pickle doesn't know about directly 1951*cda5da8dSAndroid Build Coastguard Worker # (user-defined classes). I despair of documenting this accurately 1952*cda5da8dSAndroid Build Coastguard Worker # and comprehensibly -- you really have to read the pickle code to 1953*cda5da8dSAndroid Build Coastguard Worker # find all the special cases. 1954*cda5da8dSAndroid Build Coastguard Worker 1955*cda5da8dSAndroid Build Coastguard Worker I(name='REDUCE', 1956*cda5da8dSAndroid Build Coastguard Worker code='R', 1957*cda5da8dSAndroid Build Coastguard Worker arg=None, 1958*cda5da8dSAndroid Build Coastguard Worker stack_before=[anyobject, anyobject], 1959*cda5da8dSAndroid Build Coastguard Worker stack_after=[anyobject], 1960*cda5da8dSAndroid Build Coastguard Worker proto=0, 1961*cda5da8dSAndroid Build Coastguard Worker doc="""Push an object built from a callable and an argument tuple. 1962*cda5da8dSAndroid Build Coastguard Worker 1963*cda5da8dSAndroid Build Coastguard Worker The opcode is named to remind of the __reduce__() method. 1964*cda5da8dSAndroid Build Coastguard Worker 1965*cda5da8dSAndroid Build Coastguard Worker Stack before: ... callable pytuple 1966*cda5da8dSAndroid Build Coastguard Worker Stack after: ... callable(*pytuple) 1967*cda5da8dSAndroid Build Coastguard Worker 1968*cda5da8dSAndroid Build Coastguard Worker The callable and the argument tuple are the first two items returned 1969*cda5da8dSAndroid Build Coastguard Worker by a __reduce__ method. Applying the callable to the argtuple is 1970*cda5da8dSAndroid Build Coastguard Worker supposed to reproduce the original object, or at least get it started. 1971*cda5da8dSAndroid Build Coastguard Worker If the __reduce__ method returns a 3-tuple, the last component is an 1972*cda5da8dSAndroid Build Coastguard Worker argument to be passed to the object's __setstate__, and then the REDUCE 1973*cda5da8dSAndroid Build Coastguard Worker opcode is followed by code to create setstate's argument, and then a 1974*cda5da8dSAndroid Build Coastguard Worker BUILD opcode to apply __setstate__ to that argument. 1975*cda5da8dSAndroid Build Coastguard Worker 1976*cda5da8dSAndroid Build Coastguard Worker If not isinstance(callable, type), REDUCE complains unless the 1977*cda5da8dSAndroid Build Coastguard Worker callable has been registered with the copyreg module's 1978*cda5da8dSAndroid Build Coastguard Worker safe_constructors dict, or the callable has a magic 1979*cda5da8dSAndroid Build Coastguard Worker '__safe_for_unpickling__' attribute with a true value. I'm not sure 1980*cda5da8dSAndroid Build Coastguard Worker why it does this, but I've sure seen this complaint often enough when 1981*cda5da8dSAndroid Build Coastguard Worker I didn't want to <wink>. 1982*cda5da8dSAndroid Build Coastguard Worker """), 1983*cda5da8dSAndroid Build Coastguard Worker 1984*cda5da8dSAndroid Build Coastguard Worker I(name='BUILD', 1985*cda5da8dSAndroid Build Coastguard Worker code='b', 1986*cda5da8dSAndroid Build Coastguard Worker arg=None, 1987*cda5da8dSAndroid Build Coastguard Worker stack_before=[anyobject, anyobject], 1988*cda5da8dSAndroid Build Coastguard Worker stack_after=[anyobject], 1989*cda5da8dSAndroid Build Coastguard Worker proto=0, 1990*cda5da8dSAndroid Build Coastguard Worker doc="""Finish building an object, via __setstate__ or dict update. 1991*cda5da8dSAndroid Build Coastguard Worker 1992*cda5da8dSAndroid Build Coastguard Worker Stack before: ... anyobject argument 1993*cda5da8dSAndroid Build Coastguard Worker Stack after: ... anyobject 1994*cda5da8dSAndroid Build Coastguard Worker 1995*cda5da8dSAndroid Build Coastguard Worker where anyobject may have been mutated, as follows: 1996*cda5da8dSAndroid Build Coastguard Worker 1997*cda5da8dSAndroid Build Coastguard Worker If the object has a __setstate__ method, 1998*cda5da8dSAndroid Build Coastguard Worker 1999*cda5da8dSAndroid Build Coastguard Worker anyobject.__setstate__(argument) 2000*cda5da8dSAndroid Build Coastguard Worker 2001*cda5da8dSAndroid Build Coastguard Worker is called. 2002*cda5da8dSAndroid Build Coastguard Worker 2003*cda5da8dSAndroid Build Coastguard Worker Else the argument must be a dict, the object must have a __dict__, and 2004*cda5da8dSAndroid Build Coastguard Worker the object is updated via 2005*cda5da8dSAndroid Build Coastguard Worker 2006*cda5da8dSAndroid Build Coastguard Worker anyobject.__dict__.update(argument) 2007*cda5da8dSAndroid Build Coastguard Worker """), 2008*cda5da8dSAndroid Build Coastguard Worker 2009*cda5da8dSAndroid Build Coastguard Worker I(name='INST', 2010*cda5da8dSAndroid Build Coastguard Worker code='i', 2011*cda5da8dSAndroid Build Coastguard Worker arg=stringnl_noescape_pair, 2012*cda5da8dSAndroid Build Coastguard Worker stack_before=[markobject, stackslice], 2013*cda5da8dSAndroid Build Coastguard Worker stack_after=[anyobject], 2014*cda5da8dSAndroid Build Coastguard Worker proto=0, 2015*cda5da8dSAndroid Build Coastguard Worker doc="""Build a class instance. 2016*cda5da8dSAndroid Build Coastguard Worker 2017*cda5da8dSAndroid Build Coastguard Worker This is the protocol 0 version of protocol 1's OBJ opcode. 2018*cda5da8dSAndroid Build Coastguard Worker INST is followed by two newline-terminated strings, giving a 2019*cda5da8dSAndroid Build Coastguard Worker module and class name, just as for the GLOBAL opcode (and see 2020*cda5da8dSAndroid Build Coastguard Worker GLOBAL for more details about that). self.find_class(module, name) 2021*cda5da8dSAndroid Build Coastguard Worker is used to get a class object. 2022*cda5da8dSAndroid Build Coastguard Worker 2023*cda5da8dSAndroid Build Coastguard Worker In addition, all the objects on the stack following the topmost 2024*cda5da8dSAndroid Build Coastguard Worker markobject are gathered into a tuple and popped (along with the 2025*cda5da8dSAndroid Build Coastguard Worker topmost markobject), just as for the TUPLE opcode. 2026*cda5da8dSAndroid Build Coastguard Worker 2027*cda5da8dSAndroid Build Coastguard Worker Now it gets complicated. If all of these are true: 2028*cda5da8dSAndroid Build Coastguard Worker 2029*cda5da8dSAndroid Build Coastguard Worker + The argtuple is empty (markobject was at the top of the stack 2030*cda5da8dSAndroid Build Coastguard Worker at the start). 2031*cda5da8dSAndroid Build Coastguard Worker 2032*cda5da8dSAndroid Build Coastguard Worker + The class object does not have a __getinitargs__ attribute. 2033*cda5da8dSAndroid Build Coastguard Worker 2034*cda5da8dSAndroid Build Coastguard Worker then we want to create an old-style class instance without invoking 2035*cda5da8dSAndroid Build Coastguard Worker its __init__() method (pickle has waffled on this over the years; not 2036*cda5da8dSAndroid Build Coastguard Worker calling __init__() is current wisdom). In this case, an instance of 2037*cda5da8dSAndroid Build Coastguard Worker an old-style dummy class is created, and then we try to rebind its 2038*cda5da8dSAndroid Build Coastguard Worker __class__ attribute to the desired class object. If this succeeds, 2039*cda5da8dSAndroid Build Coastguard Worker the new instance object is pushed on the stack, and we're done. 2040*cda5da8dSAndroid Build Coastguard Worker 2041*cda5da8dSAndroid Build Coastguard Worker Else (the argtuple is not empty, it's not an old-style class object, 2042*cda5da8dSAndroid Build Coastguard Worker or the class object does have a __getinitargs__ attribute), the code 2043*cda5da8dSAndroid Build Coastguard Worker first insists that the class object have a __safe_for_unpickling__ 2044*cda5da8dSAndroid Build Coastguard Worker attribute. Unlike as for the __safe_for_unpickling__ check in REDUCE, 2045*cda5da8dSAndroid Build Coastguard Worker it doesn't matter whether this attribute has a true or false value, it 2046*cda5da8dSAndroid Build Coastguard Worker only matters whether it exists (XXX this is a bug). If 2047*cda5da8dSAndroid Build Coastguard Worker __safe_for_unpickling__ doesn't exist, UnpicklingError is raised. 2048*cda5da8dSAndroid Build Coastguard Worker 2049*cda5da8dSAndroid Build Coastguard Worker Else (the class object does have a __safe_for_unpickling__ attr), 2050*cda5da8dSAndroid Build Coastguard Worker the class object obtained from INST's arguments is applied to the 2051*cda5da8dSAndroid Build Coastguard Worker argtuple obtained from the stack, and the resulting instance object 2052*cda5da8dSAndroid Build Coastguard Worker is pushed on the stack. 2053*cda5da8dSAndroid Build Coastguard Worker 2054*cda5da8dSAndroid Build Coastguard Worker NOTE: checks for __safe_for_unpickling__ went away in Python 2.3. 2055*cda5da8dSAndroid Build Coastguard Worker NOTE: the distinction between old-style and new-style classes does 2056*cda5da8dSAndroid Build Coastguard Worker not make sense in Python 3. 2057*cda5da8dSAndroid Build Coastguard Worker """), 2058*cda5da8dSAndroid Build Coastguard Worker 2059*cda5da8dSAndroid Build Coastguard Worker I(name='OBJ', 2060*cda5da8dSAndroid Build Coastguard Worker code='o', 2061*cda5da8dSAndroid Build Coastguard Worker arg=None, 2062*cda5da8dSAndroid Build Coastguard Worker stack_before=[markobject, anyobject, stackslice], 2063*cda5da8dSAndroid Build Coastguard Worker stack_after=[anyobject], 2064*cda5da8dSAndroid Build Coastguard Worker proto=1, 2065*cda5da8dSAndroid Build Coastguard Worker doc="""Build a class instance. 2066*cda5da8dSAndroid Build Coastguard Worker 2067*cda5da8dSAndroid Build Coastguard Worker This is the protocol 1 version of protocol 0's INST opcode, and is 2068*cda5da8dSAndroid Build Coastguard Worker very much like it. The major difference is that the class object 2069*cda5da8dSAndroid Build Coastguard Worker is taken off the stack, allowing it to be retrieved from the memo 2070*cda5da8dSAndroid Build Coastguard Worker repeatedly if several instances of the same class are created. This 2071*cda5da8dSAndroid Build Coastguard Worker can be much more efficient (in both time and space) than repeatedly 2072*cda5da8dSAndroid Build Coastguard Worker embedding the module and class names in INST opcodes. 2073*cda5da8dSAndroid Build Coastguard Worker 2074*cda5da8dSAndroid Build Coastguard Worker Unlike INST, OBJ takes no arguments from the opcode stream. Instead 2075*cda5da8dSAndroid Build Coastguard Worker the class object is taken off the stack, immediately above the 2076*cda5da8dSAndroid Build Coastguard Worker topmost markobject: 2077*cda5da8dSAndroid Build Coastguard Worker 2078*cda5da8dSAndroid Build Coastguard Worker Stack before: ... markobject classobject stackslice 2079*cda5da8dSAndroid Build Coastguard Worker Stack after: ... new_instance_object 2080*cda5da8dSAndroid Build Coastguard Worker 2081*cda5da8dSAndroid Build Coastguard Worker As for INST, the remainder of the stack above the markobject is 2082*cda5da8dSAndroid Build Coastguard Worker gathered into an argument tuple, and then the logic seems identical, 2083*cda5da8dSAndroid Build Coastguard Worker except that no __safe_for_unpickling__ check is done (XXX this is 2084*cda5da8dSAndroid Build Coastguard Worker a bug). See INST for the gory details. 2085*cda5da8dSAndroid Build Coastguard Worker 2086*cda5da8dSAndroid Build Coastguard Worker NOTE: In Python 2.3, INST and OBJ are identical except for how they 2087*cda5da8dSAndroid Build Coastguard Worker get the class object. That was always the intent; the implementations 2088*cda5da8dSAndroid Build Coastguard Worker had diverged for accidental reasons. 2089*cda5da8dSAndroid Build Coastguard Worker """), 2090*cda5da8dSAndroid Build Coastguard Worker 2091*cda5da8dSAndroid Build Coastguard Worker I(name='NEWOBJ', 2092*cda5da8dSAndroid Build Coastguard Worker code='\x81', 2093*cda5da8dSAndroid Build Coastguard Worker arg=None, 2094*cda5da8dSAndroid Build Coastguard Worker stack_before=[anyobject, anyobject], 2095*cda5da8dSAndroid Build Coastguard Worker stack_after=[anyobject], 2096*cda5da8dSAndroid Build Coastguard Worker proto=2, 2097*cda5da8dSAndroid Build Coastguard Worker doc="""Build an object instance. 2098*cda5da8dSAndroid Build Coastguard Worker 2099*cda5da8dSAndroid Build Coastguard Worker The stack before should be thought of as containing a class 2100*cda5da8dSAndroid Build Coastguard Worker object followed by an argument tuple (the tuple being the stack 2101*cda5da8dSAndroid Build Coastguard Worker top). Call these cls and args. They are popped off the stack, 2102*cda5da8dSAndroid Build Coastguard Worker and the value returned by cls.__new__(cls, *args) is pushed back 2103*cda5da8dSAndroid Build Coastguard Worker onto the stack. 2104*cda5da8dSAndroid Build Coastguard Worker """), 2105*cda5da8dSAndroid Build Coastguard Worker 2106*cda5da8dSAndroid Build Coastguard Worker I(name='NEWOBJ_EX', 2107*cda5da8dSAndroid Build Coastguard Worker code='\x92', 2108*cda5da8dSAndroid Build Coastguard Worker arg=None, 2109*cda5da8dSAndroid Build Coastguard Worker stack_before=[anyobject, anyobject, anyobject], 2110*cda5da8dSAndroid Build Coastguard Worker stack_after=[anyobject], 2111*cda5da8dSAndroid Build Coastguard Worker proto=4, 2112*cda5da8dSAndroid Build Coastguard Worker doc="""Build an object instance. 2113*cda5da8dSAndroid Build Coastguard Worker 2114*cda5da8dSAndroid Build Coastguard Worker The stack before should be thought of as containing a class 2115*cda5da8dSAndroid Build Coastguard Worker object followed by an argument tuple and by a keyword argument dict 2116*cda5da8dSAndroid Build Coastguard Worker (the dict being the stack top). Call these cls and args. They are 2117*cda5da8dSAndroid Build Coastguard Worker popped off the stack, and the value returned by 2118*cda5da8dSAndroid Build Coastguard Worker cls.__new__(cls, *args, *kwargs) is pushed back onto the stack. 2119*cda5da8dSAndroid Build Coastguard Worker """), 2120*cda5da8dSAndroid Build Coastguard Worker 2121*cda5da8dSAndroid Build Coastguard Worker # Machine control. 2122*cda5da8dSAndroid Build Coastguard Worker 2123*cda5da8dSAndroid Build Coastguard Worker I(name='PROTO', 2124*cda5da8dSAndroid Build Coastguard Worker code='\x80', 2125*cda5da8dSAndroid Build Coastguard Worker arg=uint1, 2126*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 2127*cda5da8dSAndroid Build Coastguard Worker stack_after=[], 2128*cda5da8dSAndroid Build Coastguard Worker proto=2, 2129*cda5da8dSAndroid Build Coastguard Worker doc="""Protocol version indicator. 2130*cda5da8dSAndroid Build Coastguard Worker 2131*cda5da8dSAndroid Build Coastguard Worker For protocol 2 and above, a pickle must start with this opcode. 2132*cda5da8dSAndroid Build Coastguard Worker The argument is the protocol version, an int in range(2, 256). 2133*cda5da8dSAndroid Build Coastguard Worker """), 2134*cda5da8dSAndroid Build Coastguard Worker 2135*cda5da8dSAndroid Build Coastguard Worker I(name='STOP', 2136*cda5da8dSAndroid Build Coastguard Worker code='.', 2137*cda5da8dSAndroid Build Coastguard Worker arg=None, 2138*cda5da8dSAndroid Build Coastguard Worker stack_before=[anyobject], 2139*cda5da8dSAndroid Build Coastguard Worker stack_after=[], 2140*cda5da8dSAndroid Build Coastguard Worker proto=0, 2141*cda5da8dSAndroid Build Coastguard Worker doc="""Stop the unpickling machine. 2142*cda5da8dSAndroid Build Coastguard Worker 2143*cda5da8dSAndroid Build Coastguard Worker Every pickle ends with this opcode. The object at the top of the stack 2144*cda5da8dSAndroid Build Coastguard Worker is popped, and that's the result of unpickling. The stack should be 2145*cda5da8dSAndroid Build Coastguard Worker empty then. 2146*cda5da8dSAndroid Build Coastguard Worker """), 2147*cda5da8dSAndroid Build Coastguard Worker 2148*cda5da8dSAndroid Build Coastguard Worker # Framing support. 2149*cda5da8dSAndroid Build Coastguard Worker 2150*cda5da8dSAndroid Build Coastguard Worker I(name='FRAME', 2151*cda5da8dSAndroid Build Coastguard Worker code='\x95', 2152*cda5da8dSAndroid Build Coastguard Worker arg=uint8, 2153*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 2154*cda5da8dSAndroid Build Coastguard Worker stack_after=[], 2155*cda5da8dSAndroid Build Coastguard Worker proto=4, 2156*cda5da8dSAndroid Build Coastguard Worker doc="""Indicate the beginning of a new frame. 2157*cda5da8dSAndroid Build Coastguard Worker 2158*cda5da8dSAndroid Build Coastguard Worker The unpickler may use this opcode to safely prefetch data from its 2159*cda5da8dSAndroid Build Coastguard Worker underlying stream. 2160*cda5da8dSAndroid Build Coastguard Worker """), 2161*cda5da8dSAndroid Build Coastguard Worker 2162*cda5da8dSAndroid Build Coastguard Worker # Ways to deal with persistent IDs. 2163*cda5da8dSAndroid Build Coastguard Worker 2164*cda5da8dSAndroid Build Coastguard Worker I(name='PERSID', 2165*cda5da8dSAndroid Build Coastguard Worker code='P', 2166*cda5da8dSAndroid Build Coastguard Worker arg=stringnl_noescape, 2167*cda5da8dSAndroid Build Coastguard Worker stack_before=[], 2168*cda5da8dSAndroid Build Coastguard Worker stack_after=[anyobject], 2169*cda5da8dSAndroid Build Coastguard Worker proto=0, 2170*cda5da8dSAndroid Build Coastguard Worker doc="""Push an object identified by a persistent ID. 2171*cda5da8dSAndroid Build Coastguard Worker 2172*cda5da8dSAndroid Build Coastguard Worker The pickle module doesn't define what a persistent ID means. PERSID's 2173*cda5da8dSAndroid Build Coastguard Worker argument is a newline-terminated str-style (no embedded escapes, no 2174*cda5da8dSAndroid Build Coastguard Worker bracketing quote characters) string, which *is* "the persistent ID". 2175*cda5da8dSAndroid Build Coastguard Worker The unpickler passes this string to self.persistent_load(). Whatever 2176*cda5da8dSAndroid Build Coastguard Worker object that returns is pushed on the stack. There is no implementation 2177*cda5da8dSAndroid Build Coastguard Worker of persistent_load() in Python's unpickler: it must be supplied by an 2178*cda5da8dSAndroid Build Coastguard Worker unpickler subclass. 2179*cda5da8dSAndroid Build Coastguard Worker """), 2180*cda5da8dSAndroid Build Coastguard Worker 2181*cda5da8dSAndroid Build Coastguard Worker I(name='BINPERSID', 2182*cda5da8dSAndroid Build Coastguard Worker code='Q', 2183*cda5da8dSAndroid Build Coastguard Worker arg=None, 2184*cda5da8dSAndroid Build Coastguard Worker stack_before=[anyobject], 2185*cda5da8dSAndroid Build Coastguard Worker stack_after=[anyobject], 2186*cda5da8dSAndroid Build Coastguard Worker proto=1, 2187*cda5da8dSAndroid Build Coastguard Worker doc="""Push an object identified by a persistent ID. 2188*cda5da8dSAndroid Build Coastguard Worker 2189*cda5da8dSAndroid Build Coastguard Worker Like PERSID, except the persistent ID is popped off the stack (instead 2190*cda5da8dSAndroid Build Coastguard Worker of being a string embedded in the opcode bytestream). The persistent 2191*cda5da8dSAndroid Build Coastguard Worker ID is passed to self.persistent_load(), and whatever object that 2192*cda5da8dSAndroid Build Coastguard Worker returns is pushed on the stack. See PERSID for more detail. 2193*cda5da8dSAndroid Build Coastguard Worker """), 2194*cda5da8dSAndroid Build Coastguard Worker] 2195*cda5da8dSAndroid Build Coastguard Workerdel I 2196*cda5da8dSAndroid Build Coastguard Worker 2197*cda5da8dSAndroid Build Coastguard Worker# Verify uniqueness of .name and .code members. 2198*cda5da8dSAndroid Build Coastguard Workername2i = {} 2199*cda5da8dSAndroid Build Coastguard Workercode2i = {} 2200*cda5da8dSAndroid Build Coastguard Worker 2201*cda5da8dSAndroid Build Coastguard Workerfor i, d in enumerate(opcodes): 2202*cda5da8dSAndroid Build Coastguard Worker if d.name in name2i: 2203*cda5da8dSAndroid Build Coastguard Worker raise ValueError("repeated name %r at indices %d and %d" % 2204*cda5da8dSAndroid Build Coastguard Worker (d.name, name2i[d.name], i)) 2205*cda5da8dSAndroid Build Coastguard Worker if d.code in code2i: 2206*cda5da8dSAndroid Build Coastguard Worker raise ValueError("repeated code %r at indices %d and %d" % 2207*cda5da8dSAndroid Build Coastguard Worker (d.code, code2i[d.code], i)) 2208*cda5da8dSAndroid Build Coastguard Worker 2209*cda5da8dSAndroid Build Coastguard Worker name2i[d.name] = i 2210*cda5da8dSAndroid Build Coastguard Worker code2i[d.code] = i 2211*cda5da8dSAndroid Build Coastguard Worker 2212*cda5da8dSAndroid Build Coastguard Workerdel name2i, code2i, i, d 2213*cda5da8dSAndroid Build Coastguard Worker 2214*cda5da8dSAndroid Build Coastguard Worker############################################################################## 2215*cda5da8dSAndroid Build Coastguard Worker# Build a code2op dict, mapping opcode characters to OpcodeInfo records. 2216*cda5da8dSAndroid Build Coastguard Worker# Also ensure we've got the same stuff as pickle.py, although the 2217*cda5da8dSAndroid Build Coastguard Worker# introspection here is dicey. 2218*cda5da8dSAndroid Build Coastguard Worker 2219*cda5da8dSAndroid Build Coastguard Workercode2op = {} 2220*cda5da8dSAndroid Build Coastguard Workerfor d in opcodes: 2221*cda5da8dSAndroid Build Coastguard Worker code2op[d.code] = d 2222*cda5da8dSAndroid Build Coastguard Workerdel d 2223*cda5da8dSAndroid Build Coastguard Worker 2224*cda5da8dSAndroid Build Coastguard Workerdef assure_pickle_consistency(verbose=False): 2225*cda5da8dSAndroid Build Coastguard Worker 2226*cda5da8dSAndroid Build Coastguard Worker copy = code2op.copy() 2227*cda5da8dSAndroid Build Coastguard Worker for name in pickle.__all__: 2228*cda5da8dSAndroid Build Coastguard Worker if not re.match("[A-Z][A-Z0-9_]+$", name): 2229*cda5da8dSAndroid Build Coastguard Worker if verbose: 2230*cda5da8dSAndroid Build Coastguard Worker print("skipping %r: it doesn't look like an opcode name" % name) 2231*cda5da8dSAndroid Build Coastguard Worker continue 2232*cda5da8dSAndroid Build Coastguard Worker picklecode = getattr(pickle, name) 2233*cda5da8dSAndroid Build Coastguard Worker if not isinstance(picklecode, bytes) or len(picklecode) != 1: 2234*cda5da8dSAndroid Build Coastguard Worker if verbose: 2235*cda5da8dSAndroid Build Coastguard Worker print(("skipping %r: value %r doesn't look like a pickle " 2236*cda5da8dSAndroid Build Coastguard Worker "code" % (name, picklecode))) 2237*cda5da8dSAndroid Build Coastguard Worker continue 2238*cda5da8dSAndroid Build Coastguard Worker picklecode = picklecode.decode("latin-1") 2239*cda5da8dSAndroid Build Coastguard Worker if picklecode in copy: 2240*cda5da8dSAndroid Build Coastguard Worker if verbose: 2241*cda5da8dSAndroid Build Coastguard Worker print("checking name %r w/ code %r for consistency" % ( 2242*cda5da8dSAndroid Build Coastguard Worker name, picklecode)) 2243*cda5da8dSAndroid Build Coastguard Worker d = copy[picklecode] 2244*cda5da8dSAndroid Build Coastguard Worker if d.name != name: 2245*cda5da8dSAndroid Build Coastguard Worker raise ValueError("for pickle code %r, pickle.py uses name %r " 2246*cda5da8dSAndroid Build Coastguard Worker "but we're using name %r" % (picklecode, 2247*cda5da8dSAndroid Build Coastguard Worker name, 2248*cda5da8dSAndroid Build Coastguard Worker d.name)) 2249*cda5da8dSAndroid Build Coastguard Worker # Forget this one. Any left over in copy at the end are a problem 2250*cda5da8dSAndroid Build Coastguard Worker # of a different kind. 2251*cda5da8dSAndroid Build Coastguard Worker del copy[picklecode] 2252*cda5da8dSAndroid Build Coastguard Worker else: 2253*cda5da8dSAndroid Build Coastguard Worker raise ValueError("pickle.py appears to have a pickle opcode with " 2254*cda5da8dSAndroid Build Coastguard Worker "name %r and code %r, but we don't" % 2255*cda5da8dSAndroid Build Coastguard Worker (name, picklecode)) 2256*cda5da8dSAndroid Build Coastguard Worker if copy: 2257*cda5da8dSAndroid Build Coastguard Worker msg = ["we appear to have pickle opcodes that pickle.py doesn't have:"] 2258*cda5da8dSAndroid Build Coastguard Worker for code, d in copy.items(): 2259*cda5da8dSAndroid Build Coastguard Worker msg.append(" name %r with code %r" % (d.name, code)) 2260*cda5da8dSAndroid Build Coastguard Worker raise ValueError("\n".join(msg)) 2261*cda5da8dSAndroid Build Coastguard Worker 2262*cda5da8dSAndroid Build Coastguard Workerassure_pickle_consistency() 2263*cda5da8dSAndroid Build Coastguard Workerdel assure_pickle_consistency 2264*cda5da8dSAndroid Build Coastguard Worker 2265*cda5da8dSAndroid Build Coastguard Worker############################################################################## 2266*cda5da8dSAndroid Build Coastguard Worker# A pickle opcode generator. 2267*cda5da8dSAndroid Build Coastguard Worker 2268*cda5da8dSAndroid Build Coastguard Workerdef _genops(data, yield_end_pos=False): 2269*cda5da8dSAndroid Build Coastguard Worker if isinstance(data, bytes_types): 2270*cda5da8dSAndroid Build Coastguard Worker data = io.BytesIO(data) 2271*cda5da8dSAndroid Build Coastguard Worker 2272*cda5da8dSAndroid Build Coastguard Worker if hasattr(data, "tell"): 2273*cda5da8dSAndroid Build Coastguard Worker getpos = data.tell 2274*cda5da8dSAndroid Build Coastguard Worker else: 2275*cda5da8dSAndroid Build Coastguard Worker getpos = lambda: None 2276*cda5da8dSAndroid Build Coastguard Worker 2277*cda5da8dSAndroid Build Coastguard Worker while True: 2278*cda5da8dSAndroid Build Coastguard Worker pos = getpos() 2279*cda5da8dSAndroid Build Coastguard Worker code = data.read(1) 2280*cda5da8dSAndroid Build Coastguard Worker opcode = code2op.get(code.decode("latin-1")) 2281*cda5da8dSAndroid Build Coastguard Worker if opcode is None: 2282*cda5da8dSAndroid Build Coastguard Worker if code == b"": 2283*cda5da8dSAndroid Build Coastguard Worker raise ValueError("pickle exhausted before seeing STOP") 2284*cda5da8dSAndroid Build Coastguard Worker else: 2285*cda5da8dSAndroid Build Coastguard Worker raise ValueError("at position %s, opcode %r unknown" % ( 2286*cda5da8dSAndroid Build Coastguard Worker "<unknown>" if pos is None else pos, 2287*cda5da8dSAndroid Build Coastguard Worker code)) 2288*cda5da8dSAndroid Build Coastguard Worker if opcode.arg is None: 2289*cda5da8dSAndroid Build Coastguard Worker arg = None 2290*cda5da8dSAndroid Build Coastguard Worker else: 2291*cda5da8dSAndroid Build Coastguard Worker arg = opcode.arg.reader(data) 2292*cda5da8dSAndroid Build Coastguard Worker if yield_end_pos: 2293*cda5da8dSAndroid Build Coastguard Worker yield opcode, arg, pos, getpos() 2294*cda5da8dSAndroid Build Coastguard Worker else: 2295*cda5da8dSAndroid Build Coastguard Worker yield opcode, arg, pos 2296*cda5da8dSAndroid Build Coastguard Worker if code == b'.': 2297*cda5da8dSAndroid Build Coastguard Worker assert opcode.name == 'STOP' 2298*cda5da8dSAndroid Build Coastguard Worker break 2299*cda5da8dSAndroid Build Coastguard Worker 2300*cda5da8dSAndroid Build Coastguard Workerdef genops(pickle): 2301*cda5da8dSAndroid Build Coastguard Worker """Generate all the opcodes in a pickle. 2302*cda5da8dSAndroid Build Coastguard Worker 2303*cda5da8dSAndroid Build Coastguard Worker 'pickle' is a file-like object, or string, containing the pickle. 2304*cda5da8dSAndroid Build Coastguard Worker 2305*cda5da8dSAndroid Build Coastguard Worker Each opcode in the pickle is generated, from the current pickle position, 2306*cda5da8dSAndroid Build Coastguard Worker stopping after a STOP opcode is delivered. A triple is generated for 2307*cda5da8dSAndroid Build Coastguard Worker each opcode: 2308*cda5da8dSAndroid Build Coastguard Worker 2309*cda5da8dSAndroid Build Coastguard Worker opcode, arg, pos 2310*cda5da8dSAndroid Build Coastguard Worker 2311*cda5da8dSAndroid Build Coastguard Worker opcode is an OpcodeInfo record, describing the current opcode. 2312*cda5da8dSAndroid Build Coastguard Worker 2313*cda5da8dSAndroid Build Coastguard Worker If the opcode has an argument embedded in the pickle, arg is its decoded 2314*cda5da8dSAndroid Build Coastguard Worker value, as a Python object. If the opcode doesn't have an argument, arg 2315*cda5da8dSAndroid Build Coastguard Worker is None. 2316*cda5da8dSAndroid Build Coastguard Worker 2317*cda5da8dSAndroid Build Coastguard Worker If the pickle has a tell() method, pos was the value of pickle.tell() 2318*cda5da8dSAndroid Build Coastguard Worker before reading the current opcode. If the pickle is a bytes object, 2319*cda5da8dSAndroid Build Coastguard Worker it's wrapped in a BytesIO object, and the latter's tell() result is 2320*cda5da8dSAndroid Build Coastguard Worker used. Else (the pickle doesn't have a tell(), and it's not obvious how 2321*cda5da8dSAndroid Build Coastguard Worker to query its current position) pos is None. 2322*cda5da8dSAndroid Build Coastguard Worker """ 2323*cda5da8dSAndroid Build Coastguard Worker return _genops(pickle) 2324*cda5da8dSAndroid Build Coastguard Worker 2325*cda5da8dSAndroid Build Coastguard Worker############################################################################## 2326*cda5da8dSAndroid Build Coastguard Worker# A pickle optimizer. 2327*cda5da8dSAndroid Build Coastguard Worker 2328*cda5da8dSAndroid Build Coastguard Workerdef optimize(p): 2329*cda5da8dSAndroid Build Coastguard Worker 'Optimize a pickle string by removing unused PUT opcodes' 2330*cda5da8dSAndroid Build Coastguard Worker put = 'PUT' 2331*cda5da8dSAndroid Build Coastguard Worker get = 'GET' 2332*cda5da8dSAndroid Build Coastguard Worker oldids = set() # set of all PUT ids 2333*cda5da8dSAndroid Build Coastguard Worker newids = {} # set of ids used by a GET opcode 2334*cda5da8dSAndroid Build Coastguard Worker opcodes = [] # (op, idx) or (pos, end_pos) 2335*cda5da8dSAndroid Build Coastguard Worker proto = 0 2336*cda5da8dSAndroid Build Coastguard Worker protoheader = b'' 2337*cda5da8dSAndroid Build Coastguard Worker for opcode, arg, pos, end_pos in _genops(p, yield_end_pos=True): 2338*cda5da8dSAndroid Build Coastguard Worker if 'PUT' in opcode.name: 2339*cda5da8dSAndroid Build Coastguard Worker oldids.add(arg) 2340*cda5da8dSAndroid Build Coastguard Worker opcodes.append((put, arg)) 2341*cda5da8dSAndroid Build Coastguard Worker elif opcode.name == 'MEMOIZE': 2342*cda5da8dSAndroid Build Coastguard Worker idx = len(oldids) 2343*cda5da8dSAndroid Build Coastguard Worker oldids.add(idx) 2344*cda5da8dSAndroid Build Coastguard Worker opcodes.append((put, idx)) 2345*cda5da8dSAndroid Build Coastguard Worker elif 'FRAME' in opcode.name: 2346*cda5da8dSAndroid Build Coastguard Worker pass 2347*cda5da8dSAndroid Build Coastguard Worker elif 'GET' in opcode.name: 2348*cda5da8dSAndroid Build Coastguard Worker if opcode.proto > proto: 2349*cda5da8dSAndroid Build Coastguard Worker proto = opcode.proto 2350*cda5da8dSAndroid Build Coastguard Worker newids[arg] = None 2351*cda5da8dSAndroid Build Coastguard Worker opcodes.append((get, arg)) 2352*cda5da8dSAndroid Build Coastguard Worker elif opcode.name == 'PROTO': 2353*cda5da8dSAndroid Build Coastguard Worker if arg > proto: 2354*cda5da8dSAndroid Build Coastguard Worker proto = arg 2355*cda5da8dSAndroid Build Coastguard Worker if pos == 0: 2356*cda5da8dSAndroid Build Coastguard Worker protoheader = p[pos:end_pos] 2357*cda5da8dSAndroid Build Coastguard Worker else: 2358*cda5da8dSAndroid Build Coastguard Worker opcodes.append((pos, end_pos)) 2359*cda5da8dSAndroid Build Coastguard Worker else: 2360*cda5da8dSAndroid Build Coastguard Worker opcodes.append((pos, end_pos)) 2361*cda5da8dSAndroid Build Coastguard Worker del oldids 2362*cda5da8dSAndroid Build Coastguard Worker 2363*cda5da8dSAndroid Build Coastguard Worker # Copy the opcodes except for PUTS without a corresponding GET 2364*cda5da8dSAndroid Build Coastguard Worker out = io.BytesIO() 2365*cda5da8dSAndroid Build Coastguard Worker # Write the PROTO header before any framing 2366*cda5da8dSAndroid Build Coastguard Worker out.write(protoheader) 2367*cda5da8dSAndroid Build Coastguard Worker pickler = pickle._Pickler(out, proto) 2368*cda5da8dSAndroid Build Coastguard Worker if proto >= 4: 2369*cda5da8dSAndroid Build Coastguard Worker pickler.framer.start_framing() 2370*cda5da8dSAndroid Build Coastguard Worker idx = 0 2371*cda5da8dSAndroid Build Coastguard Worker for op, arg in opcodes: 2372*cda5da8dSAndroid Build Coastguard Worker frameless = False 2373*cda5da8dSAndroid Build Coastguard Worker if op is put: 2374*cda5da8dSAndroid Build Coastguard Worker if arg not in newids: 2375*cda5da8dSAndroid Build Coastguard Worker continue 2376*cda5da8dSAndroid Build Coastguard Worker data = pickler.put(idx) 2377*cda5da8dSAndroid Build Coastguard Worker newids[arg] = idx 2378*cda5da8dSAndroid Build Coastguard Worker idx += 1 2379*cda5da8dSAndroid Build Coastguard Worker elif op is get: 2380*cda5da8dSAndroid Build Coastguard Worker data = pickler.get(newids[arg]) 2381*cda5da8dSAndroid Build Coastguard Worker else: 2382*cda5da8dSAndroid Build Coastguard Worker data = p[op:arg] 2383*cda5da8dSAndroid Build Coastguard Worker frameless = len(data) > pickler.framer._FRAME_SIZE_TARGET 2384*cda5da8dSAndroid Build Coastguard Worker pickler.framer.commit_frame(force=frameless) 2385*cda5da8dSAndroid Build Coastguard Worker if frameless: 2386*cda5da8dSAndroid Build Coastguard Worker pickler.framer.file_write(data) 2387*cda5da8dSAndroid Build Coastguard Worker else: 2388*cda5da8dSAndroid Build Coastguard Worker pickler.write(data) 2389*cda5da8dSAndroid Build Coastguard Worker pickler.framer.end_framing() 2390*cda5da8dSAndroid Build Coastguard Worker return out.getvalue() 2391*cda5da8dSAndroid Build Coastguard Worker 2392*cda5da8dSAndroid Build Coastguard Worker############################################################################## 2393*cda5da8dSAndroid Build Coastguard Worker# A symbolic pickle disassembler. 2394*cda5da8dSAndroid Build Coastguard Worker 2395*cda5da8dSAndroid Build Coastguard Workerdef dis(pickle, out=None, memo=None, indentlevel=4, annotate=0): 2396*cda5da8dSAndroid Build Coastguard Worker """Produce a symbolic disassembly of a pickle. 2397*cda5da8dSAndroid Build Coastguard Worker 2398*cda5da8dSAndroid Build Coastguard Worker 'pickle' is a file-like object, or string, containing a (at least one) 2399*cda5da8dSAndroid Build Coastguard Worker pickle. The pickle is disassembled from the current position, through 2400*cda5da8dSAndroid Build Coastguard Worker the first STOP opcode encountered. 2401*cda5da8dSAndroid Build Coastguard Worker 2402*cda5da8dSAndroid Build Coastguard Worker Optional arg 'out' is a file-like object to which the disassembly is 2403*cda5da8dSAndroid Build Coastguard Worker printed. It defaults to sys.stdout. 2404*cda5da8dSAndroid Build Coastguard Worker 2405*cda5da8dSAndroid Build Coastguard Worker Optional arg 'memo' is a Python dict, used as the pickle's memo. It 2406*cda5da8dSAndroid Build Coastguard Worker may be mutated by dis(), if the pickle contains PUT or BINPUT opcodes. 2407*cda5da8dSAndroid Build Coastguard Worker Passing the same memo object to another dis() call then allows disassembly 2408*cda5da8dSAndroid Build Coastguard Worker to proceed across multiple pickles that were all created by the same 2409*cda5da8dSAndroid Build Coastguard Worker pickler with the same memo. Ordinarily you don't need to worry about this. 2410*cda5da8dSAndroid Build Coastguard Worker 2411*cda5da8dSAndroid Build Coastguard Worker Optional arg 'indentlevel' is the number of blanks by which to indent 2412*cda5da8dSAndroid Build Coastguard Worker a new MARK level. It defaults to 4. 2413*cda5da8dSAndroid Build Coastguard Worker 2414*cda5da8dSAndroid Build Coastguard Worker Optional arg 'annotate' if nonzero instructs dis() to add short 2415*cda5da8dSAndroid Build Coastguard Worker description of the opcode on each line of disassembled output. 2416*cda5da8dSAndroid Build Coastguard Worker The value given to 'annotate' must be an integer and is used as a 2417*cda5da8dSAndroid Build Coastguard Worker hint for the column where annotation should start. The default 2418*cda5da8dSAndroid Build Coastguard Worker value is 0, meaning no annotations. 2419*cda5da8dSAndroid Build Coastguard Worker 2420*cda5da8dSAndroid Build Coastguard Worker In addition to printing the disassembly, some sanity checks are made: 2421*cda5da8dSAndroid Build Coastguard Worker 2422*cda5da8dSAndroid Build Coastguard Worker + All embedded opcode arguments "make sense". 2423*cda5da8dSAndroid Build Coastguard Worker 2424*cda5da8dSAndroid Build Coastguard Worker + Explicit and implicit pop operations have enough items on the stack. 2425*cda5da8dSAndroid Build Coastguard Worker 2426*cda5da8dSAndroid Build Coastguard Worker + When an opcode implicitly refers to a markobject, a markobject is 2427*cda5da8dSAndroid Build Coastguard Worker actually on the stack. 2428*cda5da8dSAndroid Build Coastguard Worker 2429*cda5da8dSAndroid Build Coastguard Worker + A memo entry isn't referenced before it's defined. 2430*cda5da8dSAndroid Build Coastguard Worker 2431*cda5da8dSAndroid Build Coastguard Worker + The markobject isn't stored in the memo. 2432*cda5da8dSAndroid Build Coastguard Worker 2433*cda5da8dSAndroid Build Coastguard Worker + A memo entry isn't redefined. 2434*cda5da8dSAndroid Build Coastguard Worker """ 2435*cda5da8dSAndroid Build Coastguard Worker 2436*cda5da8dSAndroid Build Coastguard Worker # Most of the hair here is for sanity checks, but most of it is needed 2437*cda5da8dSAndroid Build Coastguard Worker # anyway to detect when a protocol 0 POP takes a MARK off the stack 2438*cda5da8dSAndroid Build Coastguard Worker # (which in turn is needed to indent MARK blocks correctly). 2439*cda5da8dSAndroid Build Coastguard Worker 2440*cda5da8dSAndroid Build Coastguard Worker stack = [] # crude emulation of unpickler stack 2441*cda5da8dSAndroid Build Coastguard Worker if memo is None: 2442*cda5da8dSAndroid Build Coastguard Worker memo = {} # crude emulation of unpickler memo 2443*cda5da8dSAndroid Build Coastguard Worker maxproto = -1 # max protocol number seen 2444*cda5da8dSAndroid Build Coastguard Worker markstack = [] # bytecode positions of MARK opcodes 2445*cda5da8dSAndroid Build Coastguard Worker indentchunk = ' ' * indentlevel 2446*cda5da8dSAndroid Build Coastguard Worker errormsg = None 2447*cda5da8dSAndroid Build Coastguard Worker annocol = annotate # column hint for annotations 2448*cda5da8dSAndroid Build Coastguard Worker for opcode, arg, pos in genops(pickle): 2449*cda5da8dSAndroid Build Coastguard Worker if pos is not None: 2450*cda5da8dSAndroid Build Coastguard Worker print("%5d:" % pos, end=' ', file=out) 2451*cda5da8dSAndroid Build Coastguard Worker 2452*cda5da8dSAndroid Build Coastguard Worker line = "%-4s %s%s" % (repr(opcode.code)[1:-1], 2453*cda5da8dSAndroid Build Coastguard Worker indentchunk * len(markstack), 2454*cda5da8dSAndroid Build Coastguard Worker opcode.name) 2455*cda5da8dSAndroid Build Coastguard Worker 2456*cda5da8dSAndroid Build Coastguard Worker maxproto = max(maxproto, opcode.proto) 2457*cda5da8dSAndroid Build Coastguard Worker before = opcode.stack_before # don't mutate 2458*cda5da8dSAndroid Build Coastguard Worker after = opcode.stack_after # don't mutate 2459*cda5da8dSAndroid Build Coastguard Worker numtopop = len(before) 2460*cda5da8dSAndroid Build Coastguard Worker 2461*cda5da8dSAndroid Build Coastguard Worker # See whether a MARK should be popped. 2462*cda5da8dSAndroid Build Coastguard Worker markmsg = None 2463*cda5da8dSAndroid Build Coastguard Worker if markobject in before or (opcode.name == "POP" and 2464*cda5da8dSAndroid Build Coastguard Worker stack and 2465*cda5da8dSAndroid Build Coastguard Worker stack[-1] is markobject): 2466*cda5da8dSAndroid Build Coastguard Worker assert markobject not in after 2467*cda5da8dSAndroid Build Coastguard Worker if __debug__: 2468*cda5da8dSAndroid Build Coastguard Worker if markobject in before: 2469*cda5da8dSAndroid Build Coastguard Worker assert before[-1] is stackslice 2470*cda5da8dSAndroid Build Coastguard Worker if markstack: 2471*cda5da8dSAndroid Build Coastguard Worker markpos = markstack.pop() 2472*cda5da8dSAndroid Build Coastguard Worker if markpos is None: 2473*cda5da8dSAndroid Build Coastguard Worker markmsg = "(MARK at unknown opcode offset)" 2474*cda5da8dSAndroid Build Coastguard Worker else: 2475*cda5da8dSAndroid Build Coastguard Worker markmsg = "(MARK at %d)" % markpos 2476*cda5da8dSAndroid Build Coastguard Worker # Pop everything at and after the topmost markobject. 2477*cda5da8dSAndroid Build Coastguard Worker while stack[-1] is not markobject: 2478*cda5da8dSAndroid Build Coastguard Worker stack.pop() 2479*cda5da8dSAndroid Build Coastguard Worker stack.pop() 2480*cda5da8dSAndroid Build Coastguard Worker # Stop later code from popping too much. 2481*cda5da8dSAndroid Build Coastguard Worker try: 2482*cda5da8dSAndroid Build Coastguard Worker numtopop = before.index(markobject) 2483*cda5da8dSAndroid Build Coastguard Worker except ValueError: 2484*cda5da8dSAndroid Build Coastguard Worker assert opcode.name == "POP" 2485*cda5da8dSAndroid Build Coastguard Worker numtopop = 0 2486*cda5da8dSAndroid Build Coastguard Worker else: 2487*cda5da8dSAndroid Build Coastguard Worker errormsg = markmsg = "no MARK exists on stack" 2488*cda5da8dSAndroid Build Coastguard Worker 2489*cda5da8dSAndroid Build Coastguard Worker # Check for correct memo usage. 2490*cda5da8dSAndroid Build Coastguard Worker if opcode.name in ("PUT", "BINPUT", "LONG_BINPUT", "MEMOIZE"): 2491*cda5da8dSAndroid Build Coastguard Worker if opcode.name == "MEMOIZE": 2492*cda5da8dSAndroid Build Coastguard Worker memo_idx = len(memo) 2493*cda5da8dSAndroid Build Coastguard Worker markmsg = "(as %d)" % memo_idx 2494*cda5da8dSAndroid Build Coastguard Worker else: 2495*cda5da8dSAndroid Build Coastguard Worker assert arg is not None 2496*cda5da8dSAndroid Build Coastguard Worker memo_idx = arg 2497*cda5da8dSAndroid Build Coastguard Worker if memo_idx in memo: 2498*cda5da8dSAndroid Build Coastguard Worker errormsg = "memo key %r already defined" % arg 2499*cda5da8dSAndroid Build Coastguard Worker elif not stack: 2500*cda5da8dSAndroid Build Coastguard Worker errormsg = "stack is empty -- can't store into memo" 2501*cda5da8dSAndroid Build Coastguard Worker elif stack[-1] is markobject: 2502*cda5da8dSAndroid Build Coastguard Worker errormsg = "can't store markobject in the memo" 2503*cda5da8dSAndroid Build Coastguard Worker else: 2504*cda5da8dSAndroid Build Coastguard Worker memo[memo_idx] = stack[-1] 2505*cda5da8dSAndroid Build Coastguard Worker elif opcode.name in ("GET", "BINGET", "LONG_BINGET"): 2506*cda5da8dSAndroid Build Coastguard Worker if arg in memo: 2507*cda5da8dSAndroid Build Coastguard Worker assert len(after) == 1 2508*cda5da8dSAndroid Build Coastguard Worker after = [memo[arg]] # for better stack emulation 2509*cda5da8dSAndroid Build Coastguard Worker else: 2510*cda5da8dSAndroid Build Coastguard Worker errormsg = "memo key %r has never been stored into" % arg 2511*cda5da8dSAndroid Build Coastguard Worker 2512*cda5da8dSAndroid Build Coastguard Worker if arg is not None or markmsg: 2513*cda5da8dSAndroid Build Coastguard Worker # make a mild effort to align arguments 2514*cda5da8dSAndroid Build Coastguard Worker line += ' ' * (10 - len(opcode.name)) 2515*cda5da8dSAndroid Build Coastguard Worker if arg is not None: 2516*cda5da8dSAndroid Build Coastguard Worker line += ' ' + repr(arg) 2517*cda5da8dSAndroid Build Coastguard Worker if markmsg: 2518*cda5da8dSAndroid Build Coastguard Worker line += ' ' + markmsg 2519*cda5da8dSAndroid Build Coastguard Worker if annotate: 2520*cda5da8dSAndroid Build Coastguard Worker line += ' ' * (annocol - len(line)) 2521*cda5da8dSAndroid Build Coastguard Worker # make a mild effort to align annotations 2522*cda5da8dSAndroid Build Coastguard Worker annocol = len(line) 2523*cda5da8dSAndroid Build Coastguard Worker if annocol > 50: 2524*cda5da8dSAndroid Build Coastguard Worker annocol = annotate 2525*cda5da8dSAndroid Build Coastguard Worker line += ' ' + opcode.doc.split('\n', 1)[0] 2526*cda5da8dSAndroid Build Coastguard Worker print(line, file=out) 2527*cda5da8dSAndroid Build Coastguard Worker 2528*cda5da8dSAndroid Build Coastguard Worker if errormsg: 2529*cda5da8dSAndroid Build Coastguard Worker # Note that we delayed complaining until the offending opcode 2530*cda5da8dSAndroid Build Coastguard Worker # was printed. 2531*cda5da8dSAndroid Build Coastguard Worker raise ValueError(errormsg) 2532*cda5da8dSAndroid Build Coastguard Worker 2533*cda5da8dSAndroid Build Coastguard Worker # Emulate the stack effects. 2534*cda5da8dSAndroid Build Coastguard Worker if len(stack) < numtopop: 2535*cda5da8dSAndroid Build Coastguard Worker raise ValueError("tries to pop %d items from stack with " 2536*cda5da8dSAndroid Build Coastguard Worker "only %d items" % (numtopop, len(stack))) 2537*cda5da8dSAndroid Build Coastguard Worker if numtopop: 2538*cda5da8dSAndroid Build Coastguard Worker del stack[-numtopop:] 2539*cda5da8dSAndroid Build Coastguard Worker if markobject in after: 2540*cda5da8dSAndroid Build Coastguard Worker assert markobject not in before 2541*cda5da8dSAndroid Build Coastguard Worker markstack.append(pos) 2542*cda5da8dSAndroid Build Coastguard Worker 2543*cda5da8dSAndroid Build Coastguard Worker stack.extend(after) 2544*cda5da8dSAndroid Build Coastguard Worker 2545*cda5da8dSAndroid Build Coastguard Worker print("highest protocol among opcodes =", maxproto, file=out) 2546*cda5da8dSAndroid Build Coastguard Worker if stack: 2547*cda5da8dSAndroid Build Coastguard Worker raise ValueError("stack not empty after STOP: %r" % stack) 2548*cda5da8dSAndroid Build Coastguard Worker 2549*cda5da8dSAndroid Build Coastguard Worker# For use in the doctest, simply as an example of a class to pickle. 2550*cda5da8dSAndroid Build Coastguard Workerclass _Example: 2551*cda5da8dSAndroid Build Coastguard Worker def __init__(self, value): 2552*cda5da8dSAndroid Build Coastguard Worker self.value = value 2553*cda5da8dSAndroid Build Coastguard Worker 2554*cda5da8dSAndroid Build Coastguard Worker_dis_test = r""" 2555*cda5da8dSAndroid Build Coastguard Worker>>> import pickle 2556*cda5da8dSAndroid Build Coastguard Worker>>> x = [1, 2, (3, 4), {b'abc': "def"}] 2557*cda5da8dSAndroid Build Coastguard Worker>>> pkl0 = pickle.dumps(x, 0) 2558*cda5da8dSAndroid Build Coastguard Worker>>> dis(pkl0) 2559*cda5da8dSAndroid Build Coastguard Worker 0: ( MARK 2560*cda5da8dSAndroid Build Coastguard Worker 1: l LIST (MARK at 0) 2561*cda5da8dSAndroid Build Coastguard Worker 2: p PUT 0 2562*cda5da8dSAndroid Build Coastguard Worker 5: I INT 1 2563*cda5da8dSAndroid Build Coastguard Worker 8: a APPEND 2564*cda5da8dSAndroid Build Coastguard Worker 9: I INT 2 2565*cda5da8dSAndroid Build Coastguard Worker 12: a APPEND 2566*cda5da8dSAndroid Build Coastguard Worker 13: ( MARK 2567*cda5da8dSAndroid Build Coastguard Worker 14: I INT 3 2568*cda5da8dSAndroid Build Coastguard Worker 17: I INT 4 2569*cda5da8dSAndroid Build Coastguard Worker 20: t TUPLE (MARK at 13) 2570*cda5da8dSAndroid Build Coastguard Worker 21: p PUT 1 2571*cda5da8dSAndroid Build Coastguard Worker 24: a APPEND 2572*cda5da8dSAndroid Build Coastguard Worker 25: ( MARK 2573*cda5da8dSAndroid Build Coastguard Worker 26: d DICT (MARK at 25) 2574*cda5da8dSAndroid Build Coastguard Worker 27: p PUT 2 2575*cda5da8dSAndroid Build Coastguard Worker 30: c GLOBAL '_codecs encode' 2576*cda5da8dSAndroid Build Coastguard Worker 46: p PUT 3 2577*cda5da8dSAndroid Build Coastguard Worker 49: ( MARK 2578*cda5da8dSAndroid Build Coastguard Worker 50: V UNICODE 'abc' 2579*cda5da8dSAndroid Build Coastguard Worker 55: p PUT 4 2580*cda5da8dSAndroid Build Coastguard Worker 58: V UNICODE 'latin1' 2581*cda5da8dSAndroid Build Coastguard Worker 66: p PUT 5 2582*cda5da8dSAndroid Build Coastguard Worker 69: t TUPLE (MARK at 49) 2583*cda5da8dSAndroid Build Coastguard Worker 70: p PUT 6 2584*cda5da8dSAndroid Build Coastguard Worker 73: R REDUCE 2585*cda5da8dSAndroid Build Coastguard Worker 74: p PUT 7 2586*cda5da8dSAndroid Build Coastguard Worker 77: V UNICODE 'def' 2587*cda5da8dSAndroid Build Coastguard Worker 82: p PUT 8 2588*cda5da8dSAndroid Build Coastguard Worker 85: s SETITEM 2589*cda5da8dSAndroid Build Coastguard Worker 86: a APPEND 2590*cda5da8dSAndroid Build Coastguard Worker 87: . STOP 2591*cda5da8dSAndroid Build Coastguard Workerhighest protocol among opcodes = 0 2592*cda5da8dSAndroid Build Coastguard Worker 2593*cda5da8dSAndroid Build Coastguard WorkerTry again with a "binary" pickle. 2594*cda5da8dSAndroid Build Coastguard Worker 2595*cda5da8dSAndroid Build Coastguard Worker>>> pkl1 = pickle.dumps(x, 1) 2596*cda5da8dSAndroid Build Coastguard Worker>>> dis(pkl1) 2597*cda5da8dSAndroid Build Coastguard Worker 0: ] EMPTY_LIST 2598*cda5da8dSAndroid Build Coastguard Worker 1: q BINPUT 0 2599*cda5da8dSAndroid Build Coastguard Worker 3: ( MARK 2600*cda5da8dSAndroid Build Coastguard Worker 4: K BININT1 1 2601*cda5da8dSAndroid Build Coastguard Worker 6: K BININT1 2 2602*cda5da8dSAndroid Build Coastguard Worker 8: ( MARK 2603*cda5da8dSAndroid Build Coastguard Worker 9: K BININT1 3 2604*cda5da8dSAndroid Build Coastguard Worker 11: K BININT1 4 2605*cda5da8dSAndroid Build Coastguard Worker 13: t TUPLE (MARK at 8) 2606*cda5da8dSAndroid Build Coastguard Worker 14: q BINPUT 1 2607*cda5da8dSAndroid Build Coastguard Worker 16: } EMPTY_DICT 2608*cda5da8dSAndroid Build Coastguard Worker 17: q BINPUT 2 2609*cda5da8dSAndroid Build Coastguard Worker 19: c GLOBAL '_codecs encode' 2610*cda5da8dSAndroid Build Coastguard Worker 35: q BINPUT 3 2611*cda5da8dSAndroid Build Coastguard Worker 37: ( MARK 2612*cda5da8dSAndroid Build Coastguard Worker 38: X BINUNICODE 'abc' 2613*cda5da8dSAndroid Build Coastguard Worker 46: q BINPUT 4 2614*cda5da8dSAndroid Build Coastguard Worker 48: X BINUNICODE 'latin1' 2615*cda5da8dSAndroid Build Coastguard Worker 59: q BINPUT 5 2616*cda5da8dSAndroid Build Coastguard Worker 61: t TUPLE (MARK at 37) 2617*cda5da8dSAndroid Build Coastguard Worker 62: q BINPUT 6 2618*cda5da8dSAndroid Build Coastguard Worker 64: R REDUCE 2619*cda5da8dSAndroid Build Coastguard Worker 65: q BINPUT 7 2620*cda5da8dSAndroid Build Coastguard Worker 67: X BINUNICODE 'def' 2621*cda5da8dSAndroid Build Coastguard Worker 75: q BINPUT 8 2622*cda5da8dSAndroid Build Coastguard Worker 77: s SETITEM 2623*cda5da8dSAndroid Build Coastguard Worker 78: e APPENDS (MARK at 3) 2624*cda5da8dSAndroid Build Coastguard Worker 79: . STOP 2625*cda5da8dSAndroid Build Coastguard Workerhighest protocol among opcodes = 1 2626*cda5da8dSAndroid Build Coastguard Worker 2627*cda5da8dSAndroid Build Coastguard WorkerExercise the INST/OBJ/BUILD family. 2628*cda5da8dSAndroid Build Coastguard Worker 2629*cda5da8dSAndroid Build Coastguard Worker>>> import pickletools 2630*cda5da8dSAndroid Build Coastguard Worker>>> dis(pickle.dumps(pickletools.dis, 0)) 2631*cda5da8dSAndroid Build Coastguard Worker 0: c GLOBAL 'pickletools dis' 2632*cda5da8dSAndroid Build Coastguard Worker 17: p PUT 0 2633*cda5da8dSAndroid Build Coastguard Worker 20: . STOP 2634*cda5da8dSAndroid Build Coastguard Workerhighest protocol among opcodes = 0 2635*cda5da8dSAndroid Build Coastguard Worker 2636*cda5da8dSAndroid Build Coastguard Worker>>> from pickletools import _Example 2637*cda5da8dSAndroid Build Coastguard Worker>>> x = [_Example(42)] * 2 2638*cda5da8dSAndroid Build Coastguard Worker>>> dis(pickle.dumps(x, 0)) 2639*cda5da8dSAndroid Build Coastguard Worker 0: ( MARK 2640*cda5da8dSAndroid Build Coastguard Worker 1: l LIST (MARK at 0) 2641*cda5da8dSAndroid Build Coastguard Worker 2: p PUT 0 2642*cda5da8dSAndroid Build Coastguard Worker 5: c GLOBAL 'copy_reg _reconstructor' 2643*cda5da8dSAndroid Build Coastguard Worker 30: p PUT 1 2644*cda5da8dSAndroid Build Coastguard Worker 33: ( MARK 2645*cda5da8dSAndroid Build Coastguard Worker 34: c GLOBAL 'pickletools _Example' 2646*cda5da8dSAndroid Build Coastguard Worker 56: p PUT 2 2647*cda5da8dSAndroid Build Coastguard Worker 59: c GLOBAL '__builtin__ object' 2648*cda5da8dSAndroid Build Coastguard Worker 79: p PUT 3 2649*cda5da8dSAndroid Build Coastguard Worker 82: N NONE 2650*cda5da8dSAndroid Build Coastguard Worker 83: t TUPLE (MARK at 33) 2651*cda5da8dSAndroid Build Coastguard Worker 84: p PUT 4 2652*cda5da8dSAndroid Build Coastguard Worker 87: R REDUCE 2653*cda5da8dSAndroid Build Coastguard Worker 88: p PUT 5 2654*cda5da8dSAndroid Build Coastguard Worker 91: ( MARK 2655*cda5da8dSAndroid Build Coastguard Worker 92: d DICT (MARK at 91) 2656*cda5da8dSAndroid Build Coastguard Worker 93: p PUT 6 2657*cda5da8dSAndroid Build Coastguard Worker 96: V UNICODE 'value' 2658*cda5da8dSAndroid Build Coastguard Worker 103: p PUT 7 2659*cda5da8dSAndroid Build Coastguard Worker 106: I INT 42 2660*cda5da8dSAndroid Build Coastguard Worker 110: s SETITEM 2661*cda5da8dSAndroid Build Coastguard Worker 111: b BUILD 2662*cda5da8dSAndroid Build Coastguard Worker 112: a APPEND 2663*cda5da8dSAndroid Build Coastguard Worker 113: g GET 5 2664*cda5da8dSAndroid Build Coastguard Worker 116: a APPEND 2665*cda5da8dSAndroid Build Coastguard Worker 117: . STOP 2666*cda5da8dSAndroid Build Coastguard Workerhighest protocol among opcodes = 0 2667*cda5da8dSAndroid Build Coastguard Worker 2668*cda5da8dSAndroid Build Coastguard Worker>>> dis(pickle.dumps(x, 1)) 2669*cda5da8dSAndroid Build Coastguard Worker 0: ] EMPTY_LIST 2670*cda5da8dSAndroid Build Coastguard Worker 1: q BINPUT 0 2671*cda5da8dSAndroid Build Coastguard Worker 3: ( MARK 2672*cda5da8dSAndroid Build Coastguard Worker 4: c GLOBAL 'copy_reg _reconstructor' 2673*cda5da8dSAndroid Build Coastguard Worker 29: q BINPUT 1 2674*cda5da8dSAndroid Build Coastguard Worker 31: ( MARK 2675*cda5da8dSAndroid Build Coastguard Worker 32: c GLOBAL 'pickletools _Example' 2676*cda5da8dSAndroid Build Coastguard Worker 54: q BINPUT 2 2677*cda5da8dSAndroid Build Coastguard Worker 56: c GLOBAL '__builtin__ object' 2678*cda5da8dSAndroid Build Coastguard Worker 76: q BINPUT 3 2679*cda5da8dSAndroid Build Coastguard Worker 78: N NONE 2680*cda5da8dSAndroid Build Coastguard Worker 79: t TUPLE (MARK at 31) 2681*cda5da8dSAndroid Build Coastguard Worker 80: q BINPUT 4 2682*cda5da8dSAndroid Build Coastguard Worker 82: R REDUCE 2683*cda5da8dSAndroid Build Coastguard Worker 83: q BINPUT 5 2684*cda5da8dSAndroid Build Coastguard Worker 85: } EMPTY_DICT 2685*cda5da8dSAndroid Build Coastguard Worker 86: q BINPUT 6 2686*cda5da8dSAndroid Build Coastguard Worker 88: X BINUNICODE 'value' 2687*cda5da8dSAndroid Build Coastguard Worker 98: q BINPUT 7 2688*cda5da8dSAndroid Build Coastguard Worker 100: K BININT1 42 2689*cda5da8dSAndroid Build Coastguard Worker 102: s SETITEM 2690*cda5da8dSAndroid Build Coastguard Worker 103: b BUILD 2691*cda5da8dSAndroid Build Coastguard Worker 104: h BINGET 5 2692*cda5da8dSAndroid Build Coastguard Worker 106: e APPENDS (MARK at 3) 2693*cda5da8dSAndroid Build Coastguard Worker 107: . STOP 2694*cda5da8dSAndroid Build Coastguard Workerhighest protocol among opcodes = 1 2695*cda5da8dSAndroid Build Coastguard Worker 2696*cda5da8dSAndroid Build Coastguard WorkerTry "the canonical" recursive-object test. 2697*cda5da8dSAndroid Build Coastguard Worker 2698*cda5da8dSAndroid Build Coastguard Worker>>> L = [] 2699*cda5da8dSAndroid Build Coastguard Worker>>> T = L, 2700*cda5da8dSAndroid Build Coastguard Worker>>> L.append(T) 2701*cda5da8dSAndroid Build Coastguard Worker>>> L[0] is T 2702*cda5da8dSAndroid Build Coastguard WorkerTrue 2703*cda5da8dSAndroid Build Coastguard Worker>>> T[0] is L 2704*cda5da8dSAndroid Build Coastguard WorkerTrue 2705*cda5da8dSAndroid Build Coastguard Worker>>> L[0][0] is L 2706*cda5da8dSAndroid Build Coastguard WorkerTrue 2707*cda5da8dSAndroid Build Coastguard Worker>>> T[0][0] is T 2708*cda5da8dSAndroid Build Coastguard WorkerTrue 2709*cda5da8dSAndroid Build Coastguard Worker>>> dis(pickle.dumps(L, 0)) 2710*cda5da8dSAndroid Build Coastguard Worker 0: ( MARK 2711*cda5da8dSAndroid Build Coastguard Worker 1: l LIST (MARK at 0) 2712*cda5da8dSAndroid Build Coastguard Worker 2: p PUT 0 2713*cda5da8dSAndroid Build Coastguard Worker 5: ( MARK 2714*cda5da8dSAndroid Build Coastguard Worker 6: g GET 0 2715*cda5da8dSAndroid Build Coastguard Worker 9: t TUPLE (MARK at 5) 2716*cda5da8dSAndroid Build Coastguard Worker 10: p PUT 1 2717*cda5da8dSAndroid Build Coastguard Worker 13: a APPEND 2718*cda5da8dSAndroid Build Coastguard Worker 14: . STOP 2719*cda5da8dSAndroid Build Coastguard Workerhighest protocol among opcodes = 0 2720*cda5da8dSAndroid Build Coastguard Worker 2721*cda5da8dSAndroid Build Coastguard Worker>>> dis(pickle.dumps(L, 1)) 2722*cda5da8dSAndroid Build Coastguard Worker 0: ] EMPTY_LIST 2723*cda5da8dSAndroid Build Coastguard Worker 1: q BINPUT 0 2724*cda5da8dSAndroid Build Coastguard Worker 3: ( MARK 2725*cda5da8dSAndroid Build Coastguard Worker 4: h BINGET 0 2726*cda5da8dSAndroid Build Coastguard Worker 6: t TUPLE (MARK at 3) 2727*cda5da8dSAndroid Build Coastguard Worker 7: q BINPUT 1 2728*cda5da8dSAndroid Build Coastguard Worker 9: a APPEND 2729*cda5da8dSAndroid Build Coastguard Worker 10: . STOP 2730*cda5da8dSAndroid Build Coastguard Workerhighest protocol among opcodes = 1 2731*cda5da8dSAndroid Build Coastguard Worker 2732*cda5da8dSAndroid Build Coastguard WorkerNote that, in the protocol 0 pickle of the recursive tuple, the disassembler 2733*cda5da8dSAndroid Build Coastguard Workerhas to emulate the stack in order to realize that the POP opcode at 16 gets 2734*cda5da8dSAndroid Build Coastguard Workerrid of the MARK at 0. 2735*cda5da8dSAndroid Build Coastguard Worker 2736*cda5da8dSAndroid Build Coastguard Worker>>> dis(pickle.dumps(T, 0)) 2737*cda5da8dSAndroid Build Coastguard Worker 0: ( MARK 2738*cda5da8dSAndroid Build Coastguard Worker 1: ( MARK 2739*cda5da8dSAndroid Build Coastguard Worker 2: l LIST (MARK at 1) 2740*cda5da8dSAndroid Build Coastguard Worker 3: p PUT 0 2741*cda5da8dSAndroid Build Coastguard Worker 6: ( MARK 2742*cda5da8dSAndroid Build Coastguard Worker 7: g GET 0 2743*cda5da8dSAndroid Build Coastguard Worker 10: t TUPLE (MARK at 6) 2744*cda5da8dSAndroid Build Coastguard Worker 11: p PUT 1 2745*cda5da8dSAndroid Build Coastguard Worker 14: a APPEND 2746*cda5da8dSAndroid Build Coastguard Worker 15: 0 POP 2747*cda5da8dSAndroid Build Coastguard Worker 16: 0 POP (MARK at 0) 2748*cda5da8dSAndroid Build Coastguard Worker 17: g GET 1 2749*cda5da8dSAndroid Build Coastguard Worker 20: . STOP 2750*cda5da8dSAndroid Build Coastguard Workerhighest protocol among opcodes = 0 2751*cda5da8dSAndroid Build Coastguard Worker 2752*cda5da8dSAndroid Build Coastguard Worker>>> dis(pickle.dumps(T, 1)) 2753*cda5da8dSAndroid Build Coastguard Worker 0: ( MARK 2754*cda5da8dSAndroid Build Coastguard Worker 1: ] EMPTY_LIST 2755*cda5da8dSAndroid Build Coastguard Worker 2: q BINPUT 0 2756*cda5da8dSAndroid Build Coastguard Worker 4: ( MARK 2757*cda5da8dSAndroid Build Coastguard Worker 5: h BINGET 0 2758*cda5da8dSAndroid Build Coastguard Worker 7: t TUPLE (MARK at 4) 2759*cda5da8dSAndroid Build Coastguard Worker 8: q BINPUT 1 2760*cda5da8dSAndroid Build Coastguard Worker 10: a APPEND 2761*cda5da8dSAndroid Build Coastguard Worker 11: 1 POP_MARK (MARK at 0) 2762*cda5da8dSAndroid Build Coastguard Worker 12: h BINGET 1 2763*cda5da8dSAndroid Build Coastguard Worker 14: . STOP 2764*cda5da8dSAndroid Build Coastguard Workerhighest protocol among opcodes = 1 2765*cda5da8dSAndroid Build Coastguard Worker 2766*cda5da8dSAndroid Build Coastguard WorkerTry protocol 2. 2767*cda5da8dSAndroid Build Coastguard Worker 2768*cda5da8dSAndroid Build Coastguard Worker>>> dis(pickle.dumps(L, 2)) 2769*cda5da8dSAndroid Build Coastguard Worker 0: \x80 PROTO 2 2770*cda5da8dSAndroid Build Coastguard Worker 2: ] EMPTY_LIST 2771*cda5da8dSAndroid Build Coastguard Worker 3: q BINPUT 0 2772*cda5da8dSAndroid Build Coastguard Worker 5: h BINGET 0 2773*cda5da8dSAndroid Build Coastguard Worker 7: \x85 TUPLE1 2774*cda5da8dSAndroid Build Coastguard Worker 8: q BINPUT 1 2775*cda5da8dSAndroid Build Coastguard Worker 10: a APPEND 2776*cda5da8dSAndroid Build Coastguard Worker 11: . STOP 2777*cda5da8dSAndroid Build Coastguard Workerhighest protocol among opcodes = 2 2778*cda5da8dSAndroid Build Coastguard Worker 2779*cda5da8dSAndroid Build Coastguard Worker>>> dis(pickle.dumps(T, 2)) 2780*cda5da8dSAndroid Build Coastguard Worker 0: \x80 PROTO 2 2781*cda5da8dSAndroid Build Coastguard Worker 2: ] EMPTY_LIST 2782*cda5da8dSAndroid Build Coastguard Worker 3: q BINPUT 0 2783*cda5da8dSAndroid Build Coastguard Worker 5: h BINGET 0 2784*cda5da8dSAndroid Build Coastguard Worker 7: \x85 TUPLE1 2785*cda5da8dSAndroid Build Coastguard Worker 8: q BINPUT 1 2786*cda5da8dSAndroid Build Coastguard Worker 10: a APPEND 2787*cda5da8dSAndroid Build Coastguard Worker 11: 0 POP 2788*cda5da8dSAndroid Build Coastguard Worker 12: h BINGET 1 2789*cda5da8dSAndroid Build Coastguard Worker 14: . STOP 2790*cda5da8dSAndroid Build Coastguard Workerhighest protocol among opcodes = 2 2791*cda5da8dSAndroid Build Coastguard Worker 2792*cda5da8dSAndroid Build Coastguard WorkerTry protocol 3 with annotations: 2793*cda5da8dSAndroid Build Coastguard Worker 2794*cda5da8dSAndroid Build Coastguard Worker>>> dis(pickle.dumps(T, 3), annotate=1) 2795*cda5da8dSAndroid Build Coastguard Worker 0: \x80 PROTO 3 Protocol version indicator. 2796*cda5da8dSAndroid Build Coastguard Worker 2: ] EMPTY_LIST Push an empty list. 2797*cda5da8dSAndroid Build Coastguard Worker 3: q BINPUT 0 Store the stack top into the memo. The stack is not popped. 2798*cda5da8dSAndroid Build Coastguard Worker 5: h BINGET 0 Read an object from the memo and push it on the stack. 2799*cda5da8dSAndroid Build Coastguard Worker 7: \x85 TUPLE1 Build a one-tuple out of the topmost item on the stack. 2800*cda5da8dSAndroid Build Coastguard Worker 8: q BINPUT 1 Store the stack top into the memo. The stack is not popped. 2801*cda5da8dSAndroid Build Coastguard Worker 10: a APPEND Append an object to a list. 2802*cda5da8dSAndroid Build Coastguard Worker 11: 0 POP Discard the top stack item, shrinking the stack by one item. 2803*cda5da8dSAndroid Build Coastguard Worker 12: h BINGET 1 Read an object from the memo and push it on the stack. 2804*cda5da8dSAndroid Build Coastguard Worker 14: . STOP Stop the unpickling machine. 2805*cda5da8dSAndroid Build Coastguard Workerhighest protocol among opcodes = 2 2806*cda5da8dSAndroid Build Coastguard Worker 2807*cda5da8dSAndroid Build Coastguard Worker""" 2808*cda5da8dSAndroid Build Coastguard Worker 2809*cda5da8dSAndroid Build Coastguard Worker_memo_test = r""" 2810*cda5da8dSAndroid Build Coastguard Worker>>> import pickle 2811*cda5da8dSAndroid Build Coastguard Worker>>> import io 2812*cda5da8dSAndroid Build Coastguard Worker>>> f = io.BytesIO() 2813*cda5da8dSAndroid Build Coastguard Worker>>> p = pickle.Pickler(f, 2) 2814*cda5da8dSAndroid Build Coastguard Worker>>> x = [1, 2, 3] 2815*cda5da8dSAndroid Build Coastguard Worker>>> p.dump(x) 2816*cda5da8dSAndroid Build Coastguard Worker>>> p.dump(x) 2817*cda5da8dSAndroid Build Coastguard Worker>>> f.seek(0) 2818*cda5da8dSAndroid Build Coastguard Worker0 2819*cda5da8dSAndroid Build Coastguard Worker>>> memo = {} 2820*cda5da8dSAndroid Build Coastguard Worker>>> dis(f, memo=memo) 2821*cda5da8dSAndroid Build Coastguard Worker 0: \x80 PROTO 2 2822*cda5da8dSAndroid Build Coastguard Worker 2: ] EMPTY_LIST 2823*cda5da8dSAndroid Build Coastguard Worker 3: q BINPUT 0 2824*cda5da8dSAndroid Build Coastguard Worker 5: ( MARK 2825*cda5da8dSAndroid Build Coastguard Worker 6: K BININT1 1 2826*cda5da8dSAndroid Build Coastguard Worker 8: K BININT1 2 2827*cda5da8dSAndroid Build Coastguard Worker 10: K BININT1 3 2828*cda5da8dSAndroid Build Coastguard Worker 12: e APPENDS (MARK at 5) 2829*cda5da8dSAndroid Build Coastguard Worker 13: . STOP 2830*cda5da8dSAndroid Build Coastguard Workerhighest protocol among opcodes = 2 2831*cda5da8dSAndroid Build Coastguard Worker>>> dis(f, memo=memo) 2832*cda5da8dSAndroid Build Coastguard Worker 14: \x80 PROTO 2 2833*cda5da8dSAndroid Build Coastguard Worker 16: h BINGET 0 2834*cda5da8dSAndroid Build Coastguard Worker 18: . STOP 2835*cda5da8dSAndroid Build Coastguard Workerhighest protocol among opcodes = 2 2836*cda5da8dSAndroid Build Coastguard Worker""" 2837*cda5da8dSAndroid Build Coastguard Worker 2838*cda5da8dSAndroid Build Coastguard Worker__test__ = {'disassembler_test': _dis_test, 2839*cda5da8dSAndroid Build Coastguard Worker 'disassembler_memo_test': _memo_test, 2840*cda5da8dSAndroid Build Coastguard Worker } 2841*cda5da8dSAndroid Build Coastguard Worker 2842*cda5da8dSAndroid Build Coastguard Workerdef _test(): 2843*cda5da8dSAndroid Build Coastguard Worker import doctest 2844*cda5da8dSAndroid Build Coastguard Worker return doctest.testmod() 2845*cda5da8dSAndroid Build Coastguard Worker 2846*cda5da8dSAndroid Build Coastguard Workerif __name__ == "__main__": 2847*cda5da8dSAndroid Build Coastguard Worker import argparse 2848*cda5da8dSAndroid Build Coastguard Worker parser = argparse.ArgumentParser( 2849*cda5da8dSAndroid Build Coastguard Worker description='disassemble one or more pickle files') 2850*cda5da8dSAndroid Build Coastguard Worker parser.add_argument( 2851*cda5da8dSAndroid Build Coastguard Worker 'pickle_file', type=argparse.FileType('br'), 2852*cda5da8dSAndroid Build Coastguard Worker nargs='*', help='the pickle file') 2853*cda5da8dSAndroid Build Coastguard Worker parser.add_argument( 2854*cda5da8dSAndroid Build Coastguard Worker '-o', '--output', default=sys.stdout, type=argparse.FileType('w'), 2855*cda5da8dSAndroid Build Coastguard Worker help='the file where the output should be written') 2856*cda5da8dSAndroid Build Coastguard Worker parser.add_argument( 2857*cda5da8dSAndroid Build Coastguard Worker '-m', '--memo', action='store_true', 2858*cda5da8dSAndroid Build Coastguard Worker help='preserve memo between disassemblies') 2859*cda5da8dSAndroid Build Coastguard Worker parser.add_argument( 2860*cda5da8dSAndroid Build Coastguard Worker '-l', '--indentlevel', default=4, type=int, 2861*cda5da8dSAndroid Build Coastguard Worker help='the number of blanks by which to indent a new MARK level') 2862*cda5da8dSAndroid Build Coastguard Worker parser.add_argument( 2863*cda5da8dSAndroid Build Coastguard Worker '-a', '--annotate', action='store_true', 2864*cda5da8dSAndroid Build Coastguard Worker help='annotate each line with a short opcode description') 2865*cda5da8dSAndroid Build Coastguard Worker parser.add_argument( 2866*cda5da8dSAndroid Build Coastguard Worker '-p', '--preamble', default="==> {name} <==", 2867*cda5da8dSAndroid Build Coastguard Worker help='if more than one pickle file is specified, print this before' 2868*cda5da8dSAndroid Build Coastguard Worker ' each disassembly') 2869*cda5da8dSAndroid Build Coastguard Worker parser.add_argument( 2870*cda5da8dSAndroid Build Coastguard Worker '-t', '--test', action='store_true', 2871*cda5da8dSAndroid Build Coastguard Worker help='run self-test suite') 2872*cda5da8dSAndroid Build Coastguard Worker parser.add_argument( 2873*cda5da8dSAndroid Build Coastguard Worker '-v', action='store_true', 2874*cda5da8dSAndroid Build Coastguard Worker help='run verbosely; only affects self-test run') 2875*cda5da8dSAndroid Build Coastguard Worker args = parser.parse_args() 2876*cda5da8dSAndroid Build Coastguard Worker if args.test: 2877*cda5da8dSAndroid Build Coastguard Worker _test() 2878*cda5da8dSAndroid Build Coastguard Worker else: 2879*cda5da8dSAndroid Build Coastguard Worker annotate = 30 if args.annotate else 0 2880*cda5da8dSAndroid Build Coastguard Worker if not args.pickle_file: 2881*cda5da8dSAndroid Build Coastguard Worker parser.print_help() 2882*cda5da8dSAndroid Build Coastguard Worker elif len(args.pickle_file) == 1: 2883*cda5da8dSAndroid Build Coastguard Worker dis(args.pickle_file[0], args.output, None, 2884*cda5da8dSAndroid Build Coastguard Worker args.indentlevel, annotate) 2885*cda5da8dSAndroid Build Coastguard Worker else: 2886*cda5da8dSAndroid Build Coastguard Worker memo = {} if args.memo else None 2887*cda5da8dSAndroid Build Coastguard Worker for f in args.pickle_file: 2888*cda5da8dSAndroid Build Coastguard Worker preamble = args.preamble.format(name=f.name) 2889*cda5da8dSAndroid Build Coastguard Worker args.output.write(preamble + '\n') 2890*cda5da8dSAndroid Build Coastguard Worker dis(f, args.output, memo, args.indentlevel, annotate) 2891