[Zope-Checkins] CVS: Zope3/lib/python/Zope/ContextWrapper - wrapper.c:1.12.2.1
Fred Drake Jr
fdrake@acm.org
Wed, 28 Nov 2001 15:12:06 -0500
Update of /cvs-repository/Zope3/lib/python/Zope/ContextWrapper
In directory cvs.zope.org:/tmp/cvs-serv31004/ContextWrapper
Modified Files:
Tag: Zope-3x-branch
wrapper.c
Log Message:
Add a __reduce__() method to Wrapper so that pickling is disabled by
default. Picklable Wrapper subclasses need to replace __reduce__() to
support pickling.
Fudge attribute access for __class__ so that the type of the wrapped
object is returned. This is a Jim requirement.
=== Zope3/lib/python/Zope/ContextWrapper/wrapper.c 1.12 => 1.12.2.1 ===
+/*
+ * Slot methods.
+ */
+
static int
wrap_init(PyObject *self, PyObject *args, PyObject *kwds)
{
@@ -86,10 +90,17 @@
wrap_getattro(PyObject *self, PyObject *name)
{
PyObject *result;
- result = PyObject_GenericGetAttr(self, name);
- if (result == NULL) {
- PyErr_Clear();
- result = PyObject_GetAttr(Wrapper_GetObject(self), name);
+ char *s = PyString_AS_STRING(name);
+ if (s[0] == '_' && strcmp(s, "__class__") == 0) {
+ result = (PyObject *)(Wrapper_GetObject(self)->ob_type);
+ Py_INCREF(result);
+ }
+ else {
+ result = PyObject_GenericGetAttr(self, name);
+ if (result == NULL) {
+ PyErr_Clear();
+ result = PyObject_GetAttr(Wrapper_GetObject(self), name);
+ }
}
return result;
}
@@ -184,6 +195,39 @@
return PyObject_SetItem(Wrapper_GetObject(self), key, value);
}
+/*
+ * Normal methods
+ */
+
+static char
+reduce__doc__[] =
+"__reduce__()\n"
+"Raise an exception; this prevents wrappers from being picklable by\n"
+"default, even if the underlying object is picklable.";
+
+static PyObject *
+wrap_reduce(PyObject *self)
+{
+ PyObject *pickle_error = NULL;
+ PyObject *pickle = PyImport_ImportModule("pickle");
+
+ if (pickle == NULL)
+ PyErr_Clear();
+ else {
+ pickle_error = PyObject_GetAttrString(pickle, "PicklingError");
+ if (pickle_error == NULL)
+ PyErr_Clear();
+ }
+ if (pickle_error == NULL) {
+ pickle_error = PyExc_RuntimeError;
+ Py_INCREF(pickle_error);
+ }
+ PyErr_SetString(pickle_error,
+ "Wrapper instances cannot be pickled.");
+ Py_DECREF(pickle_error);
+ return NULL;
+}
+
static PySequenceMethods
wrap_as_sequence = {
wrap_length, /* sq_length */
@@ -203,6 +247,12 @@
wrap_setitem, /* mp_ass_subscript */
};
+static PyMethodDef
+wrap_methods[] = {
+ {"__reduce__", (PyCFunction)wrap_reduce, METH_NOARGS, reduce__doc__},
+ {NULL, NULL},
+};
+
/*
* Note that the numeric methods are not supported. This is primarily
* because of the way coercion-less operations are performed with
@@ -243,7 +293,7 @@
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
- 0, /* tp_methods */
+ wrap_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */