[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"
+
+