diff options
-rw-r--r-- | Lib/pickle.py | 46 | ||||
-rw-r--r-- | Lib/test/pickletester.py | 37 |
2 files changed, 53 insertions, 30 deletions
diff --git a/Lib/pickle.py b/Lib/pickle.py index c1c7078..1cee4d5 100644 --- a/Lib/pickle.py +++ b/Lib/pickle.py @@ -27,7 +27,7 @@ Misc variables: __version__ = "$Revision$" # Code version from types import * -from copy_reg import dispatch_table, safe_constructors +from copy_reg import dispatch_table, safe_constructors, _reconstructor import marshal import sys import struct @@ -320,6 +320,13 @@ class Pickler: raise PicklingError("Tuple returned by %s must have " "exactly two or three elements" % reduce) + # XXX Temporary hack XXX + # Override the default __reduce__ for new-style class instances + if self.proto >= 2: + if func is _reconstructor: + self.save_newobj(obj) + return + # Save the reduce() output and finally memoize the object self.save_reduce(func, args, state) self.memoize(obj) @@ -369,14 +376,37 @@ class Pickler: # Save a new-style class instance, using protocol 2. # XXX Much of this is still experimental. t = type(obj) - args = () getnewargs = getattr(obj, "__getnewargs__", None) if getnewargs: args = getnewargs() # This better not reference obj + else: + for cls in int, long, float, complex, str, unicode, tuple: + if isinstance(obj, cls): + args = (cls(obj),) + break + else: + args = () + + save = self.save + write = self.write + self.save_global(t) - self.save(args) - self.write(NEWOBJ) + save(args) + write(NEWOBJ) self.memoize(obj) + + if isinstance(obj, list): + write(MARK) + for x in obj: + save(x) + write(APPENDS) + elif isinstance(obj, dict): + write(MARK) + for k, v in obj.iteritems(): + save(k) + save(v) + write(SETITEMS) + getstate = getattr(obj, "__getstate__", None) if getstate: state = getstate() @@ -384,9 +414,8 @@ class Pickler: state = getattr(obj, "__dict__", None) # XXX What about __slots__? if state is not None: - self.save(state) - self.write(BUILD) - return + save(state) + write(BUILD) # Methods below this point are dispatched through the dispatch table @@ -1173,6 +1202,8 @@ def encode_long(x): '\x7f' >>> """ + # XXX This is still a quadratic algorithm. + # Should use hex() to get started. digits = [] while not -128 <= x < 128: digits.append(x & 0xff) @@ -1195,6 +1226,7 @@ def decode_long(data): >>> decode_long("\x7f") 127L """ + # XXX This is quadratic too. x = 0L i = 0L for c in data: diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index ea658bb..cc464a9 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -301,43 +301,34 @@ class AbstractPickleTests(unittest.TestCase): self.assert_(x is y, (proto, x, s, y)) def test_newobj_tuple(self): - x = MyTuple([1, 2, 3], foo=42, bar="hello") + x = MyTuple([1, 2, 3]) + x.foo = 42 + x.bar = "hello" s = self.dumps(x, 2) y = self.loads(s) self.assertEqual(tuple(x), tuple(y)) self.assertEqual(x.__dict__, y.__dict__) +## import pickletools +## print +## pickletools.dis(s) def test_newobj_list(self): - x = MyList([1, 2, 3], foo=42, bar="hello") + x = MyList([1, 2, 3]) + x.foo = 42 + x.bar = "hello" s = self.dumps(x, 2) y = self.loads(s) self.assertEqual(list(x), list(y)) self.assertEqual(x.__dict__, y.__dict__) +## import pickletools +## print +## pickletools.dis(s) class MyTuple(tuple): - def __new__(cls, *args, **kwds): - # Ignore **kwds - return tuple.__new__(cls, *args) - def __getnewargs__(self): - return (tuple(self),) - def __init__(self, *args, **kwds): - for k, v in kwds.items(): - setattr(self, k, v) + pass class MyList(list): - def __new__(cls, *args, **kwds): - # Ignore **kwds - return list.__new__(cls, *args) - def __init__(self, *args, **kwds): - for k, v in kwds.items(): - setattr(self, k, v) - def __getstate__(self): - return list(self), self.__dict__ - def __setstate__(self, arg): - lst, dct = arg - for x in lst: - self.append(x) - self.__init__(**dct) + pass class AbstractPickleModuleTests(unittest.TestCase): |