Skip to content

determine_setup: use invocation_dir as rootdir when -c is given#14454

Open
EternalRights wants to merge 3 commits intopytest-dev:mainfrom
EternalRights:fix-rootdir-when-config-specified
Open

determine_setup: use invocation_dir as rootdir when -c is given#14454
EternalRights wants to merge 3 commits intopytest-dev:mainfrom
EternalRights:fix-rootdir-when-config-specified

Conversation

@EternalRights
Copy link
Copy Markdown
Contributor

Ran into this while playing around with pytest -c config/pytest.ini - rootdir was jumping to config/ instead of staying at the project root. Broke conftest discovery in a pretty confusing way.

Turned out the root cause is one line in determine_setup: rootdir = inipath_.parent. When -c points to a file in a subdirectory, that line makes rootdir follow the config file, ignoring where you actually invoked pytest from.

The fix is to use invocation_dir instead (which is what everything else in determine_setup already does when no -c is given). Ronny confirmed this is a regression on the issue, so no design discussion needed here.

Also cleaned up test_with_specific_inifile which was using Path.cwd() as invocation_dir (non-deterministic) - changed it to tmp_path like every other test in the class. Added a new test specifically for the subdir-config scenario.

Would appreciate a review!

Copy link
Copy Markdown
Member

@RonnyPfannschmidt RonnyPfannschmidt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im wondering if the common root ought to be used in case of sub/siblings

@EternalRights EternalRights force-pushed the fix-rootdir-when-config-specified branch from c7d396b to 55123ac Compare May 9, 2026 16:47
@psf-chronographer psf-chronographer Bot added the bot:chronographer:provided (automation) changelog entry is part of PR label May 9, 2026
@EternalRights
Copy link
Copy Markdown
Contributor Author

Good point. Let me think through the scenarios:

  1. No args (pytest -c config/pytest.ini) — get_dirs_from_args([]) returns [], then get_common_ancestor falls back to invocation_dir. So both approaches are equivalent here.

  2. Args in subdir (pytest -c config/pytest.ini tests/) — tests/ resolves to a path under invocation_dir, so the common ancestor is invocation_dir itself. Same result.

  3. Args outside the tree (pytest -c config/pytest.ini ../other/) — now get_common_ancestor would climb to a parent directory, which could be / or an unexpected place. Thats when having an explicit --rootdir makes the intent clear.

My reasoning for sticking with invocation_dir is that -c is an explicit user choice — "I know where my config is". Setting rootdir to invocation_dir is deterministic and matches the mental model of "where I ran pytest from". If the user has args in a completely different tree, they should use --rootdir to be explicit about what the root should be.

That said, I am open to switching to get_common_ancestor(invocation_dir, dirs) if you think the sub/siblings case is important enough to handle automatically. Let me know what you prefer.

@RonnyPfannschmidt
Copy link
Copy Markdown
Member

thanks you for the elaboration

but args outside the tree is also the case im concerned in a valid case - like working in a subdir, using the config dir thats now a siebling

it may be a better solution to warn about using invocation dir as rootdir when the intent is not clear and recommending explict rootdir to disambiguate

good intentions have been used to pave this road

@EternalRights
Copy link
Copy Markdown
Contributor Author

thanks you for the elaboration

but args outside the tree is also the case im concerned in a valid case - like working in a subdir, using the config dir thats now a siebling

it may be a better solution to warn about using invocation dir as rootdir when the intent is not clear and recommending explict rootdir to disambiguate

good intentions have been used to pave this road

The warning approach makes sense. I've updated the PR with a warning
that fires when -c points to a path outside invocation_dir:

"rootdir was set to <invocation_dir> because -c was given without --rootdir.
Use --rootdir to explicitly disambiguate."

This keeps the common case silent while giving users a clear action for edge cases.

Found this while testing a project with pytest -c config/pytest.ini.
rootdir ended up pointing to config/ instead of the project root,
which broke conftest discovery since conftests are resolved relative
to rootdir.

Turned out `rootdir = inipath_.parent` was the culprit - it makes
rootdir jump to wherever the config file lives, ignoring invocation_dir.
Simple fix: use invocation_dir instead.
@EternalRights EternalRights force-pushed the fix-rootdir-when-config-specified branch from 78f4aad to b399b23 Compare May 10, 2026 03:44
@EternalRights
Copy link
Copy Markdown
Contributor Author

One more thing — the RTD build seems to be failing on a pre-existing Sphinx toctree warning (unrelated to these changes). Just a heads-up.


if ns.inifilename and not ns.rootdir:
if inipath is not None and inipath.parent != self.invocation_params.dir:
log.warning(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pytest doesnt use logging for ux we might want to find a differnt place to output this

@nicoddemus @bluetech any opinion on this - personally i lean towards the pre collection summary header that shows pytest/plugin versions + config paths already but something about that feels icky as well

@EternalRights
Copy link
Copy Markdown
Contributor Author

@RonnyPfannschmidt Fair point, logging was a bad call. I should have thought about pytest's UX conventions before reaching for that.

If the consensus is the pre-collection summary header, happy to move it there. Another option could be printing it via terminal.write_line alongside the config path info that already shows up. But I'll wait to hear what nicoddemus and bluetech think.

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

Development

Successfully merging this pull request may close these issues.

2 participants