diff options
-rw-r--r-- | Doc/library/ensurepip.rst | 6 | ||||
-rw-r--r-- | Lib/ensurepip/__init__.py | 8 | ||||
-rw-r--r-- | Lib/test/test_ensurepip.py | 8 | ||||
-rw-r--r-- | Lib/test/test_venv.py | 14 |
4 files changed, 27 insertions, 9 deletions
diff --git a/Doc/library/ensurepip.rst b/Doc/library/ensurepip.rst index 528370c..0d82135 100644 --- a/Doc/library/ensurepip.rst +++ b/Doc/library/ensurepip.rst @@ -119,6 +119,12 @@ Module API .. note:: + The bootstrapping process has side effects on both ``sys.path`` and + ``os.environ``. Invoking the command line interface in a subprocess + instead allows these side effects to be avoided. + + .. note:: + The bootstrapping process may install additional modules required by ``pip``, but other software should not assume those dependencies will always be present by default (as the dependencies may be removed in a diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py index b6bc4b6..5ceda51 100644 --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -43,10 +43,18 @@ def bootstrap(*, root=None, upgrade=False, user=False, """ Bootstrap pip into the current Python installation (or the given root directory). + + Note that calling this function will alter both sys.path and os.environ. """ if altinstall and default_pip: raise ValueError("Cannot use altinstall and default_pip together") + # We deliberately ignore all pip environment variables + # See http://bugs.python.org/issue19734 for details + keys_to_remove = [k for k in os.environ if k.startswith("PIP_")] + for k in keys_to_remove: + del os.environ[k] + # By default, installing pip and setuptools installs all of the # following scripts (X.Y == running Python version): # diff --git a/Lib/test/test_ensurepip.py b/Lib/test/test_ensurepip.py index c119327..8c125bf 100644 --- a/Lib/test/test_ensurepip.py +++ b/Lib/test/test_ensurepip.py @@ -126,6 +126,14 @@ class TestBootstrap(unittest.TestCase): ensurepip.bootstrap(altinstall=True, default_pip=True) self.run_pip.assert_not_called() + def test_pip_environment_variables_removed(self): + # ensurepip deliberately ignores all pip environment variables + # See http://bugs.python.org/issue19734 for details + self.os_environ["PIP_THIS_SHOULD_GO_AWAY"] = "test fodder" + ensurepip.bootstrap() + self.assertNotIn("PIP_THIS_SHOULD_GO_AWAY", self.os_environ) + + @contextlib.contextmanager def fake_pip(version=ensurepip._PIP_VERSION): if version is None: diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index eb225fa..e8437cf 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -294,11 +294,12 @@ class EnsurePipTest(BaseTest): # warnings in current versions of Python. Ensure related # environment settings don't cause venv to fail. envvars["PYTHONWARNINGS"] = "e" - # pip doesn't ignore environment variables when running in - # isolated mode, and we don't have an active virtualenv here, - # we're relying on the native venv support in 3.3+ + # ensurepip is different enough from a normal pip invocation + # that we want to ensure it ignores the normal pip environment + # variable settings. We set PIP_NO_INSTALL here specifically + # to check that ensurepip (and hence venv) ignores it. # See http://bugs.python.org/issue19734 for details - del envvars["PIP_REQUIRE_VIRTUALENV"] + envvars["PIP_NO_INSTALL"] = "1" try: self.run_with_capture(venv.create, self.env_dir, with_pip=True) except subprocess.CalledProcessError as exc: @@ -328,11 +329,6 @@ class EnsurePipTest(BaseTest): # installers works (at least in a virtual environment) cmd = [envpy, '-Im', 'ensurepip._uninstall'] with EnvironmentVarGuard() as envvars: - # pip doesn't ignore environment variables when running in - # isolated mode, and we don't have an active virtualenv here, - # we're relying on the native venv support in 3.3+ - # See http://bugs.python.org/issue19734 for details - del envvars["PIP_REQUIRE_VIRTUALENV"] p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = p.communicate() |