From: DongHun Kwak Date: Thu, 18 Mar 2021 02:33:40 +0000 (+0900) Subject: Imported Upstream version 6.0.2 X-Git-Tag: upstream/6.0.2^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=19a1d91e7b078503a8da87e437290016cdb3f722;p=platform%2Fupstream%2Fpython3-pytest.git Imported Upstream version 6.0.2 --- diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 49d7a04..e011aaa 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-6.0.2 release-6.0.1 release-6.0.0 release-6.0.0rc1 diff --git a/doc/en/announce/release-6.0.2.rst b/doc/en/announce/release-6.0.2.rst new file mode 100644 index 0000000..16eabc5 --- /dev/null +++ b/doc/en/announce/release-6.0.2.rst @@ -0,0 +1,19 @@ +pytest-6.0.2 +======================================= + +pytest 6.0.2 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Bruno Oliveira +* Ran Benita + + +Happy testing, +The pytest Development Team diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 7516b53..feb113e 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,25 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 6.0.2 (2020-09-04) +========================= + +Bug Fixes +--------- + +- `#7148 `_: Fixed ``--log-cli`` potentially causing unrelated ``print`` output to be swallowed. + + +- `#7672 `_: Fixed log-capturing level restored incorrectly if ``caplog.set_level`` is called more than once. + + +- `#7686 `_: Fixed `NotSetType.token` being used as the parameter ID when the parametrization list is empty. + Regressed in pytest 6.0.0. + + +- `#7707 `_: Fix internal error when handling some exceptions that contain multiple lines or the style uses multiple lines (``--tb=line`` for example). + + pytest 6.0.1 (2020-07-30) ========================= @@ -212,9 +231,9 @@ Breaking Changes - `#7224 `_: The `item.catch_log_handler` and `item.catch_log_handlers` attributes, set by the - logging plugin and never meant to be public , are no longer available. + logging plugin and never meant to be public, are no longer available. - The deprecated ``--no-print-logs`` option is removed. Use ``--show-capture`` instead. + The deprecated ``--no-print-logs`` option and ``log_print`` ini option are removed. Use ``--show-capture`` instead. - `#7226 `_: Removed the unused ``args`` parameter from ``pytest.Function.__init__``. diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index a2bed18..3334b5d 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -51,9 +51,10 @@ a public API and may break in the future. .. versionremoved:: 6.0 -Option ``--no-print-logs`` is removed. If you used ``--no-print-logs``, please use ``--show-capture`` instead. +The ``--no-print-logs`` option and ``log_print`` ini setting are removed. If +you used them, please use ``--show-capture`` instead. -``--show-capture`` command-line option was added in ``pytest 3.5.0`` and allows to specify how to +A ``--show-capture`` command-line option was added in ``pytest 3.5.0`` which allows to specify how to display captured output when tests fail: ``no``, ``stdout``, ``stderr``, ``log`` or ``all`` (the default). diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index c160191..caca6f5 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -28,7 +28,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 6.0.1 + pytest 6.0.2 .. _`simpletest`: diff --git a/doc/en/reference.rst b/doc/en/reference.rst index 775dd55..7f99cdc 100644 --- a/doc/en/reference.rst +++ b/doc/en/reference.rst @@ -783,12 +783,19 @@ ExceptionInfo :members: -pytest.ExitCode -~~~~~~~~~~~~~~~ +ExitCode +~~~~~~~~ .. autoclass:: _pytest.config.ExitCode :members: +File +~~~~ + +.. autoclass:: _pytest.nodes.File() + :members: + :show-inheritance: + FixtureDef ~~~~~~~~~~ @@ -1466,20 +1473,6 @@ passed multiple times. The expected format is ``name=value``. For example:: For more information, see :ref:`logging`. -.. confval:: log_print - - - - If set to ``False``, will disable displaying captured logging messages for failed tests. - - .. code-block:: ini - - [pytest] - log_print = False - - For more information, see :ref:`logging`. - - .. confval:: markers When the ``--strict-markers`` or ``--strict`` command-line arguments are used, diff --git a/scripts/release.minor.rst b/scripts/release.minor.rst index f71f9b1..76e447f 100644 --- a/scripts/release.minor.rst +++ b/scripts/release.minor.rst @@ -3,23 +3,20 @@ pytest-{version} The pytest team is proud to announce the {version} release! -pytest is a mature Python testing tool with more than a 2000 tests -against itself, passing on many different interpreters and platforms. +This release contains new features, improvements, bug fixes, and breaking changes, so users +are encouraged to take a look at the CHANGELOG carefully: -This release contains a number of bug fixes and improvements, so users are encouraged -to take a look at the CHANGELOG: - - https://docs.pytest.org/en/latest/changelog.html + https://docs.pytest.org/en/stable/changelog.html For complete documentation, please visit: - https://docs.pytest.org/en/latest/ + https://docs.pytest.org/en/stable/ As usual, you can upgrade from PyPI via: pip install -U pytest -Thanks to all who contributed to this release, among them: +Thanks to all of the contributors to this release: {contributors} diff --git a/scripts/release.patch.rst b/scripts/release.patch.rst index b1ad2db..59fbe50 100644 --- a/scripts/release.patch.rst +++ b/scripts/release.patch.rst @@ -7,9 +7,9 @@ This is a bug-fix release, being a drop-in replacement. To upgrade:: pip install --upgrade pytest -The full changelog is available at https://docs.pytest.org/en/latest/changelog.html. +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. -Thanks to all who contributed to this release, among them: +Thanks to all of the contributors to this release: {contributors} diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 219ebb6..14a4681 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -1038,25 +1038,21 @@ class ReprEntry(TerminalRepr): # such as "> assert 0" fail_marker = "{} ".format(FormattedExcinfo.fail_marker) indent_size = len(fail_marker) - indents = [] - source_lines = [] - failure_lines = [] - seeing_failures = False - for line in self.lines: - is_source_line = not line.startswith(fail_marker) - if is_source_line: - assert not seeing_failures, ( - "Unexpected failure lines between source lines:\n" - + "\n".join(self.lines) - ) + indents = [] # type: List[str] + source_lines = [] # type: List[str] + failure_lines = [] # type: List[str] + for index, line in enumerate(self.lines): + is_failure_line = line.startswith(fail_marker) + if is_failure_line: + # from this point on all lines are considered part of the failure + failure_lines.extend(self.lines[index:]) + break + else: if self.style == "value": source_lines.append(line) else: indents.append(line[:indent_size]) source_lines.append(line[indent_size:]) - else: - seeing_failures = True - failure_lines.append(line) tw._write_source(source_lines, indents) diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index f538b67..a20d14f 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -537,7 +537,7 @@ class MultiCapture: self._in_suspended = True def resume_capturing(self) -> None: - self._state = "resumed" + self._state = "started" if self.out: self.out.resume() if self.err: @@ -558,6 +558,10 @@ class MultiCapture: if self.in_: self.in_.done() + def is_started(self) -> bool: + """Whether actively capturing -- not suspended or stopped.""" + return self._state == "started" + def readouterr(self) -> CaptureResult: if self.out: out = self.out.snap() @@ -697,11 +701,19 @@ class CaptureManager: @contextlib.contextmanager def global_and_fixture_disabled(self) -> Generator[None, None, None]: """Context manager to temporarily disable global and current fixture capturing.""" - self.suspend() + do_fixture = self._capture_fixture and self._capture_fixture._is_started() + if do_fixture: + self.suspend_fixture() + do_global = self._global_capturing and self._global_capturing.is_started() + if do_global: + self.suspend_global_capture() try: yield finally: - self.resume() + if do_global: + self.resume_global_capture() + if do_fixture: + self.resume_fixture() @contextlib.contextmanager def item_capture(self, when: str, item: Item) -> Generator[None, None, None]: @@ -810,6 +822,12 @@ class CaptureFixture: if self._capture is not None: self._capture.resume_capturing() + def _is_started(self) -> bool: + """Whether actively capturing -- not disabled or closed.""" + if self._capture is not None: + return self._capture.is_started() + return False + @contextlib.contextmanager def disabled(self) -> Generator[None, None, None]: """Temporarily disables capture while inside the 'with' block.""" diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 0ee9457..6c42264 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -437,7 +437,8 @@ class LogCaptureFixture: # save the original log-level to restore it during teardown self._initial_logger_levels.setdefault(logger, logger_obj.level) logger_obj.setLevel(level) - self._initial_handler_level = self.handler.level + if self._initial_handler_level is None: + self._initial_handler_level = self.handler.level self.handler.setLevel(level) @contextmanager diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 560548a..91cf7e5 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -604,7 +604,10 @@ class FSCollector(Collector): class File(FSCollector): - """ base class for collecting tests from a file. """ + """Base class for collecting tests from a file. + + :ref:`non-python tests`. + """ class Item(Node): diff --git a/src/_pytest/python.py b/src/_pytest/python.py index aa81714..28c2dc8 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1254,6 +1254,9 @@ def _idval( return str(val) elif isinstance(val, REGEX_TYPE): return ascii_escaped(val.pattern) + elif val is NOTSET: + # Fallback to default. Note that NOTSET is an enum.Enum. + pass elif isinstance(val, enum.Enum): return str(val) elif isinstance(getattr(val, "__name__", None), str): diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 78b55e2..8eab319 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -4,6 +4,8 @@ import os import queue import sys import textwrap +from typing import Any +from typing import Dict from typing import Tuple from typing import Union @@ -1045,28 +1047,34 @@ raise ValueError() @pytest.mark.parametrize( "reproptions", [ - { - "style": style, - "showlocals": showlocals, - "funcargs": funcargs, - "tbfilter": tbfilter, - } - for style in ("long", "short", "no") + pytest.param( + { + "style": style, + "showlocals": showlocals, + "funcargs": funcargs, + "tbfilter": tbfilter, + }, + id="style={},showlocals={},funcargs={},tbfilter={}".format( + style, showlocals, funcargs, tbfilter + ), + ) + for style in ["long", "short", "line", "no", "native", "value", "auto"] for showlocals in (True, False) for tbfilter in (True, False) for funcargs in (True, False) ], ) - def test_format_excinfo(self, importasmod, reproptions): - mod = importasmod( - """ - def g(x): - raise ValueError(x) - def f(): - g(3) - """ - ) - excinfo = pytest.raises(ValueError, mod.f) + def test_format_excinfo(self, reproptions: Dict[str, Any]) -> None: + def bar(): + assert False, "some error" + + def foo(): + bar() + + # using inline functions as opposed to importasmod so we get source code lines + # in the tracebacks (otherwise getinspect doesn't find the source code). + with pytest.raises(AssertionError) as excinfo: + foo() file = io.StringIO() tw = TerminalWriter(file=file) repr = excinfo.getrepr(**reproptions) diff --git a/testing/logging/test_fixture.py b/testing/logging/test_fixture.py index 6e5e9c2..f18d708 100644 --- a/testing/logging/test_fixture.py +++ b/testing/logging/test_fixture.py @@ -65,6 +65,7 @@ def test_change_level_undos_handler_level(testdir: Testdir) -> None: def test1(caplog): assert caplog.handler.level == 0 + caplog.set_level(9999) caplog.set_level(41) assert caplog.handler.level == 41 diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 4e6cfaf..5d93515 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -19,6 +19,7 @@ from hypothesis import strategies import pytest from _pytest import fixtures from _pytest import python +from _pytest.compat import NOTSET from _pytest.outcomes import fail from _pytest.pytester import Testdir from _pytest.python import _idval @@ -363,6 +364,14 @@ class TestMetafunc: for val, expected in values: assert _idval(val, "a", 6, None, nodeid=None, config=None) == expected + def test_notset_idval(self) -> None: + """Test that a NOTSET value (used by an empty parameterset) generates + a proper ID. + + Regression test for #7686. + """ + assert _idval(NOTSET, "a", 0, None, nodeid=None, config=None) == "a0" + def test_idmaker_autoname(self) -> None: """#250""" result = idmaker( diff --git a/testing/test_capture.py b/testing/test_capture.py index bc89501..678bc18 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -16,6 +16,7 @@ from _pytest.capture import _get_multicapture from _pytest.capture import CaptureManager from _pytest.capture import MultiCapture from _pytest.config import ExitCode +from _pytest.pytester import Testdir # note: py.io capture tests where copied from # pylib 1.4.20.dev2 (rev 13d9af95547e) @@ -633,6 +634,34 @@ class TestCaptureFixture: else: result.stdout.no_fnmatch_line("*test_normal executed*") + def test_disabled_capture_fixture_twice(self, testdir: Testdir) -> None: + """Test that an inner disabled() exit doesn't undo an outer disabled(). + + Issue #7148. + """ + testdir.makepyfile( + """ + def test_disabled(capfd): + print('captured before') + with capfd.disabled(): + print('while capture is disabled 1') + with capfd.disabled(): + print('while capture is disabled 2') + print('while capture is disabled 1 after') + print('captured after') + assert capfd.readouterr() == ('captured before\\ncaptured after\\n', '') + """ + ) + result = testdir.runpytest_subprocess() + result.stdout.fnmatch_lines( + [ + "*while capture is disabled 1", + "*while capture is disabled 2", + "*while capture is disabled 1 after", + ], + consecutive=True, + ) + @pytest.mark.parametrize("fixture", ["capsys", "capfd"]) def test_fixture_use_by_other_fixtures(self, testdir, fixture): """