[Zope3-checkins] CVS: Zope3/src/zope/context - __init__.py:1.9.2.1 interfaces.py:1.9.4.1 wrapper.c:1.16.4.1 wrapper.h:1.5.4.1 containmentiterator.py:NONE decorator.c:NONE decorator.h:NONE

Grégoire Weber zope@i-con.ch
Sun, 22 Jun 2003 10:24:10 -0400


Update of /cvs-repository/Zope3/src/zope/context
In directory cvs.zope.org:/tmp/cvs-serv24874/src/zope/context

Modified Files:
      Tag: cw-mail-branch
	__init__.py interfaces.py wrapper.c wrapper.h 
Removed Files:
      Tag: cw-mail-branch
	containmentiterator.py decorator.c decorator.h 
Log Message:
Synced up with HEAD

=== Zope3/src/zope/context/__init__.py 1.9 => 1.9.2.1 ===
--- Zope3/src/zope/context/__init__.py:1.9	Sun May 18 14:06:45 2003
+++ Zope3/src/zope/context/__init__.py	Sun Jun 22 10:23:39 2003
@@ -18,131 +18,78 @@
 Revision information:
 $Id$
 """
+from __future__ import generators
+
 __metaclass__ = type
 
+import sys
 from zope.interface import moduleProvides
-from zope.security.proxy import Proxy, getChecker, getObject
-from zope.proxy.context.wrapper import getobject, getdict
-from zope.proxy.context.wrapper import getcontext, getinnercontext
-from zope.proxy.context.wrapper import getinnerwrapper, getbaseobject
-from zope.proxy.context.wrapper import ContextDescriptor, ContextAware
-from zope.proxy.context.wrapper import ContextMethod, ContextProperty
-from zope.proxy.context.wrapper import Wrapper
-from zope.proxy.context.decorator import Decorator
-from zope.security.checker import defineChecker, selectChecker, BasicTypes
-from zope.proxy.interfaces.context import IContextDecorator
-from zope.hookable import hookable
-
-moduleProvides(IContextDecorator)
-
-def ContextWrapper(_ob, _parent, **kw):
-    if type(_ob) in BasicTypes:
-        # Don't wrap basic objects
-        return _ob
-
-    if type(_ob) is Proxy:
-        # insert into proxies
-        checker = getChecker(_ob)
-        _ob = getObject(_ob)
-        _ob = Proxy(makeWrapper(_ob, _parent, kw, checker), checker)
+from zope.interface.advice import addClassAdvisor
+from zope.context.wrapper import getdict, getdictcreate
+from zope.context.wrapper import getcontext, getinnercontext
+from zope.context.wrapper import getinnerwrapper, getbaseobject
+from zope.context.wrapper import ContextDescriptor, ContextMethod
+from zope.context.wrapper import ContextProperty, Wrapper
+from zope.proxy import queryProxy, queryInnerProxy, isProxy, getProxiedObject
+from zope.context.interfaces import IContextAwareDescriptorSupport
+from zope.context.interfaces import IWrapperIntrospection
+
+moduleProvides(IWrapperIntrospection, IContextAwareDescriptorSupport)
+__all__ = tuple(IWrapperIntrospection) + tuple(IContextAwareDescriptorSupport)
+
+def getWrapperData(_ob, create=False):
+    wrapper = queryProxy(_ob, Wrapper)
+    if wrapper is not None:
+        if create:
+            return getdictcreate(wrapper)
+        else:
+            return getdict(wrapper)
     else:
-        _ob = makeWrapper(_ob, _parent, kw)
-
-    return _ob
-
-ContextWrapper = hookable(ContextWrapper)
-
-def makeWrapper(ob, parent, kw, checker=None):
-    return Wrapper(ob, parent, **kw)
-makeWrapper = hookable(makeWrapper)
-
-def getWrapperObject(_ob):
-    """Remove a context wrapper around an object with data
-
-    If the object is wrapped in a security proxy, then the object
-    is inserted inside an equivalent security proxy.
-    """
-
-    if type(_ob) in BasicTypes:
-        # Don't wrap basic objects
-        return _ob
-    elif type(_ob) is Proxy:
-        # insert into proxies
-        checker = getChecker(_ob)
-        _ob = getObject(_ob)
-        _ob = Proxy(getobject(_ob), checker)
-    else:
-        _ob = getobject(_ob)
-
-    return _ob
-
-def _contextWrapperChecker(ob):
-    return selectChecker(getobject(ob))
-
-def getWrapperData(_ob):
-    if type(_ob) is Proxy:
-        _ob = getObject(_ob)
-    return getdict(_ob)
+        if create:
+            raise TypeError("Not a context wrapper")
+        return None
 
 def getInnerWrapperData(_ob):
-    if type(_ob) is Proxy:
-        _ob = getObject(_ob)
-    return getdict(getinnerwrapper(_ob))
+    wrapper = queryInnerProxy(_ob, Wrapper)
+    if wrapper is not None:
+        return getdict(wrapper)
+    else:
+        return None
 
 def getWrapperContainer(_ob):
-    if type(_ob) is Proxy:
-        _ob = getObject(_ob)
-    return getinnercontext(_ob)
+    wrapper = queryInnerProxy(_ob, Wrapper)
+    if wrapper is not None:
+        return getcontext(wrapper)
+    else:
+        return None
 
 def getWrapperContext(_ob):
-    if type(_ob) is Proxy:
-        _ob = getObject(_ob)
-    return getcontext(_ob)
+    wrapper = queryProxy(_ob, Wrapper)
+    if wrapper is not None:
+        return getcontext(wrapper)
+    else:
+        return None
 
 def isWrapper(_ob):
-    if type(_ob) is Proxy:
-        _ob = getObject(_ob)
-    return type(_ob) in wrapperTypes
-
-class ContainmentIterator:
-
-    def __init__(self, obj):
-        self._ob = Wrapper(None, obj)
-
-    def __iter__(self):
-        return self
+    return isProxy(_ob, Wrapper)
 
-    def next(self):
-        _ob = self._ob
+def ContainmentIterator(obj):
+    wrapper = queryInnerProxy(obj, Wrapper)
+    while wrapper is not None:
+        yield obj
+        obj = getcontext(wrapper)
+        wrapper = queryInnerProxy(obj, Wrapper)
+
+    yield obj
+
+def ContextIterator(obj):
+    wrapper = queryProxy(obj, Wrapper)
+    while wrapper is not None:
+        yield obj
+        obj = getcontext(wrapper)
+        wrapper = queryProxy(obj, Wrapper)
 
-        if type(_ob) is Proxy:
-            _ob = getObject(_ob)
-
-        if type(_ob) not in wrapperTypes:
-            raise StopIteration
-
-        _ob = getinnercontext(_ob)
-        self._ob = _ob
-        return _ob
-
-def getItem(collection, name):
-    return ContextWrapper(collection[name], collection, name=name)
-
-def getAttr(collection, name):
-    return ContextWrapper(getattr(collection, name), collection, name=name)
-
-def queryItem(collection, name, default=None):
-    return ContextWrapper(collection.get(name, default),
-                          collection, name=name)
-
-def queryAttr(collection, name, default=None):
-    return ContextWrapper(getattr(collection, name, default),
-                          collection, name=name)
-
-wrapperTypes = (Wrapper, Decorator)
-
-defineChecker(Wrapper, _contextWrapperChecker)
-defineChecker(Decorator, _contextWrapperChecker)
+    yield obj
 
 class ContextSuper:
 
@@ -154,3 +101,55 @@
         inst = self.__inst
         return getattr(super(self.__class, getbaseobject(inst)), name
                        ).__get__(inst)
+
+class ContextAwareDescriptor(ContextDescriptor):
+    # TODO For speed, reimplement this in C
+
+    def __init__(self, descriptor):
+        self.descriptor = descriptor
+
+    def __get__(self, inst, cls=None):
+        return self.descriptor.__get__(inst, cls)
+
+    def getdoc(self):
+        return self.descriptor.__doc__
+
+    __doc__ = property(getdoc)
+
+class ContextAwareDataDescriptor(ContextAwareDescriptor):
+
+    def __set__(self, inst, value):
+        self.descriptor.__set__(inst, value)
+
+    def __delete__(self, inst):
+        self.descriptor.__delete__(inst)
+
+# Make a set of special names that we must avoid touching when making the
+# descriptors of a class context-aware.
+_special_names = [
+    '__module__', '__dict__', '__weakref__', '__doc__', '__providedBy__',
+    '__implements__'
+    ]
+_special_names = dict(zip(_special_names, _special_names))
+
+def _context_aware_advice(cls):
+    for name, obj in cls.__dict__.items():
+        if not (name in _special_names or isinstance(obj, ContextDescriptor)):
+            if getattr(obj, '__set__', None) is not None:
+                d = ContextAwareDataDescriptor(obj)
+                setattr(cls, name, d)
+            elif getattr(obj, '__get__', None) is not None:
+                m = ContextAwareDescriptor(obj)
+                setattr(cls, name, m)
+    return cls
+
+def ContextAwareDescriptors():
+    frame = sys._getframe(1)
+    locals = frame.f_locals
+
+    # Try to make sure we were called from a class def
+    if (locals is frame.f_globals) or ('__module__' not in locals):
+        raise TypeError("ContextAwareDescriptors() can be used only from a"
+                        " class definition.")
+    addClassAdvisor(_context_aware_advice, depth=2)
+


=== Zope3/src/zope/context/interfaces.py 1.9 => 1.9.4.1 ===
--- Zope3/src/zope/context/interfaces.py:1.9	Mon May 12 10:59:37 2003
+++ Zope3/src/zope/context/interfaces.py	Sun Jun 22 10:23:39 2003
@@ -40,18 +40,6 @@
         Where args is either (object,) or (object, context).
         """
 
