Skip to content

Commit 6bf89ca

Browse files
committed
Merge PEP 660 implementation (#3488)
2 parents 68157e5 + 2a30946 commit 6bf89ca

38 files changed

+2982
-316
lines changed

bootstrap.egg-info/entry_points.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
egg_info = setuptools.command.egg_info:egg_info
33
build_py = setuptools.command.build_py:build_py
44
sdist = setuptools.command.sdist:sdist
5+
editable_wheel = setuptools.command.editable_wheel:editable_wheel
56

67
[distutils.setup_keywords]
78
include_package_data = setuptools.dist:assert_bool

changelog.d/3265.breaking.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
Added implementation for *editable install* hooks (PEP 660).
2+
3+
By default the users will experience a *lenient* behavior which prioritises
4+
the ability of the users of changing the distributed packages (e.g. adding new
5+
files or removing old ones).
6+
But they can also opt into a *strict* mode, which will try to replicate as much
7+
as possible the behavior of the package as if it would be normally installed by
8+
end users. The *strict* editable installation is not able to detect if files
9+
are added or removed from the project (a new installation is required).
10+
11+
.. important::
12+
The *editable* aspect of the *editable install* supported this implementation
13+
is restricted to the Python modules contained in the distributed package.
14+
Changes in binary extensions (e.g. C/C++), entry-point definitions,
15+
dependencies, metadata, datafiles, etc may require a new installation.

changelog.d/3380.change.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Improved the handling of the ``config_settings`` parameter in both PEP 517 and
2+
PEP 660 interfaces:
3+
4+
- It is possible now to pass both ``--global-option`` and ``--build-option``.
5+
As discussed in #1928, arbitrary arguments passed via ``--global-option``
6+
should be placed before the name of the setuptools' internal command, while
7+
``--build-option`` should come after.
8+
9+
- Users can pass ``editable-mode=strict`` to select a strict behaviour for the
10+
editable installation.

changelog.d/3380.deprecation.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Passing some types of parameters via ``--global-option`` to setuptools PEP 517/PEP 660 backend
2+
is now considered deprecated. The user can pass the same arbitrary parameter
3+
via ``--build-option`` (``--global-option`` is now reserved for flags like
4+
``--verbose`` or ``--quiet``).
5+
6+
Both ``--build-option`` and ``--global-option`` are supported as a **transitional** effort (a.k.a. "escape hatch").
7+
In the future a proper list of allowed ``config_settings`` may be created.

changelog.d/3392.change.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Exposed ``get_output_mapping()`` from ``build_py`` and ``build_ext``
2+
subcommands. This interface is reserved for the use of ``setuptools``
3+
Extensions and third part packages are explicitly disallowed to calling it.
4+
However, any implementation overwriting ``build_py`` or ``build_ext`` are
5+
required to honour this interface.

changelog.d/3412.change.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Added ability of collecting source files from custom build sub-commands to
2+
``sdist``. This allows plugins and customization scripts to automatically
3+
add required source files in the source distribution.

changelog.d/3414.change.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Users can *temporarily* specify an environment variable
2+
``SETUPTOOLS_ENABLE_FEATURE=legacy-editable`` as a escape hatch for the
3+
:pep:`660` behavior. This setting is **transitional** and may be removed in the
4+
future.

changelog.d/3414.doc.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Updated :doc:`Development Mode </userguide/development_mode>` to reflect on the
2+
implementation of :pep:`660`.

changelog.d/3484.change.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Added *transient* ``compat`` mode to editable installs.
2+
This more will be temporarily available (to facilitate the transition period)
3+
for those that want to emulate the behavior of the ``develop`` command
4+
(in terms of what is added to ``sys.path``).
5+
This mode is provided "as is", with limited support, and will be removed in
6+
future versions of ``setuptools``.
Lines changed: 257 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,260 @@
1-
Development Mode
2-
================
3-
4-
Under normal circumstances, the ``setuptools`` assume that you are going to
5-
build a distribution of your project, not use it in its "raw" or "unbuilt"
6-
form. However, if you were to use the ``setuptools`` to build a distribution,
7-
you would have to rebuild and reinstall your project every time you made a
8-
change to it during development.
9-
10-
Another problem that sometimes comes is that you may
11-
need to do development on two related projects at the same time. You may need
12-
to put both projects' packages in the same directory to run them, but need to
13-
keep them separate for revision control purposes. How can you do this?
14-
15-
Setuptools allows you to deploy your projects for use in a common directory or
16-
staging area, but without copying any files. Thus, you can edit each project's
17-
code in its checkout directory, and only need to run build commands when you
18-
change files that need to be compiled or the provided metadata and setuptools configuration.
19-
20-
You can perform a ``pip`` installation passing the ``-e/--editable``
21-
flag (e.g., ``pip install -e .``). It works very similarly to
22-
``pip install .``, except that it doesn't actually install anything.
23-
Instead, it creates a special ``.egg-link`` file in the target directory
24-
(usually ``site-packages``) that links to your project's source code.
25-
It may also update an existing ``easy-install.pth`` file
26-
to include your project's source code, thereby making
27-
it available on ``sys.path`` for all programs using that Python installation.
28-
29-
You can deploy the same project to multiple staging areas, e.g., if you have
30-
multiple projects on the same machine that are sharing the same project you're
31-
doing development work.
1+
Development Mode (a.k.a. "Editable Installs")
2+
=============================================
3+
4+
When creating a Python project, developers usually want to implement and test
5+
changes iteratively, before cutting a release and preparing a distribution archive.
6+
7+
In normal circumstances this can be quite cumbersome and require the developers
8+
to manipulate the ``PATHONPATH`` environment variable or to continuous re-build
9+
and re-install the project.
10+
11+
To facilitate iterative exploration and experimentation, setuptools allows
12+
users to instruct the Python interpreter and its import machinery to load the
13+
code under development directly from the project folder without having to
14+
copy the files to a different location in the disk.
15+
This means that changes in the Python source code can immediately take place
16+
without requiring a new installation.
17+
18+
You can enter this "development mode" by performing an :doc:`editable installation
19+
<pip:topics/local-project-installs>` inside of a :term:`virtual environment`,
20+
using :doc:`pip's <pip:cli/pip_install>` ``-e/--editable`` flag, as shown bellow:
21+
22+
.. code-block:: bash
23+
24+
$ cd your-python-project
25+
$ python -m venv .venv
26+
# Activate your environemt with:
27+
# `source .venv/bin/activate` on Unix/macOS
28+
# or `.venv\Scripts\activate` on Windows
29+
30+
$ pip install --editable .
31+
32+
# Now you have access to your package
33+
# as if it was installed in .venv
34+
$ python -c "import your_python_project"
35+
36+
37+
An "editable installation" works very similarly to a regular install with
38+
``pip install .``, except that it only installs your package dependencies,
39+
metadata and wrappers for :ref:`console and GUI scripts <console-scripts>`.
40+
Under the hood, setuptools will try to create a special :mod:`.pth file <site>`
41+
in the target directory (usually ``site-packages``) that extends the
42+
``PYTHONPATH`` or install a custom :doc:`import hook <python:reference/import>`.
3243

3344
When you're done with a given development task, you can simply uninstall your
3445
package (as you would normally do with ``pip uninstall <package name>``).
46+
47+
Please note that, by default an editable install will expose at least all the
48+
files that would be available in a regular installation. However, depending on
49+
the file and directory organization in your project, it might also expose
50+
as a side effect files that would not be normally available.
51+
This is allowed so you can iteratively create new Python modules.
52+
Please have a look on the following section if you are looking for a different behaviour.
53+
54+
.. admonition:: Virtual Environments
55+
56+
You can think about virtual environments as "isolated Python runtime deployments"
57+
that allow users to install different sets of libraries and tools without
58+
messing with the global behaviour of the system.
59+
60+
They are a safe way of testing new projects and can be created easily
61+
with the :mod:`venv` module from the standard library.
62+
63+
Please note however that depending on your operating system or distribution,
64+
``venv`` might not come installed by default with Python. For those cases,
65+
you might need to use the OS package manager to install it.
66+
For example, in Debian/Ubuntu-based systems you can obtain it via:
67+
68+
.. code-block:: bash
69+
70+
sudo apt install python3-venv
71+
72+
Alternatively, you can also try installing :pypi:`virtualenᴠ`.
73+
More information is available on the Python Packaging User Guide on
74+
:doc:`PyPUG:guides/installing-using-pip-and-virtual-environments`.
75+
76+
.. note::
77+
.. versionchanged:: v64.0.0
78+
Editable installation hooks implemented according to :pep:`660`.
79+
Support for :pep:`namespace packages <420>` is still **EXPERIMENTAL**.
80+
81+
82+
"Strict" editable installs
83+
--------------------------
84+
85+
When thinking about editable installations, users might have the following
86+
expectations:
87+
88+
1. It should allow developers to add new files (or split/rename existing ones)
89+
and have them automatically exposed.
90+
2. It should behave as close as possible to a regular installation and help
91+
users to detect problems (e.g. new files not being included in the distribution).
92+
93+
Unfortunately these expectations are in conflict with each other.
94+
To solve this problem ``setuptools`` allows developers to choose a more
95+
*"strict"* mode for the editable installation. This can be done by passing
96+
a special *configuration setting* via :pypi:`pip`, as indicated bellow:
97+
98+
.. code-block:: bash
99+
100+
pip install -e . --config-settings editable_mode=strict
101+
102+
In this mode, new files **won't** be exposed and the editable installs will
103+
try to mimic as much as possible the behavior of a regular install.
104+
Under the hood, ``setuptools`` will create a tree of file links in an auxiliary
105+
directory (``$your_project_dir/build``) and add it to ``PYTHONPATH`` via a
106+
:mod:`.pth file <site>`. (Please be careful to not delete this repository
107+
by mistake otherwise your files may stop being accessible).
108+
109+
.. warning::
110+
Strict editable installs require auxiliary files to be placed in a
111+
``build/__editable__.*`` directory (relative to your project root).
112+
113+
Please be careful to not remove this directory while testing your project,
114+
otherwise your editable installation may be compromised.
115+
116+
You can remove the ``build/__editable__.*`` directory after uninstalling.
117+
118+
119+
.. note::
120+
.. versionadded:: v64.0.0
121+
Added new *strict* mode for editable installations.
122+
The exact details of how this mode is implemented may vary.
123+
124+
125+
Limitations
126+
-----------
127+
128+
- The *editable* term is used to refer only to Python modules
129+
inside the package directories. Non-Python files, external (data) files,
130+
executable script files, binary extensions, headers and metadata may be
131+
exposed as a *snapshot* of the version they were at the moment of the
132+
installation.
133+
- Adding new dependencies, entry-points or changing your project's metadata
134+
require a fresh "editable" re-installation.
135+
- Console scripts and GUI scripts **MUST** be specified via :doc:`entry-points
136+
</userguide/entry_point>` to work properly.
137+
- *Strict* editable installs require the file system to support
138+
either :wiki:`symbolic <symbolic link>` or :wiki:`hard links <hard link>`.
139+
This installation mode might also generate auxiliary files under the project directory.
140+
- There is *no guarantee* that the editable installation will be performed
141+
using a specific technique. Depending on each project, ``setuptools`` may
142+
select a different approach to ensure the package is importable at runtime.
143+
- There is *no guarantee* that files outside the top-level package directory
144+
will be accessible after an editable install.
145+
- There is *no guarantee* that attributes like ``__path__`` or ``__file__``
146+
will correspond to the exact location of the original files (e.g.,
147+
``setuptools`` might employ file links to perform the editable installation).
148+
Users are encouraged to use tools like :mod:`importlib.resources` or
149+
:mod:`importlib.metadata` when trying to access package files directly.
150+
- Editable installations may not work with
151+
:doc:`namespaces created with pkgutil or pkg_resouces
152+
<PyPUG:guides/packaging-namespace-packages>`.
153+
Please use :pep:`420`-style implicit namespaces [#namespaces]_.
154+
- Support for :pep:`420`-style implicit namespace packages for
155+
projects structured using :ref:`flat-layout` is still **experimental**.
156+
If you experience problems, you can try converting your package structure
157+
to the :ref:`src-layout`.
158+
159+
.. attention::
160+
Editable installs are **not a perfect replacement for regular installs**
161+
in a test environment. When in doubt, please test your projects as
162+
installed via a regular wheel. There are tools in the Python ecosystem,
163+
like :pypi:`tox` or :pypi:`nox`, that can help you with that
164+
(when used with appropriate configuration).
165+
166+
167+
Legacy Behavior
168+
---------------
169+
170+
If your project is not compatible with the new "editable installs" or you wish
171+
to replicate the legacy behavior, for the time being you can also perform the
172+
installation in the ``compat`` mode:
173+
174+
.. code-block:: bash
175+
176+
pip install -e . --config-settings editable_mode=compat
177+
178+
This installation mode will try to emulate how ``python setup.py develop``
179+
works (still within the context of :pep:`660`).
180+
181+
.. warning::
182+
The ``compat`` mode is *transitional* and will be removed in
183+
future versions of ``setuptools``, it exists only to help during the
184+
migration period.
185+
Also note that support for this mode is limited:
186+
it is safe to assume that the ``compat`` mode is offered "as is", and
187+
improvements are unlikely to be implemented.
188+
Users are encouraged to try out the new editable installation techniques
189+
and make the necessary adaptations.
190+
191+
If the ``compat`` mode does not work for you, you can also disable the
192+
:pep:`editable install <660>` hooks in ``setuptools`` by setting an environment
193+
variable:
194+
195+
.. code-block::
196+
197+
SETUPTOOLS_USE_FEATURE="legacy-editable"
198+
199+
This *may* cause the installer (e.g. ``pip``) to effectively run the "legacy"
200+
installation command: ``python setup.py develop`` [#installer]_.
201+
202+
203+
How editable installations work?
204+
--------------------------------
205+
206+
*Advanced topic*
207+
208+
There are many techniques that can be used to expose packages under development
209+
in such a way that they are available as if they were installed.
210+
Depending on the project file structure and the selected mode, ``setuptools``
211+
will choose one of these approaches for the editable installation [#criteria]_.
212+
213+
A non-exhaustive list of implementation mechanisms is presented below.
214+
More information is available on the text of :pep:`PEP 660 <660#what-to-put-in-the-wheel>`.
215+
216+
- A static ``.pth`` file [#static_pth]_ can be added to one of the directories
217+
listed in :func:`site.getsitepackages` or :func:`site.getusersitepackages` to
218+
extend :obj:`sys.path`.
219+
- A directory containing a *farm of file links* that mimic the
220+
project structure and point to the original files can be employed.
221+
This directory can then be added to :obj:`sys.path` using a static ``.pth`` file.
222+
- A dynamic ``.pth`` file [#dynamic_pth]_ can also be used to install an
223+
"import :term:`finder`" (:obj:`~importlib.abc.MetaPathFinder` or
224+
:obj:`~importlib.abc.PathEntryFinder`) that will hook into Python's
225+
:doc:`import system <python:reference/import>` machinery.
226+
227+
.. attention::
228+
``Setuptools`` offers **no guarantee** of which technique will be used to
229+
perform an editable installation. This will vary from project to project
230+
and may change depending on the specific version of ``setuptools`` being
231+
used.
232+
233+
234+
----
235+
236+
.. rubric:: Notes
237+
238+
.. [#namespaces]
239+
You *may* be able to use *strict* editable installations with namespace
240+
packages created with ``pkgutil`` or ``pkg_namespaces``, however this is not
241+
officially supported.
242+
243+
.. [#installer]
244+
For this workaround to work, the installer tool needs to support legacy
245+
editable installations. (Future versions of ``pip``, for example, may drop
246+
support for this feature).
247+
248+
.. [#criteria]
249+
``setuptools`` strives to find a balance between allowing the user to see
250+
the effects of project files being edited while still trying to keep the
251+
editable installation as similar as possible to a regular installation.
252+
253+
.. [#static_pth]
254+
i.e., a ``.pth`` file where each line correspond to a path that should be
255+
added to :obj:`sys.path`. See :mod:`Site-specific configuration hook <site>`.
256+
257+
.. [#dynamic_pth]
258+
i.e., a ``.pth`` file that starts where each line starts with an ``import``
259+
statement and executes arbitrary Python code. See :mod:`Site-specific
260+
configuration hook <site>`.

0 commit comments

Comments
 (0)