1from __future__ import print_function 2 3import unittest 4from test import test_support as support 5import os 6import sys 7 8# Setup bsddb warnings 9try: 10 bsddb = support.import_module('bsddb', deprecated=True) 11except unittest.SkipTest: 12 pass 13 14 15class NoAll(RuntimeError): 16 pass 17 18class FailedImport(RuntimeError): 19 pass 20 21 22class AllTest(unittest.TestCase): 23 24 def check_all(self, modname): 25 names = {} 26 with support.check_warnings((".* (module|package)", 27 DeprecationWarning), quiet=True): 28 try: 29 exec "import %s" % modname in names 30 except: 31 # Silent fail here seems the best route since some modules 32 # may not be available or not initialize properly in all 33 # environments. 34 raise FailedImport(modname) 35 if not hasattr(sys.modules[modname], "__all__"): 36 raise NoAll(modname) 37 names = {} 38 try: 39 exec "from %s import *" % modname in names 40 except Exception as e: 41 # Include the module name in the exception string 42 self.fail("__all__ failure in {}: {}: {}".format( 43 modname, e.__class__.__name__, e)) 44 if "__builtins__" in names: 45 del names["__builtins__"] 46 keys = set(names) 47 all = set(sys.modules[modname].__all__) 48 self.assertEqual(keys, all) 49 50 def walk_modules(self, basedir, modpath): 51 for fn in sorted(os.listdir(basedir)): 52 path = os.path.join(basedir, fn) 53 if os.path.isdir(path): 54 pkg_init = os.path.join(path, '__init__.py') 55 if os.path.exists(pkg_init): 56 yield pkg_init, modpath + fn 57 for p, m in self.walk_modules(path, modpath + fn + "."): 58 yield p, m 59 continue 60 if not fn.endswith('.py') or fn == '__init__.py': 61 continue 62 yield path, modpath + fn[:-3] 63 64 def test_all(self): 65 # Blacklisted modules and packages 66 blacklist = set([ 67 # Will raise a SyntaxError when compiling the exec statement 68 '__future__', 69 ]) 70 71 if not sys.platform.startswith('java'): 72 # In case _socket fails to build, make this test fail more gracefully 73 # than an AttributeError somewhere deep in CGIHTTPServer. 74 import _socket 75 76 # rlcompleter needs special consideration; it imports readline which 77 # initializes GNU readline which calls setlocale(LC_CTYPE, "")... :-( 78 import locale 79 locale_tuple = locale.getlocale(locale.LC_CTYPE) 80 try: 81 import rlcompleter 82 except ImportError: 83 pass 84 finally: 85 locale.setlocale(locale.LC_CTYPE, locale_tuple) 86 87 ignored = [] 88 failed_imports = [] 89 lib_dir = os.path.dirname(os.path.dirname(__file__)) 90 for path, modname in self.walk_modules(lib_dir, ""): 91 m = modname 92 blacklisted = False 93 while m: 94 if m in blacklist: 95 blacklisted = True 96 break 97 m = m.rpartition('.')[0] 98 if blacklisted: 99 continue 100 if support.verbose: 101 print(modname) 102 try: 103 # This heuristic speeds up the process by removing, de facto, 104 # most test modules (and avoiding the auto-executing ones). 105 with open(path, "rb") as f: 106 if "__all__" not in f.read(): 107 raise NoAll(modname) 108 self.check_all(modname) 109 except NoAll: 110 ignored.append(modname) 111 except FailedImport: 112 failed_imports.append(modname) 113 114 if support.verbose: 115 print('Following modules have no __all__ and have been ignored:', 116 ignored) 117 print('Following modules failed to be imported:', failed_imports) 118 119 120def test_main(): 121 support.run_unittest(AllTest) 122 123if __name__ == "__main__": 124 test_main() 125