blob: 3c679e596874bbf88fe4942dcdfa93ea24b6aeb9 [file] [log] [blame]
Donald Stufft8aaff542014-11-11 10:24:11 -05001#!/usr/bin/env python2
2from __future__ import print_function
3
4import os
5import os.path
6import pkgutil
7import shutil
8import sys
9import tempfile
10
11
12__all__ = ["version", "bootstrap"]
13
14
Miss Islington (bot)1ce4e5b2018-03-21 21:14:22 -070015_SETUPTOOLS_VERSION = "39.0.1"
Donald Stufft8aaff542014-11-11 10:24:11 -050016
Miss Islington (bot)4caba7a2018-04-20 13:48:43 -070017_PIP_VERSION = "10.0.1"
Donald Stufft8aaff542014-11-11 10:24:11 -050018
Donald Stufft8aaff542014-11-11 10:24:11 -050019_PROJECTS = [
20 ("setuptools", _SETUPTOOLS_VERSION),
21 ("pip", _PIP_VERSION),
22]
23
24
25def _run_pip(args, additional_paths=None):
26 # Add our bundled software to the sys.path so we can import it
27 if additional_paths is not None:
28 sys.path = additional_paths + sys.path
29
30 # Install the bundled software
Miss Islington (bot)4caba7a2018-04-20 13:48:43 -070031 import pip._internal
32 return pip._internal.main(args)
Donald Stufft8aaff542014-11-11 10:24:11 -050033
34
35def version():
36 """
37 Returns a string specifying the bundled version of pip.
38 """
39 return _PIP_VERSION
40
41
42def _disable_pip_configuration_settings():
43 # We deliberately ignore all pip environment variables
44 # when invoking pip
45 # See http://bugs.python.org/issue19734 for details
46 keys_to_remove = [k for k in os.environ if k.startswith("PIP_")]
47 for k in keys_to_remove:
48 del os.environ[k]
49 # We also ignore the settings in the default pip configuration file
50 # See http://bugs.python.org/issue20053 for details
51 os.environ['PIP_CONFIG_FILE'] = os.devnull
52
53
54def bootstrap(root=None, upgrade=False, user=False,
55 altinstall=False, default_pip=True,
56 verbosity=0):
57 """
58 Bootstrap pip into the current Python installation (or the given root
59 directory).
60
61 Note that calling this function will alter both sys.path and os.environ.
62 """
Igor Filatovcf7197a2017-09-25 04:03:24 +030063 # Discard the return value
64 _bootstrap(root=root, upgrade=upgrade, user=user,
65 altinstall=altinstall, default_pip=default_pip,
66 verbosity=verbosity)
67
68
69def _bootstrap(root=None, upgrade=False, user=False,
70 altinstall=False, default_pip=True,
71 verbosity=0):
72 """
73 Bootstrap pip into the current Python installation (or the given root
74 directory). Returns pip command status code.
75
76 Note that calling this function will alter both sys.path and os.environ.
77 """
Donald Stufft8aaff542014-11-11 10:24:11 -050078 if altinstall and default_pip:
79 raise ValueError("Cannot use altinstall and default_pip together")
80
Donald Stufft8aaff542014-11-11 10:24:11 -050081 _disable_pip_configuration_settings()
82
83 # By default, installing pip and setuptools installs all of the
84 # following scripts (X.Y == running Python version):
85 #
86 # pip, pipX, pipX.Y, easy_install, easy_install-X.Y
87 #
88 # pip 1.5+ allows ensurepip to request that some of those be left out
89 if altinstall:
90 # omit pip, pipX and easy_install
91 os.environ["ENSUREPIP_OPTIONS"] = "altinstall"
92 elif not default_pip:
93 # omit pip and easy_install
94 os.environ["ENSUREPIP_OPTIONS"] = "install"
95
96 tmpdir = tempfile.mkdtemp()
97 try:
98 # Put our bundled wheels into a temporary directory and construct the
99 # additional paths that need added to sys.path
100 additional_paths = []
101 for project, version in _PROJECTS:
102 wheel_name = "{}-{}-py2.py3-none-any.whl".format(project, version)
103 whl = pkgutil.get_data(
104 "ensurepip",
105 "_bundled/{}".format(wheel_name),
106 )
107 with open(os.path.join(tmpdir, wheel_name), "wb") as fp:
108 fp.write(whl)
109
110 additional_paths.append(os.path.join(tmpdir, wheel_name))
111
112 # Construct the arguments to be passed to the pip command
113 args = ["install", "--no-index", "--find-links", tmpdir]
114 if root:
115 args += ["--root", root]
116 if upgrade:
117 args += ["--upgrade"]
118 if user:
119 args += ["--user"]
120 if verbosity:
121 args += ["-" + "v" * verbosity]
122
Igor Filatovcf7197a2017-09-25 04:03:24 +0300123 return _run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
Donald Stufft8aaff542014-11-11 10:24:11 -0500124 finally:
125 shutil.rmtree(tmpdir, ignore_errors=True)
126
Donald Stufft8aaff542014-11-11 10:24:11 -0500127def _uninstall_helper(verbosity=0):
128 """Helper to support a clean default uninstall process on Windows
129
130 Note that calling this function may alter os.environ.
131 """
132 # Nothing to do if pip was never installed, or has been removed
133 try:
134 import pip
135 except ImportError:
136 return
137
138 # If the pip version doesn't match the bundled one, leave it alone
139 if pip.__version__ != _PIP_VERSION:
140 msg = ("ensurepip will only uninstall a matching version "
141 "({!r} installed, {!r} bundled)")
142 print(msg.format(pip.__version__, _PIP_VERSION), file=sys.stderr)
143 return
144
Donald Stufft8aaff542014-11-11 10:24:11 -0500145 _disable_pip_configuration_settings()
146
147 # Construct the arguments to be passed to the pip command
Donald Stufft69c0d262015-06-02 10:54:37 -0400148 args = ["uninstall", "-y", "--disable-pip-version-check"]
Donald Stufft8aaff542014-11-11 10:24:11 -0500149 if verbosity:
150 args += ["-" + "v" * verbosity]
151
Igor Filatovcf7197a2017-09-25 04:03:24 +0300152 return _run_pip(args + [p[0] for p in reversed(_PROJECTS)])
Donald Stufft8aaff542014-11-11 10:24:11 -0500153
154
155def _main(argv=None):
Donald Stufft8aaff542014-11-11 10:24:11 -0500156 import argparse
157 parser = argparse.ArgumentParser(prog="python -m ensurepip")
158 parser.add_argument(
159 "--version",
160 action="version",
161 version="pip {}".format(version()),
162 help="Show the version of pip that is bundled with this Python.",
163 )
164 parser.add_argument(
165 "-v", "--verbose",
166 action="count",
167 default=0,
168 dest="verbosity",
169 help=("Give more output. Option is additive, and can be used up to 3 "
170 "times."),
171 )
172 parser.add_argument(
173 "-U", "--upgrade",
174 action="store_true",
175 default=False,
176 help="Upgrade pip and dependencies, even if already installed.",
177 )
178 parser.add_argument(
179 "--user",
180 action="store_true",
181 default=False,
182 help="Install using the user scheme.",
183 )
184 parser.add_argument(
185 "--root",
186 default=None,
187 help="Install everything relative to this alternate root directory.",
188 )
189 parser.add_argument(
190 "--altinstall",
191 action="store_true",
192 default=False,
Petr Viktorinf3d269a2018-05-30 12:36:17 +0200193 help=("Make an alternate install, installing only the X.Y versioned "
194 "scripts (Default: pipX, pipX.Y, easy_install-X.Y)."),
Donald Stufft8aaff542014-11-11 10:24:11 -0500195 )
196 parser.add_argument(
197 "--default-pip",
198 action="store_true",
199 default=True,
200 dest="default_pip",
201 help=argparse.SUPPRESS,
202 )
203 parser.add_argument(
204 "--no-default-pip",
205 action="store_false",
206 dest="default_pip",
207 help=("Make a non default install, installing only the X and X.Y "
208 "versioned scripts."),
209 )
210
211 args = parser.parse_args(argv)
212
Igor Filatovcf7197a2017-09-25 04:03:24 +0300213 return _bootstrap(
Donald Stufft8aaff542014-11-11 10:24:11 -0500214 root=args.root,
215 upgrade=args.upgrade,
216 user=args.user,
217 verbosity=args.verbosity,
218 altinstall=args.altinstall,
219 default_pip=args.default_pip,
220 )