-    def getobject(obj):
-        """Return the wrapped object.
-
-        If obj is not a wrapper object, return obj.
-        """
-
-    def getbaseobject(obj):
-        """Return the innermost wrapped object.
-
-        If obj is not a wrapper, return obj.
-        """
-
     def getinnerwrapper(obj):
         """Return the innermost wrapper.
 
@@ -106,9 +94,9 @@
     It provides a place to keep the object's context, in the form of
     a reference to its context object, and a dictionary of contextual metadata.
 
-    If the wrapped object's class derives from ContextAware, or a descriptor
-    on the wrapped object's class is a ContextDescriptor, then the 'self'
-    of the method will be rebound to be the wrapper rather than the object.
+    If a descriptor on the wrapped object's class is a ContextDescriptor,
+    then the 'self' of the method will be rebound to be the wrapper rather
+    than the object.
     Rebinding does not work at all if the wrapped object is a Classic Class
     instance.
     Such rebinding is supported for ordinary descriptors, but only for
@@ -126,133 +114,10 @@
     __str__
     """
 
-    def __getstate__():
-        """Raises AttributeError if called (to prevent pickling)"""
-
-
-class IDecoratorFuncs(Interface):
-    """Interface implemented by callables in 'decorator' module"""
-
-    def Decorator(object, context=None, mixinfactory=None, names=(),
-                  attrdict={}, inner=None, **data):
-        """Create and return a new decorator for object.
-
-        Decorator is a subtype of Wrapper.
-
-        If context is not None, context will be the context object.
-
-        If mixinfactory is not None, mixinfactory is a callable that need
-        take no arguments for creating the decorator mixin.
-
-        'names' is a tuple of names that are dispatched to the mixin rather
-        than to the object. The mixin is instantiated from the factory
-        before the first dispatch of one of the names.
-        If names is passed in with a None value, it is the same as ().
-
-        'attrdict' is a dict of name:value. Values may take any value
-        including None. If an attribute with a name in 'attrdict' is
-        sought from the decorator, the value from the attrdict will be
-        returned. Attempting to setattr or delattr with this name results in
-        an AttributeError. If attrdict is passed in with a None value, it is
-        the same as {}.
-
-        If the same name appears in names and in attrdict, the behaviour is
-        as if the name appeared only in attrdict.
-
-        'inner' is the decorated object that is to be passed to the
-        mixinfactory callable. If 'inner' is None, then object is passed
-        instead.
-
-        Wrapper data may be passed as keyword arguments. The data are added
-        to the context dictionary.
 
-        Note that the arguments object, context, mixinfactory, names,
-        attrdict, and inner must be given as positional arguments. All
-        keyword arguments are taken to be part of **data.
-        """
-
-    def getmixin(obj):
-        """Returns the mixin object.
-
-        Returns None if the mixin is not instantiated.
-        """
-
-    def getmixinfactory(obj):
-        """Returns the mixin factory."""
-
-    def getnames(obj):
-        """Returns the tuple of names."""
-
-    def getnamesdict(obj):
-        """Returns a read-only dict used for fast lookup of names.
-
-        This method is provided so that unit-tests can check that the
-        dict is created properly. It should otherwise be considered
-        a private API.
-        """
-
-    def getinner(obj):
-        """Returns the 'inner' that is passed to a mixin factory callable.
-
-        If no 'inner' object was given when the decorator was created,
-        this function is equivalent to IWrapperFuncs.getobject(obj).
-        """
-
-
-class IDecorator(IWrapper):
-    """A Decorator is a subtype of Wrapper.
-
-    In addition to the description in IWrapper's docstring, a decorator
-    dispatches certain names to a separate "mixin" instance, rather than
-    to the wrapped object.
-    """
-
-
-class IDecoratorMixinFactory(Interface):
-    """The callable that creates a mixin.
-    """
-    def __call__(inner, outer):
-        """Create a new mixin instance.
-
-        inner is the object being decorated.
-        outer is the decorator wrapper.
-        """
-
-class IDecoratorMixinEnvironment(Interface):
-    """The attributes that an instantiated mixin can expect to have available.
-
-    In a mixin, the 'self' of a method is always the normal unwrapped
-    self of the mixin instance. ContextMethods and other ContextDescriptors
-    will work, but should not be necessary.
-
-    When the mixin needs context, for example for using a local service,
-    it can use self.outer.
-    self.inner is a shortcut for getobject(self.outer).
-
-    This is the application api for writing simple decorator classes.
-    """
-
-    inner = Attribute('The object that is being decorated')
-    outer = Attribute('The Decorator instance')
-
-
-class IContextWrapper(Interface):
+class IWrapperIntrospection(Interface):
     """Wrapper API provided to applications."""
 
