[Zope-Checkins] CVS: Zope3/lib/python/Zope/ContextWrapper - proxy.c:1.1.4.1 proxy.h:1.1.4.1 setup.py:1.1.2.2 wrapper.c:1.12.2.14 wrapper.h:1.3.2.3

Jim Fulton jim@zope.com
Sun, 28 Apr 2002 13:17:16 -0400


Update of /cvs-repository/Zope3/lib/python/Zope/ContextWrapper
In directory cvs.zope.org:/tmp/cvs-serv17050/lib/python/Zope/ContextWrapper

Modified Files:
      Tag: Zope-3x-branch
	setup.py wrapper.c wrapper.h 
Added Files:
      Tag: Zope-3x-branch
	proxy.c proxy.h 
Log Message:
HOTYB: Merged SecurityProxy-branch into main branch.  

All tests pass and folders can be listed and added through the web.
It is likely that most other things don't work and will need to be
fixed. The reason is that many accesses that should have been checked
before are now being checked and additional checks and thinking about
permissions and security settings are needed.

I'm in the process of drafting a paper for the wiki that describes the
changes in more detail.


=== Added File Zope3/lib/python/Zope/ContextWrapper/proxy.c === (634/734 lines abridged)
#include "Python.h"
#include "modsupport.h"

#define PROXY_MODULE
#include "proxy.h"

staticforward PyTypeObject ProxyType;

#define Proxy_Check(wrapper)   (PyObject_TypeCheck((wrapper), &ProxyType))

static PyObject *
empty_tuple = NULL;


/*
 *   Slot methods.
 */

static int
wrap_init(PyObject *self, PyObject *args, PyObject *kwds)
{
    int result = -1;
    PyObject *object;

    if (PyArg_UnpackTuple(args, "__init__", 1, 1, &object)) {
        ProxyObject *wrapper = (ProxyObject *)self;
        if (PyType_Type.tp_init(self, empty_tuple, NULL) < 0)
            goto finally;
        Py_INCREF(object);
        wrapper->proxy_object = object;
        result = 0;
    }
 finally:
    return result;
}

static int
wrap_traverse(PyObject *self, visitproc visit, void *arg)
{
    PyObject *ob = Proxy_GET_OBJECT(self);
    if (ob != NULL)
        return visit(ob, arg);
    else
        return 0;
}

static int
wrap_clear(PyObject *self)
{
    ProxyObject *proxy = (ProxyObject *)self;

[-=- -=- -=- 634 lines omitted -=- -=- -=-]

        result = Proxy_GET_OBJECT(obj);
	Py_INCREF(result);
    }
    else
        PyErr_Format(PyExc_TypeError,
		     "expected proxy, got %s", obj->ob_type->tp_name);
    return result;
}

static PyMethodDef
module_functions[] = {
    {"getobject", wrapper_getobject, METH_O, getobject__doc__},
    {NULL}
};

static char
module___doc__[] =
"Association between an object, a context object, and a dictionary.\n\
\n\
The context object and dictionary give additional context information\n\
associated with a reference to the basic object.  The wrapper objects\n\
act as proxies for the original object.";


void
initproxy(void)
{
    PyObject *m = Py_InitModule3("proxy", module_functions, module___doc__);

    if (m == NULL)
        return;

    if (empty_tuple == NULL)
        empty_tuple = PyTuple_New(0);

    ProxyType.ob_type = &PyType_Type;
    if (PyType_Ready(&ProxyType) < 0)
        return;

    Py_INCREF(&ProxyType);
    PyModule_AddObject(m, "proxy", (PyObject *)&ProxyType);

    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);
}


=== Added File Zope3/lib/python/Zope/ContextWrapper/proxy.h ===
#ifndef _proxy_H_
#define _proxy_H_ 1

typedef struct {
    PyObject_HEAD
    PyObject *proxy_object;
} ProxyObject;

#define Proxy_GET_OBJECT(ob)   (((ProxyObject *)(ob))->proxy_object)

typedef struct {
    PyTypeObject *proxytype;
    int (*check)(PyObject *obj);
    PyObject *(*create)(PyObject *obj);
    PyObject *(*getobject)(PyObject *proxy);
} ProxyInterface;


#ifndef PROXY_MODULE

/* These are only defined in the public interface, and are not
 * available within the module implementation.  There we use the
 * classic Python/C API only.
 */

static ProxyInterface *_proxy_api = NULL;

