[Python-checkins] cpython: Issue #23883: Add test.support.check__all__() and test gettext.__all__

martin.panter python-checkins at python.org
Sat Nov 14 07:54:09 EST 2015


https://hg.python.org/cpython/rev/f8fa7bc837a3
changeset:   99132:f8fa7bc837a3
user:        Martin Panter <vadmium+py at gmail.com>
date:        Sat Nov 14 11:47:00 2015 +0000
summary:
  Issue #23883: Add test.support.check__all__() and test gettext.__all__

Patches by Jacek Kołodziej.

files:
  Doc/library/test.rst         |  42 ++++++++++++++++
  Lib/test/support/__init__.py |  61 ++++++++++++++++++++++++
  Lib/test/test_gettext.py     |   6 ++
  Lib/test/test_support.py     |  22 ++++++++
  Misc/ACKS                    |   1 +
  5 files changed, 132 insertions(+), 0 deletions(-)


diff --git a/Doc/library/test.rst b/Doc/library/test.rst
--- a/Doc/library/test.rst
+++ b/Doc/library/test.rst
@@ -580,6 +580,48 @@
    .. versionadded:: 3.5
 
 
+.. function:: check__all__(test_case, module, name_of_module=None, extra=(), blacklist=())
+
+   Assert that the ``__all__`` variable of *module* contains all public names.
+
+   The module's public names (its API) are detected automatically
+   based on whether they match the public name convention and were defined in
+   *module*.
+
+   The *name_of_module* argument can specify (as a string or tuple thereof) what
+   module(s) an API could be defined in in order to be detected as a public
+   API. One case for this is when *module* imports part of its public API from
+   other modules, possibly a C backend (like ``csv`` and its ``_csv``).
+
+   The *extra* argument can be a set of names that wouldn't otherwise be automatically
+   detected as "public", like objects without a proper ``__module__``
+   attribute. If provided, it will be added to the automatically detected ones.
+
+   The *blacklist* argument can be a set of names that must not be treated as part of
+   the public API even though their names indicate otherwise.
+
+   Example use::
+
+      import bar
+      import foo
+      import unittest
+      from test import support
+
+      class MiscTestCase(unittest.TestCase):
+          def test__all__(self):
+              support.check__all__(self, foo)
+
+      class OtherTestCase(unittest.TestCase):
+          def test__all__(self):
+              extra = {'BAR_CONST', 'FOO_CONST'}
+              blacklist = {'baz'}  # Undocumented name.
+              # bar imports part of its API from _bar.
+              support.check__all__(self, bar, ('bar', '_bar'),
+                                   extra=extra, blacklist=blacklist)
+
+   .. versionadded:: 3.6
+
+
 The :mod:`test.support` module defines the following classes:
 
 .. class:: TransientResource(exc, **kwargs)
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -26,6 +26,7 @@
 import sysconfig
 import tempfile
 import time
+import types
 import unittest
 import urllib.error
 import warnings
@@ -89,6 +90,7 @@
     "bigmemtest", "bigaddrspacetest", "cpython_only", "get_attribute",
     "requires_IEEE_754", "skip_unless_xattr", "requires_zlib",
     "anticipate_failure", "load_package_tests", "detect_api_mismatch",
+    "check__all__",
     # sys
     "is_jython", "check_impl_detail",
     # network
@@ -2199,6 +2201,65 @@
     return missing_items
 
 
+def check__all__(test_case, module, name_of_module=None, extra=(),
+                 blacklist=()):
+    """Assert that the __all__ variable of 'module' contains all public names.
+
+    The module's public names (its API) are detected automatically based on
+    whether they match the public name convention and were defined in
+    'module'.
+
+    The 'name_of_module' argument can specify (as a string or tuple thereof)
+    what module(s) an API could be defined in in order to be detected as a
+    public API. One case for this is when 'module' imports part of its public
+    API from other modules, possibly a C backend (like 'csv' and its '_csv').
+
+    The 'extra' argument can be a set of names that wouldn't otherwise be
+    automatically detected as "public", like objects without a proper
+    '__module__' attriubute. If provided, it will be added to the
+    automatically detected ones.
+
+    The 'blacklist' argument can be a set of names that must not be treated
+    as part of the public API even though their names indicate otherwise.
+
+    Usage:
+        import bar
+        import foo
+        import unittest
+        from test import support
+
+        class MiscTestCase(unittest.TestCase):
+            def test__all__(self):
+                support.check__all__(self, foo)
+
+        class OtherTestCase(unittest.TestCase):
+            def test__all__(self):
+                extra = {'BAR_CONST', 'FOO_CONST'}
+                blacklist = {'baz'}  # Undocumented name.
+                # bar imports part of its API from _bar.
+                support.check__all__(self, bar, ('bar', '_bar'),
+                                     extra=extra, blacklist=blacklist)
+
+    """
+
+    if name_of_module is None:
+        name_of_module = (module.__name__, )
+    elif isinstance(name_of_module, str):
+        name_of_module = (name_of_module, )
+
+    expected = set(extra)
+
+    for name in dir(module):
+        if name.startswith('_') or name in blacklist:
+            continue
+        obj = getattr(module, name)
+        if (getattr(obj, '__module__', None) in name_of_module or
+                (not hasattr(obj, '__module__') and
+                 not isinstance(obj, types.ModuleType))):
+            expected.add(name)
+    test_case.assertCountEqual(module.__all__, expected)
+
+
 class SuppressCrashReport:
     """Try to prevent a crash report from popping up.
 
diff --git a/Lib/test/test_gettext.py b/Lib/test/test_gettext.py
--- a/Lib/test/test_gettext.py
+++ b/Lib/test/test_gettext.py
@@ -440,6 +440,12 @@
         self.assertEqual(t.__class__, DummyGNUTranslations)
 
 
+class MiscTestCase(unittest.TestCase):
+    def test__all__(self):
+        blacklist = {'c2py', 'ENOENT'}
+        support.check__all__(self, gettext, blacklist=blacklist)
+
+
 def test_main():
     support.run_unittest(__name__)
 
diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py
--- a/Lib/test/test_support.py
+++ b/Lib/test/test_support.py
@@ -312,6 +312,28 @@
                 self.OtherClass, self.RefClass, ignore=ignore)
         self.assertEqual(set(), missing_items)
 
+    def test_check__all__(self):
+        extra = {'tempdir'}
+        blacklist = {'template'}
+        support.check__all__(self,
+                             tempfile,
+                             extra=extra,
+                             blacklist=blacklist)
+
+        extra = {'TextTestResult', 'installHandler'}
+        blacklist = {'load_tests', "TestProgram", "BaseTestSuite"}
+
+        support.check__all__(self,
+                             unittest,
+                             ("unittest.result", "unittest.case",
+                              "unittest.suite", "unittest.loader",
+                              "unittest.main", "unittest.runner",
+                              "unittest.signals"),
+                             extra=extra,
+                             blacklist=blacklist)
+
+        self.assertRaises(AssertionError, support.check__all__, self, unittest)
+
     # XXX -follows a list of untested API
     # make_legacy_pyc
     # is_resource_enabled
diff --git a/Misc/ACKS b/Misc/ACKS
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -765,6 +765,7 @@
 Marko Kohtala
 Vajrasky Kok
 Guido Kollerie
+Jacek Kołodziej
 Jacek Konieczny
 Марк Коренберг
 Arkady Koplyarov

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list