-    def ContextWrapper(object, parent, **data):
-        """Create a context wrapper for object in parent
-
-        If the object is in a security proxy, then result will be
-        a security proxy for the unproxied object in context.
-
-        Consider an object, o1, in a proxy p1 with a checker c1.
-
-        If we call ContextWrapper(p1, parent, name='foo'), then we'll
-        get::
-
-          Proxy(Wrapper(o1, parent, name='foo'), c1)
-        """
-
     def getWrapperData(ob):
         """Get the context wrapper data for an object"""
 
@@ -285,17 +150,49 @@
         innermost wrapper.
         """
 
-class IContextDecorator(IContextWrapper):
-    """Wrapper and Decorator API provided to applications."""
+    def ContextIterator(ob):
+        """Get an iterator for the object's context chain.
+
+        The iteration starts at ob and proceeds through ob's contexts.
+        """
+
+class IContextAwareDescriptorSupport(Interface):
+    """Special utilities for creating context-aware descriptors 
+
+    A context-aware descriptors is bound to context wrappers, rather than to
+    unwrapped instances.
+    """
+
+    ContextDescriptor = Attribute(
+        """Marker descriptor base class
+
+        Descriptor implementations that subclass this class will have
+        wrappers passed to their descriptor methods if they are
+        accessed through wrapped objects.
+        """)
+
+    def ContextMethod(method):
+        """Convert ordinary methods to context-aware methods.
+
+        The first argument passed to methods will be context wrapped
+        if the method is called on a context-wrapped instance.
+        """
 
-    def ContextWrapper(object, parent, **data):
-        """Create a context wrapper for object in parent
+    def ContextProperty(fget, fset=None, fdel=None):
+        """\
+        Create a property with functions to be passed context-wrapped instances
 
-        If the object is in a security proxy, then result will be
-        a security proxy for the unproxied object in context.
+        This function works like Python's property function, except
+        that the access functions are passed context-wrapped instances.
+        """
 