static int
Proxy_Import(void)
{
    if (_proxy_api == NULL) {
        PyObject *m = PyImport_ImportModule("Zope.ContextWrapper.proxy");
        if (m != NULL) {
            PyObject *tmp = PyObject_GetAttrString(m, "_CAPI");
            if (tmp != NULL) {
                if (PyCObject_Check(tmp))
                    _proxy_api = (ProxyInterface *)
                        PyCObject_AsVoidPtr(tmp);
                Py_DECREF(tmp);
            }
        }
    }
    return (_proxy_api == NULL) ? -1 : 0;
}

#define ProxyType               (_proxy_api->proxytype)
#define Proxy_Check(obj)        (_proxy_api->check((obj)))
#define Proxy_CheckExact(obj)   ((obj)->ob_type == ProxyType)
#define Proxy_New(obj)          (_proxy_api->create((obj)))
#define Proxy_GetObject(proxy)  (_proxy_api->getobject((proxy)))

#endif /* PROXY_MODULE */

#endif /* _proxy_H_ */


=== Zope3/lib/python/Zope/ContextWrapper/setup.py 1.1.2.1 => 1.1.2.2 ===
 from distutils.core import setup, Extension
 
-setup(name="wrapper", version = "0.1",
-      ext_modules=[Extension("wrapper", ["wrapper.c"])])
+setup(name="wrapper", version = "0.2",
+      ext_modules=[Extension("wrapper", ["wrapper.c"]),
+                   Extension("proxy", ["proxy.c"])])


=== Zope3/lib/python/Zope/ContextWrapper/wrapper.c 1.12.2.13 => 1.12.2.14 ===
 #include "modsupport.h"
+#include "proxy.h"
 #define WRAPPER_MODULE
 #include "wrapper.h"
 
-#define Wrapper_Check(wrapper) \
-        (((wrapper)->ob_type == &WrapperType) \
-         || (PyObject_TypeCheck(wrapper, &WrapperType)))
+#define Wrapper_Check(wrapper)   (PyObject_TypeCheck(wrapper, &WrapperType))
 
-#define Wrapper_GetObject(wrapper) \
-        (((WrapperObject *)wrapper)->wrap_object)
+#define Wrapper_GetObject(wrapper) Proxy_GET_OBJECT((wrapper))
 
 #define Wrapper_GetContext(wrapper) \
         (((WrapperObject *)wrapper)->wrap_context)
@@ -32,14 +30,18 @@
 {
     int result = -1;
     PyObject *context = NULL;
+    PyObject *proxyargs = NULL;
     PyObject *object;
 
     if (PyArg_UnpackTuple(args, "__init__", 1, 2, &object, &context)) {
         WrapperObject *wrapper = (WrapperObject *)self;
-        if (PyType_Type.tp_init(self, empty_tuple, NULL) < 0)
+	proxyargs = PyTuple_New(1);
+        if (proxyargs == NULL)
+	    goto finally;
+	Py_INCREF(object);
+	PyTuple_SET_ITEM(proxyargs, 0, object);
+        if (ProxyType->tp_init(self, proxyargs, NULL) < 0)
             goto finally;
-        Py_INCREF(object);
-        wrapper->wrap_object = object;
         Py_XINCREF(context);
         wrapper->wrap_context = context;
         if (kwds != NULL && PyDict_Size(kwds) > 0) {
@@ -54,6 +56,7 @@
         result = 0;
     }
  finally:
+    Py_XDECREF(proxyargs);
     return result;
 }
 
@@ -83,31 +86,13 @@
         wrapper->wrap_context = NULL;
         Py_DECREF(temp);
     }
-    if ((temp = wrapper->wrap_object) != NULL) {
-        wrapper->wrap_object = NULL;
+    if ((temp = Proxy_GET_OBJECT(wrapper)) != NULL) {
+        wrapper->proxy_object = NULL;
         Py_DECREF(temp);
     }
     return 0;
 }
 
-static PyObject *
-wrap_richcompare(PyObject* self, PyObject* other, int op)
-{
-    while (Wrapper_Check(self)) {
-        self = Wrapper_GetObject(self);
-    }
-    while (Wrapper_Check(other)) {
-        other = Wrapper_GetObject(other);
-    }
-    return PyObject_RichCompare(self, other, op);
-}
-
-static PyObject *
-wrap_iter(PyObject *self)
-{
-    return PyObject_GetIter(Wrapper_GetObject(self));
-}
-
 static void
 wrap_dealloc(PyObject *self)
 {
@@ -115,146 +100,6 @@
     self->ob_type->tp_free(self);
 }
 
