summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2009-10-10 20:52:11 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2009-10-10 20:52:11 (GMT)
commit58d2f2689a9d50bd649b446ffde87412cd128b97 (patch)
tree8d57588e30c5bd2b03d9e72a2f33137d18b067b1
parent1c77b7f84c5fca050980854a677539ba377439dd (diff)
downloadcpython-58d2f2689a9d50bd649b446ffde87412cd128b97.zip
cpython-58d2f2689a9d50bd649b446ffde87412cd128b97.tar.gz
cpython-58d2f2689a9d50bd649b446ffde87412cd128b97.tar.bz2
Issue #7055: test___all__ now greedily detects all modules which have an
__all__ attribute, rather than using a hardcoded and incomplete list.
-rw-r--r--Lib/test/test___all__.py225
-rw-r--r--Misc/NEWS3
2 files changed, 83 insertions, 145 deletions
diff --git a/Lib/test/test___all__.py b/Lib/test/test___all__.py
index 71fdba4..8662bcb 100644
--- a/Lib/test/test___all__.py
+++ b/Lib/test/test___all__.py
@@ -1,9 +1,18 @@
+from __future__ import print_function
+
import unittest
-from test.test_support import run_unittest
+from test import test_support as support
+import os
import sys
import warnings
+class NoAll(RuntimeError):
+ pass
+
+class FailedImport(RuntimeError):
+ pass
+
class AllTest(unittest.TestCase):
@@ -14,171 +23,97 @@ class AllTest(unittest.TestCase):
DeprecationWarning)
try:
exec "import %s" % modname in 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 in names
+ try:
+ exec "from %s import *" % modname in 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("BaseHTTPServer")
- self.check_all("Bastion")
- self.check_all("CGIHTTPServer")
- self.check_all("ConfigParser")
- self.check_all("Cookie")
- self.check_all("MimeWriter")
- self.check_all("Queue")
- self.check_all("SimpleHTTPServer")
- self.check_all("SocketServer")
- self.check_all("StringIO")
- self.check_all("UserString")
- self.check_all("aifc")
- self.check_all("atexit")
- self.check_all("audiodev")
- self.check_all("base64")
- self.check_all("bdb")
- self.check_all("binhex")
- self.check_all("calendar")
- 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("commands")
- self.check_all("compileall")
- self.check_all("copy")
- self.check_all("copy_reg")
- self.check_all("csv")
- self.check_all("dbhash")
- 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("htmllib")
- self.check_all("httplib")
- self.check_all("ihooks")
- self.check_all("imaplib")
- self.check_all("imghdr")
- self.check_all("imputil")
- 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("mimetools")
- self.check_all("mimetypes")
- self.check_all("mimify")
- 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("popen2")
- 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("repr")
- self.check_all("rexec")
- self.check_all("rfc822")
- self.check_all("rlcompleter")
- self.check_all("robotparser")
- self.check_all("sched")
- self.check_all("sets")
- self.check_all("sgmllib")
- 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.test_support")
- self.check_all("textwrap")
- self.check_all("threading")
- self.check_all("timeit")
- self.check_all("toaiff")
- self.check_all("tokenize")
- self.check_all("traceback")
- self.check_all("tty")
- self.check_all("unittest")
- self.check_all("urllib")
- self.check_all("urlparse")
- 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 "__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 bdd657c..ddd909f 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -1452,6 +1452,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.