blob: e94d984f2b94b7555eb9d200e209b21b130e2250 [file] [log] [blame]
Walter Dörwaldb1ded1e2003-04-15 11:10:33 +00001import unittest
Antoine Pitrou4de39cd2009-10-10 21:08:31 +00002from test import support
3import os
Skip Montanaroe99d5ea2001-01-20 19:54:20 +00004import sys
Tim Petersb05cd492002-04-11 20:04:12 +00005
Skip Montanaroe99d5ea2001-01-20 19:54:20 +00006
Antoine Pitrou4de39cd2009-10-10 21:08:31 +00007class NoAll(RuntimeError):
8 pass
9
10class FailedImport(RuntimeError):
11 pass
12
13
Walter Dörwaldb1ded1e2003-04-15 11:10:33 +000014class AllTest(unittest.TestCase):
15
16 def check_all(self, modname):
17 names = {}
Antoine Pitroua0d2f4d2010-10-29 11:53:34 +000018 with support.check_warnings(
19 (".* (module|package)", DeprecationWarning),
20 ("", ResourceWarning),
21 quiet=True):
Christian Heimes75ca4ea2008-05-06 23:48:04 +000022 try:
23 exec("import %s" % modname, names)
Antoine Pitrou4de39cd2009-10-10 21:08:31 +000024 except:
Christian Heimes75ca4ea2008-05-06 23:48:04 +000025 # Silent fail here seems the best route since some modules
Antoine Pitrou4de39cd2009-10-10 21:08:31 +000026 # may not be available or not initialize properly in all
27 # environments.
28 raise FailedImport(modname)
29 if not hasattr(sys.modules[modname], "__all__"):
30 raise NoAll(modname)
Walter Dörwaldb1ded1e2003-04-15 11:10:33 +000031 names = {}
Ezio Melottied52f6c2013-05-01 14:58:09 +030032 with self.subTest(module=modname):
33 try:
34 exec("from %s import *" % modname, names)
35 except Exception as e:
36 # Include the module name in the exception string
37 self.fail("__all__ failure in {}: {}: {}".format(
38 modname, e.__class__.__name__, e))
39 if "__builtins__" in names:
40 del names["__builtins__"]
41 keys = set(names)
42 all_list = sys.modules[modname].__all__
43 all_set = set(all_list)
44 self.assertCountEqual(all_set, all_list, "in module {}".format(modname))
45 self.assertEqual(keys, all_set, "in module {}".format(modname))
Skip Montanaroe99d5ea2001-01-20 19:54:20 +000046
Antoine Pitrou4de39cd2009-10-10 21:08:31 +000047 def walk_modules(self, basedir, modpath):
48 for fn in sorted(os.listdir(basedir)):
49 path = os.path.join(basedir, fn)
50 if os.path.isdir(path):
51 pkg_init = os.path.join(path, '__init__.py')
52 if os.path.exists(pkg_init):
53 yield pkg_init, modpath + fn
54 for p, m in self.walk_modules(path, modpath + fn + "."):
55 yield p, m
56 continue
57 if not fn.endswith('.py') or fn == '__init__.py':
58 continue
59 yield path, modpath + fn[:-3]
60
Walter Dörwaldb1ded1e2003-04-15 11:10:33 +000061 def test_all(self):
Antoine Pitrou4de39cd2009-10-10 21:08:31 +000062 # Blacklisted modules and packages
63 blacklist = set([
64 # Will raise a SyntaxError when compiling the exec statement
65 '__future__',
66 ])
67
Walter Dörwaldb1ded1e2003-04-15 11:10:33 +000068 if not sys.platform.startswith('java'):
69 # In case _socket fails to build, make this test fail more gracefully
70 # than an AttributeError somewhere deep in CGIHTTPServer.
71 import _socket
Tim Petersab9ba272001-08-09 21:40:30 +000072
Walter Dörwaldb1ded1e2003-04-15 11:10:33 +000073 # rlcompleter needs special consideration; it import readline which
74 # initializes GNU readline which calls setlocale(LC_CTYPE, "")... :-(
Ezio Melotti8b23f5c2014-11-02 19:08:35 +020075 import locale
76 locale_tuple = locale.getlocale(locale.LC_CTYPE)
Walter Dörwaldb1ded1e2003-04-15 11:10:33 +000077 try:
Antoine Pitrou4de39cd2009-10-10 21:08:31 +000078 import rlcompleter
Brett Cannon260fbe82013-07-04 18:16:15 -040079 except ImportError:
Antoine Pitrou4de39cd2009-10-10 21:08:31 +000080 pass
Ezio Melotti8b23f5c2014-11-02 19:08:35 +020081 finally:
82 locale.setlocale(locale.LC_CTYPE, locale_tuple)
Antoine Pitrou4de39cd2009-10-10 21:08:31 +000083
84 ignored = []
85 failed_imports = []
86 lib_dir = os.path.dirname(os.path.dirname(__file__))
87 for path, modname in self.walk_modules(lib_dir, ""):
88 m = modname
89 blacklisted = False
90 while m:
91 if m in blacklist:
92 blacklisted = True
93 break
94 m = m.rpartition('.')[0]
95 if blacklisted:
96 continue
97 if support.verbose:
98 print(modname)
Walter Dörwaldb1ded1e2003-04-15 11:10:33 +000099 try:
Antoine Pitrou4de39cd2009-10-10 21:08:31 +0000100 # This heuristic speeds up the process by removing, de facto,
101 # most test modules (and avoiding the auto-executing ones).
102 with open(path, "rb") as f:
103 if b"__all__" not in f.read():
104 raise NoAll(modname)
105 self.check_all(modname)
106 except NoAll:
107 ignored.append(modname)
108 except FailedImport:
109 failed_imports.append(modname)
110
111 if support.verbose:
112 print('Following modules have no __all__ and have been ignored:',
113 ignored)
114 print('Following modules failed to be imported:', failed_imports)
Walter Dörwaldb1ded1e2003-04-15 11:10:33 +0000115
116
Walter Dörwaldb1ded1e2003-04-15 11:10:33 +0000117if __name__ == "__main__":
Brett Cannonc9a1bfe2013-06-12 20:12:30 -0400118 unittest.main()