-
-
Notifications
You must be signed in to change notification settings - Fork 549
Comparing changes
Open a pull request
base repository: tox-dev/tox
base: 4.36.1
head repository: tox-dev/tox
compare: 4.37.0
- 14 commits
- 34 files changed
- 6 contributors
Commits on Feb 17, 2026
-
feat(release): use GitHub auto-generated release notes
Replace manual changelog extraction with --generate-notes flag to use GitHub's automatic release notes based on PRs and commits. Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>
Configuration menu - View commit details
-
Copy full SHA for 03ebf9c - Browse repository at this point
Copy the full SHA 03ebf9cView commit details -
✨ feat(config): add extra_setup_commands for --notest phase (#3716)
When running `tox --notest` in CI pipelines, teams need to separate dependency installation from test execution. The existing `commands_pre`, `commands`, and `commands_post` all run during the test phase and are completely skipped with `--notest`, leaving no way to run setup tasks during the installation phase. 🔧 A common use case is installing pre-commit hooks with `pre-commit install-hooks` during the `--notest` phase, then running `pre-commit run` as the actual test command in a separate CI step. This separation allows faster feedback and better resource utilization in CI environments. This PR introduces `extra_setup_commands` that executes after all installations (dependencies and package) complete but before the test phase begins. ✨ These commands run during `--notest`, enabling users to prepare their environment with tools and hooks while deferring test execution to a separate step. The implementation adds the configuration option to `PythonRun` environments only, deliberately excluding packaging environments to maintain their clean separation of concerns. Commands execute with the same change directory and error handling semantics as other command sets. Resolves #1504 --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for 1e2e12b - Browse repository at this point
Copy the full SHA 1e2e12bView commit details -
🐛 fix(release): format changelog with pre-commit before committing (#…
…3717) The release process generates `changelog.rst` using towncrier, but towncrier's output doesn't always match our pre-commit formatting rules. 📝 This leads to the release commit containing unformatted changelog text that later gets flagged by CI, requiring follow-up formatting commits. This PR modifies the release script to run pre-commit on the generated `changelog.rst` immediately after towncrier builds it but before creating the release commit. The pre-commit hooks apply all necessary formatting (line wrapping, trailing whitespace removal, etc.) so the changelog is properly formatted from the start. The implementation catches and handles the case where pre-commit makes changes (exit code 1), stages those changes, and includes them in the release commit. This keeps the release history clean without requiring manual intervention or subsequent formatting commits. Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>
Configuration menu - View commit details
-
Copy full SHA for 5191a92 - Browse repository at this point
Copy the full SHA 5191a92View commit details -
📝 docs: restructure documentation using Diátaxis framework (#3718)
The documentation was organized in a flat structure that mixed tutorials, how-to guides, reference material, and conceptual explanations together. Users had difficulty finding information appropriate to their skill level and immediate needs. 📚 New users couldn't distinguish between learning materials and quick reference, while experienced users had to wade through explanatory content to find technical specifications. Adopted the Diátaxis documentation framework that organizes content by user needs rather than topics. The structure now separates Tutorial (learning-oriented), How-to guides (task-oriented), Reference (information-oriented), and Explanation (understanding-oriented). This matches the structure used by virtualenv and follows modern documentation best practices. Files were moved to appropriate directories, cross-references updated throughout, and installation documentation reorganized to use tabs for tool-specific details. Python compatibility specifications moved from installation guide to configuration reference where technical requirements belong. The new structure makes it immediately clear where to look: beginners start with the tutorial, practitioners consult how-to guides for specific tasks, developers check reference for technical details, and everyone can deepen understanding through explanations when needed.
Configuration menu - View commit details
-
Copy full SHA for f17313e - Browse repository at this point
Copy the full SHA f17313eView commit details -
🐛 fix(pip): set PIP_USER=0 to prevent --user installs in virtualenvs (#…
…3719) Users with `pip config --user` configured globally experienced installation failures in tox virtualenvs. 🐛 When pip attempted to honor the `--user` flag inside virtualenvs, it crashed because user site-packages aren't visible in isolated environments. This regression was introduced during the tox 4 rewrite. Tox 3 correctly set `PIP_USER=0` to override user configuration, but this protection was lost in the rewrite. The fix restores this behavior by setting the environment variable in all virtualenv-based Python environments. The solution follows pip's documented environment variable precedence where `PIP_USER=0` explicitly disables `--user` installs regardless of config file settings. This preserves user workflows while ensuring tox virtualenvs remain isolated. ✨ Fixes #3010
Configuration menu - View commit details
-
Copy full SHA for 6450988 - Browse repository at this point
Copy the full SHA 6450988View commit details -
🐛 fix(config): prevent env_run_base deps from being clobbered (#3721)
When users configure TOML environments with `deps = ["{[tool.tox.env_run_base]deps}", "extra-dep"]`, the additional dependencies were silently dropped and only the base section deps were installed. This breaks a natural pattern for extending base configurations, making it impossible to share common dependencies across environments while adding environment-specific ones. 🔧 The configuration reference expansion logic incorrectly treated `env_run_base` and `env_pkg_base` as regular test environments because their section names start with the environment prefix `tool.tox.env`. This caused the system to attempt creating a virtual environment named `run_base` instead of reading the raw configuration values, breaking the reference expansion and silently discarding any additional dependencies in the list. The fix adds an explicit check to exclude these special base sections from environment resolution, ensuring they're always treated as raw configuration sections. This preserves the intended behavior where base sections can be referenced alongside additional values without data loss. ✨ Closes #3393 --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>Configuration menu - View commit details
-
Copy full SHA for 0ee48ce - Browse repository at this point
Copy the full SHA 0ee48ceView commit details -
Fix env name with dot losing description in TOML config (#3722)
## Description Fixes #3590 Environment names containing dots (e.g. `"py3.11"`) in `pyproject.toml` had their descriptions silently ignored. `tox list` showed `[no description]` instead of the configured description. ### Reproducer ```toml [tool.tox.env."py3.11"] description = "tox test" ``` ```console $ tox list py3.11 -> [no description] ``` ### Root cause Three interrelated issues in `toml_pyproject.py`: 1. **`sections()` split the env name on dots**: `from_key("py3.11")` treats `.` as the section separator, creating `Section(prefix="py3", name="11")` instead of preserving `"py3.11"` as the name. 2. **`keys` property split ALL dots**: The full key `"tool.tox.env.py3.11"` was split into `["env", "py3", "11"]`. `get_loader()` then tried to traverse `dict["py3"]["11"]` instead of `dict["py3.11"]`, returning `None` (config not found). 3. **`envs()` yielded full key**: When `sections()` is fixed to use `test_env()`, the full key becomes `"tool.tox.env.py3.11"` instead of just `"py3.11"`, causing a phantom duplicate environment. ### Fix - **`keys` property**: Build from `prefix` and `name` components directly instead of splitting the joined key on `SEP`. This preserves dots within the env name while still splitting structural path separators. - **`sections()`**: Use `test_env(env_name)` which correctly sets `prefix="tool.tox.env"` and `name="py3.11"` as an atomic unit. - **`envs()`**: Yield `section.name` instead of `section.key` to return just the env name. - **`get_base_sections()`**: Use `test_env()` for consistency. ### After fix ```console $ tox list py3.11 -> tox test ``` --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for 83b3ed8 - Browse repository at this point
Copy the full SHA 83b3ed8View commit details -
🐛 fix(ci): add completion extras to type checker environments (#3728)
The `type` and `type-min` CI environments fail because `ty` cannot resolve the `argcomplete` module imported in `src/tox/config/cli/parse.py` and `tests/config/cli/test_argcomplete.py`. While `env_run_base` declares `extras = ["completion"]`, the type environments weren't picking it up reliably, causing `error[unresolved-import]` on fresh CI runs. 🔧 The fix explicitly sets `extras = ["completion"]` on both `env.type` and `env.type-min` in `tox.toml`, reusing the existing `optional-dependencies.completion` that already defines `argcomplete>=3.6.3` rather than duplicating the dependency.
Configuration menu - View commit details
-
Copy full SHA for 0d3f901 - Browse repository at this point
Copy the full SHA 0d3f901View commit details -
Fix factor selection via TOX_FACTORS environment variable (#3725)
## Summary - Fix `TOX_FACTORS` env var producing wrong results (each character treated as a separate factor instead of each factor string) - Root cause: `get_type()` inferred `list[str]` for `_AppendAction` with `nargs="+"`, but the actual runtime type is `list[list[str]]` - The existing `Convert` infrastructure already handles nested generics, so fixing the type inference is sufficient Closes #3557 ## Test plan - [x] Added parametrized test `test_factor_select_via_env_var` covering single factor, AND (comma-separated), and OR (semicolon-separated) - [x] All 65 env_select tests pass - [x] All 6355 config tests pass - [x] All 6 CLI env var tests pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for e7a0800 - Browse repository at this point
Copy the full SHA e7a0800View commit details -
Fix setenv PATH modifications being overwritten (#3723)
## Summary - Fixes #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 - [x] Verified the fix resolves the issue described in #3445 - [x] The `environment_variables` property already handles merging setenv with system PATH correctly — the bug was only in the setter bypassing this logic - [x] Added changelog fragment 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for d81aae7 - Browse repository at this point
Copy the full SHA d81aae7View commit details -
Fix extras with underscores not matching hyphenated metadata (#3727)
## Summary Fixes #3433 — extras with underscores in `tox.ini` (e.g. `snake_case`) were not matching hyphenated extra names in package metadata (e.g. `Provides-Extra: snake-case`), causing their dependencies to be silently skipped. ## Root cause `dependencies_with_extras_from_markers()` compared `todo` (from tox.ini extras) against `extra_markers` (from metadata markers) using set intersection, but neither side was normalized. When setuptools normalizes underscores to hyphens in wheel metadata, `"snake_case" & {"snake-case"}` produces an empty set, skipping all dependencies for that extra. ## Fix Normalize extra names using `canonicalize_name()` (from `packaging.utils`, already imported) at three points: 1. **Requested extras** from tox.ini — normalized when building the `todo` set 2. **Extra markers** from metadata — normalized when extracting from dependency markers 3. **Recursive extras** from `req.extras` — normalized when discovered during resolution This ensures underscore/hyphen equivalence throughout the resolution process, consistent with PEP 685. ## Tests Added three test cases: - `test_extras_underscore_hyphen_matching` — underscores in extras match hyphens in markers - `test_extras_underscore_in_markers` — hyphens in extras match underscores in markers - `test_extras_normalization_with_recursive` — recursive extras with underscore/hyphen mismatch All existing tests pass (the `test_load_dependency_no_extra` ordering failure is pre-existing on main). --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for 00f79b9 - Browse repository at this point
Copy the full SHA 00f79b9View commit details -
Fix install_command ignored from TOML config (#3724)
## Summary Fixes #3574 — custom `install_command` was silently ignored when specified in `tox.toml` or `pyproject.toml`, always falling back to the default pip install command. ### Root cause Two bugs conspired to produce this behavior: 1. **`get_base_sections` placed base sections under the `env` namespace.** It used `test_env(b)` which wraps the section name under `env.*`, but `env_run_base` and `env_pkg_base` are top-level sections — `[env_run_base]` in `tox.toml` and `[tool.tox.env_run_base]` in `pyproject.toml`. This caused the loader to navigate to `env.env_run_base` (which doesn't exist) and return `None`, so no settings from `env_run_base` were applied. 2. **The TOML replacement engine raised on unknown `{...}` placeholders.** When `Unroll` processed strings like `{packages}` inside an `install_command` array, `TomlReplaceLoader` tried to resolve `packages` as a config key, failed with `KeyError`, and raised — causing the config loader to fall through to the default. The INI loader's equivalent (`ReplaceReferenceIni`) returns `None` for unresolvable references (keeping the original text), matching the documented contract of `ReplaceReference.__call__`. ### Changes - **`toml_pyproject.py`**: `get_base_sections` now constructs sections with the core prefix (or `None`), correctly placing `env_run_base`/`env_pkg_base` at the top level rather than under `env`. - **`_replace.py`**: `TomlReplaceLoader.__call__` returns `None` (instead of raising) when a `KeyError` occurs with no default, consistent with the INI loader and the `ReplaceReference` protocol. - **Test**: Parameterized test verifying `install_command` is respected from both `tox.toml` and `pyproject.toml`. - **Changelog**: Added `docs/changelog/3574.bugfix.rst`. ### Test plan - [x] New parameterized test (`tox.toml` and `pyproject.toml` variants) - [x] All 27 show_config tests pass - [x] All 143 config/loader/source tests pass - [x] All 49 pip install tests pass --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for e84002a - Browse repository at this point
Copy the full SHA e84002aView commit details -
Fix deps with ~= version specifier treated as local paths (#3726)
## Summary - Fix `deps = pre-commit ~= 4` being treated as a local path instead of an invalid requirement - Root cause: `packaging.Requirement()` rejects `~=` with single-segment versions (PEP 440 requires 2+ segments), then tox's fallback treats the `~` as a tilde home directory path - Fix: detect PEP 440 version specifier operators before path detection, keep the string as-is for pip to give a clear error Closes #3447 ## Test plan - [x] Added parametrized test for `pre-commit ~= 4` and `pre-commit~=4` - [x] All 104 req file tests pass - [x] All 49 pip install tests pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for f80405e - Browse repository at this point
Copy the full SHA f80405eView commit details -
Configuration menu - View commit details
-
Copy full SHA for ab4fc8c - Browse repository at this point
Copy the full SHA ab4fc8cView commit details
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff 4.36.1...4.37.0