Skip to content

Commit 43b515b

Browse files
committed
Doc improvements (#3363, #3364, #3367)
- Improve docs by avoiding confusion with distutils - Update dependency management docs - Update userguide on miscellaneous and extension
4 parents eb75ea6 + 3ed077f + b0a6b73 + 2e36857 commit 43b515b

18 files changed

Lines changed: 537 additions & 412 deletions

changelog.d/3363.doc.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Rework some documentation pages to de-emphasize ``distutils`` and the history
2+
of packaging in the Python ecosystem. The focus of these changes is to make the
3+
documentation easier to read for new users.

changelog.d/3364.doc.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Update documentation about dependency management, removing mention to
2+
the deprecated ``dependency_links`` and adding some small improvements.

changelog.d/3367.doc.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Extracted text about automatic resource extraction and the zip-safe flag
2+
from ``userguide/miscellaneous`` to ``deprecated/resource_extraction`` and
3+
``deprecated/zip_safe``.
4+
5+
Extracted text about additional metadata files from
6+
``userguide/miscellaneous`` into the existing ``userguide/extension``
7+
document.
8+
9+
Updated ``userguide/extension`` to better reflect the status of the
10+
setuptools project.
11+
12+
Removed ``userguide/functionalities_rewrite`` (a virtually empty part of the
13+
docs).

docs/build_meta.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ or::
9595

9696
$ pip install dist/meowpkg-0.0.1.tar.gz
9797

98+
99+
.. _backend-wrapper:
100+
98101
Dynamic build dependencies and other ``build_meta`` tweaks
99102
----------------------------------------------------------
100103

docs/conf.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,6 @@
178178

179179
# Allow linking objects on other Sphinx sites seamlessly:
180180
intersphinx_mapping.update(
181-
python2=('https://docs.python.org/2', None),
182181
python=('https://docs.python.org/3', None),
183182
)
184183

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
Specifying dependencies that aren't in PyPI via ``dependency_links``
2+
====================================================================
3+
4+
.. warning::
5+
Dependency links support has been dropped by pip starting with version
6+
19.0 (released 2019-01-22).
7+
8+
If your project depends on packages that don't exist on PyPI, you *may* still be
9+
able to depend on them if they are available for download as:
10+
11+
- an egg, in the standard distutils ``sdist`` format,
12+
- a single ``.py`` file, or
13+
- a VCS repository (Subversion, Mercurial, or Git).
14+
15+
You need to add some URLs to the ``dependency_links`` argument to ``setup()``.
16+
17+
The URLs must be either:
18+
19+
1. direct download URLs,
20+
2. the URLs of web pages that contain direct download links, or
21+
3. the repository's URL
22+
23+
In general, it's better to link to web pages, because it is usually less
24+
complex to update a web page than to release a new version of your project.
25+
You can also use a SourceForge ``showfiles.php`` link in the case where a
26+
package you depend on is distributed via SourceForge.
27+
28+
If you depend on a package that's distributed as a single ``.py`` file, you
29+
must include an ``"#egg=project-version"`` suffix to the URL, to give a project
30+
name and version number. (Be sure to escape any dashes in the name or version
31+
by replacing them with underscores.) EasyInstall will recognize this suffix
32+
and automatically create a trivial ``setup.py`` to wrap the single ``.py`` file
33+
as an egg.
34+
35+
In the case of a VCS checkout, you should also append ``#egg=project-version``
36+
in order to identify for what package that checkout should be used. You can
37+
append ``@REV`` to the URL's path (before the fragment) to specify a revision.
38+
Additionally, you can also force the VCS being used by prepending the URL with
39+
a certain prefix. Currently available are:
40+
41+
- ``svn+URL`` for Subversion,
42+
- ``git+URL`` for Git, and
43+
- ``hg+URL`` for Mercurial
44+
45+
A more complete example would be:
46+
47+
``vcs+proto://host/path@revision#egg=project-version``
48+
49+
Be careful with the version. It should match the one inside the project files.
50+
If you want to disregard the version, you have to omit it both in the
51+
``requires`` and in the URL's fragment.
52+
53+
This will do a checkout (or a clone, in Git and Mercurial parlance) to a
54+
temporary folder and run ``setup.py bdist_egg``.
55+
56+
The ``dependency_links`` option takes the form of a list of URL strings. For
57+
example, this will cause a search of the specified page for eggs or source
58+
distributions, if the package's dependencies aren't already installed:
59+
60+
.. tab:: setup.cfg
61+
62+
.. code-block:: ini
63+
64+
[options]
65+
#...
66+
dependency_links = http://peak.telecommunity.com/snapshots/
67+
68+
.. tab:: setup.py
69+
70+
.. code-block:: python
71+
72+
setup(
73+
...,
74+
dependency_links=[
75+
"http://peak.telecommunity.com/snapshots/",
76+
],
77+
)

docs/deprecated/index.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@ objectives.
1414
:maxdepth: 1
1515

1616
changed_keywords
17+
dependency_links
1718
python_eggs
1819
easy_install
20+
zip_safe
21+
resource_extraction
1922
distutils/index
2023
distutils-legacy
2124
functionalities
25+
running_commands
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
.. _Automatic Resource Extraction:
2+
3+
Automatic Resource Extraction
4+
=============================
5+
6+
In a modern setup, Python packages are usually installed as directories,
7+
and all the files can be found on deterministic locations on the disk.
8+
This means that most of the tools expect package resources to be "real" files.
9+
10+
There are a few occasions however that packages are loaded in a different way
11+
(e.g., from a zip file), which is incompatible with the assumptions mentioned above.
12+
Moreover, a package developer may also include non-extension native libraries or other files that
13+
C extensions may expect to be able to access.
14+
15+
In these scenarios, the use of :mod:`importlib.resources` is recommended.
16+
17+
Old implementations (prior to the advent of :mod:`importlib.resources`) and
18+
long-living projects, however, may still rely on the library ``pkg_resources``
19+
to access these files.
20+
21+
If you have to support such systems, or want to provide backward compatibility
22+
for ``pkg_resources``, you may need to add an special configuration
23+
to ``setuptools`` when packaging a project.
24+
This can be done by listing as ``eager_resources`` (argument to ``setup()``
25+
in ``setup.py`` or field in ``setup.cfg``) all the files that need to be
26+
extracted together, whenever a C extension in the project is imported.
27+
28+
This is especially important if your project includes shared libraries *other*
29+
than ``distutils``/``setuptools``-built C extensions, and those shared libraries use file
30+
extensions other than ``.dll``, ``.so``, or ``.dylib``, which are the
31+
extensions that setuptools 0.6a8 and higher automatically detects as shared
32+
libraries and adds to the ``native_libs.txt`` file for you. Any shared
33+
libraries whose names do not end with one of those extensions should be listed
34+
as ``eager_resources``, because they need to be present in the filesystem when
35+
he C extensions that link to them are used.
36+
37+
The ``pkg_resources`` runtime for compressed packages will automatically
38+
extract *all* C extensions and ``eager_resources`` at the same time, whenever
39+
*any* C extension or eager resource is requested via the ``resource_filename()``
40+
API. (C extensions are imported using ``resource_filename()`` internally.)
41+
This ensures that C extensions will see all of the "real" files that they
42+
expect to see.
43+
44+
Note also that you can list directory resource names in ``eager_resources`` as
45+
well, in which case the directory's contents (including subdirectories) will be
46+
extracted whenever any C extension or eager resource is requested.
47+
48+
Please note that if you're not sure whether you need to use this argument, you
49+
don't! It's really intended to support projects with lots of non-Python
50+
dependencies and as a last resort for crufty projects that can't otherwise
51+
handle being compressed. If your package is pure Python, Python plus data
52+
files, or Python plus C, you really don't need this. You've got to be using
53+
either C or an external program that needs "real" files in your project before
54+
there's any possibility of ``eager_resources`` being relevant to your project.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Running ``setuptools`` commands
2+
===============================
3+
4+
Historically, ``setuptools`` allowed running commands via a ``setup.py`` script
5+
at the root of a Python project, as indicated in the examples below::
6+
7+
python setup.py --help
8+
python setup.py --help-commands
9+
python setup.py --version
10+
python setup.py sdist
11+
python setup.py bdist_wheel
12+
13+
You could also run commands in other circumstances:
14+
15+
* ``setuptools`` projects without ``setup.py`` (e.g., ``setup.cfg``-only)::
16+
17+
python -c "import setuptools; setup()" --help
18+
19+
* ``distutils`` projects (with a ``setup.py`` importing ``distutils``)::
20+
21+
python -c "import setuptools; with open('setup.py') as f: exec(compile(f.read(), 'setup.py', 'exec'))" develop
22+
23+
That is, you can simply list the normal setup commands and options following the quoted part.

docs/deprecated/zip_safe.rst

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
Understanding the ``zip_safe`` flag
2+
===================================
3+
4+
The ``zip_safe`` flag is a ``setuptools`` configuration mainly associated
5+
with the ``egg`` distribution format
6+
(which got replaced in the ecosystem by the newer ``wheel`` format) and the
7+
``easy_install`` command (deprecated in ``setuptools`` v58.3.0).
8+
9+
It is very unlikely that the values of ``zip_safe`` will affect modern
10+
deployments that use :pypi:`pip` for installing packages.
11+
Moreover, new users of ``setuptools`` should not attempt to create egg files
12+
using the deprecated ``build_egg`` command.
13+
Therefore, this flag is considered **obsolete**.
14+
15+
This document, however, describes what was the historical motivation behind
16+
this flag, and how it was used.
17+
18+
Historical Motivation
19+
---------------------
20+
21+
For some use cases (such as bundling as part of a larger application), Python
22+
packages may be run directly from a zip file.
23+
Not all packages, however, are capable of running in compressed form, because
24+
they may expect to be able to access either source code or data files as
25+
normal operating system files.
26+
27+
In the past, ``setuptools`` would install a project distributed
28+
as a zipfile or a directory (via the ``easy_install`` command or
29+
``python setup.py install``),
30+
the default choice being determined by the project's ``zip_safe`` flag.
31+
32+
How the ``zip_safe`` flag was used?
33+
-----------------------------------
34+
35+
To set this flag, a developer would pass a boolean value for the ``zip_safe`` argument to the
36+
``setup()`` function, or omit it. When omitted, the ``bdist_egg``
37+
command would analyze the project's contents to see if it could detect any
38+
conditions that preventing the project from working in a zipfile.
39+
40+
This was extremely conservative: ``bdist_egg`` would consider the
41+
project unsafe if it contained any C extensions or datafiles whatsoever. This
42+
does *not* mean that the project couldn't or wouldn't work as a zipfile! It just
43+
means that the ``bdist_egg`` authors were not yet comfortable asserting that
44+
the project *would* work. If the project did not contain any C or data files, and did not
45+
attempt to perform ``__file__`` or ``__path__`` introspection or source code manipulation, then
46+
there was an extremely solid chance the project will work when installed as a
47+
zipfile. (And if the project used ``pkg_resources`` for all its data file
48+
access, then C extensions and other data files shouldn't be a problem at all.
49+
See the :ref:`Accessing Data Files at Runtime` section for more information.)
50+
51+
The developer could manually set ``zip_safe`` to ``True`` to perform tests,
52+
or to override the default behaviour (after checking all the warnings and
53+
understanding the implications), this would allow ``setuptools`` to install the
54+
project as a zip file. Alternatively, by setting ``zip_safe`` to ``False``,
55+
developers could force ``setuptools`` to always install the project as a
56+
directory.
57+
58+
Modern ways of loading packages from zip files
59+
----------------------------------------------
60+
61+
Currently, popular Python package installers (such as :pypi:`pip`) and package
62+
indexes (such as PyPI_) consider that distribution packages are always
63+
installed as a directory.
64+
It is however still possible to load packages from zip files added to
65+
:obj:`sys.path`, thanks to the :mod:`zipimport` module
66+
and the :mod:`importlib` machinery provided by Python standard library.
67+
68+
When working with modules loaded from a zip file, it is important to keep in
69+
mind that values of ``__file__`` and ``__path__`` might not work as expected.
70+
Please check the documentation for :mod:`importlib.resources`, if file
71+
locations are important for your use case.
72+
73+
74+
.. _PyPI: https://pypi.org

0 commit comments

Comments
 (0)