pypa/build

[question] [feature-request] Supporting other (future/hypothetical) installers?

Closed this issue · 4 comments

I found that #751 added support for the --installer flag, which chooses an installer (currently hard-coded to either Pip or uv) to use for creating an isolated build environment. But I couldn't find evidence of a process that solicited the change, and the approval process appears to have been the usual informal discussion among top contributors.

As it happens, in the foreseeable future (I'm hoping I can start next month) I expect to be working on an alternative package install tool. My goals are to correct what I see as design flaws in Pip (emulating many choices made by uv - in particular, being by default a standalone tool outside of the environment - but still using pure Python) and present an elegant design with a smaller footprint. (I also intend to offer an explicit programmatic API - though using that most likely would require installing in the current venv.) In particular, I planned to have build as a dependency, to cover the task of preparing wheels for installation from downloaded sdists.

When I use build in this circumstance (most likely through the programmatic API), I'd like to be able to specify using my own installer, recursively, to set up the build environment. (It would feel rather bad to have Pip as an implicit dependency for a competing installer.)

Similarly, rather than using Pip+venv explicitly to create a build environment, users could plausibly want to use Pipx, or other third-party tools that don't immediately come to mind. (I saw there was some commentary on the PR about designing an interface for environment provisioners, but it doesn't look like it went anywhere.)

What would be involved in supporting such use cases? Is it necessary to enumerate installers in the first place, or could it work to, say, just supply a path to an executable (and assume it has an install sub-command offering some basic API)? Or would everyone who makes an installer (or wants to use an existing one) have to petition (or submit a PR) separately?

Or would I perhaps be better off just forking build, or building the specific functionality I need on top of the lower-level pyproject_hooks, etc.?

If you're gonna be driving build programmatically, you'll be able to swap out the default isolated environment with one of your choosing, with values provided by your tool. Control rests with your tool; build does not define an installer interface.

Ah, I see - programmatic users are meant to be able to implement the IsolatedEnv ABC (perhaps by subclassing DefaultIsolatedEnv, implementing a _EnvBackend and replacing the __enter__ logic to use it) and then create the ProjectBuilder using the @classmethod from_isolated_env (which is missing documentation, BTW). That provides the necessary hooks for venv creation and build requirement installation which can just call the tool's (and venv's) API.

That should allow me to make the implementation work, but it would be nice if my users could use my installer for their own invocations of build.

DefaultIsolatedEnv is public but it's not really intended to be subclassed by consumers of the library. _EnvBackend is private and you shouldn't be plugging alternative installers into DefaultIsolatedEnv. The idea is that you'll install things however you like and simply provide the two bits of information that build requires: the path to the Python executable and any extra env vars. You don't have to do it the way build does, by expanding the IsolatedEnv implementation with a context manager and an install method.

Understood, so then I just do the API equivalent of a no-isolation build, after first explicitly setting up the environment. That seems simpler, yes. (And for build users who want to isolate with my installer, I suppose I could offer my own wrapper for that process, or just document what's necessary... actually, come to think of it, I might want to offer "read the build dependencies from pyproject.toml and install them" separately, since my tool is primarily aimed at "users" rather than "developers".)

Sorry, I'm rambling now. I think my question is answered and there's no clear need to implement anything in build.