Support for interface checking. Experimental.
git-svn-id: svn://svn.code.sf.net/p/fonttools/code/trunk@68 4cde692c-a291-49d1-8350-778aa11640f8
This commit is contained in:
parent
02a739a0d5
commit
56804d237a
89
Lib/interfaceChecker.py
Normal file
89
Lib/interfaceChecker.py
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
import sys, types
|
||||||
|
|
||||||
|
try:
|
||||||
|
import describeFunction
|
||||||
|
except ImportError:
|
||||||
|
print "(Can't check interfaces, describeFunction could not be imported)"
|
||||||
|
describeFunction = None
|
||||||
|
|
||||||
|
|
||||||
|
def collectMethodNames(theClass, names=None):
|
||||||
|
if names is None:
|
||||||
|
names = {}
|
||||||
|
names.update(theClass.__dict__)
|
||||||
|
for baseClass in theClass.__bases__:
|
||||||
|
collectMethodNames(baseClass, names)
|
||||||
|
names = names.keys()
|
||||||
|
names.sort()
|
||||||
|
return names
|
||||||
|
|
||||||
|
|
||||||
|
def checkClass(moduleName, theClass):
|
||||||
|
className = theClass.__name__
|
||||||
|
if theClass.__module__ <> moduleName:
|
||||||
|
return
|
||||||
|
if not hasattr(theClass, "__implements__"):
|
||||||
|
print "Interfaceless class: %s (%s)" % (className, theClass.__module__)
|
||||||
|
return
|
||||||
|
interfaces = theClass.__implements__
|
||||||
|
if interfaces is None:
|
||||||
|
return
|
||||||
|
if isinstance(interfaces, types.ClassType):
|
||||||
|
interfaces = (interfaces,)
|
||||||
|
gotOne = 0
|
||||||
|
for interface in interfaces:
|
||||||
|
methodNames = collectMethodNames(interface)
|
||||||
|
methodNames.sort()
|
||||||
|
for methodName in methodNames:
|
||||||
|
method = getattr(interface, methodName)
|
||||||
|
if not isinstance(method, types.UnboundMethodType):
|
||||||
|
continue
|
||||||
|
method = method.im_func
|
||||||
|
if not hasattr(theClass, methodName):
|
||||||
|
if not gotOne:
|
||||||
|
print "\nWarnings for module %s\n" % moduleName
|
||||||
|
gotOne = 1
|
||||||
|
print "class %s misses required method:\n %s" % (className, describeFunction.describe(method))
|
||||||
|
continue
|
||||||
|
method2 = getattr(theClass, methodName).im_func
|
||||||
|
argList = describeFunction._describe(method)
|
||||||
|
argList2 = describeFunction._describe(method2)
|
||||||
|
if len(argList2) < len(argList):
|
||||||
|
if not gotOne:
|
||||||
|
print "\nWarnings for module %s\n" % moduleName
|
||||||
|
gotOne = 1
|
||||||
|
print "Method has not enough arguments:"
|
||||||
|
print " interface: %s.%s" % (className, describeFunction.describe(method))
|
||||||
|
print " implementation: %s.%s" % (className, describeFunction.describe(method2))
|
||||||
|
continue
|
||||||
|
for i in range(len(argList)):
|
||||||
|
if argList[i] <> argList2[i]:
|
||||||
|
if not gotOne:
|
||||||
|
print "\nWarnings for module %s\n" % moduleName
|
||||||
|
gotOne = 1
|
||||||
|
print "Method has different arguments:"
|
||||||
|
print " interface: %s.%s" % (className, describeFunction.describe(method))
|
||||||
|
print " implementation: %s.%s" % (className, describeFunction.describe(method2))
|
||||||
|
break
|
||||||
|
for arg in argList2[len(argList):]:
|
||||||
|
if type(arg) == types.StringType:
|
||||||
|
if not gotOne:
|
||||||
|
print "\nWarnings for module %s\n" % moduleName
|
||||||
|
gotOne = 1
|
||||||
|
print "Additional argument(s) should have default value(s):"
|
||||||
|
print " interface: %s.%s" % (className, describeFunction.describe(method))
|
||||||
|
print " implementation: %s.%s" % (className, describeFunction.describe(method2))
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def checkInterface(moduleName):
|
||||||
|
if describeFunction is None:
|
||||||
|
return
|
||||||
|
items = sys.modules[moduleName].__dict__.items()
|
||||||
|
items.sort()
|
||||||
|
for name, value in items:
|
||||||
|
if not isinstance(value, types.ClassType):
|
||||||
|
continue
|
||||||
|
checkClass(moduleName, value)
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user