From c55ca155e90caa2c2b890f3bd8c765c0dec1b438 Mon Sep 17 00:00:00 2001 From: Fabien ZARIFIAN Date: Sun, 4 Nov 2018 21:55:56 +0100 Subject: [PATCH 01/18] Update __init__.py #4304 --- src/_pytest/config/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 6fbf8144a..33c6aaac7 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -476,6 +476,8 @@ class PytestPluginManager(PluginManager): def consider_pluginarg(self, arg): if arg.startswith("no:"): name = arg[3:] + if name == "cacheprovider": + self.consider_pluginarg("no:stepwise") self.set_blocked(name) if not name.startswith("pytest_"): self.set_blocked("pytest_" + name) From a447dc86fb013b7d0fac49220c5e893e6a282372 Mon Sep 17 00:00:00 2001 From: Fabien ZARIFIAN Date: Mon, 5 Nov 2018 00:14:35 +0100 Subject: [PATCH 02/18] Add test to branch --- testing/test_pluginmanager.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/testing/test_pluginmanager.py b/testing/test_pluginmanager.py index 0bee415f2..81a3a291e 100644 --- a/testing/test_pluginmanager.py +++ b/testing/test_pluginmanager.py @@ -380,3 +380,20 @@ class TestPytestPluginManagerBootstrapming(object): pytestpm.consider_preparse(["xyz", "-p", "no:abc"]) l2 = pytestpm.get_plugins() assert 42 not in l2 + + def test_plugin_prevent_register_stepwise_on_cacheprovider_unregister(self, pytestpm): + """ From PR #4304 : The only way to unregister a module is documented at + the end of https://docs.pytest.org/en/latest/plugins.html. + + When unregister cacheprovider, then unregister stepwise too + """ + pytestpm.register(42, name="cacheprovider") + pytestpm.register(43, name="stepwise") + l1 = pytestpm.get_plugins() + assert 42 in l1 + assert 43 in l1 + pytestpm.consider_preparse(["xyz", "-p", "no:cacheprovider"]) + l2 = pytestpm.get_plugins() + assert 42 not in l2 + assert 43 not in l2 + From 1793ac38a93e02103ec7892b0458b4273fb75a2b Mon Sep 17 00:00:00 2001 From: Fabien ZARIFIAN Date: Mon, 5 Nov 2018 00:21:12 +0100 Subject: [PATCH 03/18] Update __init__.py --- src/_pytest/config/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 33c6aaac7..5f5ddd81c 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -476,6 +476,7 @@ class PytestPluginManager(PluginManager): def consider_pluginarg(self, arg): if arg.startswith("no:"): name = arg[3:] + # PR #4304 : remove stepwise if cacheprovider is blocked if name == "cacheprovider": self.consider_pluginarg("no:stepwise") self.set_blocked(name) From db70c758074ae29fc8b1519f00954f72c0354d41 Mon Sep 17 00:00:00 2001 From: Fabien ZARIFIAN Date: Mon, 5 Nov 2018 00:36:25 +0100 Subject: [PATCH 04/18] Create 4304.bugfix.rst --- changelog/4304.bugfix.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/4304.bugfix.rst diff --git a/changelog/4304.bugfix.rst b/changelog/4304.bugfix.rst new file mode 100644 index 000000000..cb71ea168 --- /dev/null +++ b/changelog/4304.bugfix.rst @@ -0,0 +1 @@ +The stepwise plugin must be blocked on cacheprovider plugin block request From 5f61f0d2cb4fbda9724306179353f3d85961507e Mon Sep 17 00:00:00 2001 From: Fabien ZARIFIAN Date: Mon, 5 Nov 2018 10:51:15 +0100 Subject: [PATCH 05/18] Update __init__.py As mentionned by @RonnyPfannschmidt, use set_blocked on module stepwise (and it's brother pytest_stepwise like consider_pluginarg method does) --- src/_pytest/config/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 5f5ddd81c..d27fd7d58 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -478,7 +478,9 @@ class PytestPluginManager(PluginManager): name = arg[3:] # PR #4304 : remove stepwise if cacheprovider is blocked if name == "cacheprovider": - self.consider_pluginarg("no:stepwise") + self.set_blocked("stepwise") + self.set_blocked("pytest_stepwise") + self.set_blocked(name) if not name.startswith("pytest_"): self.set_blocked("pytest_" + name) From 9a884f1ccb11c332cf57427c67476bc5f2ef66e4 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 7 Nov 2018 18:30:13 -0200 Subject: [PATCH 06/18] Improve changelog a bit --- changelog/4304.bugfix.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/4304.bugfix.rst b/changelog/4304.bugfix.rst index cb71ea168..7d4dc033e 100644 --- a/changelog/4304.bugfix.rst +++ b/changelog/4304.bugfix.rst @@ -1 +1 @@ -The stepwise plugin must be blocked on cacheprovider plugin block request +Block the ``stepwise`` plugin if ``cacheprovider`` is also blocked, as one depends on the other. From 17b8e2d45b0e7fefdd07487391ddef6795ce4a12 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 7 Nov 2018 18:32:23 -0200 Subject: [PATCH 07/18] Fix linting --- testing/test_pluginmanager.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/testing/test_pluginmanager.py b/testing/test_pluginmanager.py index 81a3a291e..8e35290b7 100644 --- a/testing/test_pluginmanager.py +++ b/testing/test_pluginmanager.py @@ -380,11 +380,13 @@ class TestPytestPluginManagerBootstrapming(object): pytestpm.consider_preparse(["xyz", "-p", "no:abc"]) l2 = pytestpm.get_plugins() assert 42 not in l2 - - def test_plugin_prevent_register_stepwise_on_cacheprovider_unregister(self, pytestpm): + + def test_plugin_prevent_register_stepwise_on_cacheprovider_unregister( + self, pytestpm + ): """ From PR #4304 : The only way to unregister a module is documented at the end of https://docs.pytest.org/en/latest/plugins.html. - + When unregister cacheprovider, then unregister stepwise too """ pytestpm.register(42, name="cacheprovider") @@ -396,4 +398,3 @@ class TestPytestPluginManagerBootstrapming(object): l2 = pytestpm.get_plugins() assert 42 not in l2 assert 43 not in l2 - From 91404db2849eb38fcbf47e46ebbac3e9c60c1023 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 7 Nov 2018 22:45:27 +0100 Subject: [PATCH 08/18] Fix TypeError in report_collect with _collect_report_last_write `_collect_report_last_write` might be None, when `pytest_collection` was not called before. Not sure if this indicates another problem, but it can be reproduced with `testing/test_collection.py::TestCollector::()::test_getcustomfile_roundtrip`. Fixes https://github.com/pytest-dev/pytest/issues/4329 --- changelog/4329.bugfix.rst | 1 + src/_pytest/terminal.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 changelog/4329.bugfix.rst diff --git a/changelog/4329.bugfix.rst b/changelog/4329.bugfix.rst new file mode 100644 index 000000000..6acfe7e61 --- /dev/null +++ b/changelog/4329.bugfix.rst @@ -0,0 +1 @@ +Fix TypeError in report_collect with _collect_report_last_write. diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index a00dc0842..dde2750be 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -497,7 +497,10 @@ class TerminalReporter(object): if not final: # Only write "collecting" report every 0.5s. t = time.time() - if self._collect_report_last_write > t - 0.5: + if ( + self._collect_report_last_write is not None + and self._collect_report_last_write > t - 0.5 + ): return self._collect_report_last_write = t From f48a26f59c448c55a83f83546949acddb073bd38 Mon Sep 17 00:00:00 2001 From: Fabien ZARIFIAN Date: Thu, 8 Nov 2018 08:12:08 +0100 Subject: [PATCH 09/18] Update AUTHORS --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index dabeb1c06..777eda324 100644 --- a/AUTHORS +++ b/AUTHORS @@ -76,6 +76,7 @@ Endre Galaczi Eric Hunsberger Eric Siegerman Erik M. Bray +Fabien Zarifian Fabio Zadrozny Feng Ma Florian Bruhin From bb8a8495ffc1e713c8208d53cb9ea3fac39bb83f Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 9 Nov 2018 00:32:56 +0100 Subject: [PATCH 10/18] Revert "Attempt to fix macosx build setup" This reverts commit 28dbffdaf26519c79c86df67347ef09c31abf6ae. Appears to be not necessary anymore: https://travis-ci.org/pytest-dev/pytest/jobs/452598885#L906 [skip appveyor] --- .travis.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 49c94b47e..00abca0b2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,11 +47,6 @@ jobs: env: TOXENV=py37 before_install: - brew update - # remove c++ include files because upgrading python as of 2018-10-23, also - # attempts to upgrade gcc, and it fails because the include files already - # exist. removing the include files is one of the solutions recommended by brew - # this workaround might not be necessary in the future - - rm '/usr/local/include/c++' - brew upgrade python - brew unlink python - brew link python From b494d3d1c11e94a3b2d83250e031205de53d8394 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 9 Nov 2018 01:16:55 +0100 Subject: [PATCH 11/18] tests: test_fileimport: improve reporting on failure --- testing/test_modimport.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/testing/test_modimport.py b/testing/test_modimport.py index 64e9d7261..cb5f5ccd3 100644 --- a/testing/test_modimport.py +++ b/testing/test_modimport.py @@ -19,13 +19,19 @@ def test_fileimport(modfile): # without needing the pytest namespace being set # this is critical for the initialization of xdist - res = subprocess.call( + p = subprocess.Popen( [ sys.executable, "-c", "import sys, py; py.path.local(sys.argv[1]).pyimport()", modfile.strpath, - ] + ], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, ) - if res: - pytest.fail("command result %s" % res) + (out, err) = p.communicate() + if p.returncode != 0: + pytest.fail( + "importing %s failed (exitcode %d): out=%r, err=%r" + % (modfile, p.returncode, out, err) + ) From 401a3cd1bcdcb997cf68e9ebe070059648799be0 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 9 Nov 2018 01:27:11 +0100 Subject: [PATCH 12/18] minor: improve FixtureDef.__repr__ Ref: https://github.com/pytest-dev/pytest/pull/4105#pullrequestreview-163486766 --- src/_pytest/fixtures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 73aed8371..124b611db 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -927,7 +927,7 @@ class FixtureDef(object): return hook.pytest_fixture_setup(fixturedef=self, request=request) def __repr__(self): - return "" % ( + return "" % ( self.argname, self.scope, self.baseid, From a0890f98d808b76e63d5fd5c9766367e051f5247 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 9 Nov 2018 01:31:53 +0100 Subject: [PATCH 13/18] tests: harden test_config_error --- testing/acceptance_test.py | 3 ++- testing/example_scripts/conftest_usageerror/conftest.py | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 8917de6b2..19d7946cf 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -27,8 +27,9 @@ class TestGeneralUsage(object): def test_config_error(self, testdir): testdir.copy_example("conftest_usageerror/conftest.py") result = testdir.runpytest(testdir.tmpdir) - assert result.ret != 0 + assert result.ret == EXIT_USAGEERROR result.stderr.fnmatch_lines(["*ERROR: hello"]) + result.stdout.fnmatch_lines(["*pytest_unconfigure_called"]) def test_root_conftest_syntax_error(self, testdir): testdir.makepyfile(conftest="raise SyntaxError\n") diff --git a/testing/example_scripts/conftest_usageerror/conftest.py b/testing/example_scripts/conftest_usageerror/conftest.py index 7d0d39d3a..8973e4252 100644 --- a/testing/example_scripts/conftest_usageerror/conftest.py +++ b/testing/example_scripts/conftest_usageerror/conftest.py @@ -2,3 +2,7 @@ def pytest_configure(config): import pytest raise pytest.UsageError("hello") + + +def pytest_unconfigure(config): + print("pytest_unconfigure_called") From 560c055b090c2cc951c687728ee84353126a53ab Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 9 Nov 2018 01:36:20 +0100 Subject: [PATCH 14/18] Session._collect: use reversed parts --- src/_pytest/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 1de5f656f..5b9a94998 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -495,9 +495,9 @@ class Session(nodes.FSCollector): # No point in finding packages when collecting doctests if not self.config.option.doctestmodules: pm = self.config.pluginmanager - for parent in argpath.parts(): + for parent in reversed(argpath.parts()): if pm._confcutdir and pm._confcutdir.relto(parent): - continue + break if parent.isdir(): pkginit = parent.join("__init__.py") From c1bde8e0a2de06bdcdf97687dfdc271ac2abd8eb Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 9 Nov 2018 01:37:51 +0100 Subject: [PATCH 15/18] minor: check bool before function call --- src/_pytest/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 5b9a94998..910812419 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -278,7 +278,7 @@ def pytest_ignore_collect(path, config): return True allow_in_venv = config.getoption("collect_in_virtualenv") - if _in_venv(path) and not allow_in_venv: + if not allow_in_venv and _in_venv(path): return True return False From 4a74d455dec43be8f73d670a2e850b0ed21c8f40 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 9 Nov 2018 01:44:53 +0100 Subject: [PATCH 16/18] minor: typos --- testing/logging/test_fixture.py | 2 +- testing/test_config.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/logging/test_fixture.py b/testing/logging/test_fixture.py index 7a815cf12..ff772e7ec 100644 --- a/testing/logging/test_fixture.py +++ b/testing/logging/test_fixture.py @@ -136,5 +136,5 @@ def test_caplog_captures_for_all_stages(caplog, logging_during_setup_and_teardow assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"] - # This reachers into private API, don't use this type of thing in real tests! + # This reaches into private API, don't use this type of thing in real tests! assert set(caplog._item.catch_log_handlers.keys()) == {"setup", "call"} diff --git a/testing/test_config.py b/testing/test_config.py index 82466df1f..1be266387 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -874,7 +874,7 @@ class TestRootdir(object): assert inifile == inifile @pytest.mark.parametrize("name", "setup.cfg tox.ini".split()) - def test_pytestini_overides_empty_other(self, tmpdir, name): + def test_pytestini_overrides_empty_other(self, tmpdir, name): inifile = tmpdir.ensure("pytest.ini") a = tmpdir.mkdir("a") a.ensure(name) From 859b3227739d345bace43a309eb2d2a098bc9ce3 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 9 Nov 2018 01:51:04 +0100 Subject: [PATCH 17/18] doc: improve/simplify doc for breakpoint behavior --- doc/en/usage.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/usage.rst b/doc/en/usage.rst index cc118fad8..08682d614 100644 --- a/doc/en/usage.rst +++ b/doc/en/usage.rst @@ -255,8 +255,8 @@ Pytest supports the use of ``breakpoint()`` with the following behaviours: - When ``breakpoint()`` is called and ``PYTHONBREAKPOINT`` is set to the default value, pytest will use the custom internal PDB trace UI instead of the system default ``Pdb``. - When tests are complete, the system will default back to the system ``Pdb`` trace UI. - - If ``--pdb`` is called on execution of pytest, the custom internal Pdb trace UI is used on both ``breakpoint()`` and failed tests/unhandled exceptions. - - If ``--pdbcls`` is used, the custom class debugger will be executed when a test fails (as expected within existing behaviour), but also when ``breakpoint()`` is called from within a test, the custom class debugger will be instantiated. + - With ``--pdb`` passed to pytest, the custom internal Pdb trace UI is used with both ``breakpoint()`` and failed tests/unhandled exceptions. + - ``--pdbcls`` can be used to specify a custom debugger class. .. _durations: From feccf532d21f823243fb89364114ddd6a055e5b9 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 9 Nov 2018 01:54:14 +0100 Subject: [PATCH 18/18] doc: improve runpytest_subprocess --- src/_pytest/pytester.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index ca24ff1b0..8d5a6b141 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -1160,11 +1160,11 @@ class Testdir(object): def runpytest_subprocess(self, *args, **kwargs): """Run pytest as a subprocess with given arguments. - Any plugins added to the :py:attr:`plugins` list will added using the - ``-p`` command line option. Additionally ``--basetemp`` is used put + Any plugins added to the :py:attr:`plugins` list will be added using the + ``-p`` command line option. Additionally ``--basetemp`` is used to put any temporary files and directories in a numbered directory prefixed - with "runpytest-" so they do not conflict with the normal numbered - pytest location for temporary files and directories. + with "runpytest-" to not conflict with the normal numbered pytest + location for temporary files and directories. :param args: the sequence of arguments to pass to the pytest subprocess :param timeout: the period in seconds after which to timeout and raise