I see tox
, nox
, and hatch
as solving four problems at once right now :
- They define task definition formats (
nox
is sorta cheating though )
- They define task backends which can “do the work” of environment management
- They define task frontends which can invoke those backends
- They define task frontends which can examine and present that task definition data
(1) is tox.ini
, [tool.hatch.envs]
in pyproject.toml
, noxfile.py
(“just” the data format)
(2) is tox._scary_backend_modules
, hatch._also_intense_backend_code
, nox._nope_im_scared_of_all_of_these_modules
(3) is the CLI interface provided via tox
, nox
, and hatch
(the commands, not the packages) which lets you do stuff.
(4) is the CLI interface provided via tox list
, tox config
, hatch env show
, and so forth.
If we want to only standardize (1), then we’re probably restricted to a strict subset of what tox
, hatch
, and nox
already support. I’m not clear that there’s value in that if we go with “the minimal subset”. We’ll lose many valuable features that way.
If we standardize (1) with something small plus add a tool to the standard distribution which can do an intentionally very limited version of (2-4), with the note that “if you want more than this, use tox
, hatch
, nox
, or something like that”, I could easily and enthusiastically get onboard.
I think it does solve a real problem, and if (1) is backed by a standard, then, e.g., hatch
can support reading from it to be compatible, but still say “you should really use [tool.hatch.envs]
if you don’t need to interoperate”.
Imagine such a tool exists, python -m $TOOL
.
I can then define a bootstrapping flow alongside simplistic cases:
[task.lint]
requires = ["pre-commit"]
invocation = ["pre-commit", "run", "-a"]
[task.test-all]
requires = ["tox>=4"]
invocation = ["tox", "run-parallel"]
I might never, in practical fact, run tox
in this way. python -m $TOOL test-all
is not as nice as tox p
in my shell, after all.
But someone new to the project can show up, run python -m $TOOL lint
and expect it to do something. The invocation is declared somewhere which will introduce them to the project.
I’ve tried to narrow the standardization effort. There’s no notion of a uniform task backend in this suggestion, nor are any of the CLI interfaces or similar standardized. There’s some standardized data format, and a concrete new tool which uses that data.
Trying to discuss this without talking about introducing a tool which is an ultra simple wrapper over venv
, pip
, and subprocess
(or exec? I think subprocess
) feels to me like we’re pushing too much from the outside to unify concepts in tox
, hatch
, uv
, etc. without buy in or a champion amongst their maintainers.
As we all know, their feature-sets are overlapping but not identical. I think we have to enthusiastically embrace the fact that they’ve solved bigger problems than are in-scope for any centralized community effort.