mirror of
				https://github.com/python/cpython.git
				synced 2025-10-29 17:38:56 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			109 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			109 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 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()
 | 
