Issue #23883: Add test.support.check__all__() and test gettext.__all__

Patches by Jacek Kołodziej.
This commit is contained in:
Martin Panter 2015-11-14 11:47:00 +00:00
parent 63c1ebb67b
commit d226d308a3
5 changed files with 132 additions and 0 deletions

View File

@ -580,6 +580,48 @@ The :mod:`test.support` module defines the following functions:
.. 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)

View File

@ -26,6 +26,7 @@ import sys
import sysconfig
import tempfile
import time
import types
import unittest
import urllib.error
import warnings
@ -89,6 +90,7 @@ __all__ = [
"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 @@ def detect_api_mismatch(ref_api, other_api, *, ignore=()):
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.

View File

@ -440,6 +440,12 @@ class GettextCacheTestCase(GettextBaseTest):
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__)

View File

@ -312,6 +312,28 @@ class TestSupport(unittest.TestCase):
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

View File

@ -765,6 +765,7 @@ Damon Kohler
Marko Kohtala
Vajrasky Kok
Guido Kollerie
Jacek Kołodziej
Jacek Konieczny
Марк Коренберг
Arkady Koplyarov