17db96d56Sopenharmony_ciimport unittest 27db96d56Sopenharmony_cifrom test import support 37db96d56Sopenharmony_cifrom test.support import warnings_helper 47db96d56Sopenharmony_ciimport os 57db96d56Sopenharmony_ciimport sys 67db96d56Sopenharmony_ciimport types 77db96d56Sopenharmony_ci 87db96d56Sopenharmony_citry: 97db96d56Sopenharmony_ci import _multiprocessing 107db96d56Sopenharmony_ciexcept ModuleNotFoundError: 117db96d56Sopenharmony_ci _multiprocessing = None 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_ci 147db96d56Sopenharmony_ciif support.check_sanitizer(address=True, memory=True): 157db96d56Sopenharmony_ci # bpo-46633: test___all__ is skipped because importing some modules 167db96d56Sopenharmony_ci # directly can trigger known problems with ASAN (like tk or crypt). 177db96d56Sopenharmony_ci raise unittest.SkipTest("workaround ASAN build issues on loading tests " 187db96d56Sopenharmony_ci "like tk or crypt") 197db96d56Sopenharmony_ci 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ciclass NoAll(RuntimeError): 227db96d56Sopenharmony_ci pass 237db96d56Sopenharmony_ci 247db96d56Sopenharmony_ciclass FailedImport(RuntimeError): 257db96d56Sopenharmony_ci pass 267db96d56Sopenharmony_ci 277db96d56Sopenharmony_ci 287db96d56Sopenharmony_ciclass AllTest(unittest.TestCase): 297db96d56Sopenharmony_ci 307db96d56Sopenharmony_ci def setUp(self): 317db96d56Sopenharmony_ci # concurrent.futures uses a __getattr__ hook. Its __all__ triggers 327db96d56Sopenharmony_ci # import of a submodule, which fails when _multiprocessing is not 337db96d56Sopenharmony_ci # available. 347db96d56Sopenharmony_ci if _multiprocessing is None: 357db96d56Sopenharmony_ci sys.modules["_multiprocessing"] = types.ModuleType("_multiprocessing") 367db96d56Sopenharmony_ci 377db96d56Sopenharmony_ci def tearDown(self): 387db96d56Sopenharmony_ci if _multiprocessing is None: 397db96d56Sopenharmony_ci sys.modules.pop("_multiprocessing") 407db96d56Sopenharmony_ci 417db96d56Sopenharmony_ci def check_all(self, modname): 427db96d56Sopenharmony_ci names = {} 437db96d56Sopenharmony_ci with warnings_helper.check_warnings( 447db96d56Sopenharmony_ci (f".*{modname}", DeprecationWarning), 457db96d56Sopenharmony_ci (".* (module|package)", DeprecationWarning), 467db96d56Sopenharmony_ci (".* (module|package)", PendingDeprecationWarning), 477db96d56Sopenharmony_ci ("", ResourceWarning), 487db96d56Sopenharmony_ci quiet=True): 497db96d56Sopenharmony_ci try: 507db96d56Sopenharmony_ci exec("import %s" % modname, names) 517db96d56Sopenharmony_ci except: 527db96d56Sopenharmony_ci # Silent fail here seems the best route since some modules 537db96d56Sopenharmony_ci # may not be available or not initialize properly in all 547db96d56Sopenharmony_ci # environments. 557db96d56Sopenharmony_ci raise FailedImport(modname) 567db96d56Sopenharmony_ci if not hasattr(sys.modules[modname], "__all__"): 577db96d56Sopenharmony_ci raise NoAll(modname) 587db96d56Sopenharmony_ci names = {} 597db96d56Sopenharmony_ci with self.subTest(module=modname): 607db96d56Sopenharmony_ci with warnings_helper.check_warnings( 617db96d56Sopenharmony_ci ("", DeprecationWarning), 627db96d56Sopenharmony_ci ("", ResourceWarning), 637db96d56Sopenharmony_ci quiet=True): 647db96d56Sopenharmony_ci try: 657db96d56Sopenharmony_ci exec("from %s import *" % modname, names) 667db96d56Sopenharmony_ci except Exception as e: 677db96d56Sopenharmony_ci # Include the module name in the exception string 687db96d56Sopenharmony_ci self.fail("__all__ failure in {}: {}: {}".format( 697db96d56Sopenharmony_ci modname, e.__class__.__name__, e)) 707db96d56Sopenharmony_ci if "__builtins__" in names: 717db96d56Sopenharmony_ci del names["__builtins__"] 727db96d56Sopenharmony_ci if '__annotations__' in names: 737db96d56Sopenharmony_ci del names['__annotations__'] 747db96d56Sopenharmony_ci if "__warningregistry__" in names: 757db96d56Sopenharmony_ci del names["__warningregistry__"] 767db96d56Sopenharmony_ci keys = set(names) 777db96d56Sopenharmony_ci all_list = sys.modules[modname].__all__ 787db96d56Sopenharmony_ci all_set = set(all_list) 797db96d56Sopenharmony_ci self.assertCountEqual(all_set, all_list, "in module {}".format(modname)) 807db96d56Sopenharmony_ci self.assertEqual(keys, all_set, "in module {}".format(modname)) 817db96d56Sopenharmony_ci 827db96d56Sopenharmony_ci def walk_modules(self, basedir, modpath): 837db96d56Sopenharmony_ci for fn in sorted(os.listdir(basedir)): 847db96d56Sopenharmony_ci path = os.path.join(basedir, fn) 857db96d56Sopenharmony_ci if os.path.isdir(path): 867db96d56Sopenharmony_ci pkg_init = os.path.join(path, '__init__.py') 877db96d56Sopenharmony_ci if os.path.exists(pkg_init): 887db96d56Sopenharmony_ci yield pkg_init, modpath + fn 897db96d56Sopenharmony_ci for p, m in self.walk_modules(path, modpath + fn + "."): 907db96d56Sopenharmony_ci yield p, m 917db96d56Sopenharmony_ci continue 927db96d56Sopenharmony_ci if not fn.endswith('.py') or fn == '__init__.py': 937db96d56Sopenharmony_ci continue 947db96d56Sopenharmony_ci yield path, modpath + fn[:-3] 957db96d56Sopenharmony_ci 967db96d56Sopenharmony_ci def test_all(self): 977db96d56Sopenharmony_ci # List of denied modules and packages 987db96d56Sopenharmony_ci denylist = set([ 997db96d56Sopenharmony_ci # Will raise a SyntaxError when compiling the exec statement 1007db96d56Sopenharmony_ci '__future__', 1017db96d56Sopenharmony_ci ]) 1027db96d56Sopenharmony_ci 1037db96d56Sopenharmony_ci if not sys.platform.startswith('java'): 1047db96d56Sopenharmony_ci # In case _socket fails to build, make this test fail more gracefully 1057db96d56Sopenharmony_ci # than an AttributeError somewhere deep in CGIHTTPServer. 1067db96d56Sopenharmony_ci import _socket 1077db96d56Sopenharmony_ci 1087db96d56Sopenharmony_ci ignored = [] 1097db96d56Sopenharmony_ci failed_imports = [] 1107db96d56Sopenharmony_ci lib_dir = os.path.dirname(os.path.dirname(__file__)) 1117db96d56Sopenharmony_ci for path, modname in self.walk_modules(lib_dir, ""): 1127db96d56Sopenharmony_ci m = modname 1137db96d56Sopenharmony_ci denied = False 1147db96d56Sopenharmony_ci while m: 1157db96d56Sopenharmony_ci if m in denylist: 1167db96d56Sopenharmony_ci denied = True 1177db96d56Sopenharmony_ci break 1187db96d56Sopenharmony_ci m = m.rpartition('.')[0] 1197db96d56Sopenharmony_ci if denied: 1207db96d56Sopenharmony_ci continue 1217db96d56Sopenharmony_ci if support.verbose: 1227db96d56Sopenharmony_ci print(modname) 1237db96d56Sopenharmony_ci try: 1247db96d56Sopenharmony_ci # This heuristic speeds up the process by removing, de facto, 1257db96d56Sopenharmony_ci # most test modules (and avoiding the auto-executing ones). 1267db96d56Sopenharmony_ci with open(path, "rb") as f: 1277db96d56Sopenharmony_ci if b"__all__" not in f.read(): 1287db96d56Sopenharmony_ci raise NoAll(modname) 1297db96d56Sopenharmony_ci self.check_all(modname) 1307db96d56Sopenharmony_ci except NoAll: 1317db96d56Sopenharmony_ci ignored.append(modname) 1327db96d56Sopenharmony_ci except FailedImport: 1337db96d56Sopenharmony_ci failed_imports.append(modname) 1347db96d56Sopenharmony_ci 1357db96d56Sopenharmony_ci if support.verbose: 1367db96d56Sopenharmony_ci print('Following modules have no __all__ and have been ignored:', 1377db96d56Sopenharmony_ci ignored) 1387db96d56Sopenharmony_ci print('Following modules failed to be imported:', failed_imports) 1397db96d56Sopenharmony_ci 1407db96d56Sopenharmony_ci 1417db96d56Sopenharmony_ciif __name__ == "__main__": 1427db96d56Sopenharmony_ci unittest.main() 143