[Zope-CVS] CVS: Packages/ContextWrapper - wrapper.c:1.5

Fred Drake Jr fdrake@acm.org
Wed, 14 Nov 2001 14:34:24 -0500


Update of /cvs-repository/Packages/ContextWrapper
In directory cvs.zope.org:/tmp/cvs-serv8479

Modified Files:
	wrapper.c 
Log Message:
Update to the latest clarifications of the API in the Wiki:
- non-wrapper objects can be passed to the module functions
- callable version of the wrapper is removed since there is no need for it


=== Packages/ContextWrapper/wrapper.c 1.4 => 1.5 ===
 
 static int
-noncall_init(WrapperObject *self, PyObject *args, PyObject *kwds)
+wrap_init(WrapperObject *self, PyObject *args, PyObject *kwds)
 {
     int result = -1;
     PyObject *context = NULL;
@@ -29,26 +29,6 @@
 }
 
 static int
-callable_init(WrapperObject *self, PyObject *args, PyObject *kwds)
-{
-    if (PyTuple_GET_SIZE(args)) {
-        PyObject *object = PyTuple_GET_ITEM(args, 0);
-        if (!PyCallable_Check(object)) {
-            PyErr_SetString(PyExc_ValueError,
-                            "expected callable object as arg1");
-            return -1;
-        }
-    }
-    return noncall_init(self, args, kwds);
-}
-
-static PyObject *
-callable_call(WrapperObject *self, PyObject *args, PyObject *kwds)
-{
-    return PyEval_CallObjectWithKeywords(self->wrap_object, args, kwds);
-}
-
-static int
 wrap_traverse(WrapperObject *self, visitproc visit, void *arg)
 {
     int err = visit(self->wrap_object, arg);
@@ -136,52 +116,7 @@
     0,					/* tp_descr_get */
     0,					/* tp_descr_set */
     0,					/* tp_dictoffset */
-    (initproc)noncall_init,		/* tp_init */
-    PyType_GenericAlloc,		/* tp_alloc */
-    PyType_GenericNew,			/* tp_new */
-    _PyObject_GC_Del,			/* tp_free */
-};
-
-
-static PyTypeObject
-CallableWrapperType = {
-    PyObject_HEAD_INIT(NULL)
-    0,
-    "wrapper.CallableWrapperType",
-    sizeof(WrapperObject),
-    0,
-    0,					/* tp_dealloc */
-    0,					/* tp_print */
-    0,					/* tp_getattr */
-    0,					/* tp_setattr */
-    0,					/* tp_compare */
-    0,					/* tp_repr */
-    0,					/* tp_as_number */
-    0,					/* tp_as_sequence */
-    0,					/* tp_as_mapping */
-    0,					/* tp_hash */
-    (ternaryfunc)callable_call,		/* tp_call */
-    0,					/* tp_str */
-    0,					/* tp_getattro */
-    0,					/* tp_setattro */
-    0,					/* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
-    0,					/* tp_doc */
-    0,					/* tp_traverse */
-    0,					/* tp_clear */
-    0,					/* tp_richcompare */
-    0,					/* tp_weaklistoffset */
-    0,					/* tp_iter */
-    0,					/* tp_iternext */
-    0,					/* tp_methods */
-    0,					/* tp_members */
-    0,					/* tp_getset */
-    &WrapperType,			/* tp_base */
-    0,					/* tp_dict */
-    0,					/* tp_descr_get */
-    0,					/* tp_descr_set */
-    0,					/* tp_dictoffset */
-    (initproc)callable_init,		/* tp_init */
+    (initproc)wrap_init,		/* tp_init */
     PyType_GenericAlloc,		/* tp_alloc */
     PyType_GenericNew,			/* tp_new */
     _PyObject_GC_Del,			/* tp_free */
@@ -190,22 +125,16 @@
 
 #define Wrapper_Check(wrapper) \
         (((wrapper)->ob_type == &WrapperType) \
-         || ((wrapper)->ob_type == &CallableWrapperType) \
          || (PyObject_TypeCheck(wrapper, &WrapperType)))
 
 static PyObject *
 create_wrapper(PyObject *object, PyObject *context)
 {
     PyObject *result = NULL;
-    PyObject *wrappertype;
     PyObject *args;
 
     if (context == Py_None)
         context = NULL;
-    if (PyCallable_Check(object))
-        wrappertype = (PyObject *)&CallableWrapperType;
-    else
-        wrappertype = (PyObject *)&WrapperType;
     args = PyTuple_New(context ? 2 : 1);
     if (args != NULL) {
         if (context != NULL) {
@@ -214,7 +143,7 @@
         }
         PyTuple_SET_ITEM(args, 0, object);
         Py_INCREF(object);
-        result = PyObject_CallObject(wrappertype, args);
+        result = PyObject_CallObject((PyObject *)&WrapperType, args);
         Py_DECREF(args);
     }
     return result;
@@ -238,12 +167,19 @@
     return create_wrapper(object, context);
 }
 
+static PyObject *
+missing_wrapper(const char *funcname)
+{
+    PyErr_Format(PyExc_RuntimeError,
+                 "cannot pass NULL to WrapperAPI.%s()", funcname);
+    return NULL;
+}
+
 static int
 check_wrapper(PyObject *wrapper, const char *funcname)
 {
     if (wrapper == NULL) {
-        PyErr_Format(PyExc_RuntimeError,
-                     "cannot pass NULL to WrapperAPI.%s()", funcname);
+        (void) missing_wrapper(funcname);
         return 0;
     }
     if (!Wrapper_Check(wrapper)) {
@@ -257,16 +193,20 @@
 static PyObject *
 api_getobject(PyObject *wrapper)
 {
-    if (check_wrapper(wrapper, "getobject"))
+    if (wrapper == NULL)
+        return missing_wrapper("getobject");
+    if (Wrapper_Check(wrapper))
         return ((WrapperObject *)wrapper)->wrap_object;
     else
-        return NULL;
+        return wrapper;
 }
 
 static PyObject *
 api_getcontext(PyObject *wrapper)
 {
-    if (check_wrapper(wrapper, "getcontext"))
+    if (wrapper == NULL)
+        return NULL;
+    if (Wrapper_Check(wrapper))
         return ((WrapperObject *)wrapper)->wrap_context;
     else
         return NULL;
@@ -275,7 +215,9 @@
 static PyObject *
 api_getdict(PyObject *wrapper)
 {
-    if (check_wrapper(wrapper, "getdict"))
+    if (wrapper == NULL)
+        return NULL;
+    if (Wrapper_Check(wrapper))
         return ((WrapperObject *)wrapper)->wrap_dict;
     else
         return NULL;
@@ -308,16 +250,6 @@
     }
     if (!check_wrapper(wrapper, "setobject"))
         return 0;
-    if (PyObject_TypeCheck(wrapper, &CallableWrapperType)) {
-        /* If the wrapper is callable, make sure we enforce the
-         * restriction that the referent is callable as well.
-         */
-        if (!PyCallable_Check(object)) {
-            PyErr_SetString(PyExc_TypeError,
-                            "object for a callable wrapper must be callable");
-            return 0;
-        }
-    }
     wrap = (WrapperObject *) wrapper;
     oldobject = wrap->wrap_object;
     Py_INCREF(object);
@@ -356,41 +288,40 @@
 };
 
 static char
-create__doc__[] =
-"new(object[, context]) --> wrapper\n"
+getobject__doc__[] =
+"getobject(wrapper) --> object\n"
 "\n"
-"Return a new wrapper object around object and context.  If context\n"
-"is omitted, there is no context object, but one can be added.";
+"Return the underlying object for wrapper.";
 
 static PyObject *
-create(PyObject *unused, PyObject *args)
+getobject(PyObject *unused, PyObject *obj)
 {
-    PyObject *object;
-    PyObject *context = NULL;
     PyObject *result = NULL;
 
-    if (PyArg_UnpackTuple(args, "new", 1, 2, &object, &context)) {
-        result = create_wrapper(object, context);
-    }
+    if (Wrapper_Check(obj))
+        result = ((WrapperObject *)obj)->wrap_object;
+    else
+        result = Py_None;
+    Py_INCREF(result);
     return result;
 }
 
 static char
-getobject__doc__[] =
-"getobject(wrapper) --> object\n"
+getinnerobject__doc__[] =
+"getinnerobject(wrapper) --> object\n"
 "\n"
-"Return the underlying object for wrapper.";
+"Return the underlying object for the innermost wrapper in a chain of\n"
+"wrappers with 'wrapper' at the head.  Returns None if 'wrapper' isn't a\n"
+"wrapper at all.";
 
 static PyObject *
-getobject(PyObject *unused, PyObject *obj)
+getinnerobject(PyObject *unused, PyObject *obj)
 {
-    PyObject *result = NULL;
-
-    if (check_wrapper(obj, "getobject")) {
-        result = ((WrapperObject *)obj)->wrap_object;
-        Py_INCREF(result);
+    while (Wrapper_Check(obj)) {
+        obj = ((WrapperObject *)obj)->wrap_object;
     }
-    return result;
+    Py_INCREF(obj);
+    return obj;
 }
 
 static char
@@ -404,12 +335,46 @@
 {
     PyObject *result = NULL;
 
-    if (check_wrapper(obj, "getcontext")) {
+    if (Wrapper_Check(obj)) {
         result = ((WrapperObject *)obj)->wrap_context;
         if (result == NULL)
             result = Py_None;
-        Py_XINCREF(result);
     }
+    else {
+        result = Py_None;
+    }
+    Py_XINCREF(result);
+    return result;
+}
+
+static char
+getinnercontext__doc__[] =
+"getinnercontext(wrapper) --> object | None\n"
+"\n"
+"Return the context object for the innermost wrapper in a chain of wrappers\n"
+"with 'wrapper' at the head, or None if there isn't one.  Returns None if\n"
+"'wrapper' isn't a wrapper at all.";
+
+static PyObject *
+getinnercontext(PyObject *unused, PyObject *obj)
+{
+    PyObject *result;
+
+    if (Wrapper_Check(obj)) {
+        WrapperObject *wrapper = (WrapperObject *)obj;
+        obj = wrapper->wrap_object;
+        while (Wrapper_Check(obj)) {
+            wrapper = (WrapperObject *)obj;
+            obj = wrapper->wrap_object;
+        }
+        result = wrapper->wrap_context;
+        if (result == NULL)
+            result = Py_None;
+    }
+    else {
+        result = Py_None;
+    }
+    Py_INCREF(result);
     return result;
 }
 
@@ -424,12 +389,14 @@
 {
     PyObject *result = NULL;
 
-    if (check_wrapper(obj, "getdict")) {
+    if (Wrapper_Check(obj)) {
         result = ((WrapperObject *)obj)->wrap_dict;
         if (result == NULL)
             result = Py_None;
-        Py_XINCREF(result);
     }
+    else
+        result = Py_None;
+    Py_INCREF(result);
     return result;
 }
 
@@ -502,13 +469,14 @@
 
 static PyMethodDef
 module_functions[] = {
-    {"new",           create,        METH_VARARGS, create__doc__},
-    {"getobject",     getobject,     METH_O,       getobject__doc__},
-    {"getcontext",    getcontext,    METH_O,       getcontext__doc__},
-    {"getdict",       getdict,       METH_O,       getdict__doc__},
-    {"getdictcreate", getdictcreate, METH_O,       getdictcreate__doc__},
-    {"setobject",     setobject,     METH_VARARGS, setobject__doc__},
-    {"setcontext",    setcontext,    METH_VARARGS, setcontext__doc__},
+    {"getobject",       getobject,       METH_O,       getobject__doc__},
+    {"getinnerobject",  getinnerobject,  METH_O,       getinnerobject__doc__},
+    {"getcontext",      getcontext,      METH_O,       getcontext__doc__},
+    {"getinnercontext", getinnercontext, METH_O,       getinnercontext__doc__},
+    {"getdict",         getdict,         METH_O,       getdict__doc__},
+    {"getdictcreate",   getdictcreate,   METH_O,       getdictcreate__doc__},
+    {"setobject",       setobject,       METH_VARARGS, setobject__doc__},
+    {"setcontext",      setcontext,      METH_VARARGS, setcontext__doc__},
     {NULL, NULL, 0, NULL}
 };
 
@@ -535,24 +503,20 @@
         return;
 
     WrapperType.ob_type = &PyType_Type;
-    CallableWrapperType.ob_type = &PyType_Type;
     if (PyType_Ready(&WrapperType) < 0)
         return;
-    if (PyType_Ready(&CallableWrapperType) < 0)
-        return;
-    if (api_object == NULL)
-        api_object = PyCObject_FromVoidPtr(&wrapper_capi, NULL);
-    if (empty_tuple == NULL)
-        empty_tuple = PyDict_New();
 
     Py_INCREF(&WrapperType);
-    PyModule_AddObject(m, "WrapperType",
-                       (PyObject *)&WrapperType);
-    Py_INCREF(&CallableWrapperType);
-    PyModule_AddObject(m, "CallableWrapperType",
-                       (PyObject *)&CallableWrapperType);
-    if (api_object != NULL) {
-        Py_INCREF(api_object);
-        PyModule_AddObject(m, "_CAPI", api_object);
+    PyModule_AddObject(m, "Wrapper", (PyObject *)&WrapperType);
+
+    if (api_object == NULL) {
+        api_object = PyCObject_FromVoidPtr(&wrapper_capi, NULL);
+        if (api_object == NULL)
+            return;
     }
+    Py_INCREF(api_object);
+    PyModule_AddObject(m, "_CAPI", api_object);
+
+    if (empty_tuple == NULL)
+        empty_tuple = PyDict_New();
 }