Sneaking onto my computer for a few minutes but I wanted to just add:
I think the question of whether something lives in pip or twine or some other random tool that may or may not exist right now to be a bit premature. We don’t even know for sure what “it” it yet, so trying to figure out where to put it is harder because everyone has different ideas about what “it” is.
Likewise, I think whether whatever “it” is is implemented as a monolith, as a wrapper around other more focused tools, or libraries, or whatever combination is also premature, and also an implementation detail of “it”. We’ve learned that monoliths are generally bad, and whatever we do here people are likely going to want to reuse at least parts of it, so whatever we pick is likely going be to implemented in a way that other approaches can re-use them.
So basically, I don’t think we need to legislate where our end goal lives OR that we’re going to implement it with sound engineering practices towards reusability.
So what do we need to figure out? Basically what is the UX we’re trying to present here. The way I see it there are a few possible options:
- An all-in-one tool that does everything from installation to upload to building.
- It does not implement a PEP 517 backend though.
- Think npm or cargo style.
- It’s possible that the “overlap problem” (see below) is narrow enough in scope that most commands are top level (
install
, upload
), but then you have a few commands that either have longer names, or are namespaced inside of a sub command for a specific persona (foo install
, foo upload
, foo build wheel
, foo download-as-wheels
).
- Persona driven tools, aka “I’m an project author” tool vs “I’m a project user” tool.
- Think pip vs twine + flit/setuptools/etc in the current ecosystem.
- It’s possible that (2) isn’t even two tools! For example, you could have a
foo
command where all of the top level commands are focused on the “larger” persona (consumers), and then a sub command group that itself has other sub commands that handles the “smaller” persona (authors). So you’d end up with like foo install
, foo wheel
(produces a wheel house), foo build {wheel, sdist, upload}
.
- Unix philosophy, highly focused one tool per task.
Again, to be clear 1 can be implemented on top of either 2 or 3, and 2 can be implemented on top of 3. That doesn’t mean we should pick 3, because we shouldn’t be focusing on how we implement it, just what our default UX is.
Personally I find (3) to be a big no from me. I think expecting users to install different commands for each thing they do to be confusing and complex, and I think our users will hate us for it.
So to me, it really comes down to 1 vs 2, and that’s where I’m not really sure and I could easily argue one way or another here.
In favor of (1) it’s the simplest in terms of end users needing to figure out where some functionality lives-- if there’s only one tool then it all lives there (again, ignoring implementation concerns like splitting out libraries/tools etc). However I think it has a real problem in terms of the varying user personas and what they’d want out of a tool.
For instance, in the “build a wheel command”, a consumer persona is going to want the tool and it’s options focusing on primarily downloading from a repository, and building up an entire directory full of wheels. It’s going to want to fetch the entire dependency graph and ultimately produce a “wheelhouse” that can be installed from offline. However, an author is more likely going to want to produce a wheel from an existing sdist they already have locally (probably from a “build a sdist command”) and isn’t going to want to build the entire dependency graph, just that one wheel. Even beyond that you’re going to have things like, a consumer isn’t likely going to want a way to specify the specific Python tag they expect the generate wheel to have (and since you’re potentially building multiple wheels you’ll need some syntax for specifying different tags for different wheels in that case), but a project author quite possibly is going to want that functionality.
In favor of (2) is that by splitting along the lines of these “personas”, we can drastically simplify the cases where there are overlapping concerns. The current split of “twine upload” would be super simple to add to pip, because a consumer would just never call “pip upload”, so there’s no overlap there. However for the build wheel case, if we split the tooling by persona, we can have the “consumer” persona focused on producing a wheel house from a set of requirements and the “producer” persona is focused on producing a single artifact from a local sdist.
The big downside of (2) is that absent any other concerns, two tools is more complexity for end users than one tool, so we need to figure out if the “overlaping commands” complexity outweighs the additional complexity of having two tools in our “default” UX, or whether the overlap isn’t really that bad and it would be better UX to have a single tool handle it all.
There’s also the question of environment management, and whether that should be part of this discussion or whether these tools should just operate on an existing environment. Personally I’m happy to say that at a minimum, all of these tools are going to need to at least support being invoked against an existing environment, so we can consider environment management at a later date.
Once we figure out what the overlap is, and how bad of a problem it is, and what our ideal shape of the “default” ux is, then we can start figuring out if it would make sense to pip that in pip, twine, or some completely different tool.