1
1
Fork 0
mirror of https://github.com/pypa/pip synced 2023-12-13 21:30:23 +01:00

Lint src/pip/_vendor/README.rst

This commit is contained in:
Nguyễn Gia Phong 2020-05-27 16:27:25 +07:00
parent 17608c43d1
commit da9c7c7f69
2 changed files with 51 additions and 54 deletions

View file

@ -4,26 +4,19 @@ Vendoring Policy
* Vendored libraries **MUST** not be modified except as required to
successfully vendor them.
* Vendored libraries **MUST** be released copies of libraries available on
PyPI.
* Vendored libraries **MUST** be available under a license that allows
them to be integrated into ``pip``, which is released under the MIT license.
* Vendored libraries **MUST** be accompanied with LICENSE files.
* The versions of libraries vendored in pip **MUST** be reflected in
``pip/_vendor/vendor.txt``.
* Vendored libraries **MUST** function without any build steps such as ``2to3`` or
compilation of C code, practically this limits to single source 2.x/3.x and
* Vendored libraries **MUST** function without any build steps such as ``2to3``
or compilation of C code, practically this limits to single source 2.x/3.x and
pure Python.
* Any modifications made to libraries **MUST** be noted in
``pip/_vendor/README.rst`` and their corresponding patches **MUST** be
included ``tools/automation/vendoring/patches``.
* Vendored libraries should have corresponding ``vendored()`` entries in
``pip/_vendor/__init__.py``.
@ -41,41 +34,46 @@ higher quality and more battle tested code, centralization of bug fixes
However, there are several issues with having dependencies in the traditional
way (via ``install_requires``) for pip. These issues are:
* **Fragility.** When pip depends on another library to function then if for
whatever reason that library either isn't installed or an incompatible
version is installed then pip ceases to function. This is of course true for
all Python applications, however for every application *except* for pip the
way you fix it is by re-running pip. Obviously, when pip can't run, you can't
use pip to fix pip, so you're left having to manually resolve dependencies and
installing them by hand.
**Fragility**
When pip depends on another library to function then if for whatever reason
that library either isn't installed or an incompatible version is installed
then pip ceases to function. This is of course true for all Python
applications, however for every application *except* for pip the way you fix
it is by re-running pip. Obviously, when pip can't run, you can't use pip to
fix pip, so you're left having to manually resolve dependencies and
installing them by hand.
* **Making other libraries uninstallable.** One of pip's current dependencies is
the ``requests`` library, for which pip requires a fairly recent version to run.
If pip depended on ``requests`` in the traditional manner, then we'd either
have to maintain compatibility with every ``requests`` version that has ever
existed (and ever will), OR allow pip to render certain versions of ``requests``
uninstallable. (The second issue, although technically true for any Python
application, is magnified by pip's ubiquity; pip is installed by default in
Python, in ``pyvenv``, and in ``virtualenv``.)
**Making other libraries uninstallable**
One of pip's current dependencies is the ``requests`` library, for which pip
requires a fairly recent version to run. If pip depended on ``requests`` in
the traditional manner, then we'd either have to maintain compatibility with
every ``requests`` version that has ever existed (and ever will), OR allow
pip to render certain versions of ``requests`` uninstallable. (The second
issue, although technically true for any Python application, is magnified by
pip's ubiquity; pip is installed by default in Python, in ``pyvenv``, and in
``virtualenv``.)
* **Security.** This might seem puzzling at first glance, since vendoring
has a tendency to complicate updating dependencies for security updates,
and that holds true for pip. However, given the *other* reasons for avoiding
dependencies, the alternative is for pip to reinvent the wheel itself.
This is what pip did historically. It forced pip to re-implement its own
HTTPS verification routines as a workaround for the Python standard library's
lack of SSL validation, which resulted in similar bugs in the validation routine
in ``requests`` and ``urllib3``, except that they had to be discovered and
fixed independently. Even though we're vendoring, reusing libraries keeps pip
more secure by relying on the great work of our dependencies, *and* allowing for
faster, easier security fixes by simply pulling in newer versions of dependencies.
**Security**
This might seem puzzling at first glance, since vendoring has a tendency to
complicate updating dependencies for security updates, and that holds true
for pip. However, given the *other* reasons for avoiding dependencies, the
alternative is for pip to reinvent the wheel itself. This is what pip did
historically. It forced pip to re-implement its own HTTPS verification
routines as a workaround for the Python standard library's lack of SSL
validation, which resulted in similar bugs in the validation routine in
``requests`` and ``urllib3``, except that they had to be discovered and
fixed independently. Even though we're vendoring, reusing libraries keeps
pip more secure by relying on the great work of our dependencies, *and*
allowing for faster, easier security fixes by simply pulling in newer
versions of dependencies.
* **Bootstrapping.** Currently most popular methods of installing pip rely
on pip's self-contained nature to install pip itself. These tools work by bundling
a copy of pip, adding it to ``sys.path``, and then executing that copy of pip.
This is done instead of implementing a "mini installer" (to reduce duplication);
pip already knows how to install a Python package, and is far more battle-tested
than any "mini installer" could ever possibly be.
**Bootstrapping**
Currently most popular methods of installing pip rely on pip's
self-contained nature to install pip itself. These tools work by bundling a
copy of pip, adding it to ``sys.path``, and then executing that copy of pip.
This is done instead of implementing a "mini installer" (to reduce
duplication); pip already knows how to install a Python package, and is far
more battle-tested than any "mini installer" could ever possibly be.
Many downstream redistributors have policies against this kind of bundling, and
instead opt to patch the software they distribute to debundle it and make it
@ -100,15 +98,19 @@ such as OS packages.
Modifications
=============
* ``setuptools`` is completely stripped to only keep ``pkg_resources``
* ``pkg_resources`` has been modified to import its dependencies from ``pip._vendor``
* ``packaging`` has been modified to import its dependencies from ``pip._vendor``
* ``setuptools`` is completely stripped to only keep ``pkg_resources``.
* ``pkg_resources`` has been modified to import its dependencies from
``pip._vendor``.
* ``packaging`` has been modified to import its dependencies from
``pip._vendor``.
* ``html5lib`` has been modified to import six from ``pip._vendor``, to prefer
importing from ``collections.abc`` instead of ``collections`` and does not import
``xml.etree.cElementTree`` on Python 3.
* ``CacheControl`` has been modified to import its dependencies from ``pip._vendor``
* ``requests`` has been modified to import its other dependencies from ``pip._vendor``
and to *not* load ``simplejson`` (all platforms) and ``pyopenssl`` (Windows).
importing from ``collections.abc`` instead of ``collections`` and does not
import ``xml.etree.cElementTree`` on Python 3.
* ``CacheControl`` has been modified to import its dependencies from
``pip._vendor``.
* ``requests`` has been modified to import its other dependencies from
``pip._vendor`` and to *not* load ``simplejson`` (all platforms) and
``pyopenssl`` (Windows).
Automatic Vendoring
@ -131,23 +133,18 @@ extra work on your end in order to solve the problems described above.
1. Delete everything in ``pip/_vendor/`` **except** for
``pip/_vendor/__init__.py``.
2. Generate wheels for each of pip's dependencies (and any of their
dependencies) using your patched copies of these libraries. These must be
placed somewhere on the filesystem that pip can access (``pip/_vendor`` is
the default assumption).
3. Modify ``pip/_vendor/__init__.py`` so that the ``DEBUNDLED`` variable is
``True``.
4. Upon installation, the ``INSTALLER`` file in pip's own ``dist-info``
directory should be set to something other than ``pip``, so that pip
can detect that it wasn't installed using itself.
5. *(optional)* If you've placed the wheels in a location other than
``pip/_vendor/``, then modify ``pip/_vendor/__init__.py`` so that the
``WHEEL_DIR`` variable points to the location you've placed them.
6. *(optional)* Update the ``pip_self_version_check`` logic to use the
appropriate logic for determining the latest available version of pip and
prompt the user with the correct upgrade message.