mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-29 11:14:38 +08:00
Updated the pkgutil + unittest libraries + the pkgutil, unittest and import tests - v.3.13.11 (#6610)
* Updated unittest + tests * Updated pkgutil + the associated test * Updated test_import * Fixed import + unittest test errors * Updated test_dll_dependency_import with expectedFailure
This commit is contained in:
1 parent
eee360822c
commit
4bec6bb6f9
22 files changed
+2374
-268
No files matched your search
Vendored
+15
-19
@@ -14,7 +14,7 @@ import warnings
|
||||
__all__ = [
|
||||
'get_importer', 'iter_importers', 'get_loader', 'find_loader',
|
||||
'walk_packages', 'iter_modules', 'get_data',
|
||||
'ImpImporter', 'ImpLoader', 'read_code', 'extend_path',
|
||||
'read_code', 'extend_path',
|
||||
'ModuleInfo',
|
||||
]
|
||||
|
||||
@@ -23,20 +23,6 @@ ModuleInfo = namedtuple('ModuleInfo', 'module_finder name ispkg')
|
||||
ModuleInfo.__doc__ = 'A namedtuple with minimal info about a module.'
|
||||
|
||||
|
||||
def _get_spec(finder, name):
|
||||
"""Return the finder-specific module spec."""
|
||||
# Works with legacy finders.
|
||||
try:
|
||||
find_spec = finder.find_spec
|
||||
except AttributeError:
|
||||
loader = finder.find_module(name)
|
||||
if loader is None:
|
||||
return None
|
||||
return importlib.util.spec_from_loader(name, loader)
|
||||
else:
|
||||
return find_spec(name)
|
||||
|
||||
|
||||
def read_code(stream):
|
||||
# This helper is needed in order for the PEP 302 emulation to
|
||||
# correctly handle compiled files
|
||||
@@ -184,6 +170,7 @@ def _iter_file_finder_modules(importer, prefix=''):
|
||||
iter_importer_modules.register(
|
||||
importlib.machinery.FileFinder, _iter_file_finder_modules)
|
||||
|
||||
|
||||
try:
|
||||
import zipimport
|
||||
from zipimport import zipimporter
|
||||
@@ -231,6 +218,7 @@ def get_importer(path_item):
|
||||
The cache (or part of it) can be cleared manually if a
|
||||
rescan of sys.path_hooks is necessary.
|
||||
"""
|
||||
path_item = os.fsdecode(path_item)
|
||||
try:
|
||||
importer = sys.path_importer_cache[path_item]
|
||||
except KeyError:
|
||||
@@ -282,6 +270,10 @@ def get_loader(module_or_name):
|
||||
If the named module is not already imported, its containing package
|
||||
(if any) is imported, in order to establish the package __path__.
|
||||
"""
|
||||
warnings._deprecated("pkgutil.get_loader",
|
||||
f"{warnings._DEPRECATED_MSG}; "
|
||||
"use importlib.util.find_spec() instead",
|
||||
remove=(3, 14))
|
||||
if module_or_name in sys.modules:
|
||||
module_or_name = sys.modules[module_or_name]
|
||||
if module_or_name is None:
|
||||
@@ -306,6 +298,10 @@ def find_loader(fullname):
|
||||
importlib.util.find_spec that converts most failures to ImportError
|
||||
and only returns the loader rather than the full spec
|
||||
"""
|
||||
warnings._deprecated("pkgutil.find_loader",
|
||||
f"{warnings._DEPRECATED_MSG}; "
|
||||
"use importlib.util.find_spec() instead",
|
||||
remove=(3, 14))
|
||||
if fullname.startswith('.'):
|
||||
msg = "Relative module name {!r} not supported".format(fullname)
|
||||
raise ImportError(msg)
|
||||
@@ -328,10 +324,10 @@ def extend_path(path, name):
|
||||
from pkgutil import extend_path
|
||||
__path__ = extend_path(__path__, __name__)
|
||||
|
||||
This will add to the package's __path__ all subdirectories of
|
||||
directories on sys.path named after the package. This is useful
|
||||
if one wants to distribute different parts of a single logical
|
||||
package as multiple directories.
|
||||
For each directory on sys.path that has a subdirectory that
|
||||
matches the package name, add the subdirectory to the package's
|
||||
__path__. This is useful if one wants to distribute different
|
||||
parts of a single logical package as multiple directories.
|
||||
|
||||
It also looks for *.pkg files beginning where * matches the name
|
||||
argument. This feature is similar to *.pth files (see site.py),
|
||||
|
||||
Vendored
+2059
-71
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,3 @@
|
||||
import test.test_import.data.circular_imports.import_cycle as m
|
||||
|
||||
m.some_attribute
|
||||
@@ -0,0 +1,13 @@
|
||||
"""Circular import involving a single-phase-init extension.
|
||||
|
||||
This module is imported from the _testsinglephase_circular module from
|
||||
_testsinglephase, and imports that module again.
|
||||
"""
|
||||
|
||||
import importlib
|
||||
import _testsinglephase
|
||||
from test.test_import import import_extension_from_file
|
||||
|
||||
name = '_testsinglephase_circular'
|
||||
filename = _testsinglephase.__file__
|
||||
mod = import_extension_from_file(name, filename)
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
from test.support import TestFailed
|
||||
|
||||
# A test for SF bug 422177: manifest float constants varied way too much in
|
||||
# precision depending on whether Python was loading a module for the first
|
||||
# time, or reloading it from a precompiled .pyc. The "expected" failure
|
||||
# mode is that when test_import imports this after all .pyc files have been
|
||||
# erased, it passes, but when test_import imports this from
|
||||
# double_const.pyc, it fails. This indicates a woeful loss of precision in
|
||||
# the marshal format for doubles. It's also possible that repr() doesn't
|
||||
# produce enough digits to get reasonable precision for this box.
|
||||
|
||||
PI = 3.14159265358979324
|
||||
TWOPI = 6.28318530717958648
|
||||
|
||||
PI_str = "3.14159265358979324"
|
||||
TWOPI_str = "6.28318530717958648"
|
||||
|
||||
# Verify that the double x is within a few bits of eval(x_str).
|
||||
def check_ok(x, x_str):
|
||||
assert x > 0.0
|
||||
x2 = eval(x_str)
|
||||
assert x2 > 0.0
|
||||
diff = abs(x - x2)
|
||||
# If diff is no larger than 3 ULP (wrt x2), then diff/8 is no larger
|
||||
# than 0.375 ULP, so adding diff/8 to x2 should have no effect.
|
||||
if x2 + (diff / 8.) != x2:
|
||||
raise TestFailed("Manifest const %s lost too much precision " % x_str)
|
||||
|
||||
check_ok(PI, PI_str)
|
||||
check_ok(TWOPI, TWOPI_str)
|
||||
@@ -0,0 +1,2 @@
|
||||
"""Rebinding the package attribute after importing the module."""
|
||||
from .submodule import submodule
|
||||
@@ -0,0 +1,7 @@
|
||||
attr = 'submodule'
|
||||
class A:
|
||||
attr = 'submodule'
|
||||
class submodule:
|
||||
attr = 'rebound'
|
||||
class B:
|
||||
attr = 'rebound'
|
||||
@@ -0,0 +1,5 @@
|
||||
"""Binding the package attribute without importing the module."""
|
||||
class submodule:
|
||||
attr = 'origin'
|
||||
class B:
|
||||
attr = 'origin'
|
||||
@@ -0,0 +1,3 @@
|
||||
attr = 'submodule'
|
||||
class A:
|
||||
attr = 'submodule'
|
||||
Vendored
+159
-20
@@ -1,5 +1,6 @@
|
||||
from pathlib import Path
|
||||
from test.support.import_helper import unload, CleanImport
|
||||
from test.support.warnings_helper import check_warnings
|
||||
from test.support.warnings_helper import check_warnings, ignore_warnings
|
||||
import unittest
|
||||
import sys
|
||||
import importlib
|
||||
@@ -11,6 +12,10 @@ import tempfile
|
||||
import shutil
|
||||
import zipfile
|
||||
|
||||
from test.support.import_helper import DirsOnSysPath
|
||||
from test.support.os_helper import FakePath
|
||||
from test.test_importlib.util import uncache
|
||||
|
||||
# Note: pkgutil.walk_packages is currently tested in test_runpy. This is
|
||||
# a hack to get a major issue resolved for 3.3b2. Longer term, it should
|
||||
# be moved back here, perhaps by factoring out the helper code for
|
||||
@@ -91,6 +96,45 @@ class PkgutilTests(unittest.TestCase):
|
||||
|
||||
del sys.modules[pkg]
|
||||
|
||||
def test_issue44061_iter_modules(self):
|
||||
#see: issue44061
|
||||
zip = 'test_getdata_zipfile.zip'
|
||||
pkg = 'test_getdata_zipfile'
|
||||
|
||||
# Include a LF and a CRLF, to test that binary data is read back
|
||||
RESOURCE_DATA = b'Hello, world!\nSecond line\r\nThird line'
|
||||
|
||||
# Make a package with some resources
|
||||
zip_file = os.path.join(self.dirname, zip)
|
||||
z = zipfile.ZipFile(zip_file, 'w')
|
||||
|
||||
# Empty init.py
|
||||
z.writestr(pkg + '/__init__.py', "")
|
||||
# Resource files, res.txt
|
||||
z.writestr(pkg + '/res.txt', RESOURCE_DATA)
|
||||
z.close()
|
||||
|
||||
# Check we can read the resources
|
||||
sys.path.insert(0, zip_file)
|
||||
try:
|
||||
res = pkgutil.get_data(pkg, 'res.txt')
|
||||
self.assertEqual(res, RESOURCE_DATA)
|
||||
|
||||
# make sure iter_modules accepts Path objects
|
||||
names = []
|
||||
for moduleinfo in pkgutil.iter_modules([FakePath(zip_file)]):
|
||||
self.assertIsInstance(moduleinfo, pkgutil.ModuleInfo)
|
||||
names.append(moduleinfo.name)
|
||||
self.assertEqual(names, [pkg])
|
||||
finally:
|
||||
del sys.path[0]
|
||||
sys.modules.pop(pkg, None)
|
||||
|
||||
# assert path must be None or list of paths
|
||||
expected_msg = "path must be None or list of paths to look for modules in"
|
||||
with self.assertRaisesRegex(ValueError, expected_msg):
|
||||
list(pkgutil.iter_modules("invalid_path"))
|
||||
|
||||
def test_unreadable_dir_on_syspath(self):
|
||||
# issue7367 - walk_packages failed if unreadable dir on sys.path
|
||||
package_name = "unreadable_package"
|
||||
@@ -187,8 +231,7 @@ class PkgutilTests(unittest.TestCase):
|
||||
with self.assertRaises((TypeError, ValueError)):
|
||||
list(pkgutil.walk_packages(bytes_input))
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_name_resolution(self):
|
||||
import logging
|
||||
import logging.handlers
|
||||
@@ -280,6 +323,38 @@ class PkgutilTests(unittest.TestCase):
|
||||
with self.assertRaises(exc):
|
||||
pkgutil.resolve_name(s)
|
||||
|
||||
def test_name_resolution_import_rebinding(self):
|
||||
# The same data is also used for testing import in test_import and
|
||||
# mock.patch in test_unittest.
|
||||
path = os.path.join(os.path.dirname(__file__), 'test_import', 'data')
|
||||
with uncache('package3', 'package3.submodule'), DirsOnSysPath(path):
|
||||
self.assertEqual(pkgutil.resolve_name('package3.submodule.attr'), 'submodule')
|
||||
with uncache('package3', 'package3.submodule'), DirsOnSysPath(path):
|
||||
self.assertEqual(pkgutil.resolve_name('package3.submodule:attr'), 'submodule')
|
||||
with uncache('package3', 'package3.submodule'), DirsOnSysPath(path):
|
||||
self.assertEqual(pkgutil.resolve_name('package3:submodule.attr'), 'rebound')
|
||||
self.assertEqual(pkgutil.resolve_name('package3.submodule.attr'), 'submodule')
|
||||
self.assertEqual(pkgutil.resolve_name('package3:submodule.attr'), 'rebound')
|
||||
with uncache('package3', 'package3.submodule'), DirsOnSysPath(path):
|
||||
self.assertEqual(pkgutil.resolve_name('package3:submodule.attr'), 'rebound')
|
||||
self.assertEqual(pkgutil.resolve_name('package3.submodule:attr'), 'submodule')
|
||||
self.assertEqual(pkgutil.resolve_name('package3:submodule.attr'), 'rebound')
|
||||
|
||||
def test_name_resolution_import_rebinding2(self):
|
||||
path = os.path.join(os.path.dirname(__file__), 'test_import', 'data')
|
||||
with uncache('package4', 'package4.submodule'), DirsOnSysPath(path):
|
||||
self.assertEqual(pkgutil.resolve_name('package4.submodule.attr'), 'submodule')
|
||||
with uncache('package4', 'package4.submodule'), DirsOnSysPath(path):
|
||||
self.assertEqual(pkgutil.resolve_name('package4.submodule:attr'), 'submodule')
|
||||
with uncache('package4', 'package4.submodule'), DirsOnSysPath(path):
|
||||
self.assertEqual(pkgutil.resolve_name('package4:submodule.attr'), 'origin')
|
||||
self.assertEqual(pkgutil.resolve_name('package4.submodule.attr'), 'submodule')
|
||||
self.assertEqual(pkgutil.resolve_name('package4:submodule.attr'), 'submodule')
|
||||
with uncache('package4', 'package4.submodule'), DirsOnSysPath(path):
|
||||
self.assertEqual(pkgutil.resolve_name('package4:submodule.attr'), 'origin')
|
||||
self.assertEqual(pkgutil.resolve_name('package4.submodule:attr'), 'submodule')
|
||||
self.assertEqual(pkgutil.resolve_name('package4:submodule.attr'), 'submodule')
|
||||
|
||||
|
||||
class PkgutilPEP302Tests(unittest.TestCase):
|
||||
|
||||
@@ -391,7 +466,7 @@ class ExtendPathTests(unittest.TestCase):
|
||||
importers = list(iter_importers(fullname))
|
||||
expected_importer = get_importer(pathitem)
|
||||
for finder in importers:
|
||||
spec = pkgutil._get_spec(finder, fullname)
|
||||
spec = finder.find_spec(fullname)
|
||||
loader = spec.loader
|
||||
try:
|
||||
loader = loader.loader
|
||||
@@ -403,7 +478,7 @@ class ExtendPathTests(unittest.TestCase):
|
||||
self.assertEqual(finder, expected_importer)
|
||||
self.assertIsInstance(loader,
|
||||
importlib.machinery.SourceFileLoader)
|
||||
self.assertIsNone(pkgutil._get_spec(finder, pkgname))
|
||||
self.assertIsNone(finder.find_spec(pkgname))
|
||||
|
||||
with self.assertRaises(ImportError):
|
||||
list(iter_importers('invalid.module'))
|
||||
@@ -448,7 +523,43 @@ class ExtendPathTests(unittest.TestCase):
|
||||
del sys.modules['foo.bar']
|
||||
del sys.modules['foo.baz']
|
||||
|
||||
# XXX: test .pkg files
|
||||
|
||||
def test_extend_path_argument_types(self):
|
||||
pkgname = 'foo'
|
||||
dirname_0 = self.create_init(pkgname)
|
||||
|
||||
# If the input path is not a list it is returned unchanged
|
||||
self.assertEqual('notalist', pkgutil.extend_path('notalist', 'foo'))
|
||||
self.assertEqual(('not', 'a', 'list'), pkgutil.extend_path(('not', 'a', 'list'), 'foo'))
|
||||
self.assertEqual(123, pkgutil.extend_path(123, 'foo'))
|
||||
self.assertEqual(None, pkgutil.extend_path(None, 'foo'))
|
||||
|
||||
# Cleanup
|
||||
shutil.rmtree(dirname_0)
|
||||
del sys.path[0]
|
||||
|
||||
|
||||
def test_extend_path_pkg_files(self):
|
||||
pkgname = 'foo'
|
||||
dirname_0 = self.create_init(pkgname)
|
||||
|
||||
with open(os.path.join(dirname_0, 'bar.pkg'), 'w') as pkg_file:
|
||||
pkg_file.write('\n'.join([
|
||||
'baz',
|
||||
'/foo/bar/baz',
|
||||
'',
|
||||
'#comment'
|
||||
]))
|
||||
|
||||
extended_paths = pkgutil.extend_path(sys.path, 'bar')
|
||||
|
||||
self.assertEqual(extended_paths[:-2], sys.path)
|
||||
self.assertEqual(extended_paths[-2], 'baz')
|
||||
self.assertEqual(extended_paths[-1], '/foo/bar/baz')
|
||||
|
||||
# Cleanup
|
||||
shutil.rmtree(dirname_0)
|
||||
del sys.path[0]
|
||||
|
||||
|
||||
class NestedNamespacePackageTest(unittest.TestCase):
|
||||
@@ -491,36 +602,50 @@ class NestedNamespacePackageTest(unittest.TestCase):
|
||||
self.assertEqual(c, 1)
|
||||
self.assertEqual(d, 2)
|
||||
|
||||
|
||||
class ImportlibMigrationTests(unittest.TestCase):
|
||||
# With full PEP 302 support in the standard import machinery, the
|
||||
# PEP 302 emulation in this module is in the process of being
|
||||
# deprecated in favour of importlib proper
|
||||
|
||||
@unittest.skipIf(__name__ == '__main__', 'not compatible with __main__')
|
||||
@ignore_warnings(category=DeprecationWarning)
|
||||
def test_get_loader_handles_missing_loader_attribute(self):
|
||||
global __loader__
|
||||
this_loader = __loader__
|
||||
del __loader__
|
||||
try:
|
||||
with check_warnings() as w:
|
||||
self.assertIsNotNone(pkgutil.get_loader(__name__))
|
||||
self.assertEqual(len(w.warnings), 0)
|
||||
self.assertIsNotNone(pkgutil.get_loader(__name__))
|
||||
finally:
|
||||
__loader__ = this_loader
|
||||
|
||||
@ignore_warnings(category=DeprecationWarning)
|
||||
def test_get_loader_handles_missing_spec_attribute(self):
|
||||
name = 'spam'
|
||||
mod = type(sys)(name)
|
||||
del mod.__spec__
|
||||
with CleanImport(name):
|
||||
sys.modules[name] = mod
|
||||
loader = pkgutil.get_loader(name)
|
||||
try:
|
||||
sys.modules[name] = mod
|
||||
loader = pkgutil.get_loader(name)
|
||||
finally:
|
||||
sys.modules.pop(name, None)
|
||||
self.assertIsNone(loader)
|
||||
|
||||
@ignore_warnings(category=DeprecationWarning)
|
||||
def test_get_loader_handles_spec_attribute_none(self):
|
||||
name = 'spam'
|
||||
mod = type(sys)(name)
|
||||
mod.__spec__ = None
|
||||
with CleanImport(name):
|
||||
sys.modules[name] = mod
|
||||
loader = pkgutil.get_loader(name)
|
||||
try:
|
||||
sys.modules[name] = mod
|
||||
loader = pkgutil.get_loader(name)
|
||||
finally:
|
||||
sys.modules.pop(name, None)
|
||||
self.assertIsNone(loader)
|
||||
|
||||
@ignore_warnings(category=DeprecationWarning)
|
||||
def test_get_loader_None_in_sys_modules(self):
|
||||
name = 'totally bogus'
|
||||
sys.modules[name] = None
|
||||
@@ -530,24 +655,38 @@ class NestedNamespacePackageTest(unittest.TestCase):
|
||||
del sys.modules[name]
|
||||
self.assertIsNone(loader)
|
||||
|
||||
def test_get_loader_is_deprecated(self):
|
||||
with check_warnings(
|
||||
(r".*\bpkgutil.get_loader\b.*", DeprecationWarning),
|
||||
):
|
||||
res = pkgutil.get_loader("sys")
|
||||
self.assertIsNotNone(res)
|
||||
|
||||
def test_find_loader_is_deprecated(self):
|
||||
with check_warnings(
|
||||
(r".*\bpkgutil.find_loader\b.*", DeprecationWarning),
|
||||
):
|
||||
res = pkgutil.find_loader("sys")
|
||||
self.assertIsNotNone(res)
|
||||
|
||||
@ignore_warnings(category=DeprecationWarning)
|
||||
def test_find_loader_missing_module(self):
|
||||
name = 'totally bogus'
|
||||
loader = pkgutil.find_loader(name)
|
||||
self.assertIsNone(loader)
|
||||
|
||||
def test_find_loader_avoids_emulation(self):
|
||||
with check_warnings() as w:
|
||||
self.assertIsNotNone(pkgutil.find_loader("sys"))
|
||||
self.assertIsNotNone(pkgutil.find_loader("os"))
|
||||
self.assertIsNotNone(pkgutil.find_loader("test.support"))
|
||||
self.assertEqual(len(w.warnings), 0)
|
||||
|
||||
def test_get_importer_avoids_emulation(self):
|
||||
# We use an illegal path so *none* of the path hooks should fire
|
||||
with check_warnings() as w:
|
||||
self.assertIsNone(pkgutil.get_importer("*??"))
|
||||
self.assertEqual(len(w.warnings), 0)
|
||||
|
||||
def test_issue44061(self):
|
||||
try:
|
||||
pkgutil.get_importer(Path("/home"))
|
||||
except AttributeError:
|
||||
self.fail("Unexpected AttributeError when calling get_importer")
|
||||
|
||||
def test_iter_importers_avoids_emulation(self):
|
||||
with check_warnings() as w:
|
||||
for importer in pkgutil.iter_importers(): pass
|
||||
|
||||
+3
-6
@@ -48,8 +48,7 @@ class TestAsyncCase(unittest.TestCase):
|
||||
# starting a new event loop
|
||||
self.addCleanup(support.gc_collect)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_full_cycle(self):
|
||||
expected = ['setUp',
|
||||
'asyncSetUp',
|
||||
@@ -296,8 +295,7 @@ class TestAsyncCase(unittest.TestCase):
|
||||
test.doCleanups()
|
||||
self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup2', 'cleanup1'])
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_deprecation_of_return_val_from_test(self):
|
||||
# Issue 41322 - deprecate return of value that is not None from a test
|
||||
class Nothing:
|
||||
@@ -488,8 +486,7 @@ class TestAsyncCase(unittest.TestCase):
|
||||
result = test.run()
|
||||
self.assertTrue(result.wasSuccessful())
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_loop_factory(self):
|
||||
asyncio.set_event_loop_policy(None)
|
||||
|
||||
|
||||
-4
@@ -364,8 +364,6 @@ class TestDiscovery(unittest.TestCase):
|
||||
[(loader, [], 'test*.py'),
|
||||
(loader, [], 'test*.py')])
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_discover(self):
|
||||
loader = unittest.TestLoader()
|
||||
|
||||
@@ -412,8 +410,6 @@ class TestDiscovery(unittest.TestCase):
|
||||
self.assertEqual(_find_tests_args, [(start_dir, 'pattern')])
|
||||
self.assertIn(top_level_dir, sys.path)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_discover_should_not_persist_top_level_dir_between_calls(self):
|
||||
original_isfile = os.path.isfile
|
||||
original_isdir = os.path.isdir
|
||||
|
||||
-6
@@ -90,8 +90,6 @@ class Test_TestLoader(unittest.TestCase):
|
||||
self.assertIsInstance(suite, loader.suiteClass)
|
||||
self.assertEqual(list(suite), [])
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
# "Do not load any tests from `FunctionTestCase` class."
|
||||
def test_loadTestsFromTestCase__from_FunctionTestCase(self):
|
||||
loader = unittest.TestLoader()
|
||||
@@ -121,8 +119,6 @@ class Test_TestLoader(unittest.TestCase):
|
||||
expected = [loader.suiteClass([MyTestCase('test')])]
|
||||
self.assertEqual(list(suite), expected)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
# "This test ensures that internal `TestCase` subclasses are not loaded"
|
||||
def test_loadTestsFromModule__TestCase_subclass_internals(self):
|
||||
# See https://github.com/python/cpython/issues/84867
|
||||
@@ -187,8 +183,6 @@ class Test_TestLoader(unittest.TestCase):
|
||||
self.assertEqual(list(suite), reference)
|
||||
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
# Check that loadTestsFromModule honors a module
|
||||
# with a load_tests function.
|
||||
def test_loadTestsFromModule__load_tests(self):
|
||||
|
||||
+22
-2
@@ -75,6 +75,14 @@ class Test_TestProgram(unittest.TestCase):
|
||||
class Empty(unittest.TestCase):
|
||||
pass
|
||||
|
||||
class SetUpClassFailure(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
raise Exception
|
||||
def testPass(self):
|
||||
pass
|
||||
|
||||
class TestLoader(unittest.TestLoader):
|
||||
"""Test loader that returns a suite containing the supplied testcase."""
|
||||
|
||||
@@ -191,6 +199,18 @@ class Test_TestProgram(unittest.TestCase):
|
||||
out = stream.getvalue()
|
||||
self.assertIn('\nNO TESTS RAN\n', out)
|
||||
|
||||
def test_ExitSetUpClassFailureSuite(self):
|
||||
stream = BufferedWriter()
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
unittest.main(
|
||||
argv=["setup_class_failure"],
|
||||
testRunner=unittest.TextTestRunner(stream=stream),
|
||||
testLoader=self.TestLoader(self.SetUpClassFailure))
|
||||
self.assertEqual(cm.exception.code, 1)
|
||||
out = stream.getvalue()
|
||||
self.assertIn("ERROR: setUpClass", out)
|
||||
self.assertIn("SetUpClassFailure", out)
|
||||
|
||||
|
||||
class InitialisableProgram(unittest.TestProgram):
|
||||
exit = False
|
||||
@@ -485,8 +505,8 @@ class TestCommandLineArgs(unittest.TestCase):
|
||||
|
||||
self.assertEqual(program.testNamePatterns, ['*foo*', '*bar*', '*pat*'])
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailureIf(sys.platform != 'win32', "TODO: RUSTPYTHON")
|
||||
@unittest.expectedFailureIf(sys.platform != 'win32', 'TODO: RUSTPYTHON')
|
||||
|
||||
def testSelectedTestNamesFunctionalTest(self):
|
||||
def run_unittest(args):
|
||||
# Use -E to ignore PYTHONSAFEPATH env var
|
||||
|
||||
+1
-2
@@ -1297,8 +1297,7 @@ class Test_TextTestRunner(unittest.TestCase):
|
||||
expected = ['startTestRun', 'stopTestRun']
|
||||
self.assertEqual(events, expected)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_pickle_unpickle(self):
|
||||
# Issue #7197: a TextTestRunner should be (un)pickleable. This is
|
||||
# required by test_multiprocessing under Windows (in verbose mode).
|
||||
|
||||
+12
-24
@@ -340,8 +340,7 @@ class AsyncSpecTest(unittest.TestCase):
|
||||
# only the shape of the spec at the time of mock construction matters
|
||||
self.assertNotIsInstance(mock_async_instance.later_async_func_attr, AsyncMock)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_spec_mock_type_kw(self):
|
||||
def inner_test(mock_type):
|
||||
async_mock = mock_type(spec=async_func)
|
||||
@@ -356,8 +355,7 @@ class AsyncSpecTest(unittest.TestCase):
|
||||
with self.subTest(f"test spec kwarg with {mock_type}"):
|
||||
inner_test(mock_type)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_spec_mock_type_positional(self):
|
||||
def inner_test(mock_type):
|
||||
async_mock = mock_type(async_func)
|
||||
@@ -736,8 +734,7 @@ class AsyncIteratorTest(unittest.TestCase):
|
||||
|
||||
async def __anext__(self): pass
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_aiter_set_return_value(self):
|
||||
mock_iter = AsyncMock(name="tester")
|
||||
mock_iter.__aiter__.return_value = [1, 2, 3]
|
||||
@@ -763,8 +760,7 @@ class AsyncIteratorTest(unittest.TestCase):
|
||||
inner_test(mock_type)
|
||||
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_mock_async_for(self):
|
||||
async def iterate(iterator):
|
||||
accumulator = []
|
||||
@@ -810,8 +806,7 @@ class AsyncMockAssert(unittest.TestCase):
|
||||
async def _await_coroutine(self, coroutine):
|
||||
return await coroutine
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_assert_called_but_not_awaited(self):
|
||||
mock = AsyncMock(AsyncClass)
|
||||
with assertNeverAwaited(self):
|
||||
@@ -852,8 +847,7 @@ class AsyncMockAssert(unittest.TestCase):
|
||||
self.mock.assert_called_once()
|
||||
self.mock.assert_awaited_once()
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_assert_called_twice_and_awaited_once(self):
|
||||
mock = AsyncMock(AsyncClass)
|
||||
coroutine = mock.async_method()
|
||||
@@ -868,8 +862,7 @@ class AsyncMockAssert(unittest.TestCase):
|
||||
mock.async_method.assert_awaited()
|
||||
mock.async_method.assert_awaited_once()
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_assert_called_once_and_awaited_twice(self):
|
||||
mock = AsyncMock(AsyncClass)
|
||||
coroutine = mock.async_method()
|
||||
@@ -894,8 +887,7 @@ class AsyncMockAssert(unittest.TestCase):
|
||||
with self.assertRaises(AssertionError):
|
||||
self.mock.assert_called()
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_assert_has_calls_not_awaits(self):
|
||||
kalls = [call('foo')]
|
||||
with assertNeverAwaited(self):
|
||||
@@ -904,8 +896,7 @@ class AsyncMockAssert(unittest.TestCase):
|
||||
with self.assertRaises(AssertionError):
|
||||
self.mock.assert_has_awaits(kalls)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_assert_has_mock_calls_on_async_mock_no_spec(self):
|
||||
with assertNeverAwaited(self):
|
||||
self.mock()
|
||||
@@ -919,8 +910,7 @@ class AsyncMockAssert(unittest.TestCase):
|
||||
mock_kalls = ([call(), call('foo'), call('baz')])
|
||||
self.assertEqual(self.mock.mock_calls, mock_kalls)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_assert_has_mock_calls_on_async_mock_with_spec(self):
|
||||
a_class_mock = AsyncMock(AsyncClass)
|
||||
with assertNeverAwaited(self):
|
||||
@@ -936,8 +926,7 @@ class AsyncMockAssert(unittest.TestCase):
|
||||
self.assertEqual(a_class_mock.async_method.mock_calls, method_kalls)
|
||||
self.assertEqual(a_class_mock.mock_calls, mock_kalls)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_async_method_calls_recorded(self):
|
||||
with assertNeverAwaited(self):
|
||||
self.mock.something(3, fish=None)
|
||||
@@ -953,8 +942,7 @@ class AsyncMockAssert(unittest.TestCase):
|
||||
[("something", (6,), {'cake': sentinel.Cake})],
|
||||
"method calls not recorded correctly")
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_async_arg_lists(self):
|
||||
def assert_attrs(mock):
|
||||
names = ('call_args_list', 'method_calls', 'mock_calls')
|
||||
|
||||
+1
-2
@@ -43,8 +43,7 @@ class AnyTest(unittest.TestCase):
|
||||
mock.assert_called_with(ANY, foo=ANY)
|
||||
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_any_mock_calls_comparison_order(self):
|
||||
mock = Mock()
|
||||
class Foo(object):
|
||||
|
||||
+1
-6
@@ -1778,8 +1778,6 @@ class PatchTest(unittest.TestCase):
|
||||
'exception traceback not propagated')
|
||||
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_name_resolution_import_rebinding(self):
|
||||
# Currently mock.patch uses pkgutil.resolve_name(), but repeat
|
||||
# similar tests just for the case.
|
||||
@@ -1814,8 +1812,6 @@ class PatchTest(unittest.TestCase):
|
||||
check('package3:submodule.B.attr')
|
||||
check_error('package3:submodule.A.attr')
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_name_resolution_import_rebinding2(self):
|
||||
path = os.path.join(os.path.dirname(test.__file__), 'test_import', 'data')
|
||||
def check(name):
|
||||
@@ -2016,8 +2012,7 @@ class PatchTest(unittest.TestCase):
|
||||
self.assertEqual(dic2, origdic2)
|
||||
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_special_attrs(self):
|
||||
def foo(x=0):
|
||||
"""TEST"""
|
||||
|
||||
Vendored
+2
-19
@@ -51,10 +51,6 @@ __all__ = ['TestResult', 'TestCase', 'IsolatedAsyncioTestCase', 'TestSuite',
|
||||
'registerResult', 'removeResult', 'removeHandler',
|
||||
'addModuleCleanup', 'doModuleCleanups', 'enterModuleContext']
|
||||
|
||||
# Expose obsolete functions for backwards compatibility
|
||||
# bpo-5846: Deprecated in Python 3.11, scheduled for removal in Python 3.13.
|
||||
__all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases'])
|
||||
|
||||
__unittest = True
|
||||
|
||||
from .result import TestResult
|
||||
@@ -67,20 +63,6 @@ from .main import TestProgram, main
|
||||
from .runner import TextTestRunner, TextTestResult
|
||||
from .signals import installHandler, registerResult, removeResult, removeHandler
|
||||
# IsolatedAsyncioTestCase will be imported lazily.
|
||||
from .loader import makeSuite, getTestCaseNames, findTestCases
|
||||
|
||||
# deprecated
|
||||
_TextTestResult = TextTestResult
|
||||
|
||||
|
||||
# There are no tests here, so don't try to run anything discovered from
|
||||
# introspecting the symbols (e.g. FunctionTestCase). Instead, all our
|
||||
# tests come from within unittest.test.
|
||||
def load_tests(loader, tests, pattern):
|
||||
import os.path
|
||||
# top level directory cached on loader instance
|
||||
this_dir = os.path.dirname(__file__)
|
||||
return loader.discover(start_dir=this_dir, pattern=pattern)
|
||||
|
||||
|
||||
# Lazy import of IsolatedAsyncioTestCase from .async_case
|
||||
@@ -98,6 +80,7 @@ def __getattr__(name):
|
||||
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
||||
|
||||
|
||||
|
||||
# XXX: RUSTPYTHON
|
||||
# This is very useful to reduce platform difference boilerplates in tests.
|
||||
def expectedFailureIf(condition, reason):
|
||||
@@ -111,4 +94,4 @@ def expectedFailureIf(condition, reason):
|
||||
# Even more useful because most of them are windows only.
|
||||
def expectedFailureIfWindows(reason):
|
||||
import sys
|
||||
return expectedFailureIf(sys.platform == 'win32', reason)
|
||||
return expectedFailureIf(sys.platform == 'win32', reason)
|
||||
Vendored
+6
-2
@@ -5,6 +5,7 @@ import warnings
|
||||
|
||||
from .case import TestCase
|
||||
|
||||
__unittest = True
|
||||
|
||||
class IsolatedAsyncioTestCase(TestCase):
|
||||
# Names intentionally have a long prefix
|
||||
@@ -25,12 +26,15 @@ class IsolatedAsyncioTestCase(TestCase):
|
||||
# them inside the same task.
|
||||
|
||||
# Note: the test case modifies event loop policy if the policy was not instantiated
|
||||
# yet.
|
||||
# yet, unless loop_factory=asyncio.EventLoop is set.
|
||||
# asyncio.get_event_loop_policy() creates a default policy on demand but never
|
||||
# returns None
|
||||
# I believe this is not an issue in user level tests but python itself for testing
|
||||
# should reset a policy in every test module
|
||||
# by calling asyncio.set_event_loop_policy(None) in tearDownModule()
|
||||
# or set loop_factory=asyncio.EventLoop
|
||||
|
||||
loop_factory = None
|
||||
|
||||
def __init__(self, methodName='runTest'):
|
||||
super().__init__(methodName)
|
||||
@@ -118,7 +122,7 @@ class IsolatedAsyncioTestCase(TestCase):
|
||||
|
||||
def _setupAsyncioRunner(self):
|
||||
assert self._asyncioRunner is None, 'asyncio runner is already initialized'
|
||||
runner = asyncio.Runner(debug=True)
|
||||
runner = asyncio.Runner(debug=True, loop_factory=self.loop_factory)
|
||||
self._asyncioRunner = runner
|
||||
|
||||
def _tearDownAsyncioRunner(self):
|
||||
|
||||
Vendored
+25
-80
@@ -6,7 +6,6 @@ import sys
|
||||
import traceback
|
||||
import types
|
||||
import functools
|
||||
import warnings
|
||||
|
||||
from fnmatch import fnmatch, fnmatchcase
|
||||
|
||||
@@ -57,9 +56,7 @@ def _make_skipped_test(methodname, exception, suiteClass):
|
||||
TestClass = type("ModuleSkipped", (case.TestCase,), attrs)
|
||||
return suiteClass((TestClass(methodname),))
|
||||
|
||||
def _jython_aware_splitext(path):
|
||||
if path.lower().endswith('$py.class'):
|
||||
return path[:-9]
|
||||
def _splitext(path):
|
||||
return os.path.splitext(path)[0]
|
||||
|
||||
|
||||
@@ -87,40 +84,26 @@ class TestLoader(object):
|
||||
raise TypeError("Test cases should not be derived from "
|
||||
"TestSuite. Maybe you meant to derive from "
|
||||
"TestCase?")
|
||||
testCaseNames = self.getTestCaseNames(testCaseClass)
|
||||
if not testCaseNames and hasattr(testCaseClass, 'runTest'):
|
||||
testCaseNames = ['runTest']
|
||||
if testCaseClass in (case.TestCase, case.FunctionTestCase):
|
||||
# We don't load any tests from base types that should not be loaded.
|
||||
testCaseNames = []
|
||||
else:
|
||||
testCaseNames = self.getTestCaseNames(testCaseClass)
|
||||
if not testCaseNames and hasattr(testCaseClass, 'runTest'):
|
||||
testCaseNames = ['runTest']
|
||||
loaded_suite = self.suiteClass(map(testCaseClass, testCaseNames))
|
||||
return loaded_suite
|
||||
|
||||
# XXX After Python 3.5, remove backward compatibility hacks for
|
||||
# use_load_tests deprecation via *args and **kws. See issue 16662.
|
||||
def loadTestsFromModule(self, module, *args, pattern=None, **kws):
|
||||
def loadTestsFromModule(self, module, *, pattern=None):
|
||||
"""Return a suite of all test cases contained in the given module"""
|
||||
# This method used to take an undocumented and unofficial
|
||||
# use_load_tests argument. For backward compatibility, we still
|
||||
# accept the argument (which can also be the first position) but we
|
||||
# ignore it and issue a deprecation warning if it's present.
|
||||
if len(args) > 0 or 'use_load_tests' in kws:
|
||||
warnings.warn('use_load_tests is deprecated and ignored',
|
||||
DeprecationWarning)
|
||||
kws.pop('use_load_tests', None)
|
||||
if len(args) > 1:
|
||||
# Complain about the number of arguments, but don't forget the
|
||||
# required `module` argument.
|
||||
complaint = len(args) + 1
|
||||
raise TypeError('loadTestsFromModule() takes 1 positional argument but {} were given'.format(complaint))
|
||||
if len(kws) != 0:
|
||||
# Since the keyword arguments are unsorted (see PEP 468), just
|
||||
# pick the alphabetically sorted first argument to complain about,
|
||||
# if multiple were given. At least the error message will be
|
||||
# predictable.
|
||||
complaint = sorted(kws)[0]
|
||||
raise TypeError("loadTestsFromModule() got an unexpected keyword argument '{}'".format(complaint))
|
||||
tests = []
|
||||
for name in dir(module):
|
||||
obj = getattr(module, name)
|
||||
if isinstance(obj, type) and issubclass(obj, case.TestCase):
|
||||
if (
|
||||
isinstance(obj, type)
|
||||
and issubclass(obj, case.TestCase)
|
||||
and obj not in (case.TestCase, case.FunctionTestCase)
|
||||
):
|
||||
tests.append(self.loadTestsFromTestCase(obj))
|
||||
|
||||
load_tests = getattr(module, 'load_tests', None)
|
||||
@@ -189,7 +172,11 @@ class TestLoader(object):
|
||||
|
||||
if isinstance(obj, types.ModuleType):
|
||||
return self.loadTestsFromModule(obj)
|
||||
elif isinstance(obj, type) and issubclass(obj, case.TestCase):
|
||||
elif (
|
||||
isinstance(obj, type)
|
||||
and issubclass(obj, case.TestCase)
|
||||
and obj not in (case.TestCase, case.FunctionTestCase)
|
||||
):
|
||||
return self.loadTestsFromTestCase(obj)
|
||||
elif (isinstance(obj, types.FunctionType) and
|
||||
isinstance(parent, type) and
|
||||
@@ -267,6 +254,7 @@ class TestLoader(object):
|
||||
Paths are sorted before being imported to ensure reproducible execution
|
||||
order even on filesystems with non-alphabetical ordering like ext3/4.
|
||||
"""
|
||||
original_top_level_dir = self._top_level_dir
|
||||
set_implicit_top = False
|
||||
if top_level_dir is None and self._top_level_dir is not None:
|
||||
# make top_level_dir optional if called from load_tests in a package
|
||||
@@ -320,6 +308,7 @@ class TestLoader(object):
|
||||
raise ImportError('Start directory is not importable: %r' % start_dir)
|
||||
|
||||
tests = list(self._find_tests(start_dir, pattern))
|
||||
self._top_level_dir = original_top_level_dir
|
||||
return self.suiteClass(tests)
|
||||
|
||||
def _get_directory_containing_module(self, module_name):
|
||||
@@ -337,7 +326,7 @@ class TestLoader(object):
|
||||
def _get_name_from_path(self, path):
|
||||
if path == self._top_level_dir:
|
||||
return '.'
|
||||
path = _jython_aware_splitext(os.path.normpath(path))
|
||||
path = _splitext(os.path.normpath(path))
|
||||
|
||||
_relpath = os.path.relpath(path, self._top_level_dir)
|
||||
assert not os.path.isabs(_relpath), "Path must be within the project"
|
||||
@@ -415,13 +404,13 @@ class TestLoader(object):
|
||||
else:
|
||||
mod_file = os.path.abspath(
|
||||
getattr(module, '__file__', full_path))
|
||||
realpath = _jython_aware_splitext(
|
||||
realpath = _splitext(
|
||||
os.path.realpath(mod_file))
|
||||
fullpath_noext = _jython_aware_splitext(
|
||||
fullpath_noext = _splitext(
|
||||
os.path.realpath(full_path))
|
||||
if realpath.lower() != fullpath_noext.lower():
|
||||
module_dir = os.path.dirname(realpath)
|
||||
mod_name = _jython_aware_splitext(
|
||||
mod_name = _splitext(
|
||||
os.path.basename(full_path))
|
||||
expected_dir = os.path.dirname(full_path)
|
||||
msg = ("%r module incorrectly imported from %r. Expected "
|
||||
@@ -462,47 +451,3 @@ class TestLoader(object):
|
||||
|
||||
|
||||
defaultTestLoader = TestLoader()
|
||||
|
||||
|
||||
# These functions are considered obsolete for long time.
|
||||
# They will be removed in Python 3.13.
|
||||
|
||||
def _makeLoader(prefix, sortUsing, suiteClass=None, testNamePatterns=None):
|
||||
loader = TestLoader()
|
||||
loader.sortTestMethodsUsing = sortUsing
|
||||
loader.testMethodPrefix = prefix
|
||||
loader.testNamePatterns = testNamePatterns
|
||||
if suiteClass:
|
||||
loader.suiteClass = suiteClass
|
||||
return loader
|
||||
|
||||
def getTestCaseNames(testCaseClass, prefix, sortUsing=util.three_way_cmp, testNamePatterns=None):
|
||||
import warnings
|
||||
warnings.warn(
|
||||
"unittest.getTestCaseNames() is deprecated and will be removed in Python 3.13. "
|
||||
"Please use unittest.TestLoader.getTestCaseNames() instead.",
|
||||
DeprecationWarning, stacklevel=2
|
||||
)
|
||||
return _makeLoader(prefix, sortUsing, testNamePatterns=testNamePatterns).getTestCaseNames(testCaseClass)
|
||||
|
||||
def makeSuite(testCaseClass, prefix='test', sortUsing=util.three_way_cmp,
|
||||
suiteClass=suite.TestSuite):
|
||||
import warnings
|
||||
warnings.warn(
|
||||
"unittest.makeSuite() is deprecated and will be removed in Python 3.13. "
|
||||
"Please use unittest.TestLoader.loadTestsFromTestCase() instead.",
|
||||
DeprecationWarning, stacklevel=2
|
||||
)
|
||||
return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(
|
||||
testCaseClass)
|
||||
|
||||
def findTestCases(module, prefix='test', sortUsing=util.three_way_cmp,
|
||||
suiteClass=suite.TestSuite):
|
||||
import warnings
|
||||
warnings.warn(
|
||||
"unittest.findTestCases() is deprecated and will be removed in Python 3.13. "
|
||||
"Please use unittest.TestLoader.loadTestsFromModule() instead.",
|
||||
DeprecationWarning, stacklevel=2
|
||||
)
|
||||
return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(\
|
||||
module)
|
||||
Vendored
+5
-5
@@ -269,12 +269,12 @@ class TestProgram(object):
|
||||
testRunner = self.testRunner
|
||||
self.result = testRunner.run(self.test)
|
||||
if self.exit:
|
||||
if self.result.testsRun == 0 and len(self.result.skipped) == 0:
|
||||
sys.exit(_NO_TESTS_EXITCODE)
|
||||
elif self.result.wasSuccessful():
|
||||
sys.exit(0)
|
||||
else:
|
||||
if not self.result.wasSuccessful():
|
||||
sys.exit(1)
|
||||
elif self.result.testsRun == 0 and len(self.result.skipped) == 0:
|
||||
sys.exit(_NO_TESTS_EXITCODE)
|
||||
else:
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
main = TestProgram
|
||||
Reference in new issue
Block a user