Repository navigation
Immutable
release. Only release title and notes can be modified.
Bug fixes
- A packaging environment whose
base_python(ordefault_base_python) is not installed no longer crashes withKeyError: 'skip_missing_interpreters'. It now fails with the missing interpreter, or skips the run environment whenskip_missing_interpretersis true, as tox did before 4.36.0 (#4213) by @gaborbernat. (#4212) - Keep environment markers when a package extra refers to another extra of the same package. For example,
demo[dev]; python_version < '3.10'keeps the version condition on dependencies fromdev(#4216) by @ericdelorefice and @gaborbernat. - A
pylock.tomlor a tox user configuration file (TOX_USER_CONFIG_FILE) saved with a UTF-8 byte order mark, as some Windows editors do, is now read instead of failing with a TOML decode error or being ignored withfailed to read config file(#4217) by @pcbeingused333. - With
args_are_pathsenabled, a positional argument naming an existing file whose rewritten path relative tochange_dirstarts with-(for exampletests/--config=evil.cfg) is now prefixed with./so the command still receives a path instead of an option (#4317) by @rahuldevikar and @gaborbernat. (#4218) - An extending TOML
replacetable with a nonemptymarkernow raises an error instead of adding its internalvalueandmarkerkeys todepsorrequires. Markers onset_envvalues remain supported (#4320) by @rahuldevikar and @gaborbernat. (#4220) - A TOML type mismatch no longer includes an expanded string or container value. A malformed
commandssetting with{env:...}reports its type instead of the substituted text (#4327) by @rahuldevikar and @gaborbernat. (#4221) - Keep artifacts supplied with
--installpkgout of tox's provisioning environment while installing them in the requested test environments (#4304) by @Pratham2511 and @gaborbernat. (#4222) - A
file:URI passed to--installpkgis now percent-decoded once instead of twice, so a path containing a literal%sequence, such as a directory namedfeature%2Flogin, selects the package the user named (#4300) by @pcbeingused333 and @gaborbernat. (#4223) - A relative
TOX_INSTALL_PKGor user configurationinstall_pkgpath is now resolved against the invocation directory, as--installpkgalready was, so tox inspects and installs from the same path (#4333) by @rahuldevikar and @gaborbernat. (#4224) - tox refuses a symlink or Windows junction at
meta_dirbecause the build frontend empties that directory during metadata preparation (#4332) by @rahuldevikar and @gaborbernat. (#4225) - An explicitly empty
base_python(for example{env:TOXPYTHON:python3.11}withTOXPYTHONempty) now fails during configuration withbase_python for env <name> is empty. Blank entries in abase_pythonlist are ignored (#4326) by @rahuldevikar and @gaborbernat. (#4226) - A path setting that expands to an empty value, such as
env_tmp_dir = {env:SCRATCH_DIR}withSCRATCH_DIRunset, now fails with a configuration error instead of resolving to the current directory, which tox could then clear (#4330) by @rahuldevikar and @gaborbernat. (#4227) - Keep every value of a multi-value command line flag, such as
-f py legacy, with that flag. The command scanner took a later value matching a subcommand as the command, causing environments without that factor to run (#4319) by @rahuldevikar and @gaborbernat. (#4228) - Unreadable wheels, invalid wheel metadata, and unreadable or empty source archives supplied through
--installpkgnow produce errors that name the artifact instead of internal error tracebacks (#4287) by @santhiprakash and @gaborbernat. (#4230) - Reject NUL characters in
set_envfile assignments with a handled input error instead of a subprocess traceback (#4279) by @Doomguy-BFG9000 and @gaborbernat. (#4231) - Limit each requirement or constraint file to 10 MiB, so oversized and endless includes fail with a size error. For remote files, tox checks a 120-second deadline between response body reads. Slow HTTP framing can delay that check (#4312) by @rahuldevikar and @gaborbernat. (#4232)
- tox now validates inline script
dependenciesas requirements before installing them. An invalid entry such as a pip option fails before tox passes the dependencies to pip (#4306) by @santhiprakash and @gaborbernat. (#4233) - Read static package dependencies and the
editable-legacyinstall path from the packaging environment'spackage_rootinstead of the core one, so apackage_rootset in[testenv:.pkg]no longer pairs the built package with the dependencies declared next totox.ini(#4321) by @rahuldevikar and @gaborbernat. (#4234) - A package environment path that is already a symlink no longer causes
tox listto createfile.lockunder the link target (#4311) by @rahuldevikar and @gaborbernat. (#4235) - tox now expands
${VAR}in requirements and constraints files using the environment running pip, includingpass_envandset_env, instead of the tox process. A variable absent from that environment stays literal, so tox cannot put its host value in a fetched URL. To retain expansion, add it topass_envor define it withset_env(#4323) by @rahuldevikar and @gaborbernat. (#4236) - Mask values when a flag or environment variable name contains a secret keyword after a newline (#4259) by @haigou-web and @gaborbernat. (#4237)
tox -hno longer prints secret-looking--key=valuevalues fromTOX_OVERRIDE. Conversion warnings also mask those values in invalidTOX_options (#4303) by @faresrafat3 and @gaborbernat. (#4238)- A
tox.tomlorpyproject.tomlstring with literal braces around text containing a colon, such as a JSON argument holding a URL or a time, is now kept as written, as intox.ini, instead of being read as a{key:default}reference. Positional arguments such asset_env:xpassed into such braces through{posargs}no longer expand into the value of that setting (#4269) by @Anandb71 and @gaborbernat. (#4239) - Reject wheel metadata entries over 8 MiB uncompressed, limiting memory use during package installation (#4328) by @rahuldevikar and @gaborbernat. (#4240)
- Recreate an environment when its
.tox-info.jsoncontains a non-mapping value for a section that requires a mapping (#4258) by @haigou-web and @gaborbernat. (#4241) - Preserve empty positional arguments when rewriting relative paths for
change_dir(#4256) by @Fire162 and @gaborbernat. (#4242) base_python_filerejects non-regular files, undecodable content, and version lines over 1024 characters with a handled error naming the file. It reads comments in bounded chunks, so a long comment can still precede the version (#4325) by @rahuldevikar and @gaborbernat. (#4243)base_python_filenow accepts only a Python version specifier (such as3.13orpypy3.10) from the version file. A path or program name there no longer makes tox start that program during interpreter discovery, and the rejected line is not echoed in the error message (#4324) by @rahuldevikar and @gaborbernat. (#4244)- An inline
depsorconstraintsentry that directly substitutes a host variable via{env:NAME}or a TOMLreplace = "env"table now passes${OTHER}text in that value to pip unchanged. A TOML reference to the loaded entry keeps the same behavior. A${NAME}reference written in the configuration or a substitution default still expands (#4329) by @rahuldevikar and @gaborbernat. (#4245) pylocknow evaluates Python and platform markers using a complete environment from the target interpreter. Previously, missing values such asimplementation_versioncame from the Python running tox, which could select a package locked for the wrong interpreter (#4331) by @rahuldevikar and @gaborbernat. (#4246)- For active packages in a
pylock.toml, reject whitespace or control characters in hash tokens, archive or VCS URLs, commit IDs, and subdirectories before writing pip requirements. A line break in one of these fields could add a pip option such as--index-url. The check also covers values pip expands from${VAR}references. Changing a referenced value reinstalls the locked packages (#4315) by @rahuldevikar and @gaborbernat. (#4247) - A direct URL entry in
requires(such astox @ file:///path/to/tox.whl) now triggers provisioning unless the installed distribution'sdirect_url.jsonrecords the requested source, including a supported archive hash, subdirectory, or VCS revision. pip discards fragment fields such asegg; these no longer trigger repeat provisioning. When the installer omits credentials from the origin record, a credentialed direct URL without a requested archive hash fails with an explanation instead of hanging during provisioning (#4314) by @rahuldevikar and @gaborbernat. (#4248) - tox now rejects sdist members whose paths or link targets escape the extraction directory. On Python versions without the
tarfiledata filter, tox checks each member as it extracts the archive (#4316) by @rahuldevikar and @gaborbernat. (#4249) - Report the file and line number for an invalid
set_envfile line, since its content may contain a secret (#4298) by @r3wretrhy and @gaborbernat. (#4250) - Keep input bytes out of
tox configINI, JSON, and TOML output when a configuration key reads non-UTF-8 data (#4302) by @ducanhnguyen223, ducanhnguyen223 and @gaborbernat. (#4251) - A pre-existing symlink at
.tox-info.jsonno longer supplies cached state. When tox writes state, it replaces the link and leaves its target untouched (#4322) by @rahuldevikar and @gaborbernat. (#4253) - When rebuilding a stale bootstrap environment for
virtualenv_spec, tox removes a link at the cache path and creates the replacement withoutvenv'sclearoption. A link placed there after cleanup and before directory creation stops the rebuild without emptying its target (#4313) by @rahuldevikar and @gaborbernat. (#4254) - Redirected Windows output now escapes characters its code page cannot encode instead of raising
UnicodeEncodeError. The stream keeps its encoding (#4257) by @haigou-web and @gaborbernat. (#4255) - Read the Docs now fetches Git history and tags before installing tox, so VCS version detection can satisfy
tox-uv(#4337) by @gaborbernat. (#4336) - A host variable substituted through
set_envintodepsorconstraintsnow keeps${NAME}text literal for pip. A${NAME}written in the configuration still expands (#4342) by @gaborbernat. (#4338) - On Windows, building a
virtualenv_specbootstrap environment no longer writes through a junction swapped into its cache entry. A linked project work directory still works; the work directory must allow temporary subdirectories (#4341) by @gaborbernat. (#4339) test_parallel_generaluses an absolute missing-interpreter path to avoid Windows registry probes in CI (#4346) by @gaborbernat. (#4344)- A
set_envline with a substituted key keeps its value in one variable, even when the input contains a line break. A key that expands to=or a line separator raises an error (#4265) by @gaborbernat. - A host environment value selected by
{env:NAME}that references itself twice could stall tox during recursive expansion. tox now stops expansion at the first depth-limit hit, logs one warning, and leaves the remaining text unexpanded (#4272) by @gaborbernat. - An included
set_envkeeps{env:...}values intact when the source environment inherits the setting, usessetenvor comes from a generative section. The TOML string form"{[env.name]set_env}"does the same. Line breaks,;andfile|text inside values no longer becomeset_envsyntax (#4268) by @gaborbernat. - An invalid
pylock.toml, including malformed TOML or non-UTF-8 bytes, now reportsinvalid pylock filewith the filename and the parser or decoder error instead of an internal traceback (#4215) by @PRINCE2-AI, Prince and @gaborbernat. - Help with an invalid
-cconfiguration now looks for an inline plugin in the requested file's parent directory or inside the selected directory (#4267) by @gaborbernat. - INI commands now keep a path reference such as
{tox_root},{env_tmp_dir}or{env_python}within one argument, including when the path contains spaces, quotes or backslashes. The same applies to tox-provided values such as{host_python}and{tox_root_name}, entries of a list such as{base_python}, and file names matched by{glob:PATTERN}. Command values set with-xorTOX_OVERRIDEfollow the same rule (#4290) by @gaborbernat. - INI commands that reference
depsnow preserve each pip option operand as one argument. A substituted--find-linkspath containing spaces can no longer add options to the command. Thetox configdisplay escapes spaces, quotes and backslashes in those operands (#4276) by @gaborbernat. - Keep a substitution within the quoted INI command argument it is part of:
"--title={env:TITLE}"is one argument even when the value ofTITLEholds quotes or whitespace, as it is for a TOML argument array. tox used to paste the value into the command text before splitting it, so a quote in the value ended the argument and the rest of the value arrived as further arguments of the command.install_commandandlist_dependencies_commandget the same handling (#4283) by @gaborbernat. - Mask credentials in
requiresdirect URLs in missing-requirement messages and echoed provisioning commands (#4334) by @gaborbernat. - Mask secret-looking inline flag values in result JSON command lists, retry warnings, subprocess start errors, path debug logs, unknown-argument errors, and
ExecuteRequestrepresentations (#4264) by @gaborbernat. - On POSIX, tox now pins each directory on the path to the project root while reading or changing a
.venvredirect. A concurrent path swap can no longer redirect removal or replacement into another directory (#4308) by @gaborbernat. - On POSIX, tox now resolves relative commands and
PATHentries from the command's working directory. Theallowlist_externalscheck andTOX_LIMITED_SHEBANGinterpreter selection use the file that the child executes (#4275) by @gaborbernat. - On Windows, INI command references such as
{[testenv:a]commands}now preserve argument boundaries when a positional argument contains an apostrophe or backslash.tox configdisplays the command with the same quoting tox uses to parse a reference (#4277) by @gaborbernat. - On Windows, tox pins the project path while reading or changing a
.venvredirect. A concurrent directory rename or junction added to an empty project directory cannot redirect a write or removal into another project. Redirect writes replace.venvwith a temporary file, leaving the target of a swapped.venvsymlink or hard link unchanged (#4335) by @gaborbernat. - On Windows, tox quotes arguments passed to
.batand.cmdcommands forcmd.exe. Values containing shell operators or percent signs reach the batch file without starting another command or expanding environment variables. Batch scripts that inspect raw%1may now see surrounding quotes for arguments that need them (#4288) by @gaborbernat. - Pass each
base_pythonentry to virtualenv as a separate--pythonargument. virtualenv split the oldVIRTUALENV_PYTHONvalue on commas andos.pathsep, then tried the first candidate last; that could start an unintended program (#4292) by @gaborbernat. - Prefix normalized dependency paths whose first component starts with
-using./on POSIX or.\on Windows. The resulting pip argument no longer starts with-(#4266) by @gaborbernat. - Preserve
#in INI references to paths, sochange_dir,env_dirandset_env = file|...use the checkout directory when its name contains#. On POSIX, requirement-file paths with a space before#remain readable (#4285) by @gaborbernat. - Preserve frozen dependency constraints when using
--no-captureor setting up an environment withtox exec(#4301) by @Pratham2511 and @gaborbernat. - Reject a bootstrap cache parent that already resolves outside the work directory before opening its lock or creating an environment (#4345) by @gaborbernat.
- Reject a line break in a substitution within one
depsorconstraintsentry, and a backslash ending a substituted requirement line. Also reject line breaks and trailing backslashes in globbed requirement paths and provisioning requirements. These values can no longer add pip options or consume the following entry (#4295) by @gaborbernat. - Reject an entry separator supplied by a substitution within an INI list, set, dictionary or
env_listentry. This prevents a value inside onerequiresentry from adding a requirement, and a value inside oneenv_listentry from selecting another environment. A substitution that occupies a whole entry can still expand to several entries. The same check applies to text overrides supplied with-xorTOX_OVERRIDE(#4284) by @gaborbernat. - Replace line breaks in positional arguments before quoting them for
{posargs}and INI command references. This prevents a line break in one argument from starting another command (#4294) by @gaborbernat. - Shell completion now uses the
-c/--confpath from the typed line when loadingtoxfile.pyand offering environments. While that path is incomplete, completion loads no inline plugin (#4278) by @gaborbernat. - The provisioned tox now starts with Python's safe path option. During its
-m toxre-exec, Python no longer puts the start directory first onsys.path, where an unrelated file could replace tox or a dependency (#4270) by @gaborbernat. - Validate built-in command options before selecting an inline plugin. An invalid option value no longer causes tox to import a plugin from an unselected project. Put
-c/--confor--rootbefore options defined by an inline plugin (#4281) by @gaborbernat. - Values expanded from secret-named environment variables in requirements files no longer appear in the install cache, recreation warnings, or file-read errors. tox may recreate an existing environment once to replace a cache written by an older version (#4280) by @gaborbernat.
- When positional arguments supply the command, as in
tox execorcommands = {posargs}, tox now leaves a bare program name such aspythonunchanged. It also leaves a bare executable first positional value unchanged, including when a command uses that value as data, because wrappers can run it as a program. A same-named file in the start directory no longer replaces the environment's program. An explicit path such as./pythonstill followsargs_are_paths(#4289) by @gaborbernat. - With
TOX_LIMITED_SHEBANGenabled, tox now keeps quote and backslash characters in an unquoted shebang interpreter path. They no longer change the executable tox starts. The existing double-quoted form for paths with spaces remains supported (#4274) by @gaborbernat. - With
args_are_pathson POSIX, tox now rewrites positional paths from the resolvedchange_dir. A linked.toxcan no longer redirect a positional path to a file beside the link target (#4273) by @gaborbernat. pylockanddependency_groupsnow usepackage_rootwhen a run has no package environment. They previously usedtox_rootin that case (#4299) by @pcbeingused333 and @gaborbernat.- tox now rejects environment names that are not a single path component before creating an environment. This prevents a substituted
env_list, label or package environment name from selecting a directory outsidework_dir(#4271) by @gaborbernat. - tox now resolves relative
env_dir,env_tmp_dir,env_log_dir,work_dir,temp_dir,package_root,meta_dir,pkg_dirandpackage_globvalues againsttox_root. Withtox -c path/to/tox.inistarted elsewhere, it no longer clears or reuses those directories in the start directory or selects a package from there (#4291) by @gaborbernat. - tox passes positional arguments,
{glob:PATTERN}matches andTOX_FACTOR_<label>overrides literally in INI configuration: a{...}or[]in them is no longer substituted again, sotox run -- '{env:SECRET}'hands the command{env:SECRET}instead of the variable's value andtox run -- '{posargs} -x'stays one argument. TheDEFAULTSof{posargs:DEFAULTS}and referenced keys still expand their own substitutions (#4286) by @gaborbernat.
Security
- Keep virtualenv's pip seeder debug line visible and mask secret-named environment values before tox prints it (#4293) by @gaborbernat.
- Mask secret-looking inline flags inside a command argument when INI parsing leaves several words in that argument (#4263) by @gaborbernat.
- Reject pip options added through partial
depsorconstraintssubstitutions, including${VAR}expansion. tox still accepts options written on the same line in either setting (#4297) by @gaborbernat. - Replace stale package staging links under the work directory and reject staging paths another account can change. Create the staged package exclusively so a substituted destination link cannot overwrite its target (#4305) by @gaborbernat.
- Validate
virtualenv_specas avirtualenvrequirement with optional version specifiers before invoking pip (#4261) by @gaborbernat. - Where descriptor-based
rmtreeandO_DIRECTORY/O_NOFOLLOWare available, clean environment, log, and temporary directories relative to an open directory descriptor so a symlink swap cannot redirect deletions outside tox's work directory. Replace a link already at the cleanup path without emptying its target (#4296) by @gaborbernat. set_envenvironment files now split entries only at LF or CR line endings. Embedded Unicode separators no longer start a new variable (#4260) by @gaborbernat.
New Contributors
- @Doomguy-BFG9000 made their first contribution in #4279
- @Anandb71 made their first contribution in #4269
- @haigou-web made their first contribution in #4257
- @Fire162 made their first contribution in #4256
- @Pratham2511 made their first contribution in #4301
- @santhiprakash made their first contribution in #4306
- @faresrafat3 made their first contribution in #4303
- @PRINCE2-AI made their first contribution in #4215
- @ducanhnguyen223 made their first contribution in #4302