-        The object is examined to see if it should be wrapped with
-        a Wrapper or with a Decorator. How this is done is up to the
-        implementation.
+    def ContextSuper(cls, wrapped_instance):
+        """Call an inherited method on a wrapped instances
         """
 
+    def ContextAwareDescriptors():
+        """Function used in a class suite to advise use of context descriptors
+
+        All descriptors defined in that class suite will be made
+        context-aware.
+        """


=== Zope3/src/zope/context/wrapper.c 1.16 => 1.16.4.1 ===
--- Zope3/src/zope/context/wrapper.c:1.16	Mon May 12 12:17:39 2003
+++ Zope3/src/zope/context/wrapper.c	Sun Jun 22 10:23:39 2003
@@ -1,9 +1,10 @@
+#include <stdio.h>
 #include <Python.h>
 #include "structmember.h"
 #include "modsupport.h"
 #include "zope/proxy/proxy.h"
 #define WRAPPER_MODULE
-#include "zope/proxy/context/wrapper.h"
+#include "zope/context/wrapper.h"
 
 #define Wrapper_Check(wrapper)   (PyObject_TypeCheck(wrapper, &WrapperType))
 
@@ -15,9 +16,7 @@
 #define Wrapper_GetDict(wrapper) \
         (((WrapperObject *)wrapper)->wrap_dict)
 
