Skip to content

Commit 0c93c18

Browse files
ncoghlanpfmoore
andauthored
Clarify specs for external installer interactions (#1215)
Co-authored-by: Paul Moore <p.f.moore@gmail.com>
1 parent a103b56 commit 0c93c18

6 files changed

Lines changed: 139 additions & 12 deletions

File tree

source/specifications/direct-url.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ Recording the Direct URL Origin of installed distributions
66
==========================================================
77

88
This document specifies a :file:`direct_url.json` file in the
9-
:file:`*.dist-info` directory of an installed distribution, to record the
10-
Direct URL Origin of the distribution.
9+
``*.dist-info`` directory of an installed distribution, to record the
10+
Direct URL Origin of the distribution. The general structure and usage of
11+
``*.dist-info`` directories is described in :ref:`recording-installed-packages`.
1112

1213
.. contents:: Contents
1314
:local:

source/specifications/entry-points.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,9 @@ File format
8181

8282
Entry points are defined in a file called :file:`entry_points.txt` in the
8383
:file:`*.dist-info` directory of the distribution. This is the directory
84-
described in :pep:`376` for installed distributions, and in :pep:`427` for
85-
wheels. The file uses the UTF-8 character encoding.
84+
described in :ref:`recording-installed-packages` for installed distributions,
85+
and in :ref:`binary-distribution-format` for wheels.
86+
The file uses the UTF-8 character encoding.
8687

8788
The file contents are in INI format, as read by Python's :mod:`configparser`
8889
module. However, configparser treats names as case-insensitive by default,
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
.. _externally-managed-environments:
3+
4+
===============================
5+
Externally Managed Environments
6+
===============================
7+
8+
While some Python installations are entirely managed by the user that installed
9+
Python, others may be provided and managed by another means (such as the
10+
operating system package manager in a Linux distribution, or as a bundled
11+
Python environment in an application with a dedicated installer).
12+
13+
Attempting to use conventional Python packaging tools to manipulate such
14+
environments can be confusing at best and outright break the entire underlying
15+
operating system at worst. Documentation and interoperability guides only go
16+
so far in resolving such problems.
17+
18+
:pep:`668` defined an ``EXTERNALLY-MANAGED`` marker file that allows a Python
19+
installation to indicate to Python-specific tools such as ``pip`` that they
20+
neither install nor remove packages into the interpreter’s default installation
21+
environment, and should instead guide the end user towards using
22+
:ref:`virtual-environments`.

source/specifications/index.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,18 @@ Package Distribution Metadata
2222
declaring-build-dependencies
2323
declaring-project-metadata
2424
platform-compatibility-tags
25+
26+
Package Installation Environment Metadata
27+
-----------------------------------------
28+
29+
.. toctree::
30+
:maxdepth: 1
31+
2532
recording-installed-packages
2633
entry-points
2734
direct-url
28-
35+
virtual-environments
36+
externally-managed-environments
2937

3038
Package Distribution File Formats
3139
---------------------------------

source/specifications/recording-installed-packages.rst

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@ History and change workflow
2121
===========================
2222

2323
The metadata described here was first specified in :pep:`376`, and later
24-
amended in :pep:`627`.
24+
amended in :pep:`627` (and other PEPs).
2525
It was formerly known as *Database of Installed Python Distributions*.
26-
Further amendments (except trivial language or typography fixes) must be made
27-
through the PEP process (see :pep:`1`).
26+
As with other PyPA specifications, editorial amendments with no functional
27+
impact may be made through the GitHub pull request workflow. Proposals for
28+
functional changes that would require amendments to package building and/or
29+
installation tools must be made through the PEP process (see :pep:`1`).
2830

29-
While this document is the normative specification, these PEPs that introduce
31+
While this document is the normative specification, the PEPs that introduce
3032
changes to it may include additional information such as rationales and
3133
backwards compatibility considerations.
3234

@@ -66,12 +68,14 @@ encouraged to start normalizing those fields.
6668
provide API for such tools to consume, so tools can have access to the
6769
unnormalized name when displaying distrubution information.
6870

69-
This ``.dist-info`` directory can contain these files, described in detail
70-
below:
71+
This ``.dist-info`` directory may contain the following files, described in
72+
detail below:
7173

7274
* ``METADATA``: contains project metadata
7375
* ``RECORD``: records the list of installed files.
7476
* ``INSTALLER``: records the name of the tool used to install the project.
77+
* ``entry_points.txt``: see :ref:`entry-points` for details
78+
* ``direct_url.json``: see :ref:`direct-url` for details
7579

7680
The ``METADATA`` file is mandatory.
7781
All other files may be omitted at the installing tool's discretion.
@@ -169,7 +173,7 @@ Here is an example snippet of a possible ``RECORD`` file::
169173

170174
If the ``RECORD`` file is missing, tools that rely on ``.dist-info`` must not
171175
attempt to uninstall or upgrade the package.
172-
(This does not apply to tools that rely on other sources of information,
176+
(This restriction does not apply to tools that rely on other sources of information,
173177
such as system package managers in Linux distros.)
174178

175179

@@ -197,6 +201,18 @@ For example, if a tool is asked to uninstall a project but finds no ``RECORD``
197201
file, it may suggest that the tool named in ``INSTALLER`` may be able to do the
198202
uninstallation.
199203

204+
205+
The entry_points.txt file
206+
=========================
207+
208+
This file MAY be created by installers to indicate when packages contain
209+
components intended for discovery and use by other code, including console
210+
scripts and other applications that the installer has made available for
211+
execution.
212+
213+
Its detailed specification is at :ref:`entry-points`.
214+
215+
200216
The direct_url.json file
201217
========================
202218

@@ -207,3 +223,32 @@ This file MUST NOT be created when installing a distribution from an other type
207223
of requirement (i.e. name plus version specifier).
208224

209225
Its detailed specification is at :ref:`direct-url`.
226+
227+
228+
Intentionally preventing changes to installed packages
229+
======================================================
230+
231+
In some cases (such as when needing to manage external dependencies in addition
232+
to Python ecosystem dependencies), it is desirable for a tool that installs
233+
packages into a Python environment to ensure that other tools are not used to
234+
uninstall or otherwise modify that installed package, as doing so may cause
235+
compatibility problems with the wider environment.
236+
237+
To achieve this, affected tools should take the folllowing steps:
238+
239+
* Rename or remove the ``RECORD`` file to prevent changes via other tools (e.g.
240+
appending a suffix to create a non-standard ``RECORD.tool`` file if the tool
241+
itself needs the information, or omitting the file entirely if the package
242+
contents are tracked and managed via other means)
243+
* Write an ``INSTALLER`` file indicating the name of the tool that should be used
244+
to manage the package (this allows ``RECORD``-aware tools to provide better
245+
error notices when asked to modify affected packages)
246+
247+
Python runtime providers may also prevent inadvertent modification of platform
248+
provided packages by modifying the default Python package installation scheme
249+
to use a location other than that used by platform provided packages (while also
250+
ensuring both locations appear on the default Python import path).
251+
252+
In some circumstances, it may be desirable to block even installation of
253+
additional packages via Python-specific tools. For these cases refer to
254+
:ref:`externally-managed-environments`
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
2+
.. _virtual-environments:
3+
4+
===========================
5+
Python Virtual Environments
6+
===========================
7+
8+
For Python 3.3 and later versions, :pep:`405` introduced interpreter level support
9+
for the concept of "Python Virtual Environments". Each virtual environment has
10+
its own Python binary (allowing creation of environments with various Python
11+
versions) and can have its own independent set of installed Python packages in
12+
its site directories, but shares the standard library with the base installed
13+
Python. While the concept of virtual environments existed prior to this update,
14+
there was no previously standardised mechanism for declaring or discovering them.
15+
16+
17+
Runtime detection of virtual environments
18+
=========================================
19+
20+
At runtime, virtual environments can be identified by virtue of ``sys.prefix``
21+
(the filesystem location of the running interpreter) having a different value
22+
from ``sys.base_prefix`` (the default filesytem location of the standard library
23+
directories).
24+
25+
:ref:`venv-explanation` in the Python standard library documentation for the
26+
:py:mod:`venv` module covers this along with the concept of "activating" a
27+
virtual environment in an interactive operating system shell (this activation
28+
step is optional and hence the changes it makes can't be reliably used to
29+
detect whether a Python program is running in a virtual environment or not).
30+
31+
32+
Declaring installation environments as Python virtual environments
33+
==================================================================
34+
35+
As described in :pep:`405`, a Python virtual environment in its simplest form
36+
consists of nothing more than a copy or symlink of the Python binary accompanied
37+
by a ``site-packages`` directory and a ``pyvenv.cfg`` file with a ``home`` key
38+
that indicates where to find the Python standard library modules.
39+
40+
While designed to meet the needs of the standard :py:mod:`venv` module, this
41+
split installation and ``pyvenv.cfg`` file approach can be used by *any*
42+
Python installation provider that desires Python-specific tools to be aware that
43+
they are already operating in a virtual environment and no further environment
44+
nesting is required or desired.
45+
46+
Even in the absence of a ``pyvenv.cfg`` file, any approach (e.g.
47+
``sitecustomize.py``, patching the installed Python runtime) that results in
48+
``sys.prefix`` and ``sys.base_prefix`` having different values, while still
49+
providing a matching default package installation scheme in ``sysconfig``, will
50+
be detected and behave as a Python virtual environment.

0 commit comments

Comments
 (0)