Blob Blame History Raw
From 36b63e76209e4cefaf5be790be6b8adaf2e3fc2b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
Date: Tue, 10 Mar 2020 22:16:28 +0100
Subject: [PATCH] bpo-38662: ensurepip invokes pip via runpy (GH-18901)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The ensurepip module now invokes pip via the runpy module.
Hence it is no longer tightly coupled with the internal API of the bundled
pip version, allowing easier updates to a newer pip version both
internally and for distributors.

This way, any changes to the internal pip API won't mean ensurepip needs to be
changed as well. Also, distributors can update their pip wheels independent on
CPython release schedule.

Co-Authored-By: Pradyun Gedam <pradyunsg@gmail.com>
Co-Authored-By: Miro HronĨok <miro@hroncok.cz>
---
 Lib/ensurepip/__init__.py | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py
index f5999ca..65b78c6 100644
--- a/Lib/ensurepip/__init__.py
+++ b/Lib/ensurepip/__init__.py
@@ -3,6 +3,7 @@ import glob
 import os
 import os.path
 import sys
+import runpy
 import tempfile
 
 
@@ -34,9 +35,18 @@ def _run_pip(args, additional_paths=None):
     if additional_paths is not None:
         sys.path = additional_paths + sys.path
 
-    # Install the bundled software
-    import pip._internal
-    return pip._internal.main(args)
+    # Invoke pip as if it's the main module, and catch the exit.
+    backup_argv = sys.argv[:]
+    sys.argv[1:] = args
+    try:
+        # run_module() alters sys.modules and sys.argv, but restores them at exit
+        runpy.run_module("pip", run_name="__main__", alter_sys=True)
+    except SystemExit as exc:
+        return exc.code
+    finally:
+        sys.argv[:] = backup_argv
+
+    raise SystemError("pip did not exit, this should never happen")
 
 
 def version():
-- 
2.25.3