From 086a7ee3837bfc000d4b1c8f5dec32d99d5a4a2e Mon Sep 17 00:00:00 2001 From: Polina Date: Thu, 2 Jul 2026 19:44:47 +0000 Subject: [PATCH] =?UTF-8?q?=D0=97=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D1=84=D0=B0=D0=B9=D0=BB=D1=8B=20=D0=B2=20=C2=AB?= =?UTF-8?q?venv/Lib/site-packages/pip/=5Fvendor=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- venv/Lib/site-packages/pip/_vendor/README.rst | 180 ++++++++++++++++++ .../Lib/site-packages/pip/_vendor/__init__.py | 117 ++++++++++++ venv/Lib/site-packages/pip/_vendor/vendor.txt | 19 ++ 3 files changed, 316 insertions(+) create mode 100644 venv/Lib/site-packages/pip/_vendor/README.rst create mode 100644 venv/Lib/site-packages/pip/_vendor/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/vendor.txt diff --git a/venv/Lib/site-packages/pip/_vendor/README.rst b/venv/Lib/site-packages/pip/_vendor/README.rst new file mode 100644 index 0000000..a925e8c --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/README.rst @@ -0,0 +1,180 @@ +================ +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 + pure Python. +* Any modifications made to libraries **MUST** be noted in + ``pip/_vendor/README.rst`` and their corresponding patches **MUST** be + included ``tools/vendoring/patches``. +* Vendored libraries should have corresponding ``vendored()`` entries in + ``pip/_vendor/__init__.py``. + +Rationale +========= + +Historically pip has not had any dependencies except for ``setuptools`` itself, +choosing instead to implement any functionality it needed to prevent needing +a dependency. However, starting with pip 1.5, we began to replace code that was +implemented inside of pip with reusable libraries from PyPI. This brought the +typical benefits of reusing libraries instead of reinventing the wheel like +higher quality and more battle tested code, centralization of bug fixes +(particularly security sensitive ones), and better/more features for less work. + +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. + +**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. + +**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 +rely on the global versions of the software that they already have packaged +(which may have its own patches applied to it). We (the pip team) would prefer +it if pip was *not* debundled in this manner due to the above reasons and +instead we would prefer it if pip would be left intact as it is now. + +In the longer term, if someone has a *portable* solution to the above problems, +other than the bundling method we currently use, that doesn't add additional +problems that are unreasonable then we would be happy to consider, and possibly +switch to said method. This solution must function correctly across all of the +situation that we expect pip to be used and not mandate some external mechanism +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``, and to use the vendored copy of ``platformdirs`` + rather than ``appdirs``. +* ``packaging`` has been modified to import its dependencies from + ``pip._vendor``. +* ``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). +* ``platformdirs`` has been modified to import its submodules from ``pip._vendor.platformdirs``. + +Automatic Vendoring +=================== + +Vendoring is automated via the `vendoring `_ tool from the content of +``pip/_vendor/vendor.txt`` and the different patches in +``tools/vendoring/patches``. +Launch it via ``vendoring sync . -v`` (requires ``vendoring>=0.2.2``). +Tool configuration is done via ``pyproject.toml``. + +To update the vendored library versions, we have a session defined in ``nox``. +The command to upgrade everything is:: + + nox -s vendoring -- --upgrade-all --skip urllib3 --skip setuptools + +At the time of writing (April 2025) we do not upgrade ``urllib3`` because the +next version is a major upgrade and will be handled as an independent PR. We also +do not upgrade ``setuptools``, because we only rely on ``pkg_resources``, and +tracking every ``setuptools`` change is unnecessary for our needs. + + +Managing Local Patches +====================== + +The ``vendoring`` tool automatically applies our local patches, but updating, +the patches sometimes no longer apply cleanly. In that case, the update will +fail. To resolve this, take the following steps: + +1. Revert any incomplete changes in the revendoring branch, to ensure you have + a clean starting point. +2. Run the revendoring of the library with a problem again: ``nox -s vendoring + -- --upgrade ``. +3. This will fail again, but you will have the original source in your working + directory. Review the existing patch against the source, and modify the patch + to reflect the new version of the source. If you ``git add`` the changes the + vendoring made, you can modify the source to reflect the patch file and then + generate a new patch with ``git diff``. +4. Now, revert everything *except* the patch file changes. Leave the modified + patch file unstaged but saved in the working tree. +5. Re-run the vendoring. This time, it should pick up the changed patch file + and apply it cleanly. The patch file changes will be committed along with the + revendoring, so the new commit should be ready to test and publish as a PR. + + +Debundling +========== + +As mentioned in the rationale, we, the pip team, would prefer it if pip was not +debundled (other than optionally ``pip/_vendor/requests/cacert.pem``) and that +pip was left intact. However, if you insist on doing so, we have a +semi-supported method (that we don't test in our CI) and requires a bit of +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`` and ``pip/_vendor/vendor.txt``. +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. + +Note that partial debundling is **NOT** supported. You need to prepare wheels +for all dependencies for successful debundling. diff --git a/venv/Lib/site-packages/pip/_vendor/__init__.py b/venv/Lib/site-packages/pip/_vendor/__init__.py new file mode 100644 index 0000000..34ccb99 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/__init__.py @@ -0,0 +1,117 @@ +""" +pip._vendor is for vendoring dependencies of pip to prevent needing pip to +depend on something external. + +Files inside of pip._vendor should be considered immutable and should only be +updated to versions from upstream. +""" +from __future__ import absolute_import + +import glob +import os.path +import sys + +# Downstream redistributors which have debundled our dependencies should also +# patch this value to be true. This will trigger the additional patching +# to cause things like "six" to be available as pip. +DEBUNDLED = False + +# By default, look in this directory for a bunch of .whl files which we will +# add to the beginning of sys.path before attempting to import anything. This +# is done to support downstream re-distributors like Debian and Fedora who +# wish to create their own Wheels for our dependencies to aid in debundling. +WHEEL_DIR = os.path.abspath(os.path.dirname(__file__)) + + +# Define a small helper function to alias our vendored modules to the real ones +# if the vendored ones do not exist. This idea of this was taken from +# https://github.com/kennethreitz/requests/pull/2567. +def vendored(modulename): + vendored_name = "{0}.{1}".format(__name__, modulename) + + try: + __import__(modulename, globals(), locals(), level=0) + except ImportError: + # We can just silently allow import failures to pass here. If we + # got to this point it means that ``import pip._vendor.whatever`` + # failed and so did ``import whatever``. Since we're importing this + # upfront in an attempt to alias imports, not erroring here will + # just mean we get a regular import error whenever pip *actually* + # tries to import one of these modules to use it, which actually + # gives us a better error message than we would have otherwise + # gotten. + pass + else: + sys.modules[vendored_name] = sys.modules[modulename] + base, head = vendored_name.rsplit(".", 1) + setattr(sys.modules[base], head, sys.modules[modulename]) + + +# If we're operating in a debundled setup, then we want to go ahead and trigger +# the aliasing of our vendored libraries as well as looking for wheels to add +# to our sys.path. This will cause all of this code to be a no-op typically +# however downstream redistributors can enable it in a consistent way across +# all platforms. +if DEBUNDLED: + # Actually look inside of WHEEL_DIR to find .whl files and add them to the + # front of our sys.path. + sys.path[:] = glob.glob(os.path.join(WHEEL_DIR, "*.whl")) + sys.path + + # Actually alias all of our vendored dependencies. + vendored("cachecontrol") + vendored("certifi") + vendored("dependency-groups") + vendored("distlib") + vendored("distro") + vendored("packaging") + vendored("packaging.version") + vendored("packaging.specifiers") + vendored("pkg_resources") + vendored("platformdirs") + vendored("progress") + vendored("pyproject_hooks") + vendored("requests") + vendored("requests.exceptions") + vendored("requests.packages") + vendored("requests.packages.urllib3") + vendored("requests.packages.urllib3._collections") + vendored("requests.packages.urllib3.connection") + vendored("requests.packages.urllib3.connectionpool") + vendored("requests.packages.urllib3.contrib") + vendored("requests.packages.urllib3.contrib.ntlmpool") + vendored("requests.packages.urllib3.contrib.pyopenssl") + vendored("requests.packages.urllib3.exceptions") + vendored("requests.packages.urllib3.fields") + vendored("requests.packages.urllib3.filepost") + vendored("requests.packages.urllib3.packages") + vendored("requests.packages.urllib3.packages.ordered_dict") + vendored("requests.packages.urllib3.packages.six") + vendored("requests.packages.urllib3.packages.ssl_match_hostname") + vendored("requests.packages.urllib3.packages.ssl_match_hostname." + "_implementation") + vendored("requests.packages.urllib3.poolmanager") + vendored("requests.packages.urllib3.request") + vendored("requests.packages.urllib3.response") + vendored("requests.packages.urllib3.util") + vendored("requests.packages.urllib3.util.connection") + vendored("requests.packages.urllib3.util.request") + vendored("requests.packages.urllib3.util.response") + vendored("requests.packages.urllib3.util.retry") + vendored("requests.packages.urllib3.util.ssl_") + vendored("requests.packages.urllib3.util.timeout") + vendored("requests.packages.urllib3.util.url") + vendored("resolvelib") + vendored("rich") + vendored("rich.console") + vendored("rich.highlighter") + vendored("rich.logging") + vendored("rich.markup") + vendored("rich.progress") + vendored("rich.segment") + vendored("rich.style") + vendored("rich.text") + vendored("rich.traceback") + if sys.version_info < (3, 11): + vendored("tomli") + vendored("truststore") + vendored("urllib3") diff --git a/venv/Lib/site-packages/pip/_vendor/vendor.txt b/venv/Lib/site-packages/pip/_vendor/vendor.txt new file mode 100644 index 0000000..dd2f5f3 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/vendor.txt @@ -0,0 +1,19 @@ +CacheControl==0.14.4 +distlib==0.4.0 +distro==1.9.0 +msgpack==1.1.2 +packaging==26.0 +platformdirs==4.5.1 +pyproject-hooks==1.2.0 +requests==2.32.5 + certifi==2026.1.4 + idna==3.11 + urllib3==1.26.20 +rich==14.2.0 + pygments==2.19.2 +resolvelib==1.2.1 +setuptools==70.3.0 +tomli==2.3.0 +tomli-w==1.2.0 +truststore==0.10.4 +dependency-groups==1.3.1