-static PyObject *
-wrap_getattro(PyObject *self, PyObject *name)
-{
-    /*
-      This commented-out version allows subclasses of the Wrapper type
-      to add new attributes.  To do so and still make __class__ still
-      evaluate to the __class__ of the wrapped object, we have to
-      special case that attribute.  There may need to be other
-      special-cased attributes as well, which introduces Deep
-      Questions.
-     */
-    /*
-    PyObject *result;
-
-    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;
-    */
-    return PyObject_GetAttr(Wrapper_GetObject(self), name);
-}
-
-static int
-wrap_setattro(PyObject *self, PyObject *name, PyObject *value)
-{
-    if (Wrapper_GetObject(self) != NULL)
-        return PyObject_SetAttr(Wrapper_GetObject(self), name, value);
-    PyErr_Format(PyExc_RuntimeError,
-                 "object is NULL; requested to set attribute '%s'",
-                 PyString_AS_STRING(name));
-    return -1;
-}
-
-static int
-wrap_print(PyObject *wrapper, FILE *fp, int flags)
-{
-    return PyObject_Print(Wrapper_GetObject(wrapper), fp, flags);
-}
-
-static PyObject *
-wrap_str(PyObject *wrapper) {
-    return PyObject_Str(Wrapper_GetObject(wrapper));
-}
-
-static PyObject *
-wrap_repr(PyObject *wrapper)
-{
-    return PyObject_Repr(Wrapper_GetObject(wrapper));
-}
-
-
-static int
-wrap_setattr(PyObject *wrapper, PyObject *name, PyObject *value)
-{
-    return PyObject_SetAttr(Wrapper_GetObject(wrapper), name, value);
-}
-
-static int
-wrap_compare(PyObject *wrapper, PyObject *v)
-{
-    return PyObject_Compare(Wrapper_GetObject(wrapper), v);
-}
-
-static long
-wrap_hash(PyObject *self)
-{
-    return PyObject_Hash(Wrapper_GetObject(self));
-}
-
-static PyObject *
-wrap_call(PyObject *self, PyObject *args, PyObject *kw)
-{
-  if (kw)
-    return PyEval_CallObjectWithKeywords(Wrapper_GetObject(self), args, kw);
-  else
-    return PyObject_CallObject(Wrapper_GetObject(self), args);
-}
-
-/*
- *   Number methods
- */
-
-static int
-wrap_nonzero(PyObject *self)
-{
-    return PyObject_IsTrue(Wrapper_GetObject(self));
-}
-
-/*
- *   Sequence methods
- */
-
-static int
-wrap_length(PyObject *self)
-{
-    return PyObject_Length(Wrapper_GetObject(self));
-}
-
-static PyObject *
-wrap_slice(PyObject *self, int start, int end)
-{
-    return PySequence_GetSlice(Wrapper_GetObject(self), start, end);
-}
-
-static int
-wrap_ass_slice(PyObject *self, int i, int j, PyObject *value)
-{
-    return PySequence_SetSlice(Wrapper_GetObject(self), i, j, value);
-}
-
-static int
-wrap_contains(PyObject *self, PyObject *value)
-{
-    return PySequence_Contains(Wrapper_GetObject(self), value);
-}
-
-/*
- *   Mapping methods
- */
-
-static PyObject *
-wrap_getitem(PyObject *wrapper, PyObject *v) {
-    return PyObject_GetItem(Wrapper_GetObject(wrapper), v);
-}
-
-static int
-wrap_setitem(PyObject *self, PyObject *key, PyObject *value)
-{
-    return PyObject_SetItem(Wrapper_GetObject(self), key, value);
-}
-
 /*
  *   Normal methods
  */
@@ -288,56 +133,12 @@
     return NULL;
 }
 
