From c6587afc0e17cc58f517659ae5a888dd16f2f8d8 Mon Sep 17 00:00:00 2001 From: Toshio Kuratomi Date: Fri, 15 May 2020 00:54:23 -0700 Subject: [PATCH] More intelligently insert the pip path into sys.path When inserting pip's library path into sys.path we do not want to override the stdlib. This is for several reasons: (1) The stdlib should only contain the stdlib. So there should not be other instances of pip there which will override our desired library. (2) If we were to override the stdlib and the path the pip library is installed in contains any libraries which override the stdlib (*cough*enum34*cough*) then we could break code which depends on the stdlib's APIs. Fixes #8214 --- news/8214.bugfix | 1 + src/pip/__main__.py | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 news/8214.bugfix diff --git a/news/8214.bugfix b/news/8214.bugfix new file mode 100644 index 00000000000..1dc5cd79d11 --- /dev/null +++ b/news/8214.bugfix @@ -0,0 +1 @@ +Fix installing packages which have a pyproject.toml when enum34 is installed. diff --git a/src/pip/__main__.py b/src/pip/__main__.py index 7c2505fa5bd..0662d0c2c9c 100644 --- a/src/pip/__main__.py +++ b/src/pip/__main__.py @@ -2,6 +2,7 @@ import os import sys +import sysconfig # Remove '' and current working directory from the first entry # of sys.path, if present to avoid using current directory @@ -13,12 +14,27 @@ # If we are running from a wheel, add the wheel to sys.path # This allows the usage python pip-*.whl/pip install pip-*.whl if __package__ == '': + # Retrieve the index in sys.path where all stdlib paths reside + # (DESTSHARED is where some extension modules like math live). + stdlib_path_indexes = [] + stdlib_paths = (sysconfig.get_path('stdlib'), + sysconfig.get_path('platstdlib'), + sysconfig.get_config_var('DESTSHARED')) + for path in (p for p in stdlib_paths if p is not None): + try: + stdlib_path_indexes.append(sys.path.index(path)) + except ValueError: + continue + # __file__ is pip-*.whl/pip/__main__.py # first dirname call strips of '/__main__.py', second strips off '/pip' # Resulting path is the name of the wheel itself # Add that to sys.path so we can import pip - path = os.path.dirname(os.path.dirname(__file__)) - sys.path.insert(0, path) + pip_installed_path = os.path.dirname(os.path.dirname(__file__)) + + # Insert this pip's library path directly after the stdlib so that + # we import this pip's library even if another pip is installed. + sys.path.insert(max(stdlib_path_indexes) + 1, pip_installed_path) from pip._internal.cli.main import main as _main # isort:skip # noqa