return complex, (c.real, c.imag)
pickle(type(1j), pickle_complex, complex)
+
+# Support for picking new-style objects
+
+_dummy_classes = {}
+
+def _reconstructor(cls, base, state):
+ dummy = _dummy_classes.get(base)
+ if dummy is None:
+ class dummy(base): pass
+ _dummy_classes[base] = dummy
+ obj = dummy(state)
+ obj._foo = 1; del obj._foo # hack to create __dict__
+ obj.__class__ = cls
+ return obj
+_reconstructor.__safe_for_unpickling__ = 1
+
+_HEAPTYPE = 1<<9
+
+def _reduce(self):
+ for base in self.__class__.__mro__:
+ if not base.__flags__ & _HEAPTYPE:
+ break
+ else:
+ base = object # not really reachable
+ if base is object:
+ state = None
+ else:
+ state = base(self)
+ return _reconstructor, (self.__class__, base, state), self.__dict__
class Cdict(object):
pass
x = Cdict()
- verify(x.__dict__ is None)
+ verify(x.__dict__ == {})
x.foo = 1
verify(x.foo == 1)
verify(x.__dict__ == {'foo': 1})
cant(object(), list)
cant(list(), object)
+def pickles():
+ if verbose: print "Testing pickling new-style classes and objects..."
+ import pickle, cPickle
+
+ def sorteditems(d):
+ L = d.items()
+ L.sort()
+ return L
+
+ global C
+ class C(object):
+ def __init__(self, a, b):
+ super(C, self).__init__()
+ self.a = a
+ self.b = b
+ def __repr__(self):
+ return "C(%r, %r)" % (self.a, self.b)
+
+ global C1
+ class C1(list):
+ def __new__(cls, a, b):
+ return super(C1, cls).__new__(cls)
+ def __init__(self, a, b):
+ self.a = a
+ self.b = b
+ def __repr__(self):
+ return "C1(%r, %r)<%r>" % (self.a, self.b, list(self))
+
+ global C2
+ class C2(int):
+ def __new__(cls, a, b, val=0):
+ return super(C2, cls).__new__(cls, val)
+ def __init__(self, a, b, val=0):
+ self.a = a
+ self.b = b
+ def __repr__(self):
+ return "C2(%r, %r)<%r>" % (self.a, self.b, int(self))
+
+ for p in pickle, cPickle:
+ for bin in 0, 1:
+
+ for cls in C, C1, C2:
+ s = p.dumps(cls, bin)
+ cls2 = p.loads(s)
+ verify(cls2 is cls)
+
+ a = C1(1, 2); a.append(42); a.append(24)
+ b = C2("hello", "world", 42)
+ s = p.dumps((a, b), bin)
+ x, y = p.loads(s)
+ assert x.__class__ == a.__class__
+ assert sorteditems(x.__dict__) == sorteditems(a.__dict__)
+ assert y.__class__ == b.__class__
+ assert sorteditems(y.__dict__) == sorteditems(b.__dict__)
+ assert `x` == `a`
+ assert `y` == `b`
+ if verbose:
+ print "a = x =", a
+ print "b = y =", b
+
def test_main():
lists()
coercions()
descrdoc()
setclass()
+ pickles()
if verbose: print "All OK"
if __name__ == "__main__":
return NULL;
}
+static int
+type_set_module(PyTypeObject *type, PyObject *value, void *context)
+{
+ if (!(type->tp_flags & Py_TPFLAGS_DYNAMICTYPE) ||
+ strrchr(type->tp_name, '.')) {
+ PyErr_Format(PyExc_TypeError,
+ "can't set %s.__module__", type->tp_name);
+ return -1;
+ }
+ if (!value) {
+ PyErr_Format(PyExc_TypeError,
+ "can't delete %s.__module__", type->tp_name);
+ return -1;
+ }
+ return PyDict_SetItemString(type->tp_dict, "__module__", value);
+}
+
static PyObject *
type_dict(PyTypeObject *type, void *context)
{
PyGetSetDef type_getsets[] = {
{"__name__", (getter)type_name, NULL, NULL},
- {"__module__", (getter)type_module, NULL, NULL},
+ {"__module__", (getter)type_module, (setter)type_set_module, NULL},
{"__dict__", (getter)type_dict, NULL, NULL},
{"__defined__", (getter)type_defined, NULL, NULL},
{"__dynamic__", (getter)type_dynamic, NULL, NULL},
return NULL;
}
dict = *dictptr;
- if (dict == NULL) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- else {
- Py_INCREF(dict);
- return dict;
- }
+ if (dict == NULL)
+ *dictptr = dict = PyDict_New();
+ Py_XINCREF(dict);
+ return dict;
}
PyGetSetDef subtype_getsets[] = {
{0}
};
+static PyObject *
+object_reduce(PyObject *self, PyObject *args)
+{
+ /* Call copy_reg._reduce(self) */
+ static PyObject *copy_reg_str;
+ PyObject *copy_reg, *res;
+
+ if (!copy_reg_str) {
+ copy_reg_str = PyString_InternFromString("copy_reg");
+ if (copy_reg_str == NULL)
+ return NULL;
+ }
+ copy_reg = PyImport_Import(copy_reg_str);
+ if (!copy_reg)
+ return NULL;
+ res = PyEval_CallMethod(copy_reg, "_reduce", "(O)", self);
+ Py_DECREF(copy_reg);
+ return res;
+}
+
+static PyMethodDef object_methods[] = {
+ {"__reduce__", object_reduce, METH_NOARGS, "helper for pickle"},
+ {0}
+};
+
PyTypeObject PyBaseObject_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0, /* ob_size */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
- 0, /* tp_methods */
+ object_methods, /* tp_methods */
0, /* tp_members */
object_getsets, /* tp_getset */
0, /* tp_base */
res = PyObject_GenericGetAttr(self, name);
else
res = PyObject_CallFunction(getattribute, "OO", self, name);
- if (res == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
+ if (getattr != NULL &&
+ res == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
res = PyObject_CallFunction(getattr, "OO", self, name);
}