[Zope3-checkins] CVS: Zope3/src/zope/context - declarations.py:1.1 wrapper.c:1.22
Jim Fulton
jim@zope.com
Sat, 31 May 2003 18:13:09 -0400
Update of /cvs-repository/Zope3/src/zope/context
In directory cvs.zope.org:/tmp/cvs-serv21814/src/zope/context
Modified Files:
wrapper.c
Added Files:
declarations.py
Log Message:
Implemented object interface specifications for wrappers/decorators.
=== Added File Zope3/src/zope/context/declarations.py ===
##############################################################################
#
# Copyright (c) 2003 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.
#
##############################################################################
"""Support for interface declarations on decorators
>>> from zope.context import Wrapper
>>> from zope.interface import *
>>> class I1(Interface):
... pass
>>> class I2(Interface):
... pass
>>> class I3(Interface):
... pass
>>> class I4(Interface):
... pass
>>> class D1(Wrapper):
... implements(I1)
>>> class D2(Wrapper):
... implements(I2)
>>> class X:
... implements(I3)
>>> x = X()
>>> directlyProvides(x, I4)
Interfaces of X are ordered with the directly-provided interfaces first
>>> [interface.__name__ for interface in list(providedBy(x))]
['I4', 'I3']
When we decorate objects, what order should the interfaces come in?
One could argue that decorators are less specific, so they should come last.
>>> [interface.__name__ for interface in list(providedBy(D1(x)))]
['I4', 'I3', 'I1']
>>> [interface.__name__ for interface in list(providedBy(D2(D1(x))))]
['I4', 'I3', 'I1', 'I2']
$Id: declarations.py,v 1.1 2003/05/31 22:12:38 jim Exp $
"""
from zope.proxy import getProxiedObject
from zope.interface import providedBy
from zope.interface.declarations import getObjectSpecification
from zope.interface.declarations import ObjectSpecification
from zope.interface.declarations import ObjectSpecificationDescriptor
class DecoratorSpecificationDescriptor(ObjectSpecificationDescriptor):
def __get__(self, inst, cls):
if inst is None:
return getObjectSpecification(cls)
else:
provided = providedBy(getProxiedObject(inst))
# Use type rather than __class__ because inst is a proxy and
# will return the proxied object's class.
cls = type(inst)
return ObjectSpecification(provided, cls)
decoratorSpecificationDescriptor = DecoratorSpecificationDescriptor()
=== Zope3/src/zope/context/wrapper.c 1.21 => 1.22 ===
--- Zope3/src/zope/context/wrapper.c:1.21 Thu May 29 15:31:20 2003
+++ Zope3/src/zope/context/wrapper.c Sat May 31 18:12:38 2003
@@ -729,6 +729,8 @@
strcmp(name_as_string, "__reduce__") == 0
||
strcmp(name_as_string, "__reduce_ex__") == 0
+ ||
+ strcmp(name_as_string, "__providedBy__") == 0
)
)
);
@@ -1684,7 +1686,17 @@
void
initwrapper(void)
{
- PyObject *m;
+ PyObject *m, *descr;
+
+ /* Get the __providedBy__ descr */
+ m = PyImport_ImportModule("zope.context.declarations");
+ if (m == NULL)
+ return;
+ descr = PyObject_GetAttrString(m, "decoratorSpecificationDescriptor");
+ Py_DECREF(m);
+ if (descr == NULL)
+ return;
+
if (Proxy_Import() < 0)
return;
@@ -1708,6 +1720,10 @@
WrapperType.tp_alloc = PyType_GenericAlloc;
WrapperType.tp_free = _PyObject_GC_Del;
if (PyType_Ready(&WrapperType) < 0)
+ return;
+
+ /* Install the __providedBy__ descr */
+ if (PyDict_SetItemString(WrapperType.tp_dict, "__providedBy__", descr) < 0)
return;
Py_INCREF(&WrapperType);