[Zope3-checkins] SVN: Zope3/trunk/ The `Attribute` and `Method`
class of the `zope.interface` have now a
Stephan Richter
srichter at cosmos.phy.tufts.edu
Sat Sep 25 14:50:42 EDT 2004
Log message for revision 27687:
The `Attribute` and `Method` class of the `zope.interface` have now a
new public `interface` attribute that stores the interface they are
defined in.
See
http://mail.zope.org/pipermail/interface-dev/2004-September/000073.html
Changed:
U Zope3/trunk/doc/CHANGES.txt
U Zope3/trunk/src/zope/interface/interface.py
U Zope3/trunk/src/zope/interface/interfaces.py
U Zope3/trunk/src/zope/interface/tests/test_interface.py
U Zope3/trunk/src/zope/interface/verify.py
-=-
Modified: Zope3/trunk/doc/CHANGES.txt
===================================================================
--- Zope3/trunk/doc/CHANGES.txt 2004-09-25 17:05:28 UTC (rev 27686)
+++ Zope3/trunk/doc/CHANGES.txt 2004-09-25 18:50:41 UTC (rev 27687)
@@ -10,6 +10,10 @@
New features
+ - The `Attribute` and `Method` class of the `zope.interface` have now a
+ new public `interface` attribute that stores the interface they are
+ defined in.
+
- If the adapter factory returns `None` as adapter instance, the default
is returned instead of `None`. For benefits and the discussions see
http://mail.zope.org/pipermail/interface-dev/2004-September/000070.html
Modified: Zope3/trunk/src/zope/interface/interface.py
===================================================================
--- Zope3/trunk/src/zope/interface/interface.py 2004-09-25 17:05:28 UTC (rev 27686)
+++ Zope3/trunk/src/zope/interface/interface.py 2004-09-25 18:50:41 UTC (rev 27687)
@@ -433,21 +433,23 @@
for key, val in tagged_data.items():
self.setTaggedValue(key, val)
- for b in bases:
- if not isinstance(b, InterfaceClass):
+ for base in bases:
+ if not isinstance(base, InterfaceClass):
raise TypeError, 'Expected base interfaces'
Specification.__init__(self, bases)
- for k, v in attrs.items():
- if isinstance(v, Attribute):
- v.interface = name
- if not v.__name__:
- v.__name__ = k
- elif isinstance(v, FunctionType):
- attrs[k] = fromFunction(v, name, name=k)
+ # Make sure that all recorded attributes (and methods) are of type
+ # `Attribute` and `Method`
+ for name, attr in attrs.items():
+ if isinstance(attr, Attribute):
+ attr.interface = self
+ if not attr.__name__:
+ attr.__name__ = name
+ elif isinstance(attr, FunctionType):
+ attrs[name] = fromFunction(attr, self, name=name)
else:
- raise InvalidInterface("Concrete attribute, %s" % k)
+ raise InvalidInterface("Concrete attribute, %s" %name)
self.__attrs = attrs
@@ -822,8 +824,11 @@
# We can't say this yet because we don't have enough
# infrastructure in place.
#
- #__implemented__ = IAttribute
+ # implements(IAttribute)
+ interface = None
+
+
class Method(Attribute):
"""Method interfaces
@@ -834,10 +839,8 @@
# We can't say this yet because we don't have enough
# infrastructure in place.
#
- #__implemented__ = IMethod
+ # implements(IMethod)
- interface=''
-
def __call__(self, *args, **kw):
raise BrokenImplementation(self.interface, self.__name__)
@@ -869,47 +872,55 @@
return sig
-def fromFunction(func, interface='', imlevel=0, name=None):
+def fromFunction(func, interface=None, imlevel=0, name=None):
name = name or func.__name__
- m=Method(name, func.__doc__)
- defaults=func.func_defaults or ()
- c=func.func_code
- na=c.co_argcount-imlevel
- names=c.co_varnames[imlevel:]
- d={}
- nr=na-len(defaults)
+ method = Method(name, func.__doc__)
+ defaults = func.func_defaults or ()
+ code = func.func_code
+ # Number of positional arguments
+ na = code.co_argcount-imlevel
+ names = code.co_varnames[imlevel:]
+ opt = {}
+ # Number of required arguments
+ nr = na-len(defaults)
if nr < 0:
defaults=defaults[-nr:]
- nr=0
+ nr = 0
+ # Determine the optional arguments.
for i in range(len(defaults)):
- d[names[i+nr]]=defaults[i]
+ opt[names[i+nr]] = defaults[i]
- m.positional=names[:na]
- m.required=names[:nr]
- m.optional=d
+ method.positional = names[:na]
+ method.required = names[:nr]
+ method.optional = opt
argno = na
- if c.co_flags & CO_VARARGS:
- m.varargs = names[argno]
+
+ # Determine the function's variable argument's name (i.e. *args)
+ if code.co_flags & CO_VARARGS:
+ method.varargs = names[argno]
argno = argno + 1
else:
- m.varargs = None
- if c.co_flags & CO_VARKEYWORDS:
- m.kwargs = names[argno]
+ method.varargs = None
+
+ # Determine the function's keyword argument's name (i.e. **kw)
+ if code.co_flags & CO_VARKEYWORDS:
+ method.kwargs = names[argno]
else:
- m.kwargs = None
+ method.kwargs = None
- m.interface=interface
+ method.interface = interface
- for k, v in func.__dict__.items():
- m.setTaggedValue(k, v)
+ for key, value in func.__dict__.items():
+ method.setTaggedValue(key, value)
- return m
+ return method
-def fromMethod(meth, interface=''):
+
+def fromMethod(meth, interface=None, name=None):
func = meth.im_func
- return fromFunction(func, interface, imlevel=1)
+ return fromFunction(func, interface, imlevel=1, name=name)
# Now we can create the interesting interfaces and wire them up:
Modified: Zope3/trunk/src/zope/interface/interfaces.py
===================================================================
--- Zope3/trunk/src/zope/interface/interfaces.py 2004-09-25 17:05:28 UTC (rev 27686)
+++ Zope3/trunk/src/zope/interface/interfaces.py 2004-09-25 18:50:41 UTC (rev 27687)
@@ -48,7 +48,11 @@
class IAttribute(IElement):
"""Attribute descriptors"""
+ interface = Attribute('interface',
+ 'Stores the interface instance in which the '
+ 'attribute is located.')
+
class IMethod(IAttribute):
"""Method attributes
"""
Modified: Zope3/trunk/src/zope/interface/tests/test_interface.py
===================================================================
--- Zope3/trunk/src/zope/interface/tests/test_interface.py 2004-09-25 17:05:28 UTC (rev 27686)
+++ Zope3/trunk/src/zope/interface/tests/test_interface.py 2004-09-25 18:50:41 UTC (rev 27687)
@@ -24,6 +24,12 @@
class InterfaceTests(unittest.TestCase):
+ def testInterfaceSetOnAttributes(self):
+ self.assertEqual(FooInterface['foobar'].interface,
+ FooInterface)
+ self.assertEqual(FooInterface['aMethod'].interface,
+ FooInterface)
+
def testClassImplements(self):
self.assert_(IC.implementedBy(C))
Modified: Zope3/trunk/src/zope/interface/verify.py
===================================================================
--- Zope3/trunk/src/zope/interface/verify.py 2004-09-25 17:05:28 UTC (rev 27686)
+++ Zope3/trunk/src/zope/interface/verify.py 2004-09-25 18:50:41 UTC (rev 27687)
@@ -50,39 +50,42 @@
if not tentative and not tester(candidate):
raise DoesNotImplement(iface)
- for n, d in iface.namesAndDescriptions(1):
- if not hasattr(candidate, n):
- if (not isinstance(d, Method)) and vtype == 'c':
+ # Here the `desc` is either an `Attribute` or `Method` instance
+ for name, desc in iface.namesAndDescriptions(1):
+ if not hasattr(candidate, name):
+ if (not isinstance(desc, Method)) and vtype == 'c':
# We can't verify non-methods on classes, since the
# class may provide attrs in it's __init__.
continue
- raise BrokenImplementation(iface, n)
+ raise BrokenImplementation(iface, name)
- attr = getattr(candidate, n)
- if not isinstance(d, Method):
+ attr = getattr(candidate, name)
+ if not isinstance(desc, Method):
# If it's not a method, there's nothing else we can test
continue
- if type(attr) is FunctionType:
- # should never get here
- meth = fromFunction(attr, n)
+ if isinstance(attr, FunctionType):
+ # should never get here, since classes should not provide functions
+ meth = fromFunction(attr, iface, name=name)
elif (isinstance(attr, MethodTypes)
and type(attr.im_func) is FunctionType):
- meth = fromMethod(attr, n)
+ meth = fromMethod(attr, iface, name)
else:
if not callable(attr):
- raise BrokenMethodImplementation(n, "Not a method")
- # sigh, it's callable,but we don't know how to intrspect it, so
+ raise BrokenMethodImplementation(name, "Not a method")
+ # sigh, it's callable, but we don't know how to intrspect it, so
# we have to give it a pass.
continue
- d=d.getSignatureInfo()
+ # Make sure that the required and implemented method signatures are
+ # the same.
+ desc = desc.getSignatureInfo()
meth = meth.getSignatureInfo()
- mess = _incompat(d, meth)
+ mess = _incompat(desc, meth)
if mess:
- raise BrokenMethodImplementation(n, mess)
+ raise BrokenMethodImplementation(name, mess)
return True
More information about the Zope3-Checkins
mailing list