|
| 1 | +PEP: 660 |
| 2 | +Title: Editable installs for PEP 517 style build backends |
| 3 | +Author: Daniel Holth <dholth@gmail.com>, Stéphane Bidoul <stephane.bidoul@gmail.com> |
| 4 | +Sponsor: Paul Moore <p.f.moore@gmail.com> |
| 5 | +Discussions-To: https://discuss.python.org/t/draft-pep-editable-installs-for-pep-517-style-build-backends/8510 |
| 6 | +Status: Draft |
| 7 | +Type: Standards Track |
| 8 | +Content-Type: text/x-rst |
| 9 | +Created: 30-Mar-2021 |
| 10 | +Post-History: |
| 11 | + |
| 12 | + |
| 13 | +Abstract |
| 14 | +======== |
| 15 | + |
| 16 | +This document describes a PEP 517 style method for the installation of packages |
| 17 | +in editable mode. |
| 18 | + |
| 19 | +Motivation |
| 20 | +========== |
| 21 | + |
| 22 | +Python programmers want to be able to develop packages without having to |
| 23 | +install (i.e. copy) them into ``site-packages``, for example, by working in a |
| 24 | +checkout of the source repository. |
| 25 | + |
| 26 | +While this can be done by adding the relevant source directories to |
| 27 | +``PYTHONPATH``, ``setuptools`` provides the ``setup.py develop`` mechanism that |
| 28 | +makes the process easier, and also installs dependencies and entry points such |
| 29 | +as console scripts. ``pip`` exposes this mechanism via its ``pip install |
| 30 | +--editable`` option. |
| 31 | + |
| 32 | +The installation of projects in such a way that the python code being |
| 33 | +imported remains in the source directory is known as the *editable* |
| 34 | +installation mode. |
| 35 | + |
| 36 | +Now that PEP 517 provides a mechanism to create alternatives to setuptools, and |
| 37 | +decouple installation front ends from build backends, we need a new mechanism |
| 38 | +to install packages in editable mode. |
| 39 | + |
| 40 | +Rationale |
| 41 | +========= |
| 42 | + |
| 43 | +PEP 517 deferred "Editable installs", meaning non-``setup.py`` |
| 44 | +distributions lacked that feature. The only way to retain ``editable`` installs |
| 45 | +for these distributions was to provide a compatible ``setup.py develop`` |
| 46 | +implementation. By definining an editable hook other build frontends gain |
| 47 | +parity with ``setup.py``. |
| 48 | + |
| 49 | +Terminology and goals |
| 50 | +===================== |
| 51 | + |
| 52 | +The editable installation mode implies that the source code of the project |
| 53 | +being installed is available in a local directory. |
| 54 | + |
| 55 | +Once the project is installed in editable mode, users expect that changes to |
| 56 | +the project *python* code in the local source tree become effective without the |
| 57 | +need of a new installation step. |
| 58 | + |
| 59 | +Some kind of changes, such as the addition or modification of entry points, or |
| 60 | +the addition of new dependencies, require a new installation step to become |
| 61 | +effective. These changes are typically made in build backend configuration |
| 62 | +files (such as ``pyproject.toml``), so it is consistent with the general user |
| 63 | +expectation that *python* source code is imported from the source tree. |
| 64 | + |
| 65 | +The modification of non-python source code such a C extension modules obviously |
| 66 | +require a compilation and/or installation step to become effective. The exact |
| 67 | +steps to perform will remain specific to the build backend used. |
| 68 | + |
| 69 | +When a project is installed in editable mode, users expect the installation to |
| 70 | +behave identically as a regular installation. Depending on the way build |
| 71 | +backends implement this specification, some minor differences may be visible |
| 72 | +such as the presence of additional files that are in the source tree and would |
| 73 | +not be part of a regular install. Build backends are encouraged to document |
| 74 | +such potential differences. |
| 75 | + |
| 76 | +The Mechanism |
| 77 | +============= |
| 78 | + |
| 79 | +This PEP adds a single optional hook to the PEP 517 backend interface. The hook |
| 80 | +is used to build a wheel that, when installed, allows that distribution to be |
| 81 | +imported from its source folder. |
| 82 | + |
| 83 | +build_wheel_for_editable |
| 84 | +------------------------ |
| 85 | + |
| 86 | +:: |
| 87 | + |
| 88 | + def build_wheel_for_editable( |
| 89 | + wheel_directory, |
| 90 | + scheme=scheme, |
| 91 | + config_settings=None): |
| 92 | + ... |
| 93 | + |
| 94 | +``scheme``: a dictionary of installation categories ``{ 'purelib': |
| 95 | +'/home/py/.../site-packages', 'platlib': '...'}``. This makes it possible to |
| 96 | +use relative paths to the source code, which might help the interpreter find |
| 97 | +the package after the root path changes with ``chroot`` or similar. |
| 98 | + |
| 99 | +Must build a ``.whl`` file, and place it in the specified ``wheel_directory``. |
| 100 | +It must return the basename (not the full path) of the .whl file it creates, as |
| 101 | +a unicode string. |
| 102 | + |
| 103 | +May do an in-place build of the distribution as a side effect so that any |
| 104 | +extension modules or other built artifacts are ready to be used. |
| 105 | + |
| 106 | +The .whl file must comply with the Wheel binary file format specification (PEP |
| 107 | +427). In particular it must contain a compliant .dist-info directory. |
| 108 | +Metadata must be identical as the one that would have been produced by |
| 109 | +``build_wheel`` or ``prepare_metadata_for_build_wheel``, except for |
| 110 | +``Requires-Dist`` which may differ slightly as explained below. |
| 111 | + |
| 112 | +Build-backends must produce wheels that have the same dependencies |
| 113 | +(``Requires-Dist`` metadata) as wheels produced by the ``build_wheel`` hook, |
| 114 | +with the exception that they can add dependencies necessary for their editable |
| 115 | +mechanism to function at runtime (such as `editables`_). |
| 116 | + |
| 117 | +The filename for the “editable” wheel needs to be PEP 427 compliant too. It |
| 118 | +does not need to use the same tags as ``build_wheel`` but it must be tagged as |
| 119 | +compatible with the system. |
| 120 | + |
| 121 | +An “editable” wheel uses the wheel format not for distribution but as ephemeral |
| 122 | +communication between the build system and the front end. This avoids having |
| 123 | +the build backend install anything directly. This wheel must not be exposed |
| 124 | +to end users, nor cached, nor distributed. |
| 125 | + |
| 126 | +get_requires_for_build_wheel_for_editable |
| 127 | +----------------------------------------- |
| 128 | + |
| 129 | +:: |
| 130 | + |
| 131 | + def get_requires_for_build_wheel_for_editable(config_settings=None): |
| 132 | + ... |
| 133 | + |
| 134 | +This hook MUST return an additional list of strings containing PEP 508 |
| 135 | +dependency specifications, above and beyond those specified in the |
| 136 | +``pyproject.toml`` file, to be installed when calling the |
| 137 | +``build_wheel_for_editable`` hooks. |
| 138 | + |
| 139 | +If not defined, the default implementation is equivalent to ``return []``. |
| 140 | + |
| 141 | + |
| 142 | +What to put in the wheel |
| 143 | +------------------------ |
| 144 | + |
| 145 | +Build backends may use different techniques to achive the goals of an editable |
| 146 | +install. This section provides examples and is not normative. |
| 147 | + |
| 148 | +* Build backends may choose to place a ``.pth`` file at the root of the ``.whl`` file, |
| 149 | + containing the root directory of the source tree. This approach is simple but |
| 150 | + not very precise, although it may be considered good enough (especially when |
| 151 | + using the ``src`` layout) and is similar to what ``setup.py develop`` |
| 152 | + currently does. |
| 153 | +* The `editables`_ library shows how to build proxy modules that |
| 154 | + provide a high quality editable installation. It accepts a list of modules |
| 155 | + to include, and hide. When imported, these proxy modules replace themselves |
| 156 | + with the code from the source tree. Path-based methods make all scripts under |
| 157 | + a path importable, often including the project's own ``setup.py`` and other |
| 158 | + scripts that would not be part of a normal installation. The proxy strategy |
| 159 | + can achieve a higher level of fidelity than path-based methods. |
| 160 | + |
| 161 | +Frontend requirements |
| 162 | +--------------------- |
| 163 | + |
| 164 | +Frontends must install editable wheels in the same way as regular wheels. |
| 165 | +This also means uninstallation of editables does not require any special treatment. |
| 166 | + |
| 167 | +Frontends must create a ``direct_url.json`` file in the ``.dist-info`` |
| 168 | +directory of the installed distribution, in compliance with PEP 610. The |
| 169 | +``url`` value must be a ``file://`` url pointing to the project directory |
| 170 | +(i.e. the directory containing ``pyproject.toml``), and the ``dir_info`` value |
| 171 | +must be ``{'editable': true}``. |
| 172 | + |
| 173 | +Frontends must execute ``get_requires_for_build_wheel_for_editable`` hooks in |
| 174 | +an environment which contains the bootstrap requirements specified in the |
| 175 | +``pyproject.toml`` file. |
| 176 | + |
| 177 | +Frontends must execute the ``build_wheel_for_editable`` hook in an environment |
| 178 | +which contains the bootstrap requirements from ``pyproject.toml`` and those |
| 179 | +specified by the ``get_requires_for_build_wheel_for_editable`` hook. |
| 180 | + |
| 181 | +Frontends must not rely on the ``prepare_metadata_for_build_wheel`` hook when |
| 182 | +installing in editable mode. They must use ``build_wheel_for_editable`` and |
| 183 | +inspect the resulting wheel. |
| 184 | + |
| 185 | +Frontends must not expose the wheel obtained from ``build_wheel_for_editable`` |
| 186 | +to end users. The wheel must be discarded after installation and must not be |
| 187 | +cached nor distributed. |
| 188 | + |
| 189 | +Rejected ideas |
| 190 | +============== |
| 191 | + |
| 192 | +The ideas of having build backends append or modify the local version |
| 193 | +identifier to include the ``editable`` string has been rejected because it |
| 194 | +would not satisfy ``==`` version speicifier that include the local version |
| 195 | +identifier. In other workds ``pkg==1.0+local`` is not satisfied by version |
| 196 | +``1.0+local.editable``. |
| 197 | + |
| 198 | +References |
| 199 | +========== |
| 200 | + |
| 201 | +.. _`editables`: https://pypi.org/project/editables/ |
| 202 | + |
| 203 | +Copyright |
| 204 | +========= |
| 205 | + |
| 206 | +This document is placed in the public domain or under the |
| 207 | +CC0-1.0-Universal license, whichever is more permissive. |
| 208 | + |
| 209 | + |
| 210 | + |
| 211 | +.. |
| 212 | + Local Variables: |
| 213 | + mode: indented-text |
| 214 | + indent-tabs-mode: nil |
| 215 | + sentence-end-double-space: t |
| 216 | + fill-column: 70 |
| 217 | + coding: utf-8 |
| 218 | + End: |
0 commit comments