Skip to content

Latest commit

 

History

History
201 lines (157 loc) · 8.16 KB

README.md

File metadata and controls

201 lines (157 loc) · 8.16 KB

pyproject-installer

This tool is intended to build wheel from Python source tree and install it.

Description

  • Supported platform: Unix.
    Currently, platform-specific parts:

    • pipe is used for calling build backend hooks in subprocess
    • script wrappers are generated only for Unix systems
  • OS environment of this project is a network-isolated environment, which implies that a local loopback interface is the only available network interface. Thus, pyproject-installer doesn't perform any network activity (e.g. it doesn't install build dependencies specified via PEP518 configuration or PEP517's get_requires_for_* hooks). This also makes it difficult or impossible to create an isolated Python environment for calling build backend hooks specified in PEP517, therefore, current Python environment is the only available environment.

  • Source tree can be either checkout of VCS or unpacked source distribution.

  • An installation result will be consumed by external tool like RPM.
    The main usage of pyproject-installer looks like:

    external tool => (pyproject-installer: build => install to destdir) => external tool packages destdir
    

    Therefore, there is no need to build intermediate source distribution for build wheel, only build_wheel backend's hook is actually called.

    Note: an installation into Python virtual environment is also supported, but only the manual uninstallation of such packages is possible (tools should refuse an uninstallation of distribution with missing RECORD file).

  • Only stdlib or vendored dependencies can be used in runtime for bootstrapping any Python project.
    Currently, only tomli (used for parsing pyproject.toml configuration file) is vendored by pyproject_installer.

    Note: tomli is the part of stdlib since Python 3.11.

  • Installation of build dependencies is up to the caller.
    Moreover, parsing of build requirements requires two additional external packages: packaging and its dependency pyparsing. But since the validation of build dependencies is optional (disabled by default) there is no point to vendor them.

  • There is no post-installation bytecompilation.
    PEP427 says that wheel installers should compile any installed .py to .pyc. External tools like RPM already provide Python bytecompilation means, which compile for multiple optimization levels at a time. No point to compile modules twice.

  • RECORD file is not installed.
    https://peps.python.org/pep-0627/#optional-record-file:

    Specifically, the RECORD file is unnecessary when projects are installed by a Linux system packaging system, which has its own ways to keep track of files, uninstall them or check their integrity. Having to keep a RECORD file in sync with the disk and the system package database would be unreasonably fragile, and no RECORD file is better than one that does not correspond to reality.

  • INSTALLER file is not installed by default(optional).
    https://peps.python.org/pep-0627/#optional-installer-file:

    The INSTALLER file is also made optional, and specified to be used for informational purposes only. It is still a single-line text file containing the name of the installer.

    https://packaging.python.org/en/latest/specifications/recording-installed-packages/#the-installer-file:

    This value should be used for informational purposes only. For example, if a tool is asked to uninstall a project but finds no RECORD file, it may suggest that the tool named in INSTALLER may be able to do the uninstallation.

Usage

Build

python -m pyproject_installer build

Build positional arguments:

description: source directory
default: current working directory
example: python -m pyproject_installer build .

Build options:

name: --outdir OUTDIR, -o OUTDIR
description: output directory for built wheel
default: {srcdir}/dist
example: python -m pyproject_installer build --outdir ~/outdir

Upon successful build pyproject_installer dumps wheel filename into {OUTDIR}/.wheeltracker.

name: --sdist
description: build source distribution(sdist) instead of binary
one(wheel).
note: installer supports only wheel format.
default: build wheel
example: python -m pyproject_installer build --sdist
name: --backend-config-settings BACKEND_CONFIG_SETTINGS
description: ad-hoc configuration for build backend as dumped JSON dictionary
default: None

Example of passing config_settings for setuptools>=64.0.0 backend:
python -m pyproject_installer build --backend-config-settings='{"--build-option": ["--python-tag=sometag", "--build-number=123"]}'

Example of passing config_settings for setuptools<64.0.0 backend:
python -m pyproject_installer build --backend-config-settings='{"--global-option": ["--python-tag=sometag", "--build-number=123"]}'

Example of passing config_settings for pdm backend:
python -m pyproject_installer build --backend-config-settings='{"--python-tag": "sometag"}'

Install

python -m pyproject_installer install

Install positional arguments:

description: wheel file to install
default: contructed as directory {cwd}/dist and wheel filename read from
{cwd}/dist/.wheeltracker
example: python -m pyproject_installer install wheel.whl

Install options:

name: --destdir DESTDIR, -d DESTDIR
description: Wheel installation root will be prepended with destdir
default: /
example: python -m pyproject_installer install --destdir ~/destdir
name: --installer INSTALLER
description: Name of installer to be recorded in dist-info/INSTALLER
default: None, INSTALLER will be omitted
example: python -m pyproject_installer install --installer custom_installer
name: --no-strip-dist-info
description: Don't strip dist-info. By default only METADATA
and entry_points.txt files are allowed in dist-info directory.
note: RECORD is unconditionally filtered out.
default: False
example: python -m pyproject_installer install --no-strip-dist-info

Comparison with other tools

pyproject-installer consists of builder and installer, both provide only necessary and sufficient functionality.

builder

Functionally, today's builder is similar to build.
The key differences are:

  • highly specialized defaults (see description)
  • highly specialized features to drop extra runtime dependencies like pep517 or packaging. No point to vendor pep517 to call only build_wheel backend hook in subprocess.

installer

Functionally, today's installer is similar to installer.
The key differences are:

  • highly specialized defaults and features (see description)

Both can be replaced with pip. But again, no point to use full-featured complex pip to highly specialized task.

Bootstrap

There is a self-hosted build backend to avoid dependency on any other backend.

For example, bootstrap can be done as:

export PYTHONPATH=$(pwd)/src
python -m pyproject_installer build
python -m pyproject_installer install --destdir=/rootdir

License

Distributed under the terms of the MIT license, pyproject-installer is free and open source software.