-
 static PyTypeObject WrapperType;
-static PyTypeObject ContextAwareType;
 
 static PyObject *empty_tuple = NULL;
 
@@ -38,63 +37,6 @@
 #define STR_IDX 9
 
 
-/* ContextAware type
- *
- * This is a 'marker' type with no methods or members.
- * It is used to mark types that should have all of their binding descriptors
- * rebound to have the self argument be the wrapper instead.
- */
-
-typedef struct {
-    PyObject_HEAD
-} ContextAwareObject;
-
-statichere PyTypeObject
-ContextAwareType = {
-    PyObject_HEAD_INIT(NULL)
-    0,
-    "wrapper.ContextAware",
-    sizeof(ContextAwareObject),
-    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 */
-    0,						/* tp_call */
-    0,						/* tp_str */
-    0,						/* tp_getattro */
-    0,						/* tp_setattro */
-    0,						/* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,	/* tp_flags */
-    "ContextAware marker class",		/* 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 */
-    0,						/* tp_base */
-    0,						/* tp_dict */
-    0,						/* tp_descr_get */
-    0,						/* tp_descr_set */
-    0,						/* tp_dictoffset */
-    0,						/* tp_init */
-    0,						/* tp_alloc */
-    0,/*PyType_GenericNew,*/				/* tp_new */
-    0,						/* tp_free */
-};
-
-/* End of ContextAware. */
-
 /* ContextDescriptor type
  *
  * This is a 'marker' type with no methods or members. It is the base type
@@ -525,7 +467,7 @@
         PyObject *proxyargs = create_proxy_args(args, object);
         if (proxyargs == NULL)
             goto finally;
-        result = ProxyType->tp_new(type, proxyargs, NULL);
+        result = ProxyType.tp_new(type, proxyargs, NULL);
         Py_DECREF(proxyargs);
     }
  finally:
@@ -546,7 +488,7 @@
         proxyargs = create_proxy_args(args, object);
         if (proxyargs == NULL)
             goto finally;
-        if (ProxyType->tp_init(self, proxyargs, NULL) < 0)
+        if (ProxyType.tp_init(self, proxyargs, NULL) < 0)
             goto finally;
         if (wrapper->wrap_context != context) {
             /* XXX This might be a little weird: if a subclass initializes
@@ -619,9 +561,8 @@
 }
 
 /* Provide tp_getattro and tp_setattro implementations that check to see
- * if the wrapped object's class is ContextAware or the descriptor that
- * implements the attribute is a ContextDescriptor. If either of these
- * holds true, then the descriptor is used with the wrapper's self instead
+ * if the descriptor that implements the attribute is a ContextDescriptor.
+ * If it is, then the descriptor is used with the wrapper's self instead
  * of the object's self.
  *
  * We use _PyType_Lookup to get descriptors directly from the class.
@@ -633,7 +574,60 @@
  *
  * _PyType_Lookup is about 20 lines of code, so we could reproduce it here if
  * we don't want to depend on the Internal API.
+ *
+ * However, Guido says that it is ok to use _PyType_Lookup, and that the
+ * function isn't going to go away.
+ */
+
+
+/* A variant of _PyType_Lookup that doesn't look in WrapperType or ProxyType.
+ *
+ * If argument search_wrappertype is nonzero, we can look in WrapperType.
  */
