[Zope3-checkins] SVN: Zope3/trunk/src/zope/ Changed implementedBy
so it always suceeds for callable objects.
Jim Fulton
jim at zope.com
Fri Feb 11 12:44:17 EST 2005
Log message for revision 29118:
Changed implementedBy so it always suceeds for callable objects.
Added an api function, factoryImplements, for declating interfaces
implemented by a factory, which are the interfaces provided by the
objects created by the factory.
Changed:
U Zope3/trunk/src/zope/component/factory.py
U Zope3/trunk/src/zope/component/tests/test_factory.py
U Zope3/trunk/src/zope/interface/README.txt
U Zope3/trunk/src/zope/interface/__init__.py
U Zope3/trunk/src/zope/interface/declarations.py
U Zope3/trunk/src/zope/interface/interfaces.py
-=-
Modified: Zope3/trunk/src/zope/component/factory.py
===================================================================
--- Zope3/trunk/src/zope/component/factory.py 2005-02-11 17:04:02 UTC (rev 29117)
+++ Zope3/trunk/src/zope/component/factory.py 2005-02-11 17:44:16 UTC (rev 29118)
@@ -41,9 +41,4 @@
spec = Implements(*self._interfaces)
spec.__name__ = getattr(self._callable, '__name__', '[callable]')
return spec
- try:
- return implementedBy(self._callable)
- except TypeError:
- spec = Implements()
- spec.__name__ = getattr(self._callable, '__name__', '[callable]')
- return spec
+ return implementedBy(self._callable)
Modified: Zope3/trunk/src/zope/component/tests/test_factory.py
===================================================================
--- Zope3/trunk/src/zope/component/tests/test_factory.py 2005-02-11 17:04:02 UTC (rev 29117)
+++ Zope3/trunk/src/zope/component/tests/test_factory.py 2005-02-11 17:44:16 UTC (rev 29118)
@@ -66,16 +66,12 @@
implemented = self._factory.getInterfaces()
self.assert_(implemented.isOrExtends(IKlass))
self.assertEqual(list(implemented), [IKlass])
- self.assertEqual(implemented.__name__,
- 'zope.component.tests.test_factory.Klass')
implemented2 = self._factory2.getInterfaces()
self.assertEqual(list(implemented2), [])
- self.assertEqual(implemented2.__name__, '<lambda>')
implemented3 = self._factory3.getInterfaces()
self.assertEqual(list(implemented3), [IFunction])
- self.assertEqual(implemented3.__name__, '<lambda>')
class TestFactoryZAPIFunctions(PlacelessSetup, unittest.TestCase):
Modified: Zope3/trunk/src/zope/interface/README.txt
===================================================================
--- Zope3/trunk/src/zope/interface/README.txt 2005-02-11 17:04:02 UTC (rev 29117)
+++ Zope3/trunk/src/zope/interface/README.txt 2005-02-11 17:44:16 UTC (rev 29118)
@@ -147,9 +147,16 @@
It is important to note that classes don't usually provide the
interfaces that the implement.
+ We can generalize this to factories. For any callable object we
+ can declare that it produces objects that provides some interfaces
+ by saying that the factory implements the interfaces.
+
Now that we've defined these terms, we can talk about the API for
declaring interfaces.
+Declaring implemented interfaces
+--------------------------------
+
The most common way to declare interfaces is using the implements
function in a class statement::
@@ -190,17 +197,18 @@
>>> list(zope.interface.implementedBy(Foo))
[<InterfaceClass __main__.IFoo>]
-It's an error to ask for interfaces implemented by a non-class::
+It's an error to ask for interfaces implemented by a non-callable
+object::
>>> IFoo.implementedBy(foo)
Traceback (most recent call last):
...
- TypeError: ('ImplementedBy called for non-type', Foo(None))
+ TypeError: ('ImplementedBy called for non-factory', Foo(None))
>>> list(zope.interface.implementedBy(foo))
Traceback (most recent call last):
...
- TypeError: ('ImplementedBy called for non-type', Foo(None))
+ TypeError: ('ImplementedBy called for non-factory', Foo(None))
Similarly, we can ask what interfaces are provided by an object::
@@ -209,6 +217,36 @@
>>> list(zope.interface.providedBy(Foo))
[]
+We can declare interfaces implemented by other factories (besides
+classes). We do this using a Python-2.4-style decorator named
+`implementer`. In versions of Python before 2.4, this looks like:
+
+
+ >>> def yfoo(y):
+ ... foo = Foo()
+ ... foo.y = y
+ ... return foo
+ >>> zope.interface.implementer(IFoo)(yfoo)
+
+ >>> list(zope.interface.implementedBy(yfoo))
+ [<InterfaceClass __main__.IFoo>]
+
+Note that the implementer decorator may modify it's argument. Callers
+should not assume that a new object is created.
+
+Also note that, at least for now, implementer cannt be used with
+classes:
+
+ >>> zope.interface.implementer(IFoo)(Foo)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ TypeError: Can't use implementer with classes.
+ Use one of the class-declaration functions instead.
+
+Declaring provided interfaces
+-----------------------------
+
We can declare interfaces directly provided by objects. Suppose that
we want to document what the `__init__` method of the `Foo` class
does. It's not *really* part of `IFoo`. You wouldn't normally call
Modified: Zope3/trunk/src/zope/interface/__init__.py
===================================================================
--- Zope3/trunk/src/zope/interface/__init__.py 2005-02-11 17:04:02 UTC (rev 29117)
+++ Zope3/trunk/src/zope/interface/__init__.py 2005-02-11 17:44:16 UTC (rev 29118)
@@ -63,7 +63,7 @@
from zope.interface.declarations import providedBy, implementedBy
from zope.interface.declarations import classImplements, classImplementsOnly
from zope.interface.declarations import directlyProvidedBy, directlyProvides
-from zope.interface.declarations import alsoProvides
+from zope.interface.declarations import alsoProvides, implementer
from zope.interface.declarations import implements, implementsOnly
from zope.interface.declarations import classProvides, moduleProvides
from zope.interface.declarations import Declaration
Modified: Zope3/trunk/src/zope/interface/declarations.py
===================================================================
--- Zope3/trunk/src/zope/interface/declarations.py 2005-02-11 17:04:02 UTC (rev 29117)
+++ Zope3/trunk/src/zope/interface/declarations.py 2005-02-11 17:44:16 UTC (rev 29118)
@@ -346,7 +346,9 @@
try:
bases = cls.__bases__
except AttributeError:
- raise TypeError("ImplementedBy called for non-type", cls)
+ if not callable(cls):
+ raise TypeError("ImplementedBy called for non-factory", cls)
+ bases = ()
spec = Implements(*[implementedBy(c) for c in bases])
spec.inherit = cls
@@ -485,6 +487,23 @@
classImplements(cls, *interfaces)
return cls
+
+class implementer:
+
+ def __init__(self, *interfaces):
+ self.interfaces = interfaces
+
+ def __call__(self, ob):
+ if isinstance(ob, DescriptorAwareMetaClasses):
+ raise TypeError("Can't use implementer with classes. Use one of "
+ "the class-declaration functions instead."
+ )
+ spec = Implements(*self.interfaces)
+ try:
+ ob.__implemented__ = spec
+ except AttributeError:
+ raise TypeError("Can't declare implements", ob)
+
def _implements(name, interfaces, classImplements):
frame = sys._getframe(2)
locals = frame.f_locals
Modified: Zope3/trunk/src/zope/interface/interfaces.py
===================================================================
--- Zope3/trunk/src/zope/interface/interfaces.py 2005-02-11 17:04:02 UTC (rev 29117)
+++ Zope3/trunk/src/zope/interface/interfaces.py 2005-02-11 17:44:16 UTC (rev 29118)
@@ -418,6 +418,14 @@
instances of ``A`` and ``B`` provide.
"""
+ def implementer(*interfaces):
+ """Create a decorator for declaring interfaces implemented by a facory
+
+ A callable is returned that makes an implements declaration on
+ objects passed to it.
+
+ """
+
def classImplementsOnly(class_, *interfaces):
"""Declare the only interfaces implemented by instances of a class
More information about the Zope3-Checkins
mailing list