14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom __future__ import print_function
24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport unittest
44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom test import test_support as support
54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport os
64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport sys
74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Setup bsddb warnings
94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtry:
104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    bsddb = support.import_module('bsddb', deprecated=True)
114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmexcept unittest.SkipTest:
124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    pass
134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass NoAll(RuntimeError):
164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    pass
174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass FailedImport(RuntimeError):
194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    pass
204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass AllTest(unittest.TestCase):
234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def check_all(self, modname):
254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        names = {}
264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with support.check_warnings((".* (module|package)",
274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                     DeprecationWarning), quiet=True):
284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                exec "import %s" % modname in names
304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except:
314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # Silent fail here seems the best route since some modules
324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # may not be available or not initialize properly in all
334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # environments.
344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                raise FailedImport(modname)
354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if not hasattr(sys.modules[modname], "__all__"):
364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            raise NoAll(modname)
374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        names = {}
384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            exec "from %s import *" % modname in names
404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except Exception as e:
414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Include the module name in the exception string
424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.fail("__all__ failure in {}: {}: {}".format(
434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                      modname, e.__class__.__name__, e))
444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if "__builtins__" in names:
454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            del names["__builtins__"]
464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        keys = set(names)
474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        all = set(sys.modules[modname].__all__)
484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(keys, all)
494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def walk_modules(self, basedir, modpath):
514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for fn in sorted(os.listdir(basedir)):
524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            path = os.path.join(basedir, fn)
534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if os.path.isdir(path):
544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                pkg_init = os.path.join(path, '__init__.py')
554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if os.path.exists(pkg_init):
564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    yield pkg_init, modpath + fn
574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    for p, m in self.walk_modules(path, modpath + fn + "."):
584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        yield p, m
594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                continue
604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if not fn.endswith('.py') or fn == '__init__.py':
614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                continue
624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            yield path, modpath + fn[:-3]
634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_all(self):
654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Blacklisted modules and packages
664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        blacklist = set([
674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Will raise a SyntaxError when compiling the exec statement
684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            '__future__',
694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ])
704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if not sys.platform.startswith('java'):
724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # In case _socket fails to build, make this test fail more gracefully
734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # than an AttributeError somewhere deep in CGIHTTPServer.
744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            import _socket
754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # rlcompleter needs special consideration; it import readline which
774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # initializes GNU readline which calls setlocale(LC_CTYPE, "")... :-(
784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            import rlcompleter
804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            import locale
814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except ImportError:
824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            pass
834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            locale.setlocale(locale.LC_CTYPE, 'C')
854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ignored = []
874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        failed_imports = []
884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        lib_dir = os.path.dirname(os.path.dirname(__file__))
894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for path, modname in self.walk_modules(lib_dir, ""):
904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m = modname
914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            blacklisted = False
924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            while m:
934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if m in blacklist:
944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    blacklisted = True
954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    break
964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                m = m.rpartition('.')[0]
974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if blacklisted:
984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                continue
994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if support.verbose:
1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                print(modname)
1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # This heuristic speeds up the process by removing, de facto,
1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # most test modules (and avoiding the auto-executing ones).
1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                with open(path, "rb") as f:
1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    if "__all__" not in f.read():
1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        raise NoAll(modname)
1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    self.check_all(modname)
1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except NoAll:
1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ignored.append(modname)
1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except FailedImport:
1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                failed_imports.append(modname)
1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if support.verbose:
1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            print('Following modules have no __all__ and have been ignored:',
1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                  ignored)
1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            print('Following modules failed to be imported:', failed_imports)
1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef test_main():
1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    support.run_unittest(AllTest)
1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmif __name__ == "__main__":
1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    test_main()
124