Kaydet (Commit) a3e32c92 authored tarafından Serhiy Storchaka's avatar Serhiy Storchaka

Closes #16551. Cleanup pickle.py.

üst c8fb047d
...@@ -26,9 +26,10 @@ Misc variables: ...@@ -26,9 +26,10 @@ Misc variables:
from types import FunctionType, BuiltinFunctionType from types import FunctionType, BuiltinFunctionType
from copyreg import dispatch_table from copyreg import dispatch_table
from copyreg import _extension_registry, _inverted_registry, _extension_cache from copyreg import _extension_registry, _inverted_registry, _extension_cache
import marshal from itertools import islice
import sys import sys
import struct from sys import maxsize
from struct import pack, unpack
import re import re
import io import io
import codecs import codecs
...@@ -58,11 +59,6 @@ HIGHEST_PROTOCOL = 3 ...@@ -58,11 +59,6 @@ HIGHEST_PROTOCOL = 3
# there are too many issues with that. # there are too many issues with that.
DEFAULT_PROTOCOL = 3 DEFAULT_PROTOCOL = 3
# Why use struct.pack() for pickling but marshal.loads() for
# unpickling? struct.pack() is 40% faster than marshal.dumps(), but
# marshal.loads() is twice as fast as struct.unpack()!
mloads = marshal.loads
class PickleError(Exception): class PickleError(Exception):
"""A common base class for the other pickling exceptions.""" """A common base class for the other pickling exceptions."""
pass pass
...@@ -231,7 +227,7 @@ class _Pickler: ...@@ -231,7 +227,7 @@ class _Pickler:
raise PicklingError("Pickler.__init__() was not called by " raise PicklingError("Pickler.__init__() was not called by "
"%s.__init__()" % (self.__class__.__name__,)) "%s.__init__()" % (self.__class__.__name__,))
if self.proto >= 2: if self.proto >= 2:
self.write(PROTO + bytes([self.proto])) self.write(PROTO + pack("<B", self.proto))
self.save(obj) self.save(obj)
self.write(STOP) self.write(STOP)
...@@ -258,20 +254,20 @@ class _Pickler: ...@@ -258,20 +254,20 @@ class _Pickler:
self.memo[id(obj)] = memo_len, obj self.memo[id(obj)] = memo_len, obj
# Return a PUT (BINPUT, LONG_BINPUT) opcode string, with argument i. # Return a PUT (BINPUT, LONG_BINPUT) opcode string, with argument i.
def put(self, i, pack=struct.pack): def put(self, i):
if self.bin: if self.bin:
if i < 256: if i < 256:
return BINPUT + bytes([i]) return BINPUT + pack("<B", i)
else: else:
return LONG_BINPUT + pack("<I", i) return LONG_BINPUT + pack("<I", i)
return PUT + repr(i).encode("ascii") + b'\n' return PUT + repr(i).encode("ascii") + b'\n'
# Return a GET (BINGET, LONG_BINGET) opcode string, with argument i. # Return a GET (BINGET, LONG_BINGET) opcode string, with argument i.
def get(self, i, pack=struct.pack): def get(self, i):
if self.bin: if self.bin:
if i < 256: if i < 256:
return BINGET + bytes([i]) return BINGET + pack("<B", i)
else: else:
return LONG_BINGET + pack("<I", i) return LONG_BINGET + pack("<I", i)
...@@ -286,20 +282,20 @@ class _Pickler: ...@@ -286,20 +282,20 @@ class _Pickler:
# Check the memo # Check the memo
x = self.memo.get(id(obj)) x = self.memo.get(id(obj))
if x: if x is not None:
self.write(self.get(x[0])) self.write(self.get(x[0]))
return return
# Check the type dispatch table # Check the type dispatch table
t = type(obj) t = type(obj)
f = self.dispatch.get(t) f = self.dispatch.get(t)
if f: if f is not None:
f(self, obj) # Call unbound method with explicit self f(self, obj) # Call unbound method with explicit self
return return
# Check private dispatch table if any, or else copyreg.dispatch_table # Check private dispatch table if any, or else copyreg.dispatch_table
reduce = getattr(self, 'dispatch_table', dispatch_table).get(t) reduce = getattr(self, 'dispatch_table', dispatch_table).get(t)
if reduce: if reduce is not None:
rv = reduce(obj) rv = reduce(obj)
else: else:
# Check for a class with a custom metaclass; treat as regular class # Check for a class with a custom metaclass; treat as regular class
...@@ -313,11 +309,11 @@ class _Pickler: ...@@ -313,11 +309,11 @@ class _Pickler:
# Check for a __reduce_ex__ method, fall back to __reduce__ # Check for a __reduce_ex__ method, fall back to __reduce__
reduce = getattr(obj, "__reduce_ex__", None) reduce = getattr(obj, "__reduce_ex__", None)
if reduce: if reduce is not None:
rv = reduce(self.proto) rv = reduce(self.proto)
else: else:
reduce = getattr(obj, "__reduce__", None) reduce = getattr(obj, "__reduce__", None)
if reduce: if reduce is not None:
rv = reduce() rv = reduce()
else: else:
raise PicklingError("Can't pickle %r object: %r" % raise PicklingError("Can't pickle %r object: %r" %
...@@ -448,12 +444,12 @@ class _Pickler: ...@@ -448,12 +444,12 @@ class _Pickler:
def save_bool(self, obj): def save_bool(self, obj):
if self.proto >= 2: if self.proto >= 2:
self.write(obj and NEWTRUE or NEWFALSE) self.write(NEWTRUE if obj else NEWFALSE)
else: else:
self.write(obj and TRUE or FALSE) self.write(TRUE if obj else FALSE)
dispatch[bool] = save_bool dispatch[bool] = save_bool
def save_long(self, obj, pack=struct.pack): def save_long(self, obj):
if self.bin: if self.bin:
# If the int is small enough to fit in a signed 4-byte 2's-comp # If the int is small enough to fit in a signed 4-byte 2's-comp
# format, we can store it more efficiently than the general # format, we can store it more efficiently than the general
...@@ -461,39 +457,36 @@ class _Pickler: ...@@ -461,39 +457,36 @@ class _Pickler:
# First one- and two-byte unsigned ints: # First one- and two-byte unsigned ints:
if obj >= 0: if obj >= 0:
if obj <= 0xff: if obj <= 0xff:
self.write(BININT1 + bytes([obj])) self.write(BININT1 + pack("<B", obj))
return return
if obj <= 0xffff: if obj <= 0xffff:
self.write(BININT2 + bytes([obj&0xff, obj>>8])) self.write(BININT2 + pack("<H", obj))
return return
# Next check for 4-byte signed ints: # Next check for 4-byte signed ints:
high_bits = obj >> 31 # note that Python shift sign-extends if -0x80000000 <= obj <= 0x7fffffff:
if high_bits == 0 or high_bits == -1:
# All high bits are copies of bit 2**31, so the value
# fits in a 4-byte signed int.
self.write(BININT + pack("<i", obj)) self.write(BININT + pack("<i", obj))
return return
if self.proto >= 2: if self.proto >= 2:
encoded = encode_long(obj) encoded = encode_long(obj)
n = len(encoded) n = len(encoded)
if n < 256: if n < 256:
self.write(LONG1 + bytes([n]) + encoded) self.write(LONG1 + pack("<B", n) + encoded)
else: else:
self.write(LONG4 + pack("<i", n) + encoded) self.write(LONG4 + pack("<i", n) + encoded)
return return
self.write(LONG + repr(obj).encode("ascii") + b'L\n') self.write(LONG + repr(obj).encode("ascii") + b'L\n')
dispatch[int] = save_long dispatch[int] = save_long
def save_float(self, obj, pack=struct.pack): def save_float(self, obj):
if self.bin: if self.bin:
self.write(BINFLOAT + pack('>d', obj)) self.write(BINFLOAT + pack('>d', obj))
else: else:
self.write(FLOAT + repr(obj).encode("ascii") + b'\n') self.write(FLOAT + repr(obj).encode("ascii") + b'\n')
dispatch[float] = save_float dispatch[float] = save_float
def save_bytes(self, obj, pack=struct.pack): def save_bytes(self, obj):
if self.proto < 3: if self.proto < 3:
if len(obj) == 0: if not obj: # bytes object is empty
self.save_reduce(bytes, (), obj=obj) self.save_reduce(bytes, (), obj=obj)
else: else:
self.save_reduce(codecs.encode, self.save_reduce(codecs.encode,
...@@ -501,13 +494,13 @@ class _Pickler: ...@@ -501,13 +494,13 @@ class _Pickler:
return return
n = len(obj) n = len(obj)
if n < 256: if n < 256:
self.write(SHORT_BINBYTES + bytes([n]) + bytes(obj)) self.write(SHORT_BINBYTES + pack("<B", n) + obj)
else: else:
self.write(BINBYTES + pack("<I", n) + bytes(obj)) self.write(BINBYTES + pack("<I", n) + obj)
self.memoize(obj) self.memoize(obj)
dispatch[bytes] = save_bytes dispatch[bytes] = save_bytes
def save_str(self, obj, pack=struct.pack): def save_str(self, obj):
if self.bin: if self.bin:
encoded = obj.encode('utf-8', 'surrogatepass') encoded = obj.encode('utf-8', 'surrogatepass')
n = len(encoded) n = len(encoded)
...@@ -515,39 +508,36 @@ class _Pickler: ...@@ -515,39 +508,36 @@ class _Pickler:
else: else:
obj = obj.replace("\\", "\\u005c") obj = obj.replace("\\", "\\u005c")
obj = obj.replace("\n", "\\u000a") obj = obj.replace("\n", "\\u000a")
self.write(UNICODE + bytes(obj.encode('raw-unicode-escape')) + self.write(UNICODE + obj.encode('raw-unicode-escape') + b'\n')
b'\n')
self.memoize(obj) self.memoize(obj)
dispatch[str] = save_str dispatch[str] = save_str
def save_tuple(self, obj): def save_tuple(self, obj):
write = self.write if not obj: # tuple is empty
proto = self.proto if self.bin:
self.write(EMPTY_TUPLE)
n = len(obj)
if n == 0:
if proto:
write(EMPTY_TUPLE)
else: else:
write(MARK + TUPLE) self.write(MARK + TUPLE)
return return
n = len(obj)
save = self.save save = self.save
memo = self.memo memo = self.memo
if n <= 3 and proto >= 2: if n <= 3 and self.proto >= 2:
for element in obj: for element in obj:
save(element) save(element)
# Subtle. Same as in the big comment below. # Subtle. Same as in the big comment below.
if id(obj) in memo: if id(obj) in memo:
get = self.get(memo[id(obj)][0]) get = self.get(memo[id(obj)][0])
write(POP * n + get) self.write(POP * n + get)
else: else:
write(_tuplesize2code[n]) self.write(_tuplesize2code[n])
self.memoize(obj) self.memoize(obj)
return return
# proto 0 or proto 1 and tuple isn't empty, or proto > 1 and tuple # proto 0 or proto 1 and tuple isn't empty, or proto > 1 and tuple
# has more than 3 elements. # has more than 3 elements.
write = self.write
write(MARK) write(MARK)
for element in obj: for element in obj:
save(element) save(element)
...@@ -561,25 +551,23 @@ class _Pickler: ...@@ -561,25 +551,23 @@ class _Pickler:
# could have been done in the "for element" loop instead, but # could have been done in the "for element" loop instead, but
# recursive tuples are a rare thing. # recursive tuples are a rare thing.
get = self.get(memo[id(obj)][0]) get = self.get(memo[id(obj)][0])
if proto: if self.bin:
write(POP_MARK + get) write(POP_MARK + get)
else: # proto 0 -- POP_MARK not available else: # proto 0 -- POP_MARK not available
write(POP * (n+1) + get) write(POP * (n+1) + get)
return return
# No recursion. # No recursion.
self.write(TUPLE) write(TUPLE)
self.memoize(obj) self.memoize(obj)
dispatch[tuple] = save_tuple dispatch[tuple] = save_tuple
def save_list(self, obj): def save_list(self, obj):
write = self.write
if self.bin: if self.bin:
write(EMPTY_LIST) self.write(EMPTY_LIST)
else: # proto 0 -- can't use EMPTY_LIST else: # proto 0 -- can't use EMPTY_LIST
write(MARK + LIST) self.write(MARK + LIST)
self.memoize(obj) self.memoize(obj)
self._batch_appends(obj) self._batch_appends(obj)
...@@ -599,17 +587,9 @@ class _Pickler: ...@@ -599,17 +587,9 @@ class _Pickler:
write(APPEND) write(APPEND)
return return
items = iter(items) it = iter(items)
r = range(self._BATCHSIZE) while True:
while items is not None: tmp = list(islice(it, self._BATCHSIZE))
tmp = []
for i in r:
try:
x = next(items)
tmp.append(x)
except StopIteration:
items = None
break
n = len(tmp) n = len(tmp)
if n > 1: if n > 1:
write(MARK) write(MARK)
...@@ -620,14 +600,14 @@ class _Pickler: ...@@ -620,14 +600,14 @@ class _Pickler:
save(tmp[0]) save(tmp[0])
write(APPEND) write(APPEND)
# else tmp is empty, and we're done # else tmp is empty, and we're done
if n < self._BATCHSIZE:
return
def save_dict(self, obj): def save_dict(self, obj):
write = self.write
if self.bin: if self.bin:
write(EMPTY_DICT) self.write(EMPTY_DICT)
else: # proto 0 -- can't use EMPTY_DICT else: # proto 0 -- can't use EMPTY_DICT
write(MARK + DICT) self.write(MARK + DICT)
self.memoize(obj) self.memoize(obj)
self._batch_setitems(obj.items()) self._batch_setitems(obj.items())
...@@ -648,16 +628,9 @@ class _Pickler: ...@@ -648,16 +628,9 @@ class _Pickler:
write(SETITEM) write(SETITEM)
return return
items = iter(items) it = iter(items)
r = range(self._BATCHSIZE) while True:
while items is not None: tmp = list(islice(it, self._BATCHSIZE))
tmp = []
for i in r:
try:
tmp.append(next(items))
except StopIteration:
items = None
break
n = len(tmp) n = len(tmp)
if n > 1: if n > 1:
write(MARK) write(MARK)
...@@ -671,8 +644,10 @@ class _Pickler: ...@@ -671,8 +644,10 @@ class _Pickler:
save(v) save(v)
write(SETITEM) write(SETITEM)
# else tmp is empty, and we're done # else tmp is empty, and we're done
if n < self._BATCHSIZE:
return
def save_global(self, obj, name=None, pack=struct.pack): def save_global(self, obj, name=None):
write = self.write write = self.write
memo = self.memo memo = self.memo
...@@ -702,9 +677,9 @@ class _Pickler: ...@@ -702,9 +677,9 @@ class _Pickler:
if code: if code:
assert code > 0 assert code > 0
if code <= 0xff: if code <= 0xff:
write(EXT1 + bytes([code])) write(EXT1 + pack("<B", code))
elif code <= 0xffff: elif code <= 0xffff:
write(EXT2 + bytes([code&0xff, code>>8])) write(EXT2 + pack("<H", code))
else: else:
write(EXT4 + pack("<i", code)) write(EXT4 + pack("<i", code))
return return
...@@ -732,25 +707,6 @@ class _Pickler: ...@@ -732,25 +707,6 @@ class _Pickler:
dispatch[BuiltinFunctionType] = save_global dispatch[BuiltinFunctionType] = save_global
dispatch[type] = save_global dispatch[type] = save_global
# Pickling helpers
def _keep_alive(x, memo):
"""Keeps a reference to the object x in the memo.
Because we remember objects by their id, we have
to assure that possibly temporary objects are kept
alive by referencing them.
We store a reference at the id of the memo, which should
normally not be used unless someone tries to deepcopy
the memo itself...
"""
try:
memo[id(memo)].append(x)
except KeyError:
# aha, this is the first one :-)
memo[id(memo)]=[x]
# A cache for whichmodule(), mapping a function object to the name of # A cache for whichmodule(), mapping a function object to the name of
# the module in which the function was found. # the module in which the function was found.
...@@ -832,7 +788,7 @@ class _Unpickler: ...@@ -832,7 +788,7 @@ class _Unpickler:
read = self.read read = self.read
dispatch = self.dispatch dispatch = self.dispatch
try: try:
while 1: while True:
key = read(1) key = read(1)
if not key: if not key:
raise EOFError raise EOFError
...@@ -862,7 +818,7 @@ class _Unpickler: ...@@ -862,7 +818,7 @@ class _Unpickler:
dispatch = {} dispatch = {}
def load_proto(self): def load_proto(self):
proto = ord(self.read(1)) proto = self.read(1)[0]
if not 0 <= proto <= HIGHEST_PROTOCOL: if not 0 <= proto <= HIGHEST_PROTOCOL:
raise ValueError("unsupported pickle protocol: %d" % proto) raise ValueError("unsupported pickle protocol: %d" % proto)
self.proto = proto self.proto = proto
...@@ -897,40 +853,37 @@ class _Unpickler: ...@@ -897,40 +853,37 @@ class _Unpickler:
elif data == TRUE[1:]: elif data == TRUE[1:]:
val = True val = True
else: else:
try: val = int(data, 0)
val = int(data, 0)
except ValueError:
val = int(data, 0)
self.append(val) self.append(val)
dispatch[INT[0]] = load_int dispatch[INT[0]] = load_int
def load_binint(self): def load_binint(self):
self.append(mloads(b'i' + self.read(4))) self.append(unpack('<i', self.read(4))[0])
dispatch[BININT[0]] = load_binint dispatch[BININT[0]] = load_binint
def load_binint1(self): def load_binint1(self):
self.append(ord(self.read(1))) self.append(self.read(1)[0])
dispatch[BININT1[0]] = load_binint1 dispatch[BININT1[0]] = load_binint1
def load_binint2(self): def load_binint2(self):
self.append(mloads(b'i' + self.read(2) + b'\000\000')) self.append(unpack('<H', self.read(2))[0])
dispatch[BININT2[0]] = load_binint2 dispatch[BININT2[0]] = load_binint2
def load_long(self): def load_long(self):
val = self.readline()[:-1].decode("ascii") val = self.readline()[:-1]
if val and val[-1] == 'L': if val and val[-1] == b'L'[0]:
val = val[:-1] val = val[:-1]
self.append(int(val, 0)) self.append(int(val, 0))
dispatch[LONG[0]] = load_long dispatch[LONG[0]] = load_long
def load_long1(self): def load_long1(self):
n = ord(self.read(1)) n = self.read(1)[0]
data = self.read(n) data = self.read(n)
self.append(decode_long(data)) self.append(decode_long(data))
dispatch[LONG1[0]] = load_long1 dispatch[LONG1[0]] = load_long1
def load_long4(self): def load_long4(self):
n = mloads(b'i' + self.read(4)) n, = unpack('<i', self.read(4))
if n < 0: if n < 0:
# Corrupt or hostile pickle -- we never write one like this # Corrupt or hostile pickle -- we never write one like this
raise UnpicklingError("LONG pickle has negative byte count") raise UnpicklingError("LONG pickle has negative byte count")
...@@ -942,28 +895,25 @@ class _Unpickler: ...@@ -942,28 +895,25 @@ class _Unpickler:
self.append(float(self.readline()[:-1])) self.append(float(self.readline()[:-1]))
dispatch[FLOAT[0]] = load_float dispatch[FLOAT[0]] = load_float
def load_binfloat(self, unpack=struct.unpack): def load_binfloat(self):
self.append(unpack('>d', self.read(8))[0]) self.append(unpack('>d', self.read(8))[0])
dispatch[BINFLOAT[0]] = load_binfloat dispatch[BINFLOAT[0]] = load_binfloat
def load_string(self): def load_string(self):
orig = self.readline() orig = self.readline()
rep = orig[:-1] rep = orig[:-1]
for q in (b'"', b"'"): # double or single quote # Strip outermost quotes
if rep.startswith(q): if rep[0] == rep[-1] and rep[0] in b'"\'':
if not rep.endswith(q): rep = rep[1:-1]
raise ValueError("insecure string pickle")
rep = rep[len(q):-len(q)]
break
else: else:
raise ValueError("insecure string pickle: %r" % orig) raise ValueError("insecure string pickle")
self.append(codecs.escape_decode(rep)[0] self.append(codecs.escape_decode(rep)[0]
.decode(self.encoding, self.errors)) .decode(self.encoding, self.errors))
dispatch[STRING[0]] = load_string dispatch[STRING[0]] = load_string
def load_binstring(self): def load_binstring(self):
# Deprecated BINSTRING uses signed 32-bit length # Deprecated BINSTRING uses signed 32-bit length
len = mloads(b'i' + self.read(4)) len, = unpack('<i', self.read(4))
if len < 0: if len < 0:
raise UnpicklingError("BINSTRING pickle has negative byte count") raise UnpicklingError("BINSTRING pickle has negative byte count")
data = self.read(len) data = self.read(len)
...@@ -971,7 +921,7 @@ class _Unpickler: ...@@ -971,7 +921,7 @@ class _Unpickler:
self.append(value) self.append(value)
dispatch[BINSTRING[0]] = load_binstring dispatch[BINSTRING[0]] = load_binstring
def load_binbytes(self, unpack=struct.unpack, maxsize=sys.maxsize): def load_binbytes(self):
len, = unpack('<I', self.read(4)) len, = unpack('<I', self.read(4))
if len > maxsize: if len > maxsize:
raise UnpicklingError("BINBYTES exceeds system's maximum size " raise UnpicklingError("BINBYTES exceeds system's maximum size "
...@@ -983,7 +933,7 @@ class _Unpickler: ...@@ -983,7 +933,7 @@ class _Unpickler:
self.append(str(self.readline()[:-1], 'raw-unicode-escape')) self.append(str(self.readline()[:-1], 'raw-unicode-escape'))
dispatch[UNICODE[0]] = load_unicode dispatch[UNICODE[0]] = load_unicode
def load_binunicode(self, unpack=struct.unpack, maxsize=sys.maxsize): def load_binunicode(self):
len, = unpack('<I', self.read(4)) len, = unpack('<I', self.read(4))
if len > maxsize: if len > maxsize:
raise UnpicklingError("BINUNICODE exceeds system's maximum size " raise UnpicklingError("BINUNICODE exceeds system's maximum size "
...@@ -992,15 +942,15 @@ class _Unpickler: ...@@ -992,15 +942,15 @@ class _Unpickler:
dispatch[BINUNICODE[0]] = load_binunicode dispatch[BINUNICODE[0]] = load_binunicode
def load_short_binstring(self): def load_short_binstring(self):
len = ord(self.read(1)) len = self.read(1)[0]
data = bytes(self.read(len)) data = self.read(len)
value = str(data, self.encoding, self.errors) value = str(data, self.encoding, self.errors)
self.append(value) self.append(value)
dispatch[SHORT_BINSTRING[0]] = load_short_binstring dispatch[SHORT_BINSTRING[0]] = load_short_binstring
def load_short_binbytes(self): def load_short_binbytes(self):
len = ord(self.read(1)) len = self.read(1)[0]
self.append(bytes(self.read(len))) self.append(self.read(len))
dispatch[SHORT_BINBYTES[0]] = load_short_binbytes dispatch[SHORT_BINBYTES[0]] = load_short_binbytes
def load_tuple(self): def load_tuple(self):
...@@ -1039,12 +989,9 @@ class _Unpickler: ...@@ -1039,12 +989,9 @@ class _Unpickler:
def load_dict(self): def load_dict(self):
k = self.marker() k = self.marker()
d = {}
items = self.stack[k+1:] items = self.stack[k+1:]
for i in range(0, len(items), 2): d = {items[i]: items[i+1]
key = items[i] for i in range(0, len(items), 2)}
value = items[i+1]
d[key] = value
self.stack[k:] = [d] self.stack[k:] = [d]
dispatch[DICT[0]] = load_dict dispatch[DICT[0]] = load_dict
...@@ -1096,17 +1043,17 @@ class _Unpickler: ...@@ -1096,17 +1043,17 @@ class _Unpickler:
dispatch[GLOBAL[0]] = load_global dispatch[GLOBAL[0]] = load_global
def load_ext1(self): def load_ext1(self):
code = ord(self.read(1)) code = self.read(1)[0]
self.get_extension(code) self.get_extension(code)
dispatch[EXT1[0]] = load_ext1 dispatch[EXT1[0]] = load_ext1
def load_ext2(self): def load_ext2(self):
code = mloads(b'i' + self.read(2) + b'\000\000') code, = unpack('<H', self.read(2))
self.get_extension(code) self.get_extension(code)
dispatch[EXT2[0]] = load_ext2 dispatch[EXT2[0]] = load_ext2
def load_ext4(self): def load_ext4(self):
code = mloads(b'i' + self.read(4)) code, = unpack('<i', self.read(4))
self.get_extension(code) self.get_extension(code)
dispatch[EXT4[0]] = load_ext4 dispatch[EXT4[0]] = load_ext4
...@@ -1174,7 +1121,7 @@ class _Unpickler: ...@@ -1174,7 +1121,7 @@ class _Unpickler:
self.append(self.memo[i]) self.append(self.memo[i])
dispatch[BINGET[0]] = load_binget dispatch[BINGET[0]] = load_binget
def load_long_binget(self, unpack=struct.unpack): def load_long_binget(self):
i, = unpack('<I', self.read(4)) i, = unpack('<I', self.read(4))
self.append(self.memo[i]) self.append(self.memo[i])
dispatch[LONG_BINGET[0]] = load_long_binget dispatch[LONG_BINGET[0]] = load_long_binget
...@@ -1193,7 +1140,7 @@ class _Unpickler: ...@@ -1193,7 +1140,7 @@ class _Unpickler:
self.memo[i] = self.stack[-1] self.memo[i] = self.stack[-1]
dispatch[BINPUT[0]] = load_binput dispatch[BINPUT[0]] = load_binput
def load_long_binput(self, unpack=struct.unpack, maxsize=sys.maxsize): def load_long_binput(self):
i, = unpack('<I', self.read(4)) i, = unpack('<I', self.read(4))
if i > maxsize: if i > maxsize:
raise ValueError("negative LONG_BINPUT argument") raise ValueError("negative LONG_BINPUT argument")
...@@ -1238,7 +1185,7 @@ class _Unpickler: ...@@ -1238,7 +1185,7 @@ class _Unpickler:
state = stack.pop() state = stack.pop()
inst = stack[-1] inst = stack[-1]
setstate = getattr(inst, "__setstate__", None) setstate = getattr(inst, "__setstate__", None)
if setstate: if setstate is not None:
setstate(state) setstate(state)
return return
slotstate = None slotstate = None
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment