Skip to content

fix: the config file's directory no longer decides the rootdir alone - #14837

Open
RonnyPfannschmidt wants to merge 1 commit into
pytest-dev:mainfrom
RonnyPfannschmidt:fix/rootdir-not-decided-by-config-file
Open

RonnyPfannschmidt wants to merge 1 commit into
pytest-dev:mainfrom
RonnyPfannschmidt:fix/rootdir-not-decided-by-config-file

Conversation

@RonnyPfannschmidt

Copy link
Copy Markdown
Member

Split out of #14807 after review — that PR keeps the refactor and the non-breaking -c fixes, this one carries the single breaking change.

Depends on #14807 (the branch is based on it); the diff against main will shrink to one commit once that lands.

Supersedes #14454 and #14579. Closes #13246, closes #9703.

The problem

-c set the rootdir to the config file's parent directory. With the common -c config/pytest.ini layout that moved the rootdir into config/, so conftests collected an empty path prefix: same-named fixtures from sibling directories shadowed each other, and node ids came out as config::test2 rather than tests/tests2/test2.py::test2.

The change

The config file's location is evidence about where the project lives, not a decision on its own. Take the common ancestor of the config file's directory and the collected test paths, using the invocation directory in their place when no paths were given. If the two live in unrelated trees the ancestor degrades to the filesystem root, in which case the config file's directory is kept, as today.

scenario before #14454 #14579 this PR
-c config/pytest.ini (no args) config/ ✅ config/ ✅
-c config/pytest.ini tests/ config/ ✅ ✅ ✅
sibling config, invoked from a subdirectory config/ sub/ ✅ ✅
unrelated working directory config/ unrelated dir ✅ ✅

No ambiguity warning is needed once the ancestor also considers the invocation directory, because the rootdir is then derived rather than guessed.

⚠️ Breaking, and which release

This changes documented behaviour — doc/en/reference/customize.rst said "If -c is passed in the command-line, use that as configuration file, and its directory as rootdir" — so the doc is updated here and the changelog entries are filed as breaking, not bugfix.

@bluetech asked on #14807 whether the next release is intended to be major. The versionchanged directive in the doc currently says 10.0 on that assumption — tell me the target and I will adjust it. If the next release is 9.2 instead, this PR should simply wait.

Concretely, what breaks: a project that today runs -c cfg/pytest.ini and relies on the rootdir being cfg/ — node ids, .pytest_cache location, and rootdir-relative ini paths all move. In practice such a setup already has broken conftest discovery, which is what #13246 and #9703 report.

Verification

Full suite green (4349 passed, 47 skipped, 13 xfailed, 7 xpassed — the xpasses are pre-existing, #11603/#10042).

Verified against the original reproducers by swapping in main's findpaths.py and running the same commands: on main the #13246 repro gives FAILED config::test2 - assert 1 == 2 and rootdir: .../config; with this commit, 2 passed and rootdir: .../ — the project root.

@bluetech

Copy link
Copy Markdown
Member

@RonnyPfannschmidt can you rebase the PR? In github it currently contains the 2 commits that are already in main, so a little harder to review.

@RonnyPfannschmidt
RonnyPfannschmidt force-pushed the fix/rootdir-not-decided-by-config-file branch from 7cbfbd8 to f0d3607 Compare September 15, 2026 11:34
@RonnyPfannschmidt

Copy link
Copy Markdown
Member Author

done

@RonnyPfannschmidt
RonnyPfannschmidt force-pushed the fix/rootdir-not-decided-by-config-file branch from f0d3607 to 7cc8e21 Compare September 23, 2026 07:00
@RonnyPfannschmidt
RonnyPfannschmidt force-pushed the fix/rootdir-not-decided-by-config-file branch from 7cc8e21 to fe6416e Compare October 4, 2026 13:06
Passing -c/--config-file set the rootdir to the config file's parent
directory. A config kept in a subdirectory -- the common `-c config/pytest.ini`
layout -- therefore moved the rootdir into that subdirectory, which broke
conftest discovery and node ids: conftests collected an empty path prefix, so
same-named fixtures from sibling directories shadowed each other and node ids
came out as `config::test2` instead of `tests/tests2/test2.py::test2`.

The config file's location is evidence about where the project lives, not a
decision on its own. Take the common ancestor of the config file's directory
and the collected test paths instead, falling back to the invocation directory
in place of the test paths when none were given. If the two live in unrelated
trees the ancestor degrades to the filesystem root, in which case the config
file's directory is kept, as before.

This covers cases neither of the two open proposals handled alone:

  scenario                                     before      pytest-dev#14454   pytest-dev#14579   now
  -c config/pytest.ini (no args)               config/     ok       config/  ok
  -c config/pytest.ini tests/                  config/     ok       ok       ok
  sibling config, invoked from a subdirectory  config/     sub/     ok       ok
  unrelated working directory                  config/     unrel.   ok       ok

pytest-dev#14454 (@EternalRights) found the root cause and drove the design discussion;
its `invocation_dir` rule is right for the no-args case but follows the working
directory even when that is unrelated to the project. pytest-dev#14579 (@hariharan077)
contributed the common-ancestor form, which is most of the answer but leaves
the no-args case unfixed. Neither is needed once the ancestor also considers
the invocation directory, and no ambiguity warning is required because the
ancestor is derived rather than guessed.

This is a breaking change: it alters documented behaviour, so
doc/en/reference/customize.rst is updated along with it, and the changelog
entries are filed as breaking rather than as bugfixes.

Closes pytest-dev#13246
Closes pytest-dev#9703

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
@RonnyPfannschmidt
RonnyPfannschmidt force-pushed the fix/rootdir-not-decided-by-config-file branch from fe6416e to 5df7f15 Compare October 11, 2026 07:26

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:chronographer:provided (automation) changelog entry is part of PR

Projects

None yet

2 participants