blob: 0f43bc424f614a043b1863462e5491cd35384c41 [file] [log] [blame]
Nick Coghland0cf0632013-11-11 22:11:55 +10001import os
2import os.path
3import pkgutil
4import sys
5import tempfile
6
7# TODO: Remove the --pre flag when a pip 1.5 final copy is available
8
9
10__all__ = ["version", "bootstrap"]
11
12
Donald Stufft8b36dac2013-12-20 19:03:18 -050013_SETUPTOOLS_VERSION = "2.0.1"
Nick Coghland0cf0632013-11-11 22:11:55 +100014
Donald Stufft8b36dac2013-12-20 19:03:18 -050015_PIP_VERSION = "1.5rc2"
Nick Coghland0cf0632013-11-11 22:11:55 +100016
17_PROJECTS = [
18 ("setuptools", _SETUPTOOLS_VERSION),
19 ("pip", _PIP_VERSION),
20]
21
22
Nick Coghlanfdf3a622013-11-30 17:15:09 +100023def _run_pip(args, additional_paths=None):
Nick Coghland0cf0632013-11-11 22:11:55 +100024 # Add our bundled software to the sys.path so we can import it
Nick Coghlanfdf3a622013-11-30 17:15:09 +100025 if additional_paths is not None:
26 sys.path = additional_paths + sys.path
Nick Coghland0cf0632013-11-11 22:11:55 +100027
28 # Install the bundled software
29 import pip
30 pip.main(args)
31
32
33def version():
34 """
35 Returns a string specifying the bundled version of pip.
36 """
37 return _PIP_VERSION
38
Nick Coghlaned9af522013-12-23 17:39:12 +100039def _clear_pip_environment_variables():
40 # We deliberately ignore all pip environment variables
41 # when invoking pip
42 # See http://bugs.python.org/issue19734 for details
43 keys_to_remove = [k for k in os.environ if k.startswith("PIP_")]
44 for k in keys_to_remove:
45 del os.environ[k]
46
Nick Coghland0cf0632013-11-11 22:11:55 +100047
48def bootstrap(*, root=None, upgrade=False, user=False,
49 altinstall=False, default_pip=False,
50 verbosity=0):
51 """
52 Bootstrap pip into the current Python installation (or the given root
53 directory).
Nick Coghlan6256fcb2013-12-23 16:16:07 +100054
55 Note that calling this function will alter both sys.path and os.environ.
Nick Coghland0cf0632013-11-11 22:11:55 +100056 """
57 if altinstall and default_pip:
58 raise ValueError("Cannot use altinstall and default_pip together")
59
Nick Coghlaned9af522013-12-23 17:39:12 +100060 _clear_pip_environment_variables()
Nick Coghlan6256fcb2013-12-23 16:16:07 +100061
Nick Coghland0cf0632013-11-11 22:11:55 +100062 # By default, installing pip and setuptools installs all of the
63 # following scripts (X.Y == running Python version):
64 #
65 # pip, pipX, pipX.Y, easy_install, easy_install-X.Y
66 #
67 # pip 1.5+ allows ensurepip to request that some of those be left out
68 if altinstall:
69 # omit pip, pipX and easy_install
70 os.environ["ENSUREPIP_OPTIONS"] = "altinstall"
71 elif not default_pip:
72 # omit pip and easy_install
73 os.environ["ENSUREPIP_OPTIONS"] = "install"
74
75 with tempfile.TemporaryDirectory() as tmpdir:
76 # Put our bundled wheels into a temporary directory and construct the
77 # additional paths that need added to sys.path
78 additional_paths = []
79 for project, version in _PROJECTS:
80 wheel_name = "{}-{}-py2.py3-none-any.whl".format(project, version)
81 whl = pkgutil.get_data(
82 "ensurepip",
83 "_bundled/{}".format(wheel_name),
84 )
85 with open(os.path.join(tmpdir, wheel_name), "wb") as fp:
86 fp.write(whl)
87
88 additional_paths.append(os.path.join(tmpdir, wheel_name))
89
90 # Construct the arguments to be passed to the pip command
91 args = [
92 "install", "--no-index", "--find-links", tmpdir,
93 # Temporary until pip 1.5 is final
94 "--pre",
95 ]
96 if root:
97 args += ["--root", root]
98 if upgrade:
99 args += ["--upgrade"]
100 if user:
101 args += ["--user"]
102 if verbosity:
103 args += ["-" + "v" * verbosity]
104
105 _run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
Nick Coghlanfdf3a622013-11-30 17:15:09 +1000106
Nick Coghlanf71cae02013-12-23 18:20:34 +1000107def _uninstall_helper(*, verbosity=0):
Nick Coghlaned9af522013-12-23 17:39:12 +1000108 """Helper to support a clean default uninstall process on Windows
109
110 Note that calling this function may alter os.environ.
111 """
Nick Coghlanfdf3a622013-11-30 17:15:09 +1000112 # Nothing to do if pip was never installed, or has been removed
113 try:
114 import pip
115 except ImportError:
116 return
117
118 # If the pip version doesn't match the bundled one, leave it alone
119 if pip.__version__ != _PIP_VERSION:
120 msg = ("ensurepip will only uninstall a matching pip "
121 "({!r} installed, {!r} bundled)")
122 raise RuntimeError(msg.format(pip.__version__, _PIP_VERSION))
123
Nick Coghlaned9af522013-12-23 17:39:12 +1000124 _clear_pip_environment_variables()
125
Nick Coghlanfdf3a622013-11-30 17:15:09 +1000126 # Construct the arguments to be passed to the pip command
127 args = ["uninstall", "-y"]
128 if verbosity:
129 args += ["-" + "v" * verbosity]
130
131 _run_pip(args + [p[0] for p in reversed(_PROJECTS)])
Nick Coghlanf71cae02013-12-23 18:20:34 +1000132
133
134def _main(argv=None):
135 import argparse
136 parser = argparse.ArgumentParser(prog="python -m ensurepip")
137 parser.add_argument(
138 "--version",
139 action="version",
140 version="pip {}".format(version()),
141 help="Show the version of pip that is bundled with this Python.",
142 )
143 parser.add_argument(
144 "-v", "--verbose",
145 action="count",
146 default=0,
147 dest="verbosity",
148 help=("Give more output. Option is additive, and can be used up to 3 "
149 "times."),
150 )
151 parser.add_argument(
152 "-U", "--upgrade",
153 action="store_true",
154 default=False,
155 help="Upgrade pip and dependencies, even if already installed.",
156 )
157 parser.add_argument(
158 "--user",
159 action="store_true",
160 default=False,
161 help="Install using the user scheme.",
162 )
163 parser.add_argument(
164 "--root",
165 default=None,
166 help="Install everything relative to this alternate root directory.",
167 )
168 parser.add_argument(
169 "--altinstall",
170 action="store_true",
171 default=False,
172 help=("Make an alternate install, installing only the X.Y versioned"
173 "scripts (Default: pipX, pipX.Y, easy_install-X.Y)"),
174 )
175 parser.add_argument(
176 "--default-pip",
177 action="store_true",
178 default=False,
179 help=("Make a default pip install, installing the unqualified pip "
180 "and easy_install in addition to the versioned scripts"),
181 )
182
183 args = parser.parse_args(argv)
184
185 bootstrap(
186 root=args.root,
187 upgrade=args.upgrade,
188 user=args.user,
189 verbosity=args.verbosity,
190 altinstall=args.altinstall,
191 default_pip=args.default_pip,
192 )