[Zope-Checkins] CVS: Zope3/lib/python/Zope/ContextWrapper - ContainmentIterator.py:1.2 SimpleMethodWrapper.py:1.2 __init__.py:1.2 proxy.c:1.2 proxy.h:1.2 IWrapper.py:1.2 setup.py:1.2 wrapper.c:1.13 wrapper.h:1.4 test_wrapper.py:NONE

Jim Fulton jim@zope.com
Mon, 10 Jun 2002 19:29:56 -0400


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

Modified Files:
	IWrapper.py setup.py wrapper.c wrapper.h 
Added Files:
	ContainmentIterator.py SimpleMethodWrapper.py __init__.py 
	proxy.c proxy.h 
Removed Files:
	test_wrapper.py 
Log Message:
Merged Zope-3x-branch into newly forked Zope3 CVS Tree.

=== Zope3/lib/python/Zope/ContextWrapper/ContainmentIterator.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+# 
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+# 
+##############################################################################
+"""
+
+$Id$
+"""
+
+from Zope.ContextWrapper import Wrapper, wrapperTypes, getinnercontext
+
+class ContainmentIterator:
+
+    def __init__(self, obj):
+        self._ob = Wrapper(None, obj)
+
+    def __iter__(self):
+        return self
+    
+    def next(self):
+        ob = self._ob
+        if type(ob) not in wrapperTypes:
+            raise StopIteration
+
+        ob = getinnercontext(ob)
+        self._ob = ob
+        return ob
+    


=== Zope3/lib/python/Zope/ContextWrapper/SimpleMethodWrapper.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+# 
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+# 
+##############################################################################
+
+# This method wrapper does not work for builtin methods.
+
+from Zope.ContextWrapper.wrapper import Wrapper
+
+class ContextMethod(object):
+    def __new__(cls, method):
+        try:
+            method.__dict__['Zope.ContextWrapper.contextful'] = 1
+        except AttributeError:
+            raise TypeError, \
+                "Cannot make %s into a contextmethod" % type(method)
+        return method
+
+
+def wrapperCreator(object, context=None, **data):
+    if hasattr(object, '__call__'):
+        attrdict = getattr(object.__call__, '__dict__', {})
+        if attrdict.get('Zope.ContextWrapper.contextful'):
+            return SimpleCallableMethodWrapper(object, context, **data)
+
+    return SimpleMethodWrapper(object, context, **data)
+
+
+class SimpleMethodWrapper(Wrapper):
+
+    def __getattribute__(self, name, empty_dict={}):
+        attr = Wrapper.__getattribute__(self, name)
+        attrdict = getattr(attr, '__dict__', empty_dict)
+        if attrdict.get('Zope.ContextWrapper.contextful'):
+            attr = attr.__get__(self)
+        return attr
+        
+        
+class SimpleCallableMethodWrapper(SimpleMethodWrapper):
+
+    def __call__(self, *args, **kw):
+        attr = Wrapper.__getattribute__(self, '__call__')
+        return attr.__get__(self)(*args, **kw)


=== Zope3/lib/python/Zope/ContextWrapper/__init__.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+# 
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+# 
+##############################################################################
+"""
+    ContextWrapper package initialization.
+"""
+from wrapper import *
+
+# import the current, and rather hacky, python implementation of
+# method rebinding.
+# 
+# eventually this should be replaced by some C, and ContextMethod
+# should be a decriptor class rather than a factory that hacks the
+# method's __dict__, as the current ContextMethod does.
+# 
+from SimpleMethodWrapper import wrapperCreator as Wrapper
+from SimpleMethodWrapper import ContextMethod
+
+from SimpleMethodWrapper import SimpleMethodWrapper,SimpleCallableMethodWrapper
+wrapperTypes = (SimpleMethodWrapper, SimpleCallableMethodWrapper)
+del SimpleMethodWrapper, SimpleCallableMethodWrapper


