| 
									
										
										
										
											2003-04-15 11:10:33 +00:00
										 |  |  | import unittest | 
					
						
							| 
									
										
										
										
											2009-10-10 21:08:31 +00:00
										 |  |  | from test import support | 
					
						
							| 
									
										
										
										
											2020-08-07 23:18:38 +08:00
										 |  |  | from test.support import warnings_helper | 
					
						
							| 
									
										
										
										
											2009-10-10 21:08:31 +00:00
										 |  |  | import os | 
					
						
							| 
									
										
										
										
											2001-01-20 19:54:20 +00:00
										 |  |  | import sys | 
					
						
							| 
									
										
										
										
											2022-01-20 19:56:33 +02:00
										 |  |  | import types | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  |     import _multiprocessing | 
					
						
							|  |  |  | except ModuleNotFoundError: | 
					
						
							|  |  |  |     _multiprocessing = None | 
					
						
							| 
									
										
										
										
											2002-04-11 20:04:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-01-20 19:54:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-01 15:44:08 +01:00
										 |  |  | if support.check_sanitizer(address=True, memory=True): | 
					
						
							|  |  |  |     # bpo-46633: test___all__ is skipped because importing some modules | 
					
						
							|  |  |  |     # directly can trigger known problems with ASAN (like tk or crypt). | 
					
						
							|  |  |  |     raise unittest.SkipTest("workaround ASAN build issues on loading tests " | 
					
						
							|  |  |  |                             "like tk or crypt") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-10 21:08:31 +00:00
										 |  |  | class NoAll(RuntimeError): | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class FailedImport(RuntimeError): | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-15 11:10:33 +00:00
										 |  |  | class AllTest(unittest.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-20 19:56:33 +02:00
										 |  |  |     def setUp(self): | 
					
						
							|  |  |  |         # concurrent.futures uses a __getattr__ hook. Its __all__ triggers | 
					
						
							|  |  |  |         # import of a submodule, which fails when _multiprocessing is not | 
					
						
							|  |  |  |         # available. | 
					
						
							|  |  |  |         if _multiprocessing is None: | 
					
						
							|  |  |  |             sys.modules["_multiprocessing"] = types.ModuleType("_multiprocessing") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def tearDown(self): | 
					
						
							|  |  |  |         if _multiprocessing is None: | 
					
						
							|  |  |  |             sys.modules.pop("_multiprocessing") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-15 11:10:33 +00:00
										 |  |  |     def check_all(self, modname): | 
					
						
							|  |  |  |         names = {} | 
					
						
							| 
									
										
										
										
											2020-08-07 23:18:38 +08:00
										 |  |  |         with warnings_helper.check_warnings( | 
					
						
							| 
									
										
										
										
											2022-04-05 12:05:48 -07:00
										 |  |  |             (f".*{modname}", DeprecationWarning), | 
					
						
							| 
									
										
										
										
											2010-10-29 11:53:34 +00:00
										 |  |  |             (".* (module|package)", DeprecationWarning), | 
					
						
							| 
									
										
										
										
											2020-04-24 12:19:46 -06:00
										 |  |  |             (".* (module|package)", PendingDeprecationWarning), | 
					
						
							| 
									
										
										
										
											2010-10-29 11:53:34 +00:00
										 |  |  |             ("", ResourceWarning), | 
					
						
							|  |  |  |             quiet=True): | 
					
						
							| 
									
										
										
										
											2008-05-06 23:48:04 +00:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 exec("import %s" % modname, names) | 
					
						
							| 
									
										
										
										
											2009-10-10 21:08:31 +00:00
										 |  |  |             except: | 
					
						
							| 
									
										
										
										
											2008-05-06 23:48:04 +00:00
										 |  |  |                 # Silent fail here seems the best route since some modules | 
					
						
							| 
									
										
										
										
											2009-10-10 21:08:31 +00:00
										 |  |  |                 # may not be available or not initialize properly in all | 
					
						
							|  |  |  |                 # environments. | 
					
						
							|  |  |  |                 raise FailedImport(modname) | 
					
						
							|  |  |  |         if not hasattr(sys.modules[modname], "__all__"): | 
					
						
							|  |  |  |             raise NoAll(modname) | 
					
						
							| 
									
										
										
										
											2003-04-15 11:10:33 +00:00
										 |  |  |         names = {} | 
					
						
							| 
									
										
										
										
											2013-05-01 14:58:09 +03:00
										 |  |  |         with self.subTest(module=modname): | 
					
						
							| 
									
										
										
										
											2020-08-07 23:18:38 +08:00
										 |  |  |             with warnings_helper.check_warnings( | 
					
						
							| 
									
										
										
										
											2019-05-27 22:56:22 +03:00
										 |  |  |                 ("", DeprecationWarning), | 
					
						
							|  |  |  |                 ("", ResourceWarning), | 
					
						
							|  |  |  |                 quiet=True): | 
					
						
							|  |  |  |                 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__'] | 
					
						
							|  |  |  |                 if "__warningregistry__" in names: | 
					
						
							|  |  |  |                     del names["__warningregistry__"] | 
					
						
							|  |  |  |                 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)) | 
					
						
							| 
									
										
										
										
											2003-04-15 11:10:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-10 21:08:31 +00:00
										 |  |  |     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] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-15 11:10:33 +00:00
										 |  |  |     def test_all(self): | 
					
						
							| 
									
										
										
										
											2020-08-11 15:26:59 +02:00
										 |  |  |         # List of denied modules and packages | 
					
						
							|  |  |  |         denylist = set([ | 
					
						
							| 
									
										
										
										
											2009-10-10 21:08:31 +00:00
										 |  |  |             # Will raise a SyntaxError when compiling the exec statement | 
					
						
							|  |  |  |             '__future__', | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-23 23:17:24 +03:00
										 |  |  |         # In case _socket fails to build, make this test fail more gracefully | 
					
						
							|  |  |  |         # than an AttributeError somewhere deep in CGIHTTPServer. | 
					
						
							|  |  |  |         import _socket | 
					
						
							| 
									
										
										
										
											2003-04-15 11:10:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-10 21:08:31 +00:00
										 |  |  |         ignored = [] | 
					
						
							|  |  |  |         failed_imports = [] | 
					
						
							|  |  |  |         lib_dir = os.path.dirname(os.path.dirname(__file__)) | 
					
						
							|  |  |  |         for path, modname in self.walk_modules(lib_dir, ""): | 
					
						
							|  |  |  |             m = modname | 
					
						
							| 
									
										
										
										
											2020-08-13 19:20:28 +02:00
										 |  |  |             denied = False | 
					
						
							| 
									
										
										
										
											2009-10-10 21:08:31 +00:00
										 |  |  |             while m: | 
					
						
							| 
									
										
										
										
											2020-08-11 15:26:59 +02:00
										 |  |  |                 if m in denylist: | 
					
						
							| 
									
										
										
										
											2020-08-13 19:20:28 +02:00
										 |  |  |                     denied = True | 
					
						
							| 
									
										
										
										
											2009-10-10 21:08:31 +00:00
										 |  |  |                     break | 
					
						
							|  |  |  |                 m = m.rpartition('.')[0] | 
					
						
							| 
									
										
										
										
											2020-08-13 19:20:28 +02:00
										 |  |  |             if denied: | 
					
						
							| 
									
										
										
										
											2009-10-10 21:08:31 +00:00
										 |  |  |                 continue | 
					
						
							|  |  |  |             if support.verbose: | 
					
						
							|  |  |  |                 print(modname) | 
					
						
							| 
									
										
										
										
											2003-04-15 11:10:33 +00:00
										 |  |  |             try: | 
					
						
							| 
									
										
										
										
											2009-10-10 21:08:31 +00:00
										 |  |  |                 # 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) | 
					
						
							| 
									
										
										
										
											2001-01-20 19:54:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-09 21:40:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-15 11:10:33 +00:00
										 |  |  | if __name__ == "__main__": | 
					
						
							| 
									
										
										
										
											2013-06-12 20:12:30 -04:00
										 |  |  |     unittest.main() |