Merge pull request #8639 from mgorny/backport-8494-8555

This commit is contained in:
Bruno Oliveira 2021-05-06 16:01:16 -03:00 committed by GitHub
commit 8317542c9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 95 additions and 44 deletions

View File

@ -27,6 +27,8 @@ jobs:
"windows-py37",
"windows-py37-pluggy",
"windows-py38",
"windows-py39",
"windows-py310",
"ubuntu-py36",
"ubuntu-py37",
@ -34,6 +36,7 @@ jobs:
"ubuntu-py37-freeze",
"ubuntu-py38",
"ubuntu-py39",
"ubuntu-py310",
"ubuntu-pypy3",
"macos-py37",
@ -62,6 +65,14 @@ jobs:
os: windows-latest
tox_env: "py38-unittestextras"
use_coverage: true
- name: "windows-py39"
python: "3.9"
os: windows-latest
tox_env: "py39-xdist"
- name: "windows-py310"
python: "3.10-dev"
os: windows-latest
tox_env: "py310-xdist"
- name: "ubuntu-py36"
python: "3.6"
@ -88,6 +99,10 @@ jobs:
python: "3.9"
os: ubuntu-latest
tox_env: "py39-xdist"
- name: "ubuntu-py310"
python: "3.10-dev"
os: ubuntu-latest
tox_env: "py310-xdist"
- name: "ubuntu-pypy3"
python: "pypy3"
os: ubuntu-latest

View File

@ -39,11 +39,10 @@ repos:
- id: pyupgrade
args: [--py36-plus]
- repo: https://github.com/asottile/setup-cfg-fmt
rev: v1.11.0
rev: v1.17.0
hooks:
- id: setup-cfg-fmt
# TODO: when upgrading setup-cfg-fmt this can be removed
args: [--max-py-version=3.9]
args: [--max-py-version=3.10]
- repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.6.0
hooks:

View File

@ -0,0 +1 @@
Python 3.10 is now supported.

View File

@ -26,6 +26,8 @@ filterwarnings = [
# produced by older pyparsing<=2.2.0.
"default:Using or importing the ABCs:DeprecationWarning:pyparsing.*",
"default:the imp module is deprecated in favour of importlib:DeprecationWarning:nose.*",
# distutils is deprecated in 3.10, scheduled for removal in 3.12
"ignore:The distutils package is deprecated:DeprecationWarning",
# produced by python3.6/site.py itself (3.6.7 on Travis, could not trigger it with 3.6.8)."
"ignore:.*U.*mode is deprecated:DeprecationWarning:(?!(pytest|_pytest))",
# produced by pytest-xdist
@ -40,6 +42,14 @@ filterwarnings = [
"default:invalid escape sequence:DeprecationWarning",
# ignore use of unregistered marks, because we use many to test the implementation
"ignore::_pytest.warning_types.PytestUnknownMarkWarning",
# https://github.com/benjaminp/six/issues/341
"ignore:_SixMetaPathImporter\\.exec_module\\(\\) not found; falling back to load_module\\(\\):ImportWarning",
# https://github.com/benjaminp/six/pull/352
"ignore:_SixMetaPathImporter\\.find_spec\\(\\) not found; falling back to find_module\\(\\):ImportWarning",
# https://github.com/pypa/setuptools/pull/2517
"ignore:VendorImporter\\.find_spec\\(\\) not found; falling back to find_module\\(\\):ImportWarning",
# https://github.com/pytest-dev/execnet/pull/127
"ignore:isSet\\(\\) is deprecated, use is_set\\(\\) instead:DeprecationWarning",
]
pytester_example_dir = "testing/example_scripts"
markers = [

View File

@ -21,6 +21,7 @@ classifiers =
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Topic :: Software Development :: Libraries
Topic :: Software Development :: Testing
Topic :: Utilities

View File

@ -1173,7 +1173,7 @@ def test_usage_error_code(pytester: Pytester) -> None:
assert result.ret == ExitCode.USAGE_ERROR
@pytest.mark.filterwarnings("default")
@pytest.mark.filterwarnings("default::pytest.PytestUnhandledCoroutineWarning")
def test_warn_on_async_function(pytester: Pytester) -> None:
# In the below we .close() the coroutine only to avoid
# "RuntimeWarning: coroutine 'test_2' was never awaited"
@ -1206,7 +1206,7 @@ def test_warn_on_async_function(pytester: Pytester) -> None:
)
@pytest.mark.filterwarnings("default")
@pytest.mark.filterwarnings("default::pytest.PytestUnhandledCoroutineWarning")
def test_warn_on_async_gen_function(pytester: Pytester) -> None:
pytester.makepyfile(
test_async="""

View File

@ -1210,7 +1210,7 @@ def test_unorderable_types(testdir):
assert result.ret == ExitCode.NO_TESTS_COLLECTED
@pytest.mark.filterwarnings("default")
@pytest.mark.filterwarnings("default::pytest.PytestCollectionWarning")
def test_dont_collect_non_function_callable(testdir):
"""Test for issue https://github.com/pytest-dev/pytest/issues/331

View File

@ -448,7 +448,10 @@ class TestMetafunc:
enum = pytest.importorskip("enum")
e = enum.Enum("Foo", "one, two")
result = idmaker(("a", "b"), [pytest.param(e.one, e.two)])
assert result == ["Foo.one-Foo.two"]
if sys.version_info[:2] >= (3, 10):
assert result == ["one-two"]
else:
assert result == ["Foo.one-Foo.two"]
def test_idmaker_idfn(self) -> None:
"""#351"""

View File

@ -1212,7 +1212,7 @@ def test_collect_symlink_dir(pytester: Pytester) -> None:
"""A symlinked directory is collected."""
dir = pytester.mkdir("dir")
dir.joinpath("test_it.py").write_text("def test_it(): pass", "utf-8")
pytester.path.joinpath("symlink_dir").symlink_to(dir)
symlink_or_skip(pytester.path.joinpath("symlink_dir"), dir)
result = pytester.runpytest()
result.assert_outcomes(passed=2)

View File

@ -290,7 +290,7 @@ class TestParseIni:
result = pytester.runpytest()
result.stdout.no_fnmatch_line("*PytestConfigWarning*")
@pytest.mark.filterwarnings("default")
@pytest.mark.filterwarnings("default::pytest.PytestConfigWarning")
def test_disable_warnings_plugin_disables_config_warnings(
self, pytester: Pytester
) -> None:

View File

@ -741,10 +741,16 @@ def test_run_result_repr() -> None:
# known exit code
r = pytester.RunResult(1, outlines, errlines, duration=0.5)
assert (
repr(r) == "<RunResult ret=ExitCode.TESTS_FAILED len(stdout.lines)=3"
" len(stderr.lines)=4 duration=0.50s>"
)
if sys.version_info[:2] >= (3, 10):
assert repr(r) == (
"<RunResult ret=TESTS_FAILED len(stdout.lines)=3"
" len(stderr.lines)=4 duration=0.50s>"
)
else:
assert repr(r) == (
"<RunResult ret=ExitCode.TESTS_FAILED len(stdout.lines)=3"
" len(stderr.lines)=4 duration=0.50s>"
)
# unknown exit code: just the number
r = pytester.RunResult(99, outlines, errlines, duration=0.5)

View File

@ -1126,21 +1126,34 @@ def test_errors_in_xfail_skip_expressions(pytester: Pytester) -> None:
pypy_version_info = getattr(sys, "pypy_version_info", None)
if pypy_version_info is not None and pypy_version_info < (6,):
markline = markline[5:]
elif sys.version_info[:2] >= (3, 10):
markline = markline[11:]
elif sys.version_info >= (3, 8) or hasattr(sys, "pypy_version_info"):
markline = markline[4:]
result.stdout.fnmatch_lines(
[
if sys.version_info[:2] >= (3, 10):
expected = [
"*ERROR*test_nameerror*",
"*evaluating*skipif*condition*",
"*asd*",
"*ERROR*test_syntax*",
"*evaluating*xfail*condition*",
" syntax error",
markline,
"SyntaxError: invalid syntax",
"*1 pass*2 errors*",
"",
"During handling of the above exception, another exception occurred:",
]
)
else:
expected = [
"*ERROR*test_nameerror*",
]
expected += [
"*evaluating*skipif*condition*",
"*asd*",
"*ERROR*test_syntax*",
"*evaluating*xfail*condition*",
" syntax error",
markline,
"SyntaxError: invalid syntax",
"*1 pass*2 errors*",
]
result.stdout.fnmatch_lines(expected)
def test_xfail_skipif_with_globals(pytester: Pytester) -> None:

View File

@ -1618,7 +1618,7 @@ def test_terminal_summary(pytester: Pytester) -> None:
)
@pytest.mark.filterwarnings("default")
@pytest.mark.filterwarnings("default::UserWarning")
def test_terminal_summary_warnings_are_displayed(pytester: Pytester) -> None:
"""Test that warnings emitted during pytest_terminal_summary are displayed.
(#1305).
@ -1655,7 +1655,7 @@ def test_terminal_summary_warnings_are_displayed(pytester: Pytester) -> None:
assert stdout.count("=== warnings summary ") == 2
@pytest.mark.filterwarnings("default")
@pytest.mark.filterwarnings("default::UserWarning")
def test_terminal_summary_warnings_header_once(pytester: Pytester) -> None:
pytester.makepyfile(
"""

View File

@ -8,7 +8,7 @@ if sys.version_info < (3, 8):
pytest.skip("threadexception plugin needs Python>=3.8", allow_module_level=True)
@pytest.mark.filterwarnings("default")
@pytest.mark.filterwarnings("default::pytest.PytestUnhandledThreadExceptionWarning")
def test_unhandled_thread_exception(pytester: Pytester) -> None:
pytester.makepyfile(
test_it="""
@ -42,7 +42,7 @@ def test_unhandled_thread_exception(pytester: Pytester) -> None:
)
@pytest.mark.filterwarnings("default")
@pytest.mark.filterwarnings("default::pytest.PytestUnhandledThreadExceptionWarning")
def test_unhandled_thread_exception_in_setup(pytester: Pytester) -> None:
pytester.makepyfile(
test_it="""
@ -78,7 +78,7 @@ def test_unhandled_thread_exception_in_setup(pytester: Pytester) -> None:
)
@pytest.mark.filterwarnings("default")
@pytest.mark.filterwarnings("default::pytest.PytestUnhandledThreadExceptionWarning")
def test_unhandled_thread_exception_in_teardown(pytester: Pytester) -> None:
pytester.makepyfile(
test_it="""

View File

@ -8,7 +8,7 @@ if sys.version_info < (3, 8):
pytest.skip("unraisableexception plugin needs Python>=3.8", allow_module_level=True)
@pytest.mark.filterwarnings("default")
@pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning")
def test_unraisable(pytester: Pytester) -> None:
pytester.makepyfile(
test_it="""
@ -40,7 +40,7 @@ def test_unraisable(pytester: Pytester) -> None:
)
@pytest.mark.filterwarnings("default")
@pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning")
def test_unraisable_in_setup(pytester: Pytester) -> None:
pytester.makepyfile(
test_it="""
@ -76,7 +76,7 @@ def test_unraisable_in_setup(pytester: Pytester) -> None:
)
@pytest.mark.filterwarnings("default")
@pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning")
def test_unraisable_in_teardown(pytester: Pytester) -> None:
pytester.makepyfile(
test_it="""

View File

@ -38,7 +38,7 @@ def pyfile_with_warnings(testdir: Testdir, request: FixtureRequest) -> str:
return str(test_file)
@pytest.mark.filterwarnings("default")
@pytest.mark.filterwarnings("default::UserWarning", "default::RuntimeWarning")
def test_normal_flow(testdir, pyfile_with_warnings):
"""Check that the warnings section is displayed."""
result = testdir.runpytest(pyfile_with_warnings)
@ -55,7 +55,7 @@ def test_normal_flow(testdir, pyfile_with_warnings):
)
@pytest.mark.filterwarnings("always")
@pytest.mark.filterwarnings("always::UserWarning")
def test_setup_teardown_warnings(testdir):
testdir.makepyfile(
"""
@ -123,7 +123,7 @@ def test_ignore(testdir, pyfile_with_warnings, method):
assert WARNINGS_SUMMARY_HEADER not in result.stdout.str()
@pytest.mark.filterwarnings("always")
@pytest.mark.filterwarnings("always::UserWarning")
def test_unicode(testdir):
testdir.makepyfile(
"""
@ -182,7 +182,7 @@ def test_filterwarnings_mark(testdir, default_config):
testdir.makeini(
"""
[pytest]
filterwarnings = always
filterwarnings = always::RuntimeWarning
"""
)
testdir.makepyfile(
@ -202,7 +202,9 @@ def test_filterwarnings_mark(testdir, default_config):
warnings.warn(RuntimeWarning())
"""
)
result = testdir.runpytest("-W always" if default_config == "cmdline" else "")
result = testdir.runpytest(
"-W always::RuntimeWarning" if default_config == "cmdline" else ""
)
result.stdout.fnmatch_lines(["*= 1 failed, 2 passed, 1 warning in *"])
@ -217,7 +219,7 @@ def test_non_string_warning_argument(testdir):
warnings.warn(UserWarning(1, 'foo'))
"""
)
result = testdir.runpytest("-W", "always")
result = testdir.runpytest("-W", "always::UserWarning")
result.stdout.fnmatch_lines(["*= 1 passed, 1 warning in *"])
@ -236,7 +238,7 @@ def test_filterwarnings_mark_registration(testdir):
assert result.ret == 0
@pytest.mark.filterwarnings("always")
@pytest.mark.filterwarnings("always::UserWarning")
def test_warning_captured_hook(testdir):
testdir.makeconftest(
"""
@ -297,7 +299,7 @@ def test_warning_captured_hook(testdir):
assert collected_result[3] is None, str(collected)
@pytest.mark.filterwarnings("always")
@pytest.mark.filterwarnings("always::UserWarning")
def test_collection_warnings(testdir):
"""Check that we also capture warnings issued during test collection (#3251)."""
testdir.makepyfile(
@ -321,7 +323,7 @@ def test_collection_warnings(testdir):
)
@pytest.mark.filterwarnings("always")
@pytest.mark.filterwarnings("always::UserWarning")
def test_mark_regex_escape(testdir):
"""@pytest.mark.filterwarnings should not try to escape regex characters (#3936)"""
testdir.makepyfile(
@ -337,7 +339,7 @@ def test_mark_regex_escape(testdir):
assert WARNINGS_SUMMARY_HEADER not in result.stdout.str()
@pytest.mark.filterwarnings("default")
@pytest.mark.filterwarnings("default::pytest.PytestWarning")
@pytest.mark.parametrize("ignore_pytest_warnings", ["no", "ini", "cmdline"])
def test_hide_pytest_internal_warnings(testdir, ignore_pytest_warnings):
"""Make sure we can ignore internal pytest warnings using a warnings filter."""
@ -383,7 +385,7 @@ def test_option_precedence_cmdline_over_ini(testdir, ignore_on_cmdline):
testdir.makeini(
"""
[pytest]
filterwarnings = error
filterwarnings = error::UserWarning
"""
)
testdir.makepyfile(
@ -578,7 +580,7 @@ def test_warnings_checker_twice():
@pytest.mark.filterwarnings("ignore::pytest.PytestExperimentalApiWarning")
@pytest.mark.filterwarnings("always")
@pytest.mark.filterwarnings("always::UserWarning")
def test_group_warnings_by_message(testdir):
testdir.copy_example("warnings/test_group_warnings_by_message.py")
result = testdir.runpytest()
@ -610,7 +612,7 @@ def test_group_warnings_by_message(testdir):
@pytest.mark.filterwarnings("ignore::pytest.PytestExperimentalApiWarning")
@pytest.mark.filterwarnings("always")
@pytest.mark.filterwarnings("always::UserWarning")
def test_group_warnings_by_message_summary(testdir):
testdir.copy_example("warnings/test_group_warnings_by_message_summary")
testdir.syspathinsert()

View File

@ -9,6 +9,7 @@ envlist =
py37
py38
py39
py310
pypy3
py37-{pexpect,xdist,unittestextras,numpy,pluggymaster}
doctesting