Implement appropriate __getnewargs__ for all immutable subclassable builtin
types. The special handling for these can now be removed from save_newobj().
Add some testing for this.
Also add support for setting the 'fast' flag on the Python Pickler class,
which suppresses use of the memo.
diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py
index 33b96e5..ed0e436 100644
--- a/Lib/test/pickletester.py
+++ b/Lib/test/pickletester.py
@@ -324,6 +324,21 @@
## print
## pickletools.dis(s)
+ def test_newobj_generic(self):
+ for proto in [0, 1, 2]:
+ for C in myclasses:
+ B = C.__base__
+ x = C(C.sample)
+ x.foo = 42
+ s = self.dumps(x, proto)
+## import pickletools
+## print
+## pickletools.dis(s)
+ y = self.loads(s)
+ detail = (proto, C, B, x, y, type(y))
+ self.assertEqual(B(x), B(y), detail)
+ self.assertEqual(x.__dict__, y.__dict__, detail)
+
# XXX Temporary hack, so long as the C implementation of pickle protocol
# XXX 2 isn't ready. When it is, move the methods in TempAbstractPickleTests
# XXX into AbstractPickleTests above, and get rid of TempAbstractPickleTests
@@ -405,11 +420,38 @@
finally:
copy_reg.remove_extension(__name__, "MyList", 0xfffff0)
+class MyInt(int):
+ sample = 1
+
+class MyLong(long):
+ sample = 1L
+
+class MyFloat(float):
+ sample = 1.0
+
+class MyComplex(complex):
+ sample = 1.0 + 0.0j
+
+class MyStr(str):
+ sample = "hello"
+
+class MyUnicode(unicode):
+ sample = u"hello \u1234"
+
class MyTuple(tuple):
- pass
+ sample = (1, 2, 3)
class MyList(list):
- pass
+ sample = [1, 2, 3]
+
+class MyDict(dict):
+ sample = {"a": 1, "b": 2}
+
+myclasses = [MyInt, MyLong, MyFloat,
+ # MyComplex, # XXX complex somehow doesn't work here :-(
+ MyStr, MyUnicode,
+ MyTuple, MyList, MyDict]
+
class SlotList(MyList):
__slots__ = ["foo"]
diff --git a/Lib/test/test_pickle.py b/Lib/test/test_pickle.py
index d30e084..8870904 100644
--- a/Lib/test/test_pickle.py
+++ b/Lib/test/test_pickle.py
@@ -11,9 +11,13 @@
class PickleTests(AbstractPickleTests, AbstractPickleModuleTests, XXXTemp):
- def setUp(self):
- self.dumps = pickle.dumps
- self.loads = pickle.loads
+ def dumps(self, arg, proto=0, fast=0):
+ # Ignore fast
+ return pickle.dumps(arg, proto)
+
+ def loads(self, buf):
+ # Ignore fast
+ return pickle.loads(buf)
module = pickle
error = KeyError
@@ -22,9 +26,11 @@
error = KeyError
- def dumps(self, arg, proto=0):
+ def dumps(self, arg, proto=0, fast=0):
f = StringIO()
p = pickle.Pickler(f, proto)
+ if fast:
+ p.fast = fast
p.dump(arg)
f.seek(0)
return f.read()
@@ -36,12 +42,14 @@
class PersPicklerTests(AbstractPersistentPicklerTests):
- def dumps(self, arg, proto=0):
+ def dumps(self, arg, proto=0, fast=0):
class PersPickler(pickle.Pickler):
def persistent_id(subself, obj):
return self.persistent_id(obj)
f = StringIO()
p = PersPickler(f, proto)
+ if fast:
+ p.fast = fast
p.dump(arg)
f.seek(0)
return f.read()