[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 ===