-static PyNumberMethods
-wrap_as_number = {
-    0, /* nb_add */
-    0, /* nb_subtract */
-    0, /* nb_multiply */
-    0, /* nb_divide */
-    0, /* nb_remainder */
-    0, /* nb_divmod */
-    0, /* nb_power */
-    0, /* nb_negative */
-    0, /* nb_positive */
-    0, /* nb_absolute */
-    wrap_nonzero, /* nb_nonzero */
-};
-
-static PySequenceMethods
-wrap_as_sequence = {
-    wrap_length,			/* sq_length */
-    0,					/* sq_concat */
-    0,					/* sq_repeat */
-    0,					/* sq_item */
-    wrap_slice,				/* sq_slice */
-    0,					/* sq_ass_item */
-    wrap_ass_slice,			/* sq_ass_slice */
-    wrap_contains,			/* sq_contains */
-};
-
-static PyMappingMethods
-wrap_as_mapping = {
-    wrap_length,			/* mp_length */
-    wrap_getitem,			/* mp_subscript */
-    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
- * new-style numbers; since we can't tell which side of the operation
- * is 'self', we can't ensure we'd unwrap the right thing to perform
- * the actual operation.  We also can't afford to just unwrap both
- * sides the way weakrefs do, since we don't know what semantics will
- * be associated with the wrapper itself.
- */
-
 statichere PyTypeObject
 WrapperType = {
     PyObject_HEAD_INIT(NULL)
@@ -346,28 +147,28 @@
     sizeof(WrapperObject),
     0,
     wrap_dealloc,			/* tp_dealloc */
-    wrap_print,				/* tp_print */
+    0,					/* tp_print */
     0,					/* tp_getattr */
     0,					/* tp_setattr */
-    wrap_compare,			/* tp_compare */
-    wrap_repr,				/* tp_repr */
-    &wrap_as_number,			/* tp_as_number */
-    &wrap_as_sequence,			/* tp_as_sequence */
-    &wrap_as_mapping,			/* tp_as_mapping */
-    wrap_hash,				/* tp_hash */
-    wrap_call,				/* tp_call */
-    wrap_str,				/* tp_str */
-    wrap_getattro,			/* tp_getattro */
-    wrap_setattro,			/* tp_setattro */
+    0,					/* tp_compare */
+    0,					/* tp_repr */
+    0,					/* tp_as_number */
+    0,					/* tp_as_sequence */
+    0,					/* tp_as_mapping */
+    0,					/* tp_hash */
+    0,					/* tp_call */
+    0,					/* tp_str */
+    0,					/* tp_getattro */
+    0,					/* tp_setattro */
     0,					/* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
-        | Py_TPFLAGS_HAVE_GC,		/* tp_flags */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
+        | Py_TPFLAGS_BASETYPE,		/* tp_flags */
     0,					/* tp_doc */
     wrap_traverse,			/* tp_traverse */
     wrap_clear,				/* tp_clear */
-    wrap_richcompare,			/* tp_richcompare */
+    0,					/* tp_richcompare */
     0,					/* tp_weaklistoffset */
-    wrap_iter,				/* tp_iter */
+    0,					/* tp_iter */
     0,					/* tp_iternext */
     wrap_methods,			/* tp_methods */
     0,					/* tp_members */
@@ -557,7 +358,7 @@
     wrap = (WrapperObject *) wrapper;
     oldobject = Wrapper_GetObject(wrap);
     Py_INCREF(object);
-    wrap->wrap_object = object;
+    wrap->proxy_object = object;
     Py_DECREF(oldobject);
     return 1;
 }
@@ -784,7 +585,7 @@
 module_functions[] = {
     {"getobject",       wrapper_getobject,       METH_O,
      getobject__doc__},
-    {"getbaseobject",   wrapper_getbaseobject,  METH_O,
+    {"getbaseobject",   wrapper_getbaseobject,   METH_O,
      getbaseobject__doc__},
     {"getcontext",      wrapper_getcontext,      METH_O,
      getcontext__doc__},
@@ -818,14 +619,17 @@
 void
 initwrapper(void)
 {
-    PyObject *m = Py_InitModule3("wrapper",
-                                 module_functions,
-                                 module___doc__);
+    PyObject *m;
+
+    if (Proxy_Import() < 0)
+        return;
 
+    m = Py_InitModule3("wrapper", module_functions, module___doc__);
     if (m == NULL)
         return;
 
     WrapperType.ob_type = &PyType_Type;
+    WrapperType.tp_base = ProxyType;
     if (PyType_Ready(&WrapperType) < 0)
         return;
 


=== Zope3/lib/python/Zope/ContextWrapper/wrapper.h 1.3.2.2 => 1.3.2.3 ===
 #define _wrapper_H_
 
+#ifndef _proxy_H_
+#include "proxy.h"
+#endif
+
 typedef struct {
     PyObject_HEAD
-    PyObject *wrap_object;
+    PyObject *proxy_object;
     PyObject *wrap_context;
     PyObject *wrap_dict;
 } WrapperObject;
@@ -44,7 +48,7 @@
 Wrapper_Import(void)
 {
     if (_wrapper_api == NULL) {
-        PyObject *m = PyImport_ImportModule("wrapper");
+        PyObject *m = PyImport_ImportModule("Zope.ContextWrapper.wrapper");
         if (m != NULL) {
             PyObject *tmp = PyObject_GetAttrString(m, "_CAPI");
             if (tmp != NULL) {