xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/pickletools.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
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