summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/dbm/__init__.py2
-rw-r--r--Lib/test/test___all__.py206
-rw-r--r--Misc/NEWS3
3 files changed, 83 insertions, 128 deletions
diff --git a/Lib/dbm/__init__.py b/Lib/dbm/__init__.py
index 56555be..c224847 100644
--- a/Lib/dbm/__init__.py
+++ b/Lib/dbm/__init__.py
@@ -36,7 +36,7 @@ Note: 'r' and 'w' fail if the database doesn't exist; 'c' creates it
only if it doesn't exist; and 'n' always creates a new database.
"""
-__all__ = ['open', 'whichdb', 'error', 'errors']
+__all__ = ['open', 'whichdb', 'error', 'error']
import io
import os
diff --git a/Lib/test/test___all__.py b/Lib/test/test___all__.py
index a4e69b2..200db5c 100644
--- a/Lib/test/test___all__.py
+++ b/Lib/test/test___all__.py
@@ -1,9 +1,17 @@
import unittest
-from test.support import run_unittest
+from test import support
+import os
import sys
import warnings
+class NoAll(RuntimeError):
+ pass
+
+class FailedImport(RuntimeError):
+ pass
+
+
class AllTest(unittest.TestCase):
def check_all(self, modname):
@@ -13,153 +21,97 @@ class AllTest(unittest.TestCase):
DeprecationWarning)
try:
exec("import %s" % modname, names)
- except ImportError:
+ except:
# Silent fail here seems the best route since some modules
- # may not be available in all environments.
- return
- self.assertTrue(hasattr(sys.modules[modname], "__all__"),
- "%s has no __all__ attribute" % modname)
+ # may not be available or not initialize properly in all
+ # environments.
+ raise FailedImport(modname)
+ if not hasattr(sys.modules[modname], "__all__"):
+ raise NoAll(modname)
names = {}
- exec("from %s import *" % modname, names)
+ try:
+ exec("from %s import *" % modname, names)
+ except Exception as e:
+ # Include the module name in the exception string
+ self.fail("__all__ failure in {}: {}: {}".format(
+ modname, e.__class__.__name__, e))
if "__builtins__" in names:
del names["__builtins__"]
keys = set(names)
all = set(sys.modules[modname].__all__)
self.assertEqual(keys, all)
+ def walk_modules(self, basedir, modpath):
+ for fn in sorted(os.listdir(basedir)):
+ path = os.path.join(basedir, fn)
+ if os.path.isdir(path):
+ pkg_init = os.path.join(path, '__init__.py')
+ if os.path.exists(pkg_init):
+ yield pkg_init, modpath + fn
+ for p, m in self.walk_modules(path, modpath + fn + "."):
+ yield p, m
+ continue
+ if not fn.endswith('.py') or fn == '__init__.py':
+ continue
+ yield path, modpath + fn[:-3]
+
def test_all(self):
+ # Blacklisted modules and packages
+ blacklist = set([
+ # Will raise a SyntaxError when compiling the exec statement
+ '__future__',
+ ])
+
if not sys.platform.startswith('java'):
# In case _socket fails to build, make this test fail more gracefully
# than an AttributeError somewhere deep in CGIHTTPServer.
import _socket
- self.check_all("http.server")
- self.check_all("configparser")
- self.check_all("http.cookies")
- self.check_all("queue")
- self.check_all("socketserver")
- self.check_all("aifc")
- self.check_all("base64")
- self.check_all("bdb")
- self.check_all("binhex")
- self.check_all("calendar")
- self.check_all("collections")
- self.check_all("cgi")
- self.check_all("cmd")
- self.check_all("code")
- self.check_all("codecs")
- self.check_all("codeop")
- self.check_all("colorsys")
- self.check_all("compileall")
- self.check_all("copy")
- self.check_all("copyreg")
- self.check_all("csv")
- self.check_all("dbm.bsd")
- self.check_all("decimal")
- self.check_all("difflib")
- self.check_all("dircache")
- self.check_all("dis")
- self.check_all("doctest")
- self.check_all("_dummy_thread")
- self.check_all("dummy_threading")
- self.check_all("filecmp")
- self.check_all("fileinput")
- self.check_all("fnmatch")
- self.check_all("fpformat")
- self.check_all("ftplib")
- self.check_all("getopt")
- self.check_all("getpass")
- self.check_all("gettext")
- self.check_all("glob")
- self.check_all("gzip")
- self.check_all("heapq")
- self.check_all("http.client")
- self.check_all("ihooks")
- self.check_all("io")
- self.check_all("_pyio")
- self.check_all("imaplib")
- self.check_all("imghdr")
- self.check_all("keyword")
- self.check_all("linecache")
- self.check_all("locale")
- self.check_all("logging")
- self.check_all("macpath")
- self.check_all("macurl2path")
- self.check_all("mailbox")
- self.check_all("mailcap")
- self.check_all("mhlib")
- self.check_all("mimetypes")
- self.check_all("multifile")
- self.check_all("netrc")
- self.check_all("nntplib")
- self.check_all("ntpath")
- self.check_all("opcode")
- self.check_all("optparse")
- self.check_all("os")
- self.check_all("os2emxpath")
- self.check_all("pdb")
- self.check_all("pickle")
- self.check_all("pickletools")
- self.check_all("pipes")
- self.check_all("poplib")
- self.check_all("posixpath")
- self.check_all("pprint")
- self.check_all("profile")
- self.check_all("pstats")
- self.check_all("pty")
- self.check_all("py_compile")
- self.check_all("pyclbr")
- self.check_all("quopri")
- self.check_all("random")
- self.check_all("re")
- self.check_all("reprlib")
- self.check_all("rlcompleter")
- self.check_all("urllib.robotparser")
- self.check_all("sched")
- self.check_all("shelve")
- self.check_all("shlex")
- self.check_all("shutil")
- self.check_all("smtpd")
- self.check_all("smtplib")
- self.check_all("sndhdr")
- self.check_all("socket")
- self.check_all("_strptime")
- self.check_all("symtable")
- self.check_all("tabnanny")
- self.check_all("tarfile")
- self.check_all("telnetlib")
- self.check_all("tempfile")
- self.check_all("test.support")
- self.check_all("textwrap")
- self.check_all("threading")
- self.check_all("timeit")
- self.check_all("tokenize")
- self.check_all("traceback")
- self.check_all("tty")
- self.check_all("unittest")
- self.check_all("uu")
- self.check_all("warnings")
- self.check_all("wave")
- self.check_all("weakref")
- self.check_all("webbrowser")
- self.check_all("xdrlib")
- self.check_all("zipfile")
-
# rlcompleter needs special consideration; it import readline which
# initializes GNU readline which calls setlocale(LC_CTYPE, "")... :-(
try:
- self.check_all("rlcompleter")
- finally:
+ import rlcompleter
+ import locale
+ except ImportError:
+ pass
+ else:
+ locale.setlocale(locale.LC_CTYPE, 'C')
+
+ ignored = []
+ failed_imports = []
+ lib_dir = os.path.dirname(os.path.dirname(__file__))
+ for path, modname in self.walk_modules(lib_dir, ""):
+ m = modname
+ blacklisted = False
+ while m:
+ if m in blacklist:
+ blacklisted = True
+ break
+ m = m.rpartition('.')[0]
+ if blacklisted:
+ continue
+ if support.verbose:
+ print(modname)
try:
- import locale
- except ImportError:
- pass
- else:
- locale.setlocale(locale.LC_CTYPE, 'C')
+ # This heuristic speeds up the process by removing, de facto,
+ # most test modules (and avoiding the auto-executing ones).
+ with open(path, "rb") as f:
+ if b"__all__" not in f.read():
+ raise NoAll(modname)
+ self.check_all(modname)
+ except NoAll:
+ ignored.append(modname)
+ except FailedImport:
+ failed_imports.append(modname)
+
+ if support.verbose:
+ print('Following modules have no __all__ and have been ignored:',
+ ignored)
+ print('Following modules failed to be imported:', failed_imports)
def test_main():
- run_unittest(AllTest)
+ support.run_unittest(AllTest)
if __name__ == "__main__":
test_main()
diff --git a/Misc/NEWS b/Misc/NEWS
index becd5b1..f075eb4 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -108,6 +108,9 @@ Extension Modules
Tests
-----
+- Issue #7055: test___all__ now greedily detects all modules which have an
+ __all__ attribute, rather than using a hardcoded and incomplete list.
+
- Issue #7058: Added save/restore for argv and os.environ to runtest_inner
in regrtest, with warnings if the called test modifies them.