from __future__ import print_function | |
import unittest | |
from test import test_support as support | |
import os | |
import sys | |
# Setup bsddb warnings | |
try: | |
bsddb = support.import_module('bsddb', deprecated=True) | |
except unittest.SkipTest: | |
pass | |
class NoAll(RuntimeError): | |
pass | |
class FailedImport(RuntimeError): | |
pass | |
class AllTest(unittest.TestCase): | |
def check_all(self, modname): | |
names = {} | |
with support.check_warnings((".* (module|package)", | |
DeprecationWarning), quiet=True): | |
try: | |
exec "import %s" % modname in names | |
except: | |
# Silent fail here seems the best route since some modules | |
# may not be available or not initialize properly in all | |
# environments. | |
raise FailedImport(modname) | |
if not hasattr(sys.modules[modname], "__all__"): | |
raise NoAll(modname) | |
names = {} | |
try: | |
exec "from %s import *" % modname in names | |
except Exception as e: | |
# Include the module name in the exception string | |
self.fail("__all__ failure in {}: {}: {}".format( | |
modname, e.__class__.__name__, e)) | |
if "__builtins__" in names: | |
del names["__builtins__"] | |
keys = set(names) | |
all = set(sys.modules[modname].__all__) | |
self.assertEqual(keys, all) | |
def walk_modules(self, basedir, modpath): | |
for fn in sorted(os.listdir(basedir)): | |
path = os.path.join(basedir, fn) | |
if os.path.isdir(path): | |
pkg_init = os.path.join(path, '__init__.py') | |
if os.path.exists(pkg_init): | |
yield pkg_init, modpath + fn | |
for p, m in self.walk_modules(path, modpath + fn + "."): | |
yield p, m | |
continue | |
if not fn.endswith('.py') or fn == '__init__.py': | |
continue | |
yield path, modpath + fn[:-3] | |
def test_all(self): | |
# Blacklisted modules and packages | |
blacklist = set([ | |
# Will raise a SyntaxError when compiling the exec statement | |
'__future__', | |
]) | |
if not sys.platform.startswith('java'): | |
# In case _socket fails to build, make this test fail more gracefully | |
# than an AttributeError somewhere deep in CGIHTTPServer. | |
import _socket | |
# rlcompleter needs special consideration; it import readline which | |
# initializes GNU readline which calls setlocale(LC_CTYPE, "")... :-( | |
try: | |
import rlcompleter | |
import locale | |
except ImportError: | |
pass | |
else: | |
locale.setlocale(locale.LC_CTYPE, 'C') | |
ignored = [] | |
failed_imports = [] | |
lib_dir = os.path.dirname(os.path.dirname(__file__)) | |
for path, modname in self.walk_modules(lib_dir, ""): | |
m = modname | |
blacklisted = False | |
while m: | |
if m in blacklist: | |
blacklisted = True | |
break | |
m = m.rpartition('.')[0] | |
if blacklisted: | |
continue | |
if support.verbose: | |
print(modname) | |
try: | |
# This heuristic speeds up the process by removing, de facto, | |
# most test modules (and avoiding the auto-executing ones). | |
with open(path, "rb") as f: | |
if "__all__" not in f.read(): | |
raise NoAll(modname) | |
self.check_all(modname) | |
except NoAll: | |
ignored.append(modname) | |
except FailedImport: | |
failed_imports.append(modname) | |
if support.verbose: | |
print('Following modules have no __all__ and have been ignored:', | |
ignored) | |
print('Following modules failed to be imported:', failed_imports) | |
def test_main(): | |
support.run_unittest(AllTest) | |
if __name__ == "__main__": | |
test_main() |