| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-01-20 19:54:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-01 15:44:08 +01:00
										 |  |  | if support.check_sanitizer(address=True, memory=True): | 
					
						
							| 
									
										
										
										
											2023-08-22 15:52:32 +02:00
										 |  |  |     SKIP_MODULES = frozenset(( | 
					
						
							|  |  |  |         # gh-90791: Tests involving libX11 can SEGFAULT on ASAN/MSAN builds. | 
					
						
							|  |  |  |         # Skip modules, packages and tests using '_tkinter'. | 
					
						
							|  |  |  |         '_tkinter', | 
					
						
							|  |  |  |         'tkinter', | 
					
						
							|  |  |  |         'test_tkinter', | 
					
						
							|  |  |  |         'test_ttk', | 
					
						
							|  |  |  |         'test_ttk_textonly', | 
					
						
							|  |  |  |         'idlelib', | 
					
						
							|  |  |  |         'test_idle', | 
					
						
							|  |  |  |     )) | 
					
						
							|  |  |  | else: | 
					
						
							|  |  |  |     SKIP_MODULES = () | 
					
						
							| 
									
										
										
										
											2022-03-01 15:44:08 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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), | 
					
						
							| 
									
										
										
										
											2025-03-17 20:48:54 +00:00
										 |  |  |             ("", SyntaxWarning), | 
					
						
							| 
									
										
										
										
											2010-10-29 11:53:34 +00:00
										 |  |  |             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), | 
					
						
							| 
									
										
										
										
											2025-03-17 20:48:54 +00:00
										 |  |  |                 ("", SyntaxWarning), | 
					
						
							| 
									
										
										
										
											2019-05-27 22:56:22 +03:00
										 |  |  |                 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): | 
					
						
							| 
									
										
										
										
											2023-08-22 15:52:32 +02:00
										 |  |  |                 if fn in SKIP_MODULES: | 
					
						
							|  |  |  |                     continue | 
					
						
							| 
									
										
										
										
											2009-10-10 21:08:31 +00:00
										 |  |  |                 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 | 
					
						
							| 
									
										
										
										
											2023-08-22 15:52:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if fn == '__init__.py': | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             if not fn.endswith('.py'): | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             modname = fn.removesuffix('.py') | 
					
						
							|  |  |  |             if modname in SKIP_MODULES: | 
					
						
							| 
									
										
										
										
											2009-10-10 21:08:31 +00:00
										 |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2023-08-22 15:52:32 +02:00
										 |  |  |             yield path, modpath + modname | 
					
						
							| 
									
										
										
										
											2009-10-10 21:08:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2023-06-09 14:50:31 +02:00
										 |  |  |         # than an AttributeError somewhere deep in concurrent.futures, email | 
					
						
							|  |  |  |         # or unittest. | 
					
						
							| 
									
										
										
										
											2024-06-18 17:51:47 +02:00
										 |  |  |         import _socket  # noqa: F401 | 
					
						
							| 
									
										
										
										
											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: | 
					
						
							| 
									
										
										
										
											2023-08-22 15:52:32 +02:00
										 |  |  |                 print(f"Check {modname}", flush=True) | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							| 
									
										
										
										
											2023-08-22 15:52:32 +02:00
										 |  |  |                 self.check_all(modname) | 
					
						
							| 
									
										
										
										
											2009-10-10 21:08:31 +00:00
										 |  |  |             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() |