=== Zope3/lib/python/Zope/ContextWrapper/proxy.c 1.1 => 1.2 === (664/764 lines abridged)
+#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 PyObject *
+wrap_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    PyObject *result = NULL;
+    PyObject *object;
+
+    if (PyArg_UnpackTuple(args, "__new__", 1, 1, &object)) {
+        if (kwds != NULL && PyDict_Size(kwds) != 0) {
+            PyErr_SetString(PyExc_TypeError,
+                            "proxy.__new__ does not accept keyword args");
+            return NULL;
+        }
+        result = PyType_GenericNew(type, args, kwds);
+        if (result != NULL) {
+            ProxyObject *wrapper = (ProxyObject *) result;
+            Py_INCREF(object);
+            wrapper->proxy_object = object;
+        }
+    }
+    return result;
+}
+
+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 (kwds != NULL && PyDict_Size(kwds) != 0) {
+            PyErr_SetString(PyExc_TypeError,
+                            "proxy.__init__ does not accept keyword args");

[-=- -=- -=- 664 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);
+}


=== Zope3/lib/python/Zope/ContextWrapper/proxy.h 1.1 => 1.2 ===
+#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/IWrapper.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+# 
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+# 
+##############################################################################
 import Interface
 
 class IWrapperFuncs(Interface.Base):
     """ Interface implemented by callables in 'wrapper' module """
-    def Wrapper(object, context=None):
+    def Wrapper(object, context=None, **data):
         """
-        Create and return a new context wrapper for object. If context is
-        given and not None, context will be the context object. Wrapper can
-        be subclassed.
+        Create and return a new context wrapper for object. If context is given
+        and not None, context will be the context object. Wrapper can be
+        subclassed.
+
+        Wrapper data may be passed as keyword arguments. The data are
+        added to the context dictionary.
         """
+        
     def getobject(obj):
         """
         Return the wrapped object. If obj is not a wrapper object, return obj.
         """
-    def getinnerobject(obj):
+    def getbaseobject(obj):
+        """
+        Return the innermost wrapped object.  If obj is not a wrapper,
+        return obj.
         """
-        Return the innermost wrapped object in a chain of wrappers with obj
-        at the head. If obj is not a wrapper object, just return obj.
+    def getinnerwrapper(obj):
+        """
+        Return the innermost wrapper in a chain of wrappers with obj at the
+        head. If obj is wrapped, just return obj.
         """
     def getinnercontext(obj):
         """
-        Return the context object from the innermost wrapper in a chain
-        with obj at the head. If the innermost wrapper has not context
-        object, return None. If obj is not a wrapper object, just return obj.
+        Return the context object from the innermost wrapper in a chain with
+        obj at the head. If the innermost wrapper has not context object,
+        return None. If obj is not a wrapper object, just return obj.
         """
     def getcontext(obj):
         """
@@ -30,8 +52,8 @@
         """
     def getdict(obj):
         """
-        Return the context dictionary if there is one, or None. If obj is
-        not a wrapper instance, return None.
+        Return the context dictionary if there is one, or None. If obj is not a
+        wrapper instance, return None.
         """
     def getdictcreate(wrapper):
         """
@@ -40,13 +62,13 @@
         """
     def setobject(wrapper, object):
         """
-        Replace the wrapped object with object. Raises TypeError if wrapper
-        is not a wrapper object.
+        Replace the wrapped object with object. Raises TypeError if wrapper is
+        not a wrapper object.
         """
     def setcontext(wrapper, context):
         """
-        Replace the context object with context. If context is None, it will
-        be represented as NULL in C API. Raises TypeError if wrapper is not
+        Replace the context object with context. If context is None, it will be
+        represented as NULL in C API. Raises TypeError if wrapper is not
         a wrapper object.
         """
     


=== Zope3/lib/python/Zope/ContextWrapper/setup.py 1.1 => 1.2 ===
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+# 
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+# 
+##############################################################################
 
 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 => 1.13 === (484/584 lines abridged)
 #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)
@@ -17,29 +15,94 @@
         (((WrapperObject *)wrapper)->wrap_dict)
 
 
+staticforward PyTypeObject WrapperType;
+
 static PyObject *
 empty_tuple = NULL;
 
+/* Helper for wrap_new/wrap_init; return the base class args tuple
+ * from the incoming args tuple.  Returns a new reference.
+ */
+static PyObject *
+create_proxy_args(PyObject *args, PyObject *object)
+{
+    if (PyTuple_GET_SIZE(args) == 1)
+        Py_INCREF(args);
+    else {
+        args = PyTuple_New(1);
+        if (args != NULL) {
+            Py_INCREF(object);
+            PyTuple_SET_ITEM(args, 0, object);
+        }
+    }
+    return args;
+}
+
+/*
+ *   Slot methods.
+ */
+
+static PyObject *
+wrap_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{

[-=- -=- -=- 484 lines omitted -=- -=- -=-]

-    {"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__},
+    {"getobject",       wrapper_getobject,       METH_O,
+     getobject__doc__},
+    {"getbaseobject",   wrapper_getbaseobject,   METH_O,
+     getbaseobject__doc__},
+    {"getcontext",      wrapper_getcontext,      METH_O,
+     getcontext__doc__},
+    {"getinnercontext", wrapper_getinnercontext, METH_O,
+     getinnercontext__doc__},
+    {"getinnerwrapper", wrapper_getinnerwrapper, METH_O,
+     getinnerwrapper__doc__},
+    {"getdict",         wrapper_getdict,         METH_O,
+     getdict__doc__},
+    {"getdictcreate",   wrapper_getdictcreate,   METH_O,
+     getdictcreate__doc__},
+    {"setobject",       wrapper_setobject,       METH_VARARGS,
+     setobject__doc__},
+    {"setcontext",      wrapper_setcontext,      METH_VARARGS,
+     setcontext__doc__},
     {NULL, NULL, 0, NULL}
 };
 
@@ -644,14 +665,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 => 1.4 ===
 #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;
@@ -20,9 +24,10 @@
     int (*check)(PyObject *obj);
     PyObject *(*create)(PyObject *object, PyObject *context);
     PyObject *(*getobject)(PyObject *wrapper);
-    PyObject *(*getinnerobject)(PyObject *wrapper);
+    PyObject *(*getbaseobject)(PyObject *wrapper);
     PyObject *(*getcontext)(PyObject *wrapper);
     PyObject *(*getinnercontext)(PyObject *wrapper);
+    PyObject *(*getinnerwrapper)(PyObject *wrapper);
     PyObject *(*getdict)(PyObject *wrapper);
     PyObject *(*getdictcreate)(PyObject *wrapper);
     int (*setobject)(PyObject *wrapper, PyObject *object);
@@ -43,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) {
@@ -63,12 +68,14 @@
         (_wrapper_api->create((object), (context)))
 #define Wrapper_GetObject(wrapper)           \
         (_wrapper_api->getobject((wrapper)))
-#define Wrapper_GetInnerObject(wrapper)           \
-        (_wrapper_api->getinnerobject((wrapper)))
+#define Wrapper_GetBaseObject(wrapper)           \
+        (_wrapper_api->getbaseobject((wrapper)))
 #define Wrapper_GetContext(wrapper)          \
         (_wrapper_api->getcontext((wrapper)))
 #define Wrapper_GetInnerContext(wrapper)          \
         (_wrapper_api->getinnercontext((wrapper)))
+#define Wrapper_GetInnerWrapper(wrapper)          \
+        (_wrapper_api->getinnerwrapper((wrapper)))
 #define Wrapper_GetDict(wrapper)             \
         (_wrapper_api->getdict((wrapper)))
 #define Wrapper_GetDictCreate(wrapper)       \

=== Removed File Zope3/lib/python/Zope/ContextWrapper/test_wrapper.py ===