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