[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