Skip to content

Commit e8c4ff9

Browse files
committed
Improve protected_pip.py by adding additional context
This additional context provided by the various comments within the lightly-refactored implementation should make it easier to understand what this file is for, how it works and when it is useful.
1 parent 6c2013c commit e8c4ff9

File tree

1 file changed

+51
-28
lines changed

1 file changed

+51
-28
lines changed

tools/protected_pip.py

+51-28
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,61 @@
1+
"""Maintain and use a protected copy of pip for use during development.
2+
3+
The protected copy of pip can be used to manipulate the environment while keeping a
4+
potentially-non-functional installation of in-development pip in the development virtual
5+
environment.
6+
7+
This allows for setting up the test environments and exercising the in-development code,
8+
even when it is not functional-enough to install the packages for setting up the
9+
environment that it is being used it.
10+
"""
11+
112
import os
2-
import pathlib
313
import shutil
414
import subprocess
515
import sys
616
from glob import glob
7-
from typing import Iterable, Union
17+
from typing import List
818

919
VIRTUAL_ENV = os.environ["VIRTUAL_ENV"]
10-
TOX_PIP_DIR = os.path.join(VIRTUAL_ENV, "pip")
11-
12-
13-
def pip(args: Iterable[Union[str, pathlib.Path]]) -> None:
14-
# First things first, get a recent (stable) version of pip.
15-
if not os.path.exists(TOX_PIP_DIR):
16-
subprocess.check_call(
17-
[
18-
sys.executable,
19-
"-m",
20-
"pip",
21-
"--disable-pip-version-check",
22-
"install",
23-
"-t",
24-
TOX_PIP_DIR,
25-
"pip",
26-
]
27-
)
28-
shutil.rmtree(glob(os.path.join(TOX_PIP_DIR, "pip-*.dist-info"))[0])
29-
# And use that version.
30-
pypath_env = os.environ.get("PYTHONPATH")
31-
pypath = pypath_env.split(os.pathsep) if pypath_env is not None else []
32-
pypath.insert(0, TOX_PIP_DIR)
33-
os.environ["PYTHONPATH"] = os.pathsep.join(pypath)
34-
subprocess.check_call([sys.executable, "-m", "pip", *(os.fspath(a) for a in args)])
20+
PROTECTED_PIP_DIR = os.path.join(VIRTUAL_ENV, "pip")
21+
22+
23+
def _setup_protected_pip() -> None:
24+
# This setup happens before any development version of pip is installed in this
25+
# environment. So, at this point, the existing pip installation should be from a
26+
# stable release and can be safely used to create the protected copy.
27+
subprocess.check_call(
28+
[
29+
sys.executable,
30+
"-m",
31+
"pip",
32+
"--disable-pip-version-check",
33+
"install",
34+
"-t",
35+
PROTECTED_PIP_DIR,
36+
"pip",
37+
]
38+
)
39+
# Make it impossible for pip (and other Python tooling) to discover this protected
40+
# installation of pip using the metadata, by deleting the metadata.
41+
shutil.rmtree(glob(os.path.join(PROTECTED_PIP_DIR, "pip-*.dist-info"))[0])
42+
43+
44+
def main(args: List[str]) -> None:
45+
# If we don't have a protected pip, let's set it up.
46+
if not os.path.exists(PROTECTED_PIP_DIR):
47+
_setup_protected_pip()
48+
49+
# Run Python, with the protected pip copy on PYTHONPATH.
50+
pypath_env = os.environ.get("PYTHONPATH", "")
51+
old_PYTHONPATH_entries = pypath_env.split(os.pathsep) if pypath_env else []
52+
new_PYTHONPATH = os.pathsep.join([PROTECTED_PIP_DIR] + old_PYTHONPATH_entries)
53+
54+
subprocess.check_call(
55+
[sys.executable, "-m", "pip"] + args,
56+
env={"PYTHONPATH": new_PYTHONPATH},
57+
)
3558

3659

3760
if __name__ == "__main__":
38-
pip(sys.argv[1:])
61+
main(sys.argv[1:])

0 commit comments

Comments
 (0)