+PyObject *
+WrapperType_Lookup(PyTypeObject *type, PyObject *name)
+{
+    int i, n;
+    PyObject *mro, *res, *base, *dict;
+
+    /* Look in tp_dict of types in MRO */
+    mro = type->tp_mro;
+
+    /* If mro is NULL, the type is either not yet initialized
+       by PyType_Ready(), or already cleared by type_clear().
+       Either way the safest thing to do is to return NULL. */
+    if (mro == NULL)
+        return NULL;
+
+    assert(PyTuple_Check(mro));
+
+    n = PyTuple_GET_SIZE(mro) 
+      - 1; /* We don't want to look at the last item, which is object. */
+
+    for (i = 0; i < n; i++) {
+        base = PyTuple_GET_ITEM(mro, i);
+
+        if (
+            ((PyTypeObject *)base) != &ProxyType 
+            &&
+            ((PyTypeObject *)base) != &WrapperType
+            ) {
+            if (PyClass_Check(base))
+                dict = ((PyClassObject *)base)->cl_dict;
+            else {
+                assert(PyType_Check(base));
+                dict = ((PyTypeObject *)base)->tp_dict;
+            }
+            assert(dict && PyDict_Check(dict));
+            res = PyDict_GetItem(dict, name);
+            if (res != NULL)
+                return res;
+        }
+    }
+    return NULL;
+}
+
+
 static PyObject *
 wrap_getattro(PyObject *self, PyObject *name)
 {
@@ -641,6 +635,8 @@
     PyObject *descriptor;
     PyObject *wrapped_type;
     PyObject *res = NULL;
+    char *name_as_string;
+    int maybe_special_name;
 
 #ifdef Py_USING_UNICODE
     /* The Unicode to string conversion is done here because the
@@ -660,32 +656,50 @@
     else
         Py_INCREF(name);
 
+    name_as_string = PyString_AS_STRING(name);
     wrapped = Proxy_GET_OBJECT(self);
     if (wrapped == NULL) {
         PyErr_Format(PyExc_RuntimeError,
             "object is NULL; requested to get attribute '%s'",
-            PyString_AS_STRING(name));
+            name_as_string);
         goto finally;
     }
-    descriptor = _PyType_Lookup(wrapped->ob_type, name);
-    if (descriptor != NULL &&
-        PyType_HasFeature(descriptor->ob_type, Py_TPFLAGS_HAVE_CLASS) &&
-        descriptor->ob_type->tp_descr_get != NULL &&
-        (PyObject_TypeCheck(descriptor, &ContextDescriptorType) ||
-        /* If object is context-aware, still don't rebind __class__.
-         */
-         (PyObject_TypeCheck(wrapped, &ContextAwareType)
-          && ! (PyString_Check(name)
-           && strcmp(PyString_AS_STRING(name), "__class__") == 0))
-        )) {
-        wrapped_type = (PyObject *)wrapped->ob_type;
-        if (wrapped_type == NULL)
+
+    maybe_special_name = name_as_string[0] == '_' && name_as_string[1] == '_';
+
+    if (!(maybe_special_name && strcmp(name_as_string, "__class__") == 0)) {
+
+        descriptor = WrapperType_Lookup(self->ob_type, name);
+
+        if (descriptor != NULL) {
+            if (PyType_HasFeature(descriptor->ob_type, Py_TPFLAGS_HAVE_CLASS)
+                && descriptor->ob_type->tp_descr_get != NULL) {
+                res = descriptor->ob_type->tp_descr_get(
+                        descriptor,
+                        self,
+                        (PyObject *)self->ob_type);
+            } else {
+                Py_INCREF(descriptor);
+                res = descriptor;
+            }
             goto finally;
-        res = descriptor->ob_type->tp_descr_get(
-                descriptor,
-                self,
-                wrapped_type);
-        goto finally;
+        }
+
+        descriptor = _PyType_Lookup(wrapped->ob_type, name);
+        if (descriptor != NULL &&
+            PyType_HasFeature(descriptor->ob_type, Py_TPFLAGS_HAVE_CLASS) &&
+            descriptor->ob_type->tp_descr_get != NULL &&
+            PyObject_TypeCheck(descriptor, &ContextDescriptorType)
+            ) {
+            wrapped_type = (PyObject *)wrapped->ob_type;
+            if (wrapped_type == NULL)
+                goto finally;
+            res = descriptor->ob_type->tp_descr_get(
+                    descriptor,
+                    self,
+                    wrapped_type);
+            goto finally;
+        }
     }
     res = PyObject_GetAttr(wrapped, name);
 finally:
@@ -718,6 +732,19 @@
     else
         Py_INCREF(name);
 
+    descriptor = WrapperType_Lookup(self->ob_type, name);
+    if (descriptor != NULL) {
+        if (PyType_HasFeature(descriptor->ob_type, Py_TPFLAGS_HAVE_CLASS) &&
+            descriptor->ob_type->tp_descr_set != NULL) {
+            res = descriptor->ob_type->tp_descr_set(descriptor, self, value);
+        } else {
+            PyErr_Format(PyExc_TypeError,
+                "Tried to set attribute '%s' on wrapper, but it is not"
+                " a data descriptor", PyString_AS_STRING(name));
+        }
+        goto finally;
+    }
+
     wrapped = Proxy_GET_OBJECT(self);
     if (wrapped == NULL) {
         PyErr_Format(PyExc_RuntimeError,
@@ -728,8 +755,7 @@
     descriptor = _PyType_Lookup(wrapped->ob_type, name);
     if (descriptor != NULL &&
         PyType_HasFeature(descriptor->ob_type, Py_TPFLAGS_HAVE_CLASS) &&
-        (PyObject_TypeCheck(descriptor, &ContextDescriptorType) ||
-         PyObject_TypeCheck(wrapped, &ContextAwareType)) &&
+        PyObject_TypeCheck(descriptor, &ContextDescriptorType) &&
         descriptor->ob_type->tp_descr_set != NULL
         )
         res = descriptor->ob_type->tp_descr_set(descriptor, self, value);
@@ -759,8 +785,7 @@
     if (descriptor != NULL && \
         PyType_HasFeature(descriptor->ob_type, Py_TPFLAGS_HAVE_CLASS) && \
         descriptor->ob_type->tp_descr_get != NULL && \
-        (PyObject_TypeCheck(descriptor, &ContextDescriptorType) || \
-            PyObject_TypeCheck(wrapped, &ContextAwareType))\
+        PyObject_TypeCheck(descriptor, &ContextDescriptorType) \
         ) { \
         wrapped_type = (PyObject *) wrapped->ob_type; \
         if (wrapped_type == NULL) \
@@ -834,6 +859,31 @@
                      );
             return -1;
     }
+    descriptor = WrapperType_Lookup(self->ob_type, SlotStrings[LEN_IDX]);
+    if (descriptor != NULL) {
+        /* There's a __len__ defined in a wrapper subclass, so we need
+         * to call that.
+         */
+        if (PyType_HasFeature(descriptor->ob_type, Py_TPFLAGS_HAVE_CLASS)
+            && descriptor->ob_type->tp_descr_get != NULL) {
+            descriptor = descriptor->ob_type->tp_descr_get(
+                            descriptor,
+                            self,
+                            (PyObject *)self->ob_type);
+            if (descriptor == NULL)
+                return -1;
+            res = PyObject_CallFunctionObjArgs(descriptor, NULL);
+            Py_DECREF(descriptor);
+        } else {
+            res = PyObject_CallFunctionObjArgs(descriptor, self, NULL);
+        }
+        if (res == NULL)
+            return -1;
+        result = PyObject_IsTrue(res);
+        Py_DECREF(res);
+        return result;
+    }
+
     descriptor = _PyType_Lookup(wrapped->ob_type, SlotStrings[NONZERO_IDX]);
     if (descriptor == NULL)
         descriptor = _PyType_Lookup(wrapped->ob_type, SlotStrings[LEN_IDX]);
@@ -974,45 +1024,6 @@
     return PyObject_Str(wrapped);
 }
 
-/*
- * 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 PyMethodDef
-wrap_methods[] = {
-    {"__reduce__", (PyCFunction)wrap_reduce, METH_NOARGS, reduce__doc__},
-    {NULL, NULL},
-};
-
 static PySequenceMethods
 wrap_as_sequence = {
     wrap_length,				/* sq_length */
@@ -1111,7 +1122,7 @@
     0,							/* tp_weaklistoffset */
     wrap_iter,						/* tp_iter */
     wrap_iternext,					/* tp_iternext */
-    wrap_methods,					/* tp_methods */
+    0,							/* tp_methods */
     0,							/* tp_members */
     0,							/* tp_getset */
     0,							/* tp_base */
@@ -1325,7 +1336,6 @@
 wrapper_capi = {
     &WrapperType,
     &ContextDescriptorType,
-    &ContextAwareType,
     api_check,
     api_create,
     api_getobject,
@@ -1581,7 +1591,7 @@
     SlotStrings[CALL_IDX] = PyString_InternFromString("__call__");
     SlotStrings[STR_IDX] = PyString_InternFromString("__str__");
 
-    WrapperType.tp_base = ProxyType;
+    WrapperType.tp_base = &ProxyType;
     WrapperType.tp_alloc = PyType_GenericAlloc;
     WrapperType.tp_free = _PyObject_GC_Del;
     if (PyType_Ready(&WrapperType) < 0)
@@ -1589,12 +1599,6 @@
 
     Py_INCREF(&WrapperType);
     PyModule_AddObject(m, "Wrapper", (PyObject *)&WrapperType);
-
-    ContextAwareType.tp_new = PyType_GenericNew;
-    if (PyType_Ready(&ContextAwareType) < 0)
-        return;
-    Py_INCREF(&ContextAwareType);
-    PyModule_AddObject(m, "ContextAware", (PyObject *)&ContextAwareType);
 
     ContextDescriptorType.tp_new = PyType_GenericNew;
     if (PyType_Ready(&ContextDescriptorType) < 0)


=== Zope3/src/zope/context/wrapper.h 1.5 => 1.5.4.1 ===
--- Zope3/src/zope/context/wrapper.h:1.5	Thu May  8 05:39:21 2003
+++ Zope3/src/zope/context/wrapper.h	Sun Jun 22 10:23:39 2003
@@ -23,7 +23,6 @@
 typedef struct {
     PyTypeObject *wrappertype;
     PyTypeObject *contextdescriptortype;
-    PyTypeObject *contextawaretype;
     int (*check)(PyObject *obj);
     PyObject *(*create)(PyObject *object, PyObject *context);
     PyObject *(*getobject)(PyObject *wrapper);
@@ -51,7 +50,7 @@
 Wrapper_Import(void)
 {
     if (_wrapper_api == NULL) {
-        PyObject *m = PyImport_ImportModule("zope.proxy.context.wrapper");
+        PyObject *m = PyImport_ImportModule("zope.context.wrapper");
         if (m != NULL) {
             PyObject *tmp = PyObject_GetAttrString(m, "_CAPI");
             if (tmp != NULL) {
@@ -69,8 +68,6 @@
         (*_wrapper_api->wrappertype)
 #define ContextDescriptorType             \
         (*_wrapper_api->contextdescriptortype)
-#define ContextAwareType                  \
-        (*_wrapper_api->contextawaretype)
 #define Wrapper_Check(obj)                   \
         (_wrapper_api->check((obj)))
 #define Wrapper_New(object, context)         \

=== Removed File Zope3/src/zope/context/containmentiterator.py ===

=== Removed File Zope3/src/zope/context/decorator.c ===

=== Removed File Zope3/src/zope/context/decorator.h ===