TL;DR: Improving package author’s ability to expressive requirements will help more than it will hurt, with some more removal examples.
It is clearly misused sometimes, but does that mean we shouldn’t allow it at all? I would not give up the ability to quickly add a cap for a broken package just so I could force everyone else to avoid adding needless upper caps! During the numpy 2 transition, we needed <2
for a while. As bad as needless upper caps are, it’s a really important feature. I think this default extra feature is similar - it can be misused, but overall it’s an important feature that will help far more than it harms.
Again, for a closer comparison, see Rust. I think it works very well there. That’s a similar situation, with first-party distribution and dependencies. Apt, conda, etc. are all third-party repackagers.
It’s much easier to come up with examples of adding packages (like adding virtualenv to build), since we can take advantage of this right away. The removing examples (like removing the two technically optional dependencies of build) will take time, everyone needs to be on a version of pip that supports it before it can be done.
Removing example: I’ve added the pyproject.toml
parsing requirements to scikit-build-core (by vending pyproject-metadata and making the ignore-file parsing dep required). But all plugins now have to download this extra package (or two if I unvendor pyproject-metadata again); they don’t need these, since they are only used for the native builder. With this proposal, I could remove them again, and people who don’t read the docs and just pip install scikit-build-core
and try to do a non-isolated build (everyone) will still be happy. No one noticed or understood that they had to do pip install scikit-build-core[pyproject]
. But plugins could easily depend on scikit-build-core[nopyproject]
instead of vanilla scikit-build-core
, since that’s not every user, but just a few plugins that users use.
Nox could also remove virtualenv
from the requirements as it can use venv
, like build. But it’s not used in bootstrapping, so virtualenv
is in the requirements. Also argcomplete
and maybe colorlog
are in nox
’s requirements, but really could be optional. A lot of packages have added a hard dependency on uv
, like hatch
and tox-uv
. But it’s much better to have a single install of uv
(like the one I’m using to manage hatch
and tox
!), and then not install it in every venv. I could do that if I could opt-out of the uv
requirement. I’d say many packages have “optional” dependencies in the requirements, because there’s no out-out mechanism.
Splitting packages has a developer cost. Now you have to have two packages. Distros might not package the CLI package. You have to handle upper/lower bounds between your CLI and package. Python tooling is pretty bad at monorepos, so that’s usually multiple repos and tags. And making a CLI opt-out instead of opt-in makes the user experience better. My example would be repo-review. I don’t want to make the CLI required, since that would require downloading CLI dependencies when using it as a library, most notably for the WASM version. I really don’t want to download click and rich in a web browser, I want that minimal. But that means pipx run repo-review
and uvx repo-review
don’t work - it’s pipx run repo-review[cli]
and uvx --extra cli repo-review
(I think the [cli]
syntax is supported now there as well, or is about to be). If I split it into another package, like pipx run repo-review-cli
, that’s not a better user experience either, actually. Users still have to find and use the CLI package. (and uvx
doesn’t provide a nice way to have mismatched names, so it would be uvx --from repo-review-cli repo-review
). However, I don’t mind depending repo-review[]
or repo-review[minimal]
in the web app, or if I add it as requirements to another package. That’s not something you type all the time (see harmful example below)!
Another example: validate-pyproject has to require minimal dependencies, as it’s used in setuptools. However, the dependencies it’s missing are things like trove-classifier validation, packaging(!), and tomli (on older Pythons). In fact, I’d argue most build backends might like to depend on trove-classifiers by default, but won’t unless there’s a way to opt out.
Harmful example: I think it’s worth writing out how this could be misused. Say someone has a package for solving Rubik’s cubes, we’ll call it cube
. It’s really minimal, but has a fancy matplotlib integration that allows it to draw 3D cubes. This PEP comes out, and they add matplotlib as a default extra. That itself is not overly harmful, since anyone who needs the minimal package can still get it (say for WASM, or in a library). The harm comes if someone writes a package that depends on that package and doesn’t know to either disable the default extra or reexport it as a new extra. Note that this new package would also need to be able to handle matplotlib missing, or stripping the default extra is actually wrong! Let’s say the new package is cube-animation
- that probably would actually break horribly if matplotlib was missing, depending on cube
with the default would be correct. It’s only if the package, say cube-algs
, didn’t touch the matplotlib parts or made it’s integration also optional that it would be a bug to depend on cube
and not cube[minimal]
(if someone was using that new package in WASM or in a library). IMO, this is pretty convoluted to worry too much about, and if it happened it would be an easy PR to suggest. And today, the hypothetical[^1] cube
package might decide to add matplotlib
to the requirements, and then you’d have the same situation except there is no way to avoid the extra bloat (and in real packages, especially in scientific packages, this is pretty common!).
Overall, I think it allows package authors to more accurately describe what they actually require and expect most users to need. It will improve the bootstrapping story and allow some key packages to reduce their footprint. It might even encourage packages to minimize required dependencies. And it will help some cases where going with minimal dependencies has hurt users who are just using pip/pipx/uvx.