Permalink
Comparing changes
Choose two branches to see what’s changed or to start a new pull request.
If you need to, you can also .
Open a pull request
Create a new pull request by comparing changes across two branches. If you need to, you can also .
- 7 commits
- 9 files changed
- 0 comments
- 2 contributors
Commits on Sep 26, 2020
Prepare release 6.1.0
Commits on Sep 27, 2020
Commits on Sep 30, 2020
findpaths: fix regression causing incorrect rootdir to be determined (cherry picked from commit b250c9d)
[6.1.x] findpaths: fix regression causing incorrect rootdir to be determined
Commits on Oct 03, 2020
Regressed in 6.1.0 in 62e249a. The `x` is an `str` but is expected to be a `pathlib.Path`. Not caught by mypy because `config.getini()` returns `Any`. Fix by just removing the `bestrelpath` call: - testpaths are always relative to the rootdir, it thus would be very unusual to specify an absolute path there. - The code was wrong even before the regression: `py.path.local`'s `bestrelpath` function expects a `py.path.local`, not an `str`. But it had some weird `try ... except AttributeError` fallback which just returns the argument, i.e. it was a no-op. So there is no behavior change. - It seems reasonable to me to just print the full path if that's what the ini specifies. (cherry picked from commit 61f80a7)
[6.1.x] terminal: fix crash in header reporting when absolute testpaths is used
Unified
Split
Showing
with
98 additions
and 23 deletions.
- +1 −0 doc/en/announce/index.rst
- +18 −0 doc/en/announce/release-6.1.1.rst
- +12 −0 doc/en/changelog.rst
- +1 −1 doc/en/getting-started.rst
- +22 −14 doc/en/writing_plugins.rst
- +2 −5 src/_pytest/config/findpaths.py
- +3 −3 src/_pytest/terminal.py
- +15 −0 testing/test_config.py
- +24 −0 testing/test_terminal.py
| @@ -6,6 +6,7 @@ Release announcements | ||
| :maxdepth: 2 | ||
|
|
||
|
|
||
| release-6.1.1 | ||
| release-6.1.0 | ||
| release-6.0.2 | ||
| release-6.0.1 | ||
| @@ -0,0 +1,18 @@ | ||
| pytest-6.1.1 | ||
| ======================================= | ||
|
|
||
| pytest 6.1.1 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: | ||
|
|
||
| * Ran Benita | ||
|
|
||
|
|
||
| Happy testing, | ||
| The pytest Development Team |
| @@ -28,6 +28,18 @@ with advance notice in the **Deprecations** section of releases. | ||
|
|
||
| .. towncrier release notes start | ||
| pytest 6.1.1 (2020-10-03) | ||
| ========================= | ||
|
|
||
| Bug Fixes | ||
| --------- | ||
|
|
||
| - `#7807 <https://github.com/pytest-dev/pytest/issues/7807>`_: Fixed regression in pytest 6.1.0 causing incorrect rootdir to be determined in some non-trivial cases where parent directories have config files as well. | ||
|
|
||
|
|
||
| - `#7814 <https://github.com/pytest-dev/pytest/issues/7814>`_: Fixed crash in header reporting when :confval:`testpaths` is used and contains absolute paths (regression in 6.1.0). | ||
|
|
||
|
|
||
| pytest 6.1.0 (2020-09-26) | ||
| ========================= | ||
|
|
||
| @@ -28,7 +28,7 @@ Install ``pytest`` | ||
| .. code-block:: bash | ||
| $ pytest --version | ||
| pytest 6.1.0 | ||
| pytest 6.1.1 | ||
| .. _`simpletest`: | ||
|
|
||
| @@ -33,26 +33,34 @@ Plugin discovery order at tool startup | ||
|
|
||
| ``pytest`` loads plugin modules at tool startup in the following way: | ||
|
|
||
| * by loading all builtin plugins | ||
| 1. by scanning the command line for the ``-p no:name`` option | ||
| and *blocking* that plugin from being loaded (even builtin plugins can | ||
| be blocked this way). This happens before normal command-line parsing. | ||
|
|
||
| * by loading all plugins registered through `setuptools entry points`_. | ||
| 2. by loading all builtin plugins. | ||
|
|
||
| * by pre-scanning the command line for the ``-p name`` option | ||
| and loading the specified plugin before actual command line parsing. | ||
| 3. by scanning the command line for the ``-p name`` option | ||
| and loading the specified plugin. This happens before normal command-line parsing. | ||
|
|
||
| * by loading all :file:`conftest.py` files as inferred by the command line | ||
| invocation: | ||
| 4. by loading all plugins registered through `setuptools entry points`_. | ||
|
|
||
| - if no test paths are specified use current dir as a test path | ||
| - if exists, load ``conftest.py`` and ``test*/conftest.py`` relative | ||
| to the directory part of the first test path. | ||
| 5. by loading all plugins specified through the :envvar:`PYTEST_PLUGINS` environment variable. | ||
|
|
||
| Note that pytest does not find ``conftest.py`` files in deeper nested | ||
| sub directories at tool startup. It is usually a good idea to keep | ||
| your ``conftest.py`` file in the top level test or project root directory. | ||
| 6. by loading all :file:`conftest.py` files as inferred by the command line | ||
| invocation: | ||
|
|
||
| * by recursively loading all plugins specified by the | ||
| :globalvar:`pytest_plugins` variable in ``conftest.py`` files | ||
| - if no test paths are specified, use the current dir as a test path | ||
| - if exists, load ``conftest.py`` and ``test*/conftest.py`` relative | ||
| to the directory part of the first test path. After the ``conftest.py`` | ||
| file is loaded, load all plugins specified in its | ||
| :globalvar:`pytest_plugins` variable if present. | ||
|
|
||
| Note that pytest does not find ``conftest.py`` files in deeper nested | ||
| sub directories at tool startup. It is usually a good idea to keep | ||
| your ``conftest.py`` file in the top level test or project root directory. | ||
|
|
||
| 7. by recursively loading all plugins specified by the | ||
| :globalvar:`pytest_plugins` variable in ``conftest.py`` files. | ||
|
|
||
|
|
||
| .. _`pytest/plugin`: http://bitbucket.org/pytest-dev/pytest/src/tip/pytest/plugin/ | ||
| @@ -1,4 +1,3 @@ | ||
| import itertools | ||
| import os | ||
| from typing import Dict | ||
| from typing import Iterable | ||
| @@ -100,7 +99,7 @@ def locate_config( | ||
| args = [Path.cwd()] | ||
| for arg in args: | ||
| argpath = absolutepath(arg) | ||
| for base in itertools.chain((argpath,), reversed(argpath.parents)): | ||
| for base in (argpath, *argpath.parents): | ||
| for config_name in config_names: | ||
| p = base / config_name | ||
| if p.is_file(): | ||
| @@ -184,9 +183,7 @@ def determine_setup( | ||
| ancestor = get_common_ancestor(dirs) | ||
| rootdir, inipath, inicfg = locate_config([ancestor]) | ||
| if rootdir is None and rootdir_cmd_arg is None: | ||
| for possible_rootdir in itertools.chain( | ||
| (ancestor,), reversed(ancestor.parents) | ||
| ): | ||
| for possible_rootdir in (ancestor, *ancestor.parents): | ||
| if (possible_rootdir / "setup.py").is_file(): | ||
| rootdir = possible_rootdir | ||
| break | ||
| @@ -718,10 +718,10 @@ def pytest_report_header(self, config: Config) -> List[str]: | ||
| if config.inipath: | ||
| line += ", configfile: " + bestrelpath(config.rootpath, config.inipath) | ||
|
|
||
| testpaths = config.getini("testpaths") | ||
| testpaths = config.getini("testpaths") # type: List[str] | ||
| if testpaths and config.args == testpaths: | ||
| rel_paths = [bestrelpath(config.rootpath, x) for x in testpaths] | ||
| line += ", testpaths: {}".format(", ".join(rel_paths)) | ||
| line += ", testpaths: {}".format(", ".join(testpaths)) | ||
|
|
||
| result = [line] | ||
|
|
||
| plugininfo = config.pluginmanager.list_plugin_distinfo() | ||
| @@ -1375,6 +1375,21 @@ def test_with_existing_file_in_subdir( | ||
| assert rootpath == tmp_path | ||
| assert inipath is None | ||
|
|
||
| def test_with_config_also_in_parent_directory( | ||
| self, tmp_path: Path, monkeypatch: MonkeyPatch | ||
| ) -> None: | ||
| """Regression test for #7807.""" | ||
| (tmp_path / "setup.cfg").write_text("[tool:pytest]\n", "utf-8") | ||
| (tmp_path / "myproject").mkdir() | ||
| (tmp_path / "myproject" / "setup.cfg").write_text("[tool:pytest]\n", "utf-8") | ||
| (tmp_path / "myproject" / "tests").mkdir() | ||
| monkeypatch.chdir(tmp_path / "myproject") | ||
|
|
||
| rootpath, inipath, _ = determine_setup(None, ["tests/"]) | ||
|
|
||
| assert rootpath == tmp_path / "myproject" | ||
| assert inipath == tmp_path / "myproject" / "setup.cfg" | ||
|
|
||
|
|
||
| class TestOverrideIniArgs: | ||
| @pytest.mark.parametrize("name", "setup.cfg tox.ini pytest.ini".split()) | ||
| @@ -18,6 +18,7 @@ | ||
| from _pytest._io.wcwidth import wcswidth | ||
| from _pytest.config import Config | ||
| from _pytest.config import ExitCode | ||
| from _pytest.monkeypatch import MonkeyPatch | ||
| from _pytest.pathlib import Path | ||
| from _pytest.pytester import Testdir | ||
| from _pytest.reports import BaseReport | ||
| @@ -749,6 +750,29 @@ def test_header(self, testdir): | ||
| result = testdir.runpytest("tests") | ||
| result.stdout.fnmatch_lines(["rootdir: *test_header0, configfile: tox.ini"]) | ||
|
|
||
| def test_header_absolute_testpath( | ||
| self, testdir: Testdir, monkeypatch: MonkeyPatch | ||
| ) -> None: | ||
| """Regresstion test for #7814.""" | ||
| tests = testdir.tmpdir.join("tests") | ||
| tests.ensure_dir() | ||
| testdir.makepyprojecttoml( | ||
| """ | ||
| [tool.pytest.ini_options] | ||
| testpaths = ['{}'] | ||
| """.format( | ||
| tests | ||
| ) | ||
| ) | ||
| result = testdir.runpytest() | ||
| result.stdout.fnmatch_lines( | ||
| [ | ||
| "rootdir: *absolute_testpath0, configfile: pyproject.toml, testpaths: {}".format( | ||
| tests | ||
| ) | ||
| ] | ||
| ) | ||
|
|
||
| def test_no_header(self, testdir): | ||
| testdir.tmpdir.join("tests").ensure_dir() | ||
| testdir.tmpdir.join("gui").ensure_dir() | ||