blob: 63013aec3db2b0a4e8def396bb19a74422b07add [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
13_SETUPTOOLS_VERSION = "1.3.2"
14
Nick Coghlan1b1b1782013-11-30 15:56:58 +100015_PIP_VERSION = "1.5rc1"
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
39
40def bootstrap(*, root=None, upgrade=False, user=False,
41 altinstall=False, default_pip=False,
42 verbosity=0):
43 """
44 Bootstrap pip into the current Python installation (or the given root
45 directory).
46 """
47 if altinstall and default_pip:
48 raise ValueError("Cannot use altinstall and default_pip together")
49
50 # By default, installing pip and setuptools installs all of the
51 # following scripts (X.Y == running Python version):
52 #
53 # pip, pipX, pipX.Y, easy_install, easy_install-X.Y
54 #
55 # pip 1.5+ allows ensurepip to request that some of those be left out
56 if altinstall:
57 # omit pip, pipX and easy_install
58 os.environ["ENSUREPIP_OPTIONS"] = "altinstall"
59 elif not default_pip:
60 # omit pip and easy_install
61 os.environ["ENSUREPIP_OPTIONS"] = "install"
62
63 with tempfile.TemporaryDirectory() as tmpdir:
64 # Put our bundled wheels into a temporary directory and construct the
65 # additional paths that need added to sys.path
66 additional_paths = []
67 for project, version in _PROJECTS:
68 wheel_name = "{}-{}-py2.py3-none-any.whl".format(project, version)
69 whl = pkgutil.get_data(
70 "ensurepip",
71 "_bundled/{}".format(wheel_name),
72 )
73 with open(os.path.join(tmpdir, wheel_name), "wb") as fp:
74 fp.write(whl)
75
76 additional_paths.append(os.path.join(tmpdir, wheel_name))
77
78 # Construct the arguments to be passed to the pip command
79 args = [
80 "install", "--no-index", "--find-links", tmpdir,
81 # Temporary until pip 1.5 is final
82 "--pre",
83 ]
84 if root:
85 args += ["--root", root]
86 if upgrade:
87 args += ["--upgrade"]
88 if user:
89 args += ["--user"]
90 if verbosity:
91 args += ["-" + "v" * verbosity]
92
93 _run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
Nick Coghlanfdf3a622013-11-30 17:15:09 +100094
95def _uninstall(*, verbosity=0):
96 """Helper to support a clean default uninstall process on Windows"""
97 # Nothing to do if pip was never installed, or has been removed
98 try:
99 import pip
100 except ImportError:
101 return
102
103 # If the pip version doesn't match the bundled one, leave it alone
104 if pip.__version__ != _PIP_VERSION:
105 msg = ("ensurepip will only uninstall a matching pip "
106 "({!r} installed, {!r} bundled)")
107 raise RuntimeError(msg.format(pip.__version__, _PIP_VERSION))
108
109 # Construct the arguments to be passed to the pip command
110 args = ["uninstall", "-y"]
111 if verbosity:
112 args += ["-" + "v" * verbosity]
113
114 _run_pip(args + [p[0] for p in reversed(_PROJECTS)])