[Zope3-checkins] SVN: zope.testing/trunk/src/zope/testing/testrunner/importcheck.py More tweaking of the heuristics, turn them into a simple rule
Christian Theune
ct at gocept.com
Thu Jan 29 16:48:51 EST 2009
Log message for revision 95528:
More tweaking of the heuristics, turn them into a simple rule
registration.
Changed:
U zope.testing/trunk/src/zope/testing/testrunner/importcheck.py
-=-
Modified: zope.testing/trunk/src/zope/testing/testrunner/importcheck.py
===================================================================
--- zope.testing/trunk/src/zope/testing/testrunner/importcheck.py 2009-01-29 20:47:44 UTC (rev 95527)
+++ zope.testing/trunk/src/zope/testing/testrunner/importcheck.py 2009-01-29 21:48:50 UTC (rev 95528)
@@ -2,6 +2,8 @@
# Copyright (c) 2008 gocept gmbh & co. kg
# See also LICENSE.txt
+# XXX: Is there *any* way to detect instances that are shuffled around?
+
import ihooks
import os.path
import sys
@@ -11,18 +13,111 @@
WHITELIST = [('re', 'match', 'sre'),
+ ('new', 'module', '__builtin__'),
('os', 'error', 'exceptions')]
wrapper_cache = {}
seen = set()
+def guess_package_name(frame):
+ """Guess which package a code frame originated from."""
+ if '__name__' in frame.f_globals:
+ return frame.f_globals['__name__']
+ filename = frame.f_globals['__file__']
+ for mod in sys.modules.values():
+ if not hasattr(mod, '__file__'):
+ continue
+ if os.path.dirname(mod.__file__) == os.path.dirname(filename):
+ return mod.__name__
+ raise RuntimeError("Can't guess module name for %r" % frame)
+
+
+def rule_whitelist(import_mod, name, real_mod):
+ # No warning for things on the whitelist.
+ return (import_mod, name, real_mod) in WHITELIST
+
+
+def rule_doctest(import_mod, name, real_mod):
+ # doctest regularly sticks stuff somewhere else. We
+ # ignore those.
+ return real_mod in ['doctest', 'zope.testing.doctest']
+
+
+def rule_stdlib_and_builtins(import_mod, name, real_mod):
+ # Some builtins are redirected within the stdlib (and vice versa)
+ if import_mod == 'sys' and name in ['stdin', 'stdout']:
+ return True
+ if import_mod == 'os' and real_mod == 'posix':
+ return True
+ if name == '__class__' and real_mod == '__builtin__':
+ return True
+ if import_mod == '__builtin__' and real_mod == 'exceptions':
+ return True
+ if (import_mod == 'types' or
+ import_mod.startswith('xml.dom')) and real_mod == '__builtin__':
+ # No warning for the types from the type module that
+ # really originate from builtins
+ return True
+
+
+def rule_intra_package_reimport(import_mod, name, real_mod):
+ # Don't warn if the package of a module re-exports a symbol.
+ return import_mod.split('.') == real_mod.split('.')[:-1]
+
+
+def rule_intra_package_reimport2(import_mod, name, real_mod):
+ # Don't warn if symbols of an underscore module are reimported
+ # by a module belonging to the same package.
+ real_path = real_mod.split('.')
+ real_module = real_path[-1]
+ base = '.'.join(real_path[:-1]) + '.'
+ return real_module.startswith('_') and import_mod.startswith(base)
+
+
+def rule_unclean_c_module(import_mod, name, real_mod):
+ # The real module seems to be a C-Module which is regularly masked using
+ # another Python module in front of it.
+ if (real_mod in sys.modules and
+ hasattr(sys.modules[real_mod], '__file__')):
+ real_file = sys.modules[real_mod].__file__
+ extension = os.path.splitext(real_file)[1]
+ if not extension.startswith('.py'):
+ return True
+ if real_mod.startswith('_') and real_mod == import_mod.split('.')[-1]:
+ # Looks like a C-module which doesn't declare its
+ # package path correctly.
+ return True
+
+
+def rule_zope_deferredimport(import_mod, name, real_mod):
+ if real_mod == 'zope.deferredimport.deferredmodule':
+ return True
+
+
+def rule_internal_underscore_reimport(import_mod, name, real_mod):
+ # Looks like an internal module, prefixed with _ was exported to the same
+ # module name without an _
+ return real_mod.split('.')[-1] == '_' + import_mod.split('.')[-1]
+
+
+
+RULES = [func for name, func in locals().items()
+ if name.startswith('rule_')]
+
+
class IndirectAttributeAccessChecker(types.ModuleType):
def __init__(self, module, options):
self.__import_checker_module = module
self.__import_checker_options = options
+ def __eq__(self, other):
+ if isinstance(other, IndirectAttributeAccessChecker):
+ other = (
+ other._IndirectAttributeAccessChecker__import_checker_module)
+ return other == self._IndirectAttributeAccessChecker__import_checker_module
+
def __setattr__(self, name, value):
if name.startswith('_IndirectAttributeAccessChecker__import_checker_'):
object.__setattr__(self, name.replace('_IndirectAttributeAccessChecker', ''), value)
@@ -35,7 +130,8 @@
return object.__getattribute__(self, name.replace('_IndirectAttributeAccessChecker', ''))
module = self.__import_checker_module
attr = getattr(module, name)
- if getattr(attr, '__module__', None) is None:
+ if not isinstance(attr,
+ (types.ClassType, types.TypeType, types.FunctionType)):
return attr
if attr.__module__ == module.__name__:
return attr
@@ -44,7 +140,7 @@
show_only_from = self.__import_checker_options.indirect_source
if show_only_from:
for include in show_only_from:
- if frame.f_globals['__name__'].startswith(include):
+ if guess_package_name(frame).startswith(include):
break
else:
# This warning was caused in a module not under the
@@ -52,42 +148,11 @@
return attr
import_mod, real_mod = module.__name__, attr.__module__
- if (import_mod, name, real_mod) in WHITELIST:
- # No warning for things on the whitelist.
- pass
- elif real_mod in ['doctest', 'zope.testing.doctest']:
- # doctest regularly sticks stuff somewhere else. We
- # ignore those.
- pass
- elif import_mod == 'sys' and name in ['stdin', 'stdout']:
- # Those are redirected regularly.
- pass
- elif import_mod == 'os' and real_mod == 'posix':
- pass
- elif name == '__class__' and real_mod == '__builtin__':
- pass
- elif (import_mod == 'types' or
- import_mod.startswith('xml.dom')) and real_mod == '__builtin__':
- # No warning for the types from the type module that
- # really originate from builtins
- pass
- elif import_mod.split('.') == real_mod.split('.')[:-1]:
- # Don't warn if the package of a module re-exports a
- # symbol.
- pass
- elif real_mod in sys.modules and hasattr(sys.modules[real_mod], '__file__') and not sys.modules[real_mod].__file__.endswith('.py'):
- # The real module seems to be a C-Module which is
- # regularly masked using another Python module in front
- # of it.
- pass
- elif real_mod.split('.')[-1] == '_' + import_mod.split('.')[-1]:
- # Looks like an internal module, prefixed with _ was
- # exported to the same module name without an _
- pass
- elif real_mod.startswith('_') and real_mod == import_mod.split('.')[-1]:
- # Looks like a C-module which doesn't declare its
- # package path correctly.
- pass
+ for rule in RULES:
+ # Warning suppression rules: if no rule matches, we display
+ # a warning.
+ if rule(import_mod, name, real_mod):
+ break
else:
attr_type = type(attr).__name__
file = frame.f_code.co_filename
@@ -98,6 +163,7 @@
% (attr_type, import_mod, name, real_mod))
print "caused at %s:%s" % (file, line)
seen.add(signature)
+
return attr
More information about the Zope3-Checkins
mailing list