Home | History | Annotate | Download | only in test
      1 from __future__ import print_function
      2 
      3 import unittest
      4 from test import test_support as support
      5 import os
      6 import sys
      7 
      8 # Setup bsddb warnings
      9 try:
     10     bsddb = support.import_module('bsddb', deprecated=True)
     11 except unittest.SkipTest:
     12     pass
     13 
     14 
     15 class NoAll(RuntimeError):
     16     pass
     17 
     18 class FailedImport(RuntimeError):
     19     pass
     20 
     21 
     22 class 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 import readline which
     77         # initializes GNU readline which calls setlocale(LC_CTYPE, "")... :-(
     78         try:
     79             import rlcompleter
     80             import locale
     81         except ImportError:
     82             pass
     83         else:
     84             locale.setlocale(locale.LC_CTYPE, 'C')
     85 
     86         ignored = []
     87         failed_imports = []
     88         lib_dir = os.path.dirname(os.path.dirname(__file__))
     89         for path, modname in self.walk_modules(lib_dir, ""):
     90             m = modname
     91             blacklisted = False
     92             while m:
     93                 if m in blacklist:
     94                     blacklisted = True
     95                     break
     96                 m = m.rpartition('.')[0]
     97             if blacklisted:
     98                 continue
     99             if support.verbose:
    100                 print(modname)
    101             try:
    102                 # This heuristic speeds up the process by removing, de facto,
    103                 # most test modules (and avoiding the auto-executing ones).
    104                 with open(path, "rb") as f:
    105                     if "__all__" not in f.read():
    106                         raise NoAll(modname)
    107                     self.check_all(modname)
    108             except NoAll:
    109                 ignored.append(modname)
    110             except FailedImport:
    111                 failed_imports.append(modname)
    112 
    113         if support.verbose:
    114             print('Following modules have no __all__ and have been ignored:',
    115                   ignored)
    116             print('Following modules failed to be imported:', failed_imports)
    117 
    118 
    119 def test_main():
    120     support.run_unittest(AllTest)
    121 
    122 if __name__ == "__main__":
    123     test_main()
    124