-
Notifications
You must be signed in to change notification settings - Fork 297
/
default.py
152 lines (121 loc) · 5.01 KB
/
default.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/usr/bin/env python
#
# Hi There!
#
# You may be wondering what this giant blob of binary data here is, you might
# even be worried that we're up to something nefarious (good for you for being
# paranoid!). This is a base85 encoding of a zip file, this zip file contains
# an entire copy of pip (version {installed_version}).
#
# Pip is a thing that installs packages, pip itself is a package that someone
# might want to install, especially if they're looking to run this get-pip.py
# script. Pip has a lot of code to deal with the security of installing
# packages, various edge cases on various platforms, and other such sort of
# "tribal knowledge" that has been encoded in its code base. Because of this
# we basically include an entire copy of pip inside this blob. We do this
# because the alternatives are attempt to implement a "minipip" that probably
# doesn't do things correctly and has weird edge cases, or compress pip itself
# down into a single file.
#
# If you're wondering how this is created, it is generated using
# `scripts/generate.py` in https://github.com/pypa/get-pip.
import sys
this_python = sys.version_info[:2]
min_version = {minimum_supported_version}
if this_python < min_version:
message_parts = [
"This script does not work on Python {{}}.{{}}".format(*this_python),
"The minimum supported Python version is {{}}.{{}}.".format(*min_version),
"Please use https://bootstrap.pypa.io/pip/{{}}.{{}}/get-pip.py instead.".format(*this_python),
]
print("ERROR: " + " ".join(message_parts))
sys.exit(1)
import os.path
import pkgutil
import shutil
import tempfile
from base64 import b85decode
def determine_pip_install_arguments():
implicit_pip = True
implicit_setuptools = True
implicit_wheel = True
# Check if the user has requested us not to install setuptools
if "--no-setuptools" in sys.argv or os.environ.get("PIP_NO_SETUPTOOLS"):
args = [x for x in sys.argv[1:] if x != "--no-setuptools"]
implicit_setuptools = False
else:
args = sys.argv[1:]
# Check if the user has requested us not to install wheel
if "--no-wheel" in args or os.environ.get("PIP_NO_WHEEL"):
args = [x for x in args if x != "--no-wheel"]
implicit_wheel = False
# We only want to implicitly install setuptools and wheel if they don't
# already exist on the target platform.
if implicit_setuptools:
try:
import setuptools # noqa
implicit_setuptools = False
except ImportError:
pass
if implicit_wheel:
try:
import wheel # noqa
implicit_wheel = False
except ImportError:
pass
# Add any implicit installations to the end of our args
if implicit_pip:
args += ["pip{pip_version}"]
if implicit_setuptools:
args += ["setuptools{setuptools_version}"]
if implicit_wheel:
args += ["wheel{wheel_version}"]
return ["install", "--upgrade", "--force-reinstall"] + args
def monkeypatch_for_cert(tmpdir):
"""Patches `pip install` to provide default certificate with the lowest priority.
This ensures that the bundled certificates are used unless the user specifies a
custom cert via any of pip's option passing mechanisms (config, env-var, CLI).
A monkeypatch is the easiest way to achieve this, without messing too much with
the rest of pip's internals.
"""
from pip._internal.commands.install import InstallCommand
# We want to be using the internal certificates.
cert_path = os.path.join(tmpdir, "cacert.pem")
with open(cert_path, "wb") as cert:
cert.write(pkgutil.get_data("pip._vendor.certifi", "cacert.pem"))
install_parse_args = InstallCommand.parse_args
def cert_parse_args(self, args):
if not self.parser.get_default_values().cert:
# There are no user provided cert -- force use of bundled cert
self.parser.defaults["cert"] = cert_path # calculated above
return install_parse_args(self, args)
InstallCommand.parse_args = cert_parse_args
def bootstrap(tmpdir):
monkeypatch_for_cert(tmpdir)
# Execute the included pip and use it to install the latest pip and
# setuptools from PyPI
from pip._internal.cli.main import main as pip_entry_point
args = determine_pip_install_arguments()
sys.exit(pip_entry_point(args))
def main():
tmpdir = None
try:
# Create a temporary working directory
tmpdir = tempfile.mkdtemp()
# Unpack the zipfile into the temporary directory
pip_zip = os.path.join(tmpdir, "pip.zip")
with open(pip_zip, "wb") as fp:
fp.write(b85decode(DATA.replace(b"\n", b"")))
# Add the zipfile to sys.path so that we can import it
sys.path.insert(0, pip_zip)
# Run the bootstrap
bootstrap(tmpdir=tmpdir)
finally:
# Clean up our temporary working directory
if tmpdir:
shutil.rmtree(tmpdir, ignore_errors=True)
DATA = b"""
{zipfile}
"""
if __name__ == "__main__":
main()