misc/coding_tools/check-interfaces.py: clean-ups (warnings about Windows-specific modules and error stream handling).

This commit is contained in:
david-sarah 2012-06-14 21:28:29 +00:00
parent 854afc095f
commit 28069a9641
1 changed files with 39 additions and 22 deletions

View File

@ -4,7 +4,7 @@
# #
# bin/tahoe @misc/coding_tools/check-interfaces.py # bin/tahoe @misc/coding_tools/check-interfaces.py
import os, sys, re import os, sys, re, platform
import zope.interface as zi import zope.interface as zi
# We use the forked version of verifyClass below. # We use the forked version of verifyClass below.
@ -17,7 +17,10 @@ excluded_classnames = re.compile(r'(_)|(Mock)|(Fake)|(Dummy).*')
excluded_file_basenames = re.compile(r'(check)|(bench)_.*') excluded_file_basenames = re.compile(r'(check)|(bench)_.*')
other_modules_with_violations = set() _other_modules_with_violations = set()
_err = sys.stderr
_report_argname_mismatch = False # very noisy and usually not important
# deep magic # deep magic
def strictly_implements(*interfaces): def strictly_implements(*interfaces):
@ -42,46 +45,60 @@ def strictly_implements(*interfaces):
try: try:
verifyClass(interface, cls) verifyClass(interface, cls)
except Exception, e: except Exception, e:
print >>sys.stderr, ("%s.%s does not correctly implement %s.%s:\n%s" print >>_err, ("%s.%s does not correctly implement %s.%s:\n%s"
% (cls.__module__, cls.__name__, % (cls.__module__, cls.__name__,
interface.__module__, interface.__name__, e)) interface.__module__, interface.__name__, e))
else: else:
other_modules_with_violations.add(cls.__module__) _other_modules_with_violations.add(cls.__module__)
return cls return cls
f_locals['__implements_advice_data__'] = interfaces, zi.classImplements f_locals['__implements_advice_data__'] = interfaces, zi.classImplements
addClassAdvisor(_implements_advice, depth=2) addClassAdvisor(_implements_advice, depth=2)
def check(err): def check():
# patchee-monkey # patchee-monkey
zi.implements = strictly_implements zi.implements = strictly_implements
if len(sys.argv) >= 2:
if sys.argv[1] == '--help' or len(sys.argv) > 2:
print >>_err, "Usage: check-miscaptures.py [SOURCEDIR]"
return
srcdir = sys.argv[1]
else:
# import modules under src/ by default
srcdir = 'src'
# attempt to avoid side-effects from importing command scripts # attempt to avoid side-effects from importing command scripts
sys.argv = ['', '--help'] sys.argv = ['', '--help']
# import modules under src/ syslow = platform.system().lower()
srcdir = 'src' is_windows = 'cygwin' in syslow or 'windows' in syslow
for (dirpath, dirnames, filenames) in os.walk(srcdir): for (dirpath, dirnames, filenames) in os.walk(srcdir):
for fn in filenames: for fn in filenames:
(basename, ext) = os.path.splitext(fn) (basename, ext) = os.path.splitext(fn)
if ext in ('.pyc', '.pyo') and not os.path.exists(os.path.join(dirpath, basename+'.py')): if ext in ('.pyc', '.pyo') and not os.path.exists(os.path.join(dirpath, basename+'.py')):
print >>err, ("Warning: no .py source file for %r.\n" print >>_err, ("Warning: no .py source file for %r.\n"
% (os.path.join(dirpath, fn),)) % (os.path.join(dirpath, fn),))
if ext == '.py' and not excluded_file_basenames.match(basename): if ext == '.py' and not excluded_file_basenames.match(basename):
relpath = os.path.join(dirpath[len(srcdir)+1:], basename) relpath = os.path.join(dirpath[len(srcdir)+1:], basename)
module = relpath.replace(os.sep, '/').replace('/', '.') module = relpath.replace(os.sep, '/').replace('/', '.')
try: try:
__import__(module) __import__(module)
except ImportError: except ImportError, e:
import traceback if not is_windows and (' _win' in str(e) or 'win32' in str(e)):
traceback.print_exc(2, err) print >>_err, ("Warning: %r imports a Windows-specific module, so we cannot check it (%s).\n"
print >>err % (module, str(e)))
else:
import traceback
traceback.print_exc(file=_err)
print >>_err
others = list(other_modules_with_violations) others = list(_other_modules_with_violations)
others.sort() others.sort()
print >>err, "There were also interface violations in:\n", ", ".join(others), "\n" print >>_err, "There were also interface violations in:\n", ", ".join(others), "\n"
# Forked from # Forked from
@ -196,10 +213,6 @@ def verifyObject(iface, candidate, tentative=0):
return _verify(iface, candidate, tentative, vtype='o') return _verify(iface, candidate, tentative, vtype='o')
def _incompat(required, implemented): 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']): if len(implemented['required']) > len(required['required']):
return 'implementation requires too many arguments' return 'implementation requires too many arguments'
if ((len(implemented['positional']) < len(required['positional'])) if ((len(implemented['positional']) < len(required['positional']))
@ -209,9 +222,13 @@ def _incompat(required, implemented):
return "implementation doesn't support keyword arguments" return "implementation doesn't support keyword arguments"
if required['varargs'] and not implemented['varargs']: if required['varargs'] and not implemented['varargs']:
return "implementation doesn't support variable arguments" return "implementation doesn't support variable arguments"
if (_report_argname_mismatch and required['positional'] !=
implemented['positional'][:len(required['positional'])]
and implemented['kwargs'] is None):
return 'implementation has different argument names'
if __name__ == "__main__": if __name__ == "__main__":
check(sys.stderr) check()
# Avoid spurious warnings about ignored exceptions during shutdown by doing a hard exit. # Avoid spurious warnings about ignored exceptions during shutdown by doing a hard exit.
os._exit(0) os._exit(0)