Skip to content

Conversation

webknjaz
Copy link
Contributor

@webknjaz webknjaz commented Sep 2, 2025

Previously (PR #3591) a new hook point was added. The tests checked that it works well with the tox config and tox list commands. However, tox run turned out to have a problem — it would complain that there's no such env, when invoked:

ROOT: 170 E HandledError| provided environments not found in configuration file:
pip-compile-tox-env-lock [tox/run.py:23]

Turned out, this was because the config object is being interated twice in some subcommands. This in turn iterates over the discovered additional ephemeral environments list object. The implementation passes an iterator into it and so when it's first accessed, it's exhausted and the second attempt does not give the same envs, causing inconsistency.

The patch solves this by using itertools.tee(), making sure that the underlying iterable is always cached and it's possible to repeat iteration as many times as possible without loosing the data in the process.

  • ran the linter to address style issues (tox -e fix)
  • wrote descriptive pull request text
  • ensured there are test(s) validating the fix
  • added news fragment in docs/changelog folder
  • updated/extended the documentation

Previously (PR tox-dev#3591) a new hook point was added. The tests checked
that it works well with the `tox config` and `tox list` commands.
However, `tox run` turned out to have a problem — it would complain
that there's no such env, when invoked:

```console
ROOT: 170 E HandledError| provided environments not found in configuration file:
pip-compile-tox-env-lock [tox/run.py:23]
```

Turned out, this was because the config object is being interated twice
in some subcommands. This in turn iterates over the discovered
additional ephemeral environments list object. The implementation passes
an iterator into it and so when it's first accessed, it's exhausted and
the second attempt does not give the same envs, causing inconsistency.

The patch solves this by using `itertools.tee()`, making sure that the
underlying iterable is always cached and it's possible to repeat
iteration as many times as possible without loosing the data in the
process.
@webknjaz webknjaz marked this pull request as ready for review September 2, 2025 14:16
@webknjaz webknjaz marked this pull request as draft September 2, 2025 14:18
@webknjaz
Copy link
Contributor Author

webknjaz commented Sep 2, 2025

Urgh.. it looks like the fix doesn't work on older Pythons (3.11 and lower). I'll take a look.

Before Python 3.11, the first value is the the underlying iterator. And
we still exhaust it. So for backwards compatibility, we request two
iterators and disregard the first one.
@webknjaz webknjaz marked this pull request as ready for review September 2, 2025 15:40
@webknjaz webknjaz marked this pull request as draft September 2, 2025 16:07
@webknjaz webknjaz marked this pull request as ready for review September 2, 2025 16:18
@webknjaz
Copy link
Contributor Author

webknjaz commented Sep 2, 2025

@gaborbernat this is now ready for inclusion in v4.29.1

@gaborbernat gaborbernat merged commit 48fecab into tox-dev:main Sep 2, 2025
29 checks passed
@webknjaz
Copy link
Contributor Author

webknjaz commented Sep 2, 2025

@gaborbernat could you release when you have time?

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.

2 participants