[Zope-Checkins] CVS: Zope3/lib/python/Interface - Exceptions.py:1.6.134.1 Method.py:1.7.120.1 Util.py:1.7.58.2 __init__.py:1.5.134.3 iclass.py:1.11.58.2 verify.py:1.3.136.1

Jim Fulton jim@zope.com
Tue, 20 Nov 2001 13:35:36 -0500


Update of /cvs-repository/Zope3/lib/python/Interface
In directory cvs.zope.org:/tmp/cvs-serv10107

Modified Files:
      Tag: Zope-3x-branch
	Exceptions.py Method.py Util.py __init__.py iclass.py 
	verify.py 
Log Message:
fixed interface verification and added Interface.implements

=== Zope3/lib/python/Interface/Exceptions.py 1.6 => 1.6.134.1 ===
     """
 
-    def __init__(self, method):
+    def __init__(self, method, mess):
         self.method=method
+        self.mess=mess
 
     def __str__(self):
-        return """An object has failed to implement the method %(method)s
-
-        The signature is incorrect.
+        return """The implementation of %(method)s violates it's contract
+        because %(mess)s.
         """ % self.__dict__
 
 class InvalidInterface(Exception): pass


=== Zope3/lib/python/Interface/Method.py 1.7 => 1.7.120.1 ===
 class MethodClass:
 
-    def fromFunction(self, func, interface=''):
+    def fromFunction(self, func, interface='', imlevel=0):
         m=Method(func.__name__, func.__doc__)
         defaults=func.func_defaults or ()
         c=func.func_code
-        na=c.co_argcount
-        names=c.co_varnames
+        na=c.co_argcount-imlevel
+        names=c.co_varnames[imlevel:]
         d={}
         nr=na-len(defaults)
-        if nr==0:
-            defaults=defaults[1:]
-            nr=1
+        if nr < 0:
+            defaults=defaults[-nr:]
+            nr=0
+            
+        #if nr==0:
+        #    defaults=defaults[1:]
+        #    nr=1
         
         for i in range(len(defaults)):
             d[names[i+nr]]=defaults[i]
 
-        m.positional=names[1:na]
-        m.required=names[1:nr]
+        m.positional=names[:na]
+        m.required=names[:nr]
         m.optional=d
 
         argno = na
@@ -45,7 +49,7 @@
 
     def fromMethod(self, meth, interface=''):
         func = meth.im_func
-        return self.fromFunction(func, interface)
+        return self.fromFunction(func, interface, imlevel=1)
 
 class Method(Attribute):
     """Method interfaces


=== Zope3/lib/python/Interface/Util.py 1.7.58.1 => 1.7.58.2 ===
      getImplements, getImplementsOfInstances, visitImplements
 from types import FunctionType, StringType
+from verify import verify
 
 
 def impliedInterface(klass, __name__=None, __doc__=None):
@@ -32,7 +33,6 @@
     visitImplements(implements, object, r.append, getInterface)
     return r
 
-
 def instancesOfObjectImplements(klass, getInterface=None):
     r = []
     implements = getImplementsOfInstances(klass)
@@ -68,3 +68,14 @@
             index = index - 1
     return res
 
+def implements(klass, interface, check=1):
+    if check:
+        verify(interface, klass, tentative=1)
+
+    old=getattr(klass, '__implements__', None)
+    if old is None:
+        klass.__implements__ = interface
+    else:
+        klass.__implements__ = old, interface
+
+    


=== Zope3/lib/python/Interface/__init__.py 1.5.134.2 => 1.5.134.3 ===
 
 from pprint import interface_as_stx
-from verify import verify_class_implementation
+from verify import verify, verify_class_implementation
+
+from Util import implements
+    


=== Zope3/lib/python/Interface/iclass.py 1.11.58.1 => 1.11.58.2 ===
     import ExtensionClass
 except ImportError:
-    ClassTypes = (ClassType,)
+    ClassTypes = (ClassType, type(object))
 else:
     class dummy (ExtensionClass.Base): pass
-    ClassTypes = (type(dummy), ClassType)
+    ClassTypes = (type(dummy), ClassType, type(object))
 
 
 # Special value indicating the object supports


=== Zope3/lib/python/Interface/verify.py 1.3 => 1.3.136.1 ===
 import types
 
-def verify_class_implementation(iface, klass):
+def verify(iface, klass, tentative=0):
     """
 
-    Verify that 'klass' correctly implements 'iface'.  This involves:
+    Verify that 'klass' might correctly implements 'iface'.  This involves:
 
       o Making sure the klass defines all the necessary methods
 
@@ -14,9 +14,12 @@
 
       o Making sure the klass asserts that it implements the interface
 
+    Note that this isn't the same as verifying that the class does
+    implement the interface.
+
     """
 
-    if not iface.isImplementedByInstancesOf(klass):
+    if not tentative and not iface.isImplementedByInstancesOf(klass):
         raise DoesNotImplement(iface)
 
     for n, d in iface.namesAndDescriptions():
@@ -25,18 +28,37 @@
 
         attr = getattr(klass, n)
         if type(attr) is types.FunctionType:
+            # should never get here
             meth = Method().fromFunction(attr, n)
         elif type(attr) is types.MethodType:
             meth = Method().fromMethod(attr, n)
         else:
             break # must be an attribute...
-        
-        if d.getSignatureInfo() != meth.getSignatureInfo():
-                raise BrokenMethodImplementation(n)
+
+        d=d.getSignatureInfo()
+        meth = meth.getSignatureInfo()
+
+        mess = _incompat(d, meth)
+        if mess:
+            raise BrokenMethodImplementation(n, mess)
             
     return 1
 
+verify_class_implementation=verify # maybe something depends on this. :(
 
+def _incompat(required, implemented):
+    if (required['positional'] !=
+        implemented['positional'][:len(required['positional'])]
+        and implemented['kwargs'] is None):
+        return 'imlementation has different argument names'
+    if len(implemented['required']) > len(required['required']):
+        return 'implementation requires too many arguments'
+    if required['kwargs'] and not implemented['kwargs']:
+        return "implementation doesn't support keyword arguments"
+    if required['varargs'] and not implemented['varargs']:
+        return "implementation doesn't support variable arguments"
+    
+