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