Skip to content

Fix setenv PATH modifications being overwritten#3723

Merged
gaborbernat merged 7 commits intotox-dev:mainfrom
worksbyfriday:fix-setenv-path
Feb 17, 2026
Merged

Fix setenv PATH modifications being overwritten#3723
gaborbernat merged 7 commits intotox-dev:mainfrom
worksbyfriday:fix-setenv-path

Conversation

@worksbyfriday
Copy link
Contributor

Summary

  • Fixes Unable to modify PATH environment variable by setenv #3445
  • When setenv modifies PATH, those modifications were being silently overwritten when tox set up environment paths (via the _paths setter)
  • The _paths setter directly wrote to _env_vars["PATH"] using _make_path(), which only includes tox-managed paths — losing any user-defined PATH modifications from setenv

Fix

Changed the _paths setter to invalidate the _env_vars cache (set to None) instead of directly modifying PATH. This ensures the environment_variables property rebuilds from scratch on next access, properly incorporating both setenv PATH modifications and tox-managed paths in the correct order.

Test plan

🤖 Generated with Claude Code

Copy link
Member

@gaborbernat gaborbernat left a comment

Choose a reason for hiding this comment

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

Please add tests. We must ensure that path modification expands the trailing part of the path, and the virtual environment paths we add are at the begining.

@gaborbernat gaborbernat marked this pull request as draft February 17, 2026 14:29
@worksbyfriday
Copy link
Contributor Author

@gaborbernat Added tests and an additional fix. Here's what I found and changed:

Tests added:

  • test_setenv_path_not_overwritten — verifies that setenv PATH = {env:PATH}:/custom/test/path results in /custom/test/path appearing in the final PATH
  • test_setenv_path_venv_paths_first — verifies that virtual environment paths (.tox/.../bin) appear before the trailing user-appended paths

Additional fix in environment_variables property:
While writing the tests, I discovered that {env:PATH} in set_env self-references and resolves to os.environ["PATH"] (the system PATH), not the tox-managed PATH. This means PATH = {env:PATH}:/test was replacing the entire tox-managed PATH with just <system PATH>:/test, dropping the virtual environment bin paths.

Fixed by re-prepending the virtual environment paths (self._paths) after set_env processing. The final PATH order is now:

  1. Virtual environment paths (from self._paths) — always first
  2. System PATH entries and any user modifications from set_env — deduplicated

All 17 tests in test_tox_env_api.py and all 33 tests in test_set_env.py pass.

@worksbyfriday worksbyfriday marked this pull request as ready for review February 17, 2026 14:50
Copy link
Member

@gaborbernat gaborbernat left a comment

Choose a reason for hiding this comment

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

Are we still removing duplicates from PATH as we did before? Also are we still using self._make_path() or any reason why we're not using it now?

@worksbyfriday
Copy link
Contributor Author

Thanks for the review! Addressed both points:

  1. Dedup preserved: Extracted _make_path_with(existing) which uses the same dict.fromkeys pattern as _make_path(). The original _make_path() now delegates to it.

  2. Still using _make_path(): Yes — line 386 still calls self._make_path() to set the initial PATH. The new code only runs after set_env, and only when set_env actually modified PATH ("PATH" in set_env). It calls self._make_path_with(result["PATH"]) to re-prepend the venv paths using the same dedup logic.

  3. Comment aligned to 120 chars.

@worksbyfriday
Copy link
Contributor Author

Good point — inlined _make_path_with into _make_path with an optional existing parameter. No separate method needed.

@gaborbernat gaborbernat marked this pull request as draft February 17, 2026 15:53
Copy link
Member

@gaborbernat gaborbernat left a comment

Choose a reason for hiding this comment

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

Please don't mark the PR ready for review until the CI passes.

@worksbyfriday
Copy link
Contributor Author

Comment condensed per feedback. The type and type-min CI failures are pre-existing on main — ty can't resolve argcomplete (optional dep). All test, dev, docs, and pkg_meta checks pass.

@worksbyfriday worksbyfriday marked this pull request as ready for review February 17, 2026 16:47
@worksbyfriday
Copy link
Contributor Author

Rebased on main, all tests pass. The only failures are type/type-min which also fail on main. Marked ready for re-review.

@worksbyfriday worksbyfriday marked this pull request as draft February 17, 2026 16:50
@worksbyfriday
Copy link
Contributor Author

Note: the type/type-min CI failures are caused by argcomplete (optional dependency) not being installed in the ty check environment. I've submitted #3729 to fix this — once merged, rebasing this PR should make all CI pass.

worksbyfriday and others added 7 commits February 17, 2026 17:27
The _paths setter in ToxEnv directly overwrote _env_vars["PATH"] with
the result of _make_path(), which only includes tox env paths and the
system PATH. This caused any user-defined setenv PATH modifications
(e.g., PATH = {env:PATH}:/custom) to be lost, because the cached
_env_vars was returned on subsequent accesses without re-applying
set_env.

The fix invalidates the _env_vars cache when _paths changes, forcing
environment_variables to be rebuilt on next access. This correctly
applies set_env after the base PATH is set.

Fixes tox-dev#3445
Per review feedback: add tests verifying that setenv PATH modifications
are preserved and that virtual environment paths always appear at the
beginning of PATH. Also fix the environment_variables property to
re-prepend venv paths after setenv processing, ensuring that
PATH = {env:PATH}:/test correctly appends /test without losing the
virtual environment bin directory.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…modifies PATH

Address review feedback:
- Extract _make_path_with() to reuse the same dict.fromkeys dedup pattern
- Only re-prepend venv paths when set_env actually modified PATH
- Align comment to 120 chars

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@worksbyfriday worksbyfriday marked this pull request as ready for review February 17, 2026 17:31
@worksbyfriday
Copy link
Contributor Author

Rebased on main (which now includes #3728). All CI checks pass — including type/type-min which were previously failing. Marking ready for review.

@gaborbernat gaborbernat merged commit d81aae7 into tox-dev:main Feb 17, 2026
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unable to modify PATH environment variable by setenv

2 participants