diff -r e34b09c69dd3 Lib/pickle.py --- a/Lib/pickle.py Sat Mar 12 22:31:06 2011 -0500 +++ b/Lib/pickle.py Sun Mar 13 10:51:54 2011 +0100 @@ -299,20 +299,20 @@ f(self, obj) # Call unbound method with explicit self return - # Check for a class with a custom metaclass; treat as regular class - try: - issc = issubclass(t, type) - except TypeError: # t is not a class (old Boost; see SF #502085) - issc = 0 - if issc: - self.save_global(obj) - return - # Check copyreg.dispatch_table reduce = dispatch_table.get(t) if reduce: rv = reduce(obj) else: + # Check for a class with a custom metaclass; treat as regular class + try: + issc = issubclass(t, type) + except TypeError: # t is not a class (old Boost; see SF #502085) + issc = False + if issc: + self.save_global(obj) + return + # Check for a __reduce_ex__ method, fall back to __reduce__ reduce = getattr(obj, "__reduce_ex__", None) if reduce: diff -r e34b09c69dd3 Lib/test/pickletester.py --- a/Lib/test/pickletester.py Sat Mar 12 22:31:06 2011 -0500 +++ b/Lib/test/pickletester.py Sun Mar 13 10:51:54 2011 +0100 @@ -116,6 +116,21 @@ class use_metaclass(object, metaclass=metaclass): pass +class pickling_metaclass(type): + def __eq__(self, other): + r = (type(self) == type(other)) + if r: + return r + return (self.reduce_args == other.reduce_args) + + def __reduce__(self): + return (create_dynamic_class, self.reduce_args) + +def create_dynamic_class(name, bases): + result = pickling_metaclass(name, bases, dict()) + result.reduce_args = (name, bases) + return result + # DATA0 .. DATA2 are the pickles we expect under the various protocols, for # the object returned by create_data(). @@ -690,6 +705,14 @@ b = self.loads(s) self.assertEqual(a.__class__, b.__class__) + def test_dynamicclass(self): + a = create_dynamic_class("my_dynamic_class", (object,)) + copyreg.pickle(pickling_metaclass, pickling_metaclass.__reduce__) + for proto in protocols: + s = self.dumps(a, proto) + b = self.loads(s) + self.assertEqual(a, b) + def test_structseq(self): import time import os diff -r e34b09c69dd3 Modules/_pickle.c --- a/Modules/_pickle.c Sat Mar 12 22:31:06 2011 -0500 +++ b/Modules/_pickle.c Sun Mar 13 10:51:54 2011 +0100 @@ -3151,10 +3151,6 @@ status = save_global(self, obj, NULL); goto done; } - else if (PyType_IsSubtype(type, &PyType_Type)) { - status = save_global(self, obj, NULL); - goto done; - } /* XXX: This part needs some unit tests. */ @@ -3173,6 +3169,10 @@ Py_INCREF(obj); reduce_value = _Pickler_FastCall(self, reduce_func, obj); } + else if (PyType_IsSubtype(type, &PyType_Type)) { + status = save_global(self, obj, NULL); + goto done; + } else { static PyObject *reduce_str = NULL; static PyObject *reduce_ex_str = NULL;