• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1from __future__ import print_function
2
3import unittest
4from test import test_support as support
5import os
6import sys
7
8# Setup bsddb warnings
9try:
10    bsddb = support.import_module('bsddb', deprecated=True)
11except unittest.SkipTest:
12    pass
13
14
15class NoAll(RuntimeError):
16    pass
17
18class FailedImport(RuntimeError):
19    pass
20
21
22class AllTest(unittest.TestCase):
23
24    def check_all(self, modname):
25        names = {}
26        with support.check_warnings((".* (module|package)",
27                                     DeprecationWarning), quiet=True):
28            try:
29                exec "import %s" % modname in names
30            except:
31                # Silent fail here seems the best route since some modules
32                # may not be available or not initialize properly in all
33                # environments.
34                raise FailedImport(modname)
35        if not hasattr(sys.modules[modname], "__all__"):
36            raise NoAll(modname)
37        names = {}
38        try:
39            exec "from %s import *" % modname in names
40        except Exception as e:
41            # Include the module name in the exception string
42            self.fail("__all__ failure in {}: {}: {}".format(
43                      modname, e.__class__.__name__, e))
44        if "__builtins__" in names:
45            del names["__builtins__"]
46        keys = set(names)
47        all = set(sys.modules[modname].__all__)
48        self.assertEqual(keys, all)
49
50    def walk_modules(self, basedir, modpath):
51        for fn in sorted(os.listdir(basedir)):
52            path = os.path.join(basedir, fn)
53            if os.path.isdir(path):
54                pkg_init = os.path.join(path, '__init__.py')
55                if os.path.exists(pkg_init):
56                    yield pkg_init, modpath + fn
57                    for p, m in self.walk_modules(path, modpath + fn + "."):
58                        yield p, m
59                continue
60            if not fn.endswith('.py') or fn == '__init__.py':
61                continue
62            yield path, modpath + fn[:-3]
63
64    def test_all(self):
65        # Blacklisted modules and packages
66        blacklist = set([
67            # Will raise a SyntaxError when compiling the exec statement
68            '__future__',
69        ])
70
71        if not sys.platform.startswith('java'):
72            # In case _socket fails to build, make this test fail more gracefully
73            # than an AttributeError somewhere deep in CGIHTTPServer.
74            import _socket
75
76        # rlcompleter needs special consideration; it imports readline which
77        # initializes GNU readline which calls setlocale(LC_CTYPE, "")... :-(
78        import locale
79        locale_tuple = locale.getlocale(locale.LC_CTYPE)
80        try:
81            import rlcompleter
82        except ImportError:
83            pass
84        finally:
85            locale.setlocale(locale.LC_CTYPE, locale_tuple)
86
87        ignored = []
88        failed_imports = []
89        lib_dir = os.path.dirname(os.path.dirname(__file__))
90        for path, modname in self.walk_modules(lib_dir, ""):
91            m = modname
92            blacklisted = False
93            while m:
94                if m in blacklist:
95                    blacklisted = True
96                    break
97                m = m.rpartition('.')[0]
98            if blacklisted:
99                continue
100            if support.verbose:
101                print(modname)
102            try:
103                # This heuristic speeds up the process by removing, de facto,
104                # most test modules (and avoiding the auto-executing ones).
105                with open(path, "rb") as f:
106                    if "__all__" not in f.read():
107                        raise NoAll(modname)
108                    self.check_all(modname)
109            except NoAll:
110                ignored.append(modname)
111            except FailedImport:
112                failed_imports.append(modname)
113
114        if support.verbose:
115            print('Following modules have no __all__ and have been ignored:',
116                  ignored)
117            print('Following modules failed to be imported:', failed_imports)
118
119
120def test_main():
121    support.run_unittest(AllTest)
122
123if __name__ == "__main__":
124    test_main()
125