|  | import unittest | 
|  | from test import support | 
|  | import os | 
|  | import sys | 
|  |  | 
|  |  | 
|  | 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), | 
|  | ("", ResourceWarning), | 
|  | quiet=True): | 
|  | try: | 
|  | exec("import %s" % modname, 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 = {} | 
|  | with self.subTest(module=modname): | 
|  | try: | 
|  | exec("from %s import *" % modname, 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__"] | 
|  | if '__annotations__' in names: | 
|  | del names['__annotations__'] | 
|  | keys = set(names) | 
|  | all_list = sys.modules[modname].__all__ | 
|  | all_set = set(all_list) | 
|  | self.assertCountEqual(all_set, all_list, "in module {}".format(modname)) | 
|  | self.assertEqual(keys, all_set, "in module {}".format(modname)) | 
|  |  | 
|  | 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 | 
|  |  | 
|  | 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 b"__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) | 
|  |  | 
|  |  | 
|  | if __name__ == "__main__": | 
|  | unittest.main() |