pypa / installer

A low-level library for installing from a Python wheel distribution.
https://installer.readthedocs.io/
MIT License
126 stars 51 forks source link

How to bootstrap? #150

Closed adamjstewart closed 1 year ago

adamjstewart commented 1 year ago

@pradyunsg I'm considering adding the ability to use build/installer as an alternative to pip in Spack. The first step is bootstrapping. How would I install installer without the presence of pip/installer/build/flit/setuptools/distutils/etc?

For pip, we use the advice in https://discuss.python.org/t/bootstrapping-a-specific-version-of-pip/12306 (using the wheel to install itself). Would something similar be possible with installer?

eli-schwartz commented 1 year ago

Yes, that should work. I've done the same thing myself although with

PYTHONPATH=$PWD/dist/installer-*.whl python -m installer dist/installer-*.whl
pradyunsg commented 1 year ago

Closing this out since the question has been answered. :)

adamjstewart commented 1 year ago

Just remembered we're still waiting for a new release since we need the functionality in https://github.com/pypa/installer/pull/103 in order to properly use installer in Spack. Once there's a new release, I'll update Spack so that build/installer can bootstrap themselves. For future me, the package recipe will look like:

import os

from spack.package import *

class PyInstaller(Package, PythonExtension):
    """A library for installing Python wheels."""

    homepage = "https://github.com/pradyunsg/installer"
    url = "https://files.pythonhosted.org/packages/py3/i/installer/installer-0.6.0-py3-none-any.whl"
    list_url = "https://pypi.org/simple/installer/"

    maintainers = ["adamjstewart", "pradyunsg"]

    version("0.6.0", sha256="...", expand=False)

    extends("python")

    def install(self, spec, prefix):
        # To build and install installer from source, you need flit-core, build, and installer
        # already installed. We get around this by using a pre-built wheel to install itself.
        # See https://github.com/pypa/installer/issues/150 for details.

        # We can't do this in setup_build_environment because self.stage.archive_file is undefined
        wheel = self.stage.archive_file
        path = os.environ.get("PYTHONPATH", "")
        os.environ["PYTHONPATH"] = os.pathsep.join([wheel, path])

        args = ["-m", "installer", "--prefix", prefix, wheel]
        python(*args)

    def setup_dependent_package(self, module, dependent_spec):
        installer = dependent_spec["python"].command
        installer.add_default_arg("-m")
        installer.add_default_arg("installer")
        setattr(module, "installer", installer)