Skip to content
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 or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: tox-dev/tox
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 4.39.0
Choose a base ref
...
head repository: tox-dev/tox
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 4.40.0
Choose a head ref
  • 8 commits
  • 25 files changed
  • 5 contributors

Commits on Feb 19, 2026

  1. Use positive exit code for multi-env failures (#3768)

    The report() returned -1 as the exit code when multi-env runs had
    failures. On Unix, SystemExit(-1) wraps to exit code 255 (unsigned
    byte), which works fine. But on Windows CMD, the exit code stays -1, and
    IF ERRORLEVEL 1 checks %ERRORLEVEL% >= 1 — since -1 < 1, the failure was
    silently treated as success.
    
    The only behavioral difference is that multi-env failures now return 1
    instead of 255 on Unix — which is actually more idiomatic. The
    single-env case already returned the actual command exit code (e.g., 1,
    2), so this makes the multi-env case consistent.
    
    Fixes: #2945 
    
    <!-- Thank you for your contribution!
    
    Please, make sure you address all the checklists (for details on how see
    [development
    documentation](http://tox.readthedocs.org/en/latest/development.html#development))!
    -->
    
    - [x] ran the linter to address style issues (`tox -e fix`)
    - [x] wrote descriptive pull request text
    - [x] ensured there are test(s) validating the fix
    - [x] added news fragment in `docs/changelog` folder
    - [ ] updated/extended the documentation
    rahuldevikar authored Feb 19, 2026
    Configuration menu
    Copy the full SHA
    a514a12 View commit details
    Browse the repository at this point in the history
  2. ✨ feat(config): add {glob:PATTERN} substitution (#3769)

    A common pain point for tox users is referencing files by wildcard
    patterns in configuration — uploading all wheels from a dist directory,
    pointing deps at requirement files matching a pattern, or collecting
    test artifacts. Until now this required shell expansion or external
    scripting, which breaks cross-platform compatibility and complicates
    configuration.
    
    This adds a `{glob:PATTERN}` substitution that expands file system glob
    patterns inline. It works in both INI string syntax
    (`{glob:dist/*.whl}`, with optional `{glob:dist/*.whl:fallback}`
    default) and TOML dict syntax (`{ replace = "glob", pattern =
    "dist/*.whl", extend = true }`). Relative patterns resolve against
    `tox_root`, results are sorted for deterministic builds, and `**`
    enables recursive directory matching.
    
    The `extend` flag in TOML dict syntax controls whether matched paths are
    inserted as separate list elements (useful in `commands`) or joined as a
    single space-separated string (useful in `description` or other string
    fields). When no files match and no default is provided, the result is
    an empty string or empty list depending on context.
    
    Closes #1571
    gaborbernat authored Feb 19, 2026
    Configuration menu
    Copy the full SHA
    8929382 View commit details
    Browse the repository at this point in the history
  3. Add package=sdist-wheel package type (#3741)

    Adds a new `sdist-wheel` package type that builds a wheel from a source
    distribution rather than directly from the source tree. This validates
    that the sdist is complete and that the package can be correctly built
    from it — catching missing files or packaging errors early.
    
    Usage
    
    [env_run_base]
    package = "sdist-wheel"
    
    [testenv]
    package = sdist-wheel
    
    How it works
    1. Builds an sdist via build_sdist
    2. Extracts the sdist to a temporary directory
    3. Swaps the package root to the extracted source
    4. Builds a wheel via build_wheel from that extracted sdist
    5. Cleans up the sdist and extraction directory
    
    <!-- Thank you for your contribution!
    
    Please, make sure you address all the checklists (for details on how see
    [development
    documentation](http://tox.readthedocs.org/en/latest/development.html#development))!
    -->
    
    - [x] ran the linter to address style issues (`tox -e fix`)
    - [x] wrote descriptive pull request text
    - [x] ensured there are test(s) validating the fix
    - [x] added news fragment in `docs/changelog` folder
    - [x] updated/extended the documentation
    
    ---------
    
    Signed-off-by: Bernát Gábor <[email protected]>
    Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
    Co-authored-by: Bernát Gábor <[email protected]>
    3 people authored Feb 19, 2026
    Configuration menu
    Copy the full SHA
    17d3c1e View commit details
    Browse the repository at this point in the history
  4. ✨ feat(config): add conditional replace for TOML (#3771)

    TOML configurations had no way to conditionally select values based on
    environment variables, forcing users to rely on external scripts or fall
    back to INI-only factor conditions. This was one of the most frequently
    requested features (#3650), particularly for CI/CD workflows where
    behavior needs to vary based on environment context.
    
    The `replace = "if"` syntax introduces a `condition` expression field
    that supports `env.VAR` lookups, `==`/`!=` comparisons, and
    `and`/`or`/`not` boolean logic. 🔧 Expressions are parsed safely via
    Python's `ast` module — only a restricted set of node types is
    evaluated, so arbitrary code execution is not possible. The `env.VAR`
    lookups read directly from `os.environ` rather than `set_env`, avoiding
    circular dependency issues when conditionals are used inside `set_env`
    itself.
    
    The expression language was chosen over PEP 508 markers because the
    `packaging` library's marker evaluator has a hard-coded set of allowed
    variable names and cannot be extended with `os.environ` lookups. A
    custom `ast`-based evaluator provides the same familiar Python syntax
    (`and`, `or`, `not`, `==`, `!=`) while supporting the actual use case of
    environment variable inspection.
    
    Closes #3650
    gaborbernat authored Feb 19, 2026
    Configuration menu
    Copy the full SHA
    421c09c View commit details
    Browse the repository at this point in the history
  5. Create .gitignore in work_dir and info file directories (#3770)

    Automatically create a .gitignore file containing * in tox-managed
    directories so users don't need to manually add .tox (or other work
    directories) to their project's .gitignore.
    
    <!-- Thank you for your contribution!
    
    Please, make sure you address all the checklists (for details on how see
    [development
    documentation](http://tox.readthedocs.org/en/latest/development.html#development))!
    -->
    
    - [x] ran the linter to address style issues (`tox -e fix`)
    - [x] wrote descriptive pull request text
    - [x] ensured there are test(s) validating the fix
    - [x] added news fragment in `docs/changelog` folder
    - [ ] updated/extended the documentation
    rahuldevikar authored Feb 19, 2026
    Configuration menu
    Copy the full SHA
    4e822c5 View commit details
    Browse the repository at this point in the history
  6. ✨ feat(run): add commands_retry config option (#3772)

    Users running commands subject to transient failures -- network
    timeouts, flaky integration tests, intermittent CI infrastructure issues
    -- had no built-in way to automatically retry. The only workarounds were
    shell-level retry loops or wrapping commands in helper scripts, both of
    which add friction and reduce portability across platforms.
    
    This adds a `commands_retry` integer configuration option (default `0`)
    to each environment. Setting it to `N` means each command can be
    attempted up to `N + 1` times total. The retry applies uniformly to
    `commands_pre`, `commands`, and `commands_post`. When a command fails
    and retries remain, tox logs a warning with the attempt count and
    re-executes. Commands prefixed with `-` (ignore exit code) are never
    retried since their failures are already ignored. The feature composes
    naturally with `ignore_errors` -- retries are exhausted first, then the
    existing error-handling logic takes over.
    
    The default of `0` preserves existing behavior. No configuration changes
    are required for users who don't need retries.
    
    Fixes #1578
    gaborbernat authored Feb 19, 2026
    Configuration menu
    Copy the full SHA
    a310c11 View commit details
    Browse the repository at this point in the history
  7. 🐛 fix(config): set_env override lost after load (#3775)

    When `set_env` both inherits via cross-section substitution (e.g.,
    `{[testenv]set_env}`) and explicitly overrides the same variable in the
    same section, the explicit value is silently replaced by the inherited
    one. 🐛 This regression was introduced in v4.39.0 and breaks a common
    configuration pattern where users layer environment variables across
    sections.
    
    The root cause is a timing issue in `_iter_needs_replacement()`. During
    iteration, `load()` moves explicitly-set keys from `_raw` to
    `_materialized`. By the time the deferred cross-section substitution
    expands, the `key not in self._raw` guard no longer sees those keys, so
    inherited values overwrite explicit ones. The fix tracks
    originally-defined keys in a separate `_defined_keys` set that persists
    across `load()` calls, ensuring deferred substitutions never overwrite
    values the user explicitly configured.
    
    All existing precedence behaviors are preserved: defaults still get
    overridden by cross-section values (#2872), explicit values still win
    over cross-section values (#2831), and `file|` ordering still respects
    later inline definitions (#3335).
    
    Fixes #3773
    
    ---------
    
    Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
    gaborbernat and pre-commit-ci[bot] authored Feb 19, 2026
    Configuration menu
    Copy the full SHA
    5929bdb View commit details
    Browse the repository at this point in the history
  8. release 4.40.0

    gaborbernat committed Feb 19, 2026
    Configuration menu
    Copy the full SHA
    db17069 View commit details
    Browse the repository at this point in the history
Loading