diff options
| author | Shubham Saini <shubham6405@gmail.com> | 2019-08-05 08:32:33 +0000 |
|---|---|---|
| committer | Shubham Saini <shubham6405@gmail.com> | 2019-08-05 08:32:33 +0000 |
| commit | 227b2d30a8675b44918f9d9ca89b24144a938215 (patch) | |
| tree | 9f8e6a28724514b6fdf463a9ab2067a7ef309b72 /venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/misc.py | |
| parent | 842a8cfbbbdb1f92889d892e4859dbd5d40c5be8 (diff) | |
removing venv files
Diffstat (limited to 'venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/misc.py')
| -rw-r--r-- | venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/misc.py | 851 |
1 files changed, 0 insertions, 851 deletions
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/misc.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/misc.py deleted file mode 100644 index db84a7c..0000000 --- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/misc.py +++ /dev/null | |||
| @@ -1,851 +0,0 @@ | |||
| 1 | from __future__ import absolute_import | ||
| 2 | |||
| 3 | import contextlib | ||
| 4 | import errno | ||
| 5 | import io | ||
| 6 | import locale | ||
| 7 | # we have a submodule named 'logging' which would shadow this if we used the | ||
| 8 | # regular name: | ||
| 9 | import logging as std_logging | ||
| 10 | import os | ||
| 11 | import posixpath | ||
| 12 | import re | ||
| 13 | import shutil | ||
| 14 | import stat | ||
| 15 | import subprocess | ||
| 16 | import sys | ||
| 17 | import tarfile | ||
| 18 | import zipfile | ||
| 19 | from collections import deque | ||
| 20 | |||
| 21 | from pip._vendor import pkg_resources | ||
| 22 | # NOTE: retrying is not annotated in typeshed as on 2017-07-17, which is | ||
| 23 | # why we ignore the type on this import. | ||
| 24 | from pip._vendor.retrying import retry # type: ignore | ||
| 25 | from pip._vendor.six import PY2 | ||
| 26 | from pip._vendor.six.moves import input | ||
| 27 | |||
| 28 | from pip._internal.compat import console_to_str, expanduser, stdlib_pkgs | ||
| 29 | from pip._internal.exceptions import InstallationError | ||
| 30 | from pip._internal.locations import ( | ||
| 31 | running_under_virtualenv, site_packages, user_site, virtualenv_no_global, | ||
| 32 | write_delete_marker_file, | ||
| 33 | ) | ||
| 34 | |||
| 35 | if PY2: | ||
| 36 | from io import BytesIO as StringIO | ||
| 37 | else: | ||
| 38 | from io import StringIO | ||
| 39 | |||
| 40 | __all__ = ['rmtree', 'display_path', 'backup_dir', | ||
| 41 | 'ask', 'splitext', | ||
| 42 | 'format_size', 'is_installable_dir', | ||
| 43 | 'is_svn_page', 'file_contents', | ||
| 44 | 'split_leading_dir', 'has_leading_dir', | ||
| 45 | 'normalize_path', | ||
| 46 | 'renames', 'get_prog', | ||
| 47 | 'unzip_file', 'untar_file', 'unpack_file', 'call_subprocess', | ||
| 48 | 'captured_stdout', 'ensure_dir', | ||
| 49 | 'ARCHIVE_EXTENSIONS', 'SUPPORTED_EXTENSIONS', | ||
| 50 | 'get_installed_version'] | ||
| 51 | |||
| 52 | |||
| 53 | logger = std_logging.getLogger(__name__) | ||
| 54 | |||
| 55 | BZ2_EXTENSIONS = ('.tar.bz2', '.tbz') | ||
| 56 | XZ_EXTENSIONS = ('.tar.xz', '.txz', '.tlz', '.tar.lz', '.tar.lzma') | ||
| 57 | ZIP_EXTENSIONS = ('.zip', '.whl') | ||
| 58 | TAR_EXTENSIONS = ('.tar.gz', '.tgz', '.tar') | ||
| 59 | ARCHIVE_EXTENSIONS = ( | ||
| 60 | ZIP_EXTENSIONS + BZ2_EXTENSIONS + TAR_EXTENSIONS + XZ_EXTENSIONS) | ||
| 61 | SUPPORTED_EXTENSIONS = ZIP_EXTENSIONS + TAR_EXTENSIONS | ||
| 62 | try: | ||
| 63 | import bz2 # noqa | ||
| 64 | SUPPORTED_EXTENSIONS += BZ2_EXTENSIONS | ||
| 65 | except ImportError: | ||
| 66 | logger.debug('bz2 module is not available') | ||
| 67 | |||
| 68 | try: | ||
| 69 | # Only for Python 3.3+ | ||
| 70 | import lzma # noqa | ||
| 71 | SUPPORTED_EXTENSIONS += XZ_EXTENSIONS | ||
| 72 | except ImportError: | ||
| 73 | logger.debug('lzma module is not available') | ||
| 74 | |||
| 75 | |||
| 76 | def import_or_raise(pkg_or_module_string, ExceptionType, *args, **kwargs): | ||
| 77 | try: | ||
| 78 | return __import__(pkg_or_module_string) | ||
| 79 | except ImportError: | ||
| 80 | raise ExceptionType(*args, **kwargs) | ||
| 81 | |||
| 82 | |||
| 83 | def ensure_dir(path): | ||
| 84 | """os.path.makedirs without EEXIST.""" | ||
| 85 | try: | ||
| 86 | os.makedirs(path) | ||
| 87 | except OSError as e: | ||
| 88 | if e.errno != errno.EEXIST: | ||
| 89 | raise | ||
| 90 | |||
| 91 | |||
| 92 | def get_prog(): | ||
| 93 | try: | ||
| 94 | prog = os.path.basename(sys.argv[0]) | ||
| 95 | if prog in ('__main__.py', '-c'): | ||
| 96 | return "%s -m pip" % sys.executable | ||
| 97 | else: | ||
| 98 | return prog | ||
| 99 | except (AttributeError, TypeError, IndexError): | ||
| 100 | pass | ||
| 101 | return 'pip' | ||
| 102 | |||
| 103 | |||
| 104 | # Retry every half second for up to 3 seconds | ||
| 105 | @retry(stop_max_delay=3000, wait_fixed=500) | ||
| 106 | def rmtree(dir, ignore_errors=False): | ||
| 107 | shutil.rmtree(dir, ignore_errors=ignore_errors, | ||
| 108 | onerror=rmtree_errorhandler) | ||
| 109 | |||
| 110 | |||
| 111 | def rmtree_errorhandler(func, path, exc_info): | ||
| 112 | """On Windows, the files in .svn are read-only, so when rmtree() tries to | ||
| 113 | remove them, an exception is thrown. We catch that here, remove the | ||
| 114 | read-only attribute, and hopefully continue without problems.""" | ||
| 115 | # if file type currently read only | ||
| 116 | if os.stat(path).st_mode & stat.S_IREAD: | ||
| 117 | # convert to read/write | ||
| 118 | os.chmod(path, stat.S_IWRITE) | ||
| 119 | # use the original function to repeat the operation | ||
| 120 | func(path) | ||
| 121 | return | ||
| 122 | else: | ||
| 123 | raise | ||
| 124 | |||
| 125 | |||
| 126 | def display_path(path): | ||
| 127 | """Gives the display value for a given path, making it relative to cwd | ||
| 128 | if possible.""" | ||
| 129 | path = os.path.normcase(os.path.abspath(path)) | ||
| 130 | if sys.version_info[0] == 2: | ||
| 131 | path = path.decode(sys.getfilesystemencoding(), 'replace') | ||
| 132 | path = path.encode(sys.getdefaultencoding(), 'replace') | ||
| 133 | if path.startswith(os.getcwd() + os.path.sep): | ||
| 134 | path = '.' + path[len(os.getcwd()):] | ||
| 135 | return path | ||
| 136 | |||
| 137 | |||
| 138 | def backup_dir(dir, ext='.bak'): | ||
| 139 | """Figure out the name of a directory to back up the given dir to | ||
| 140 | (adding .bak, .bak2, etc)""" | ||
| 141 | n = 1 | ||
| 142 | extension = ext | ||
| 143 | while os.path.exists(dir + extension): | ||
| 144 | n += 1 | ||
| 145 | extension = ext + str(n) | ||
| 146 | return dir + extension | ||
| 147 | |||
| 148 | |||
| 149 | def ask_path_exists(message, options): | ||
| 150 | for action in os.environ.get('PIP_EXISTS_ACTION', '').split(): | ||
| 151 | if action in options: | ||
| 152 | return action | ||
| 153 | return ask(message, options) | ||
| 154 | |||
| 155 | |||
| 156 | def ask(message, options): | ||
| 157 | """Ask the message interactively, with the given possible responses""" | ||
| 158 | while 1: | ||
| 159 | if os.environ.get('PIP_NO_INPUT'): | ||
| 160 | raise Exception( | ||
| 161 | 'No input was expected ($PIP_NO_INPUT set); question: %s' % | ||
| 162 | message | ||
| 163 | ) | ||
| 164 | response = input(message) | ||
| 165 | response = response.strip().lower() | ||
| 166 | if response not in options: | ||
| 167 | print( | ||
| 168 | 'Your response (%r) was not one of the expected responses: ' | ||
| 169 | '%s' % (response, ', '.join(options)) | ||
| 170 | ) | ||
| 171 | else: | ||
| 172 | return response | ||
| 173 | |||
| 174 | |||
| 175 | def format_size(bytes): | ||
| 176 | if bytes > 1000 * 1000: | ||
| 177 | return '%.1fMB' % (bytes / 1000.0 / 1000) | ||
| 178 | elif bytes > 10 * 1000: | ||
| 179 | return '%ikB' % (bytes / 1000) | ||
| 180 | elif bytes > 1000: | ||
| 181 | return '%.1fkB' % (bytes / 1000.0) | ||
| 182 | else: | ||
| 183 | return '%ibytes' % bytes | ||
| 184 | |||
| 185 | |||
| 186 | def is_installable_dir(path): | ||
| 187 | """Return True if `path` is a directory containing a setup.py file.""" | ||
| 188 | if not os.path.isdir(path): | ||
| 189 | return False | ||
| 190 | setup_py = os.path.join(path, 'setup.py') | ||
| 191 | if os.path.isfile(setup_py): | ||
| 192 | return True | ||
| 193 | return False | ||
| 194 | |||
| 195 | |||
| 196 | def is_svn_page(html): | ||
| 197 | """ | ||
| 198 | Returns true if the page appears to be the index page of an svn repository | ||
| 199 | """ | ||
| 200 | return (re.search(r'<title>[^<]*Revision \d+:', html) and | ||
| 201 | re.search(r'Powered by (?:<a[^>]*?>)?Subversion', html, re.I)) | ||
| 202 | |||
| 203 | |||
| 204 | def file_contents(filename): | ||
| 205 | with open(filename, 'rb') as fp: | ||
| 206 | return fp.read().decode('utf-8') | ||
| 207 | |||
| 208 | |||
| 209 | def read_chunks(file, size=io.DEFAULT_BUFFER_SIZE): | ||
| 210 | """Yield pieces of data from a file-like object until EOF.""" | ||
| 211 | while True: | ||
| 212 | chunk = file.read(size) | ||
| 213 | if not chunk: | ||
| 214 | break | ||
| 215 | yield chunk | ||
| 216 | |||
| 217 | |||
| 218 | def split_leading_dir(path): | ||
| 219 | path = path.lstrip('/').lstrip('\\') | ||
| 220 | if '/' in path and (('\\' in path and path.find('/') < path.find('\\')) or | ||
| 221 | '\\' not in path): | ||
| 222 | return path.split('/', 1) | ||
| 223 | elif '\\' in path: | ||
| 224 | return path.split('\\', 1) | ||
| 225 | else: | ||
| 226 | return path, '' | ||
| 227 | |||
| 228 | |||
| 229 | def has_leading_dir(paths): | ||
| 230 | """Returns true if all the paths have the same leading path name | ||
| 231 | (i.e., everything is in one subdirectory in an archive)""" | ||
| 232 | common_prefix = None | ||
| 233 | for path in paths: | ||
| 234 | prefix, rest = split_leading_dir(path) | ||
| 235 | if not prefix: | ||
| 236 | return False | ||
| 237 | elif common_prefix is None: | ||
| 238 | common_prefix = prefix | ||
| 239 | elif prefix != common_prefix: | ||
| 240 | return False | ||
| 241 | return True | ||
| 242 | |||
| 243 | |||
| 244 | def normalize_path(path, resolve_symlinks=True): | ||
| 245 | """ | ||
| 246 | Convert a path to its canonical, case-normalized, absolute version. | ||
| 247 | |||
| 248 | """ | ||
| 249 | path = expanduser(path) | ||
| 250 | if resolve_symlinks: | ||
| 251 | path = os.path.realpath(path) | ||
| 252 | else: | ||
| 253 | path = os.path.abspath(path) | ||
| 254 | return os.path.normcase(path) | ||
| 255 | |||
| 256 | |||
| 257 | def splitext(path): | ||
| 258 | """Like os.path.splitext, but take off .tar too""" | ||
| 259 | base, ext = posixpath.splitext(path) | ||
| 260 | if base.lower().endswith('.tar'): | ||
| 261 | ext = base[-4:] + ext | ||
| 262 | base = base[:-4] | ||
| 263 | return base, ext | ||
| 264 | |||
| 265 | |||
| 266 | def renames(old, new): | ||
| 267 | """Like os.renames(), but handles renaming across devices.""" | ||
| 268 | # Implementation borrowed from os.renames(). | ||
| 269 | head, tail = os.path.split(new) | ||
| 270 | if head and tail and not os.path.exists(head): | ||
| 271 | os.makedirs(head) | ||
| 272 | |||
| 273 | shutil.move(old, new) | ||
| 274 | |||
| 275 | head, tail = os.path.split(old) | ||
| 276 | if head and tail: | ||
| 277 | try: | ||
| 278 | os.removedirs(head) | ||
| 279 | except OSError: | ||
| 280 | pass | ||
| 281 | |||
| 282 | |||
| 283 | def is_local(path): | ||
| 284 | """ | ||
| 285 | Return True if path is within sys.prefix, if we're running in a virtualenv. | ||
| 286 | |||
| 287 | If we're not in a virtualenv, all paths are considered "local." | ||
| 288 | |||
| 289 | """ | ||
| 290 | if not running_under_virtualenv(): | ||
| 291 | return True | ||
| 292 | return normalize_path(path).startswith(normalize_path(sys.prefix)) | ||
| 293 | |||
| 294 | |||
| 295 | def dist_is_local(dist): | ||
| 296 | """ | ||
| 297 | Return True if given Distribution object is installed locally | ||
| 298 | (i.e. within current virtualenv). | ||
| 299 | |||
| 300 | Always True if we're not in a virtualenv. | ||
| 301 | |||
| 302 | """ | ||
| 303 | return is_local(dist_location(dist)) | ||
| 304 | |||
| 305 | |||
| 306 | def dist_in_usersite(dist): | ||
| 307 | """ | ||
| 308 | Return True if given Distribution is installed in user site. | ||
| 309 | """ | ||
| 310 | norm_path = normalize_path(dist_location(dist)) | ||
| 311 | return norm_path.startswith(normalize_path(user_site)) | ||
| 312 | |||
| 313 | |||
| 314 | def dist_in_site_packages(dist): | ||
| 315 | """ | ||
| 316 | Return True if given Distribution is installed in | ||
| 317 | sysconfig.get_python_lib(). | ||
| 318 | """ | ||
| 319 | return normalize_path( | ||
| 320 | dist_location(dist) | ||
| 321 | ).startswith(normalize_path(site_packages)) | ||
| 322 | |||
| 323 | |||
| 324 | def dist_is_editable(dist): | ||
| 325 | """Is distribution an editable install?""" | ||
| 326 | for path_item in sys.path: | ||
| 327 | egg_link = os.path.join(path_item, dist.project_name + '.egg-link') | ||
| 328 | if os.path.isfile(egg_link): | ||
| 329 | return True | ||
| 330 | return False | ||
| 331 | |||
| 332 | |||
| 333 | def get_installed_distributions(local_only=True, | ||
| 334 | skip=stdlib_pkgs, | ||
| 335 | include_editables=True, | ||
| 336 | editables_only=False, | ||
| 337 | user_only=False): | ||
| 338 | """ | ||
| 339 | Return a list of installed Distribution objects. | ||
| 340 | |||
| 341 | If ``local_only`` is True (default), only return installations | ||
| 342 | local to the current virtualenv, if in a virtualenv. | ||
| 343 | |||
| 344 | ``skip`` argument is an iterable of lower-case project names to | ||
| 345 | ignore; defaults to stdlib_pkgs | ||
| 346 | |||
| 347 | If ``include_editables`` is False, don't report editables. | ||
| 348 | |||
| 349 | If ``editables_only`` is True , only report editables. | ||
| 350 | |||
| 351 | If ``user_only`` is True , only report installations in the user | ||
| 352 | site directory. | ||
| 353 | |||
| 354 | """ | ||
| 355 | if local_only: | ||
| 356 | local_test = dist_is_local | ||
| 357 | else: | ||
| 358 | def local_test(d): | ||
| 359 | return True | ||
| 360 | |||
| 361 | if include_editables: | ||
| 362 | def editable_test(d): | ||
| 363 | return True | ||
| 364 | else: | ||
| 365 | def editable_test(d): | ||
| 366 | return not dist_is_editable(d) | ||
| 367 | |||
| 368 | if editables_only: | ||
| 369 | def editables_only_test(d): | ||
| 370 | return dist_is_editable(d) | ||
| 371 | else: | ||
| 372 | def editables_only_test(d): | ||
| 373 | return True | ||
| 374 | |||
| 375 | if user_only: | ||
| 376 | user_test = dist_in_usersite | ||
| 377 | else: | ||
| 378 | def user_test(d): | ||
| 379 | return True | ||
| 380 | |||
| 381 | return [d for d in pkg_resources.working_set | ||
| 382 | if local_test(d) and | ||
| 383 | d.key not in skip and | ||
| 384 | editable_test(d) and | ||
| 385 | editables_only_test(d) and | ||
| 386 | user_test(d) | ||
| 387 | ] | ||
| 388 | |||
| 389 | |||
| 390 | def egg_link_path(dist): | ||
| 391 | """ | ||
| 392 | Return the path for the .egg-link file if it exists, otherwise, None. | ||
| 393 | |||
| 394 | There's 3 scenarios: | ||
| 395 | 1) not in a virtualenv | ||
| 396 | try to find in site.USER_SITE, then site_packages | ||
| 397 | 2) in a no-global virtualenv | ||
| 398 | try to find in site_packages | ||
| 399 | 3) in a yes-global virtualenv | ||
| 400 | try to find in site_packages, then site.USER_SITE | ||
| 401 | (don't look in global location) | ||
| 402 | |||
| 403 | For #1 and #3, there could be odd cases, where there's an egg-link in 2 | ||
| 404 | locations. | ||
| 405 | |||
| 406 | This method will just return the first one found. | ||
| 407 | """ | ||
| 408 | sites = [] | ||
| 409 | if running_under_virtualenv(): | ||
| 410 | if virtualenv_no_global(): | ||
| 411 | sites.append(site_packages) | ||
| 412 | else: | ||
| 413 | sites.append(site_packages) | ||
| 414 | if user_site: | ||
| 415 | sites.append(user_site) | ||
| 416 | else: | ||
| 417 | if user_site: | ||
| 418 | sites.append(user_site) | ||
| 419 | sites.append(site_packages) | ||
| 420 | |||
| 421 | for site in sites: | ||
| 422 | egglink = os.path.join(site, dist.project_name) + '.egg-link' | ||
| 423 | if os.path.isfile(egglink): | ||
| 424 | return egglink | ||
| 425 | |||
| 426 | |||
| 427 | def dist_location(dist): | ||
| 428 | """ | ||
| 429 | Get the site-packages location of this distribution. Generally | ||
| 430 | this is dist.location, except in the case of develop-installed | ||
| 431 | packages, where dist.location is the source code location, and we | ||
| 432 | want to know where the egg-link file is. | ||
| 433 | |||
| 434 | """ | ||
| 435 | egg_link = egg_link_path(dist) | ||
| 436 | if egg_link: | ||
| 437 | return egg_link | ||
| 438 | return dist.location | ||
| 439 | |||
| 440 | |||
| 441 | def current_umask(): | ||
| 442 | """Get the current umask which involves having to set it temporarily.""" | ||
| 443 | mask = os.umask(0) | ||
| 444 | os.umask(mask) | ||
| 445 | return mask | ||
| 446 | |||
| 447 | |||
| 448 | def unzip_file(filename, location, flatten=True): | ||
| 449 | """ | ||
| 450 | Unzip the file (with path `filename`) to the destination `location`. All | ||
| 451 | files are written based on system defaults and umask (i.e. permissions are | ||
| 452 | not preserved), except that regular file members with any execute | ||
| 453 | permissions (user, group, or world) have "chmod +x" applied after being | ||
| 454 | written. Note that for windows, any execute changes using os.chmod are | ||
| 455 | no-ops per the python docs. | ||
| 456 | """ | ||
| 457 | ensure_dir(location) | ||
| 458 | zipfp = open(filename, 'rb') | ||
| 459 | try: | ||
| 460 | zip = zipfile.ZipFile(zipfp, allowZip64=True) | ||
| 461 | leading = has_leading_dir(zip.namelist()) and flatten | ||
| 462 | for info in zip.infolist(): | ||
| 463 | name = info.filename | ||
| 464 | data = zip.read(name) | ||
| 465 | fn = name | ||
| 466 | if leading: | ||
| 467 | fn = split_leading_dir(name)[1] | ||
| 468 | fn = os.path.join(location, fn) | ||
| 469 | dir = os.path.dirname(fn) | ||
| 470 | if fn.endswith('/') or fn.endswith('\\'): | ||
| 471 | # A directory | ||
| 472 | ensure_dir(fn) | ||
| 473 | else: | ||
| 474 | ensure_dir(dir) | ||
| 475 | fp = open(fn, 'wb') | ||
| 476 | try: | ||
| 477 | fp.write(data) | ||
| 478 | finally: | ||
| 479 | fp.close() | ||
| 480 | mode = info.external_attr >> 16 | ||
| 481 | # if mode and regular file and any execute permissions for | ||
| 482 | # user/group/world? | ||
| 483 | if mode and stat.S_ISREG(mode) and mode & 0o111: | ||
| 484 | # make dest file have execute for user/group/world | ||
| 485 | # (chmod +x) no-op on windows per python docs | ||
| 486 | os.chmod(fn, (0o777 - current_umask() | 0o111)) | ||
| 487 | finally: | ||
| 488 | zipfp.close() | ||
| 489 | |||
| 490 | |||
| 491 | def untar_file(filename, location): | ||
| 492 | """ | ||
| 493 | Untar the file (with path `filename`) to the destination `location`. | ||
| 494 | All files are written based on system defaults and umask (i.e. permissions | ||
| 495 | are not preserved), except that regular file members with any execute | ||
| 496 | permissions (user, group, or world) have "chmod +x" applied after being | ||
| 497 | written. Note that for windows, any execute changes using os.chmod are | ||
| 498 | no-ops per the python docs. | ||
| 499 | """ | ||
| 500 | ensure_dir(location) | ||
| 501 | if filename.lower().endswith('.gz') or filename.lower().endswith('.tgz'): | ||
| 502 | mode = 'r:gz' | ||
| 503 | elif filename.lower().endswith(BZ2_EXTENSIONS): | ||
| 504 | mode = 'r:bz2' | ||
| 505 | elif filename.lower().endswith(XZ_EXTENSIONS): | ||
| 506 | mode = 'r:xz' | ||
| 507 | elif filename.lower().endswith('.tar'): | ||
| 508 | mode = 'r' | ||
| 509 | else: | ||
| 510 | logger.warning( | ||
| 511 | 'Cannot determine compression type for file %s', filename, | ||
| 512 | ) | ||
| 513 | mode = 'r:*' | ||
| 514 | tar = tarfile.open(filename, mode) | ||
| 515 | try: | ||
| 516 | # note: python<=2.5 doesn't seem to know about pax headers, filter them | ||
| 517 | leading = has_leading_dir([ | ||
| 518 | member.name for member in tar.getmembers() | ||
| 519 | if member.name != 'pax_global_header' | ||
| 520 | ]) | ||
| 521 | for member in tar.getmembers(): | ||
| 522 | fn = member.name | ||
| 523 | if fn == 'pax_global_header': | ||
| 524 | continue | ||
| 525 | if leading: | ||
| 526 | fn = split_leading_dir(fn)[1] | ||
| 527 | path = os.path.join(location, fn) | ||
| 528 | if member.isdir(): | ||
| 529 | ensure_dir(path) | ||
| 530 | elif member.issym(): | ||
| 531 | try: | ||
| 532 | tar._extract_member(member, path) | ||
| 533 | except Exception as exc: | ||
| 534 | # Some corrupt tar files seem to produce this | ||
| 535 | # (specifically bad symlinks) | ||
| 536 | logger.warning( | ||
| 537 | 'In the tar file %s the member %s is invalid: %s', | ||
| 538 | filename, member.name, exc, | ||
| 539 | ) | ||
| 540 | continue | ||
| 541 | else: | ||
| 542 | try: | ||
| 543 | fp = tar.extractfile(member) | ||
| 544 | except (KeyError, AttributeError) as exc: | ||
| 545 | # Some corrupt tar files seem to produce this | ||
| 546 | # (specifically bad symlinks) | ||
| 547 | logger.warning( | ||
| 548 | 'In the tar file %s the member %s is invalid: %s', | ||
| 549 | filename, member.name, exc, | ||
| 550 | ) | ||
| 551 | continue | ||
| 552 | ensure_dir(os.path.dirname(path)) | ||
| 553 | with open(path, 'wb') as destfp: | ||
| 554 | shutil.copyfileobj(fp, destfp) | ||
| 555 | fp.close() | ||
| 556 | # Update the timestamp (useful for cython compiled files) | ||
| 557 | tar.utime(member, path) | ||
| 558 | # member have any execute permissions for user/group/world? | ||
| 559 | if member.mode & 0o111: | ||
| 560 | # make dest file have execute for user/group/world | ||
| 561 | # no-op on windows per python docs | ||
| 562 | os.chmod(path, (0o777 - current_umask() | 0o111)) | ||
| 563 | finally: | ||
| 564 | tar.close() | ||
| 565 | |||
| 566 | |||
| 567 | def unpack_file(filename, location, content_type, link): | ||
| 568 | filename = os.path.realpath(filename) | ||
| 569 | if (content_type == 'application/zip' or | ||
| 570 | filename.lower().endswith(ZIP_EXTENSIONS) or | ||
| 571 | zipfile.is_zipfile(filename)): | ||
| 572 | unzip_file( | ||
| 573 | filename, | ||
| 574 | location, | ||
| 575 | flatten=not filename.endswith('.whl') | ||
| 576 | ) | ||
| 577 | elif (content_type == 'application/x-gzip' or | ||
| 578 | tarfile.is_tarfile(filename) or | ||
| 579 | filename.lower().endswith( | ||
| 580 | TAR_EXTENSIONS + BZ2_EXTENSIONS + XZ_EXTENSIONS)): | ||
| 581 | untar_file(filename, location) | ||
| 582 | elif (content_type and content_type.startswith('text/html') and | ||
| 583 | is_svn_page(file_contents(filename))): | ||
| 584 | # We don't really care about this | ||
| 585 | from pip._internal.vcs.subversion import Subversion | ||
| 586 | Subversion('svn+' + link.url).unpack(location) | ||
| 587 | else: | ||
| 588 | # FIXME: handle? | ||
| 589 | # FIXME: magic signatures? | ||
| 590 | logger.critical( | ||
| 591 | 'Cannot unpack file %s (downloaded from %s, content-type: %s); ' | ||
| 592 | 'cannot detect archive format', | ||
| 593 | filename, location, content_type, | ||
| 594 | ) | ||
| 595 | raise InstallationError( | ||
| 596 | 'Cannot determine archive format of %s' % location | ||
| 597 | ) | ||
| 598 | |||
| 599 | |||
| 600 | def call_subprocess(cmd, show_stdout=True, cwd=None, | ||
| 601 | on_returncode='raise', | ||
| 602 | command_desc=None, | ||
| 603 | extra_environ=None, unset_environ=None, spinner=None): | ||
| 604 | """ | ||
| 605 | Args: | ||
| 606 | unset_environ: an iterable of environment variable names to unset | ||
| 607 | prior to calling subprocess.Popen(). | ||
| 608 | """ | ||
| 609 | if unset_environ is None: | ||
| 610 | unset_environ = [] | ||
| 611 | # This function's handling of subprocess output is confusing and I | ||
| 612 | # previously broke it terribly, so as penance I will write a long comment | ||
| 613 | # explaining things. | ||
| 614 | # | ||
| 615 | # The obvious thing that affects output is the show_stdout= | ||
| 616 | # kwarg. show_stdout=True means, let the subprocess write directly to our | ||
| 617 | # stdout. Even though it is nominally the default, it is almost never used | ||
| 618 | # inside pip (and should not be used in new code without a very good | ||
| 619 | # reason); as of 2016-02-22 it is only used in a few places inside the VCS | ||
| 620 | # wrapper code. Ideally we should get rid of it entirely, because it | ||
| 621 | # creates a lot of complexity here for a rarely used feature. | ||
| 622 | # | ||
| 623 | # Most places in pip set show_stdout=False. What this means is: | ||
| 624 | # - We connect the child stdout to a pipe, which we read. | ||
| 625 | # - By default, we hide the output but show a spinner -- unless the | ||
| 626 | # subprocess exits with an error, in which case we show the output. | ||
| 627 | # - If the --verbose option was passed (= loglevel is DEBUG), then we show | ||
| 628 | # the output unconditionally. (But in this case we don't want to show | ||
| 629 | # the output a second time if it turns out that there was an error.) | ||
| 630 | # | ||
| 631 | # stderr is always merged with stdout (even if show_stdout=True). | ||
| 632 | if show_stdout: | ||
| 633 | stdout = None | ||
| 634 | else: | ||
| 635 | stdout = subprocess.PIPE | ||
| 636 | if command_desc is None: | ||
| 637 | cmd_parts = [] | ||
| 638 | for part in cmd: | ||
| 639 | if ' ' in part or '\n' in part or '"' in part or "'" in part: | ||
| 640 | part = '"%s"' % part.replace('"', '\\"') | ||
| 641 | cmd_parts.append(part) | ||
| 642 | command_desc = ' '.join(cmd_parts) | ||
| 643 | logger.debug("Running command %s", command_desc) | ||
| 644 | env = os.environ.copy() | ||
| 645 | if extra_environ: | ||
| 646 | env.update(extra_environ) | ||
| 647 | for name in unset_environ: | ||
| 648 | env.pop(name, None) | ||
| 649 | try: | ||
| 650 | proc = subprocess.Popen( | ||
| 651 | cmd, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, | ||
| 652 | stdout=stdout, cwd=cwd, env=env, | ||
| 653 | ) | ||
| 654 | proc.stdin.close() | ||
| 655 | except Exception as exc: | ||
| 656 | logger.critical( | ||
| 657 | "Error %s while executing command %s", exc, command_desc, | ||
| 658 | ) | ||
| 659 | raise | ||
| 660 | all_output = [] | ||
| 661 | if stdout is not None: | ||
| 662 | while True: | ||
| 663 | line = console_to_str(proc.stdout.readline()) | ||
| 664 | if not line: | ||
| 665 | break | ||
| 666 | line = line.rstrip() | ||
| 667 | all_output.append(line + '\n') | ||
| 668 | if logger.getEffectiveLevel() <= std_logging.DEBUG: | ||
| 669 | # Show the line immediately | ||
| 670 | logger.debug(line) | ||
| 671 | else: | ||
| 672 | # Update the spinner | ||
| 673 | if spinner is not None: | ||
| 674 | spinner.spin() | ||
| 675 | try: | ||
| 676 | proc.wait() | ||
| 677 | finally: | ||
| 678 | if proc.stdout: | ||
| 679 | proc.stdout.close() | ||
| 680 | if spinner is not None: | ||
| 681 | if proc.returncode: | ||
| 682 | spinner.finish("error") | ||
| 683 | else: | ||
| 684 | spinner.finish("done") | ||
| 685 | if proc.returncode: | ||
| 686 | if on_returncode == 'raise': | ||
| 687 | if (logger.getEffectiveLevel() > std_logging.DEBUG and | ||
| 688 | not show_stdout): | ||
| 689 | logger.info( | ||
| 690 | 'Complete output from command %s:', command_desc, | ||
| 691 | ) | ||
| 692 | logger.info( | ||
| 693 | ''.join(all_output) + | ||
| 694 | '\n----------------------------------------' | ||
| 695 | ) | ||
| 696 | raise InstallationError( | ||
| 697 | 'Command "%s" failed with error code %s in %s' | ||
| 698 | % (command_desc, proc.returncode, cwd)) | ||
| 699 | elif on_returncode == 'warn': | ||
| 700 | logger.warning( | ||
| 701 | 'Command "%s" had error code %s in %s', | ||
| 702 | command_desc, proc.returncode, cwd, | ||
| 703 | ) | ||
| 704 | elif on_returncode == 'ignore': | ||
| 705 | pass | ||
| 706 | else: | ||
| 707 | raise ValueError('Invalid value: on_returncode=%s' % | ||
| 708 | repr(on_returncode)) | ||
| 709 | if not show_stdout: | ||
| 710 | return ''.join(all_output) | ||
| 711 | |||
| 712 | |||
| 713 | def read_text_file(filename): | ||
| 714 | """Return the contents of *filename*. | ||
| 715 | |||
| 716 | Try to decode the file contents with utf-8, the preferred system encoding | ||
| 717 | (e.g., cp1252 on some Windows machines), and latin1, in that order. | ||
| 718 | Decoding a byte string with latin1 will never raise an error. In the worst | ||
| 719 | case, the returned string will contain some garbage characters. | ||
| 720 | |||
| 721 | """ | ||
| 722 | with open(filename, 'rb') as fp: | ||
| 723 | data = fp.read() | ||
| 724 | |||
| 725 | encodings = ['utf-8', locale.getpreferredencoding(False), 'latin1'] | ||
| 726 | for enc in encodings: | ||
| 727 | try: | ||
| 728 | data = data.decode(enc) | ||
| 729 | except UnicodeDecodeError: | ||
| 730 | continue | ||
| 731 | break | ||
| 732 | |||
| 733 | assert type(data) != bytes # Latin1 should have worked. | ||
| 734 | return data | ||
| 735 | |||
| 736 | |||
| 737 | def _make_build_dir(build_dir): | ||
| 738 | os.makedirs(build_dir) | ||
| 739 | write_delete_marker_file(build_dir) | ||
| 740 | |||
| 741 | |||
| 742 | class FakeFile(object): | ||
| 743 | """Wrap a list of lines in an object with readline() to make | ||
| 744 | ConfigParser happy.""" | ||
| 745 | def __init__(self, lines): | ||
| 746 | self._gen = (l for l in lines) | ||
| 747 | |||
| 748 | def readline(self): | ||
| 749 | try: | ||
| 750 | try: | ||
| 751 | return next(self._gen) | ||
| 752 | except NameError: | ||
| 753 | return self._gen.next() | ||
| 754 | except StopIteration: | ||
| 755 | return '' | ||
| 756 | |||
| 757 | def __iter__(self): | ||
| 758 | return self._gen | ||
| 759 | |||
| 760 | |||
| 761 | class StreamWrapper(StringIO): | ||
| 762 | |||
| 763 | @classmethod | ||
| 764 | def from_stream(cls, orig_stream): | ||
| 765 | cls.orig_stream = orig_stream | ||
| 766 | return cls() | ||
| 767 | |||
| 768 | # compileall.compile_dir() needs stdout.encoding to print to stdout | ||
| 769 | @property | ||
| 770 | def encoding(self): | ||
| 771 | return self.orig_stream.encoding | ||
| 772 | |||
| 773 | |||
| 774 | @contextlib.contextmanager | ||
| 775 | def captured_output(stream_name): | ||
| 776 | """Return a context manager used by captured_stdout/stdin/stderr | ||
| 777 | that temporarily replaces the sys stream *stream_name* with a StringIO. | ||
| 778 | |||
| 779 | Taken from Lib/support/__init__.py in the CPython repo. | ||
| 780 | """ | ||
| 781 | orig_stdout = getattr(sys, stream_name) | ||
| 782 | setattr(sys, stream_name, StreamWrapper.from_stream(orig_stdout)) | ||
| 783 | try: | ||
| 784 | yield getattr(sys, stream_name) | ||
| 785 | finally: | ||
| 786 | setattr(sys, stream_name, orig_stdout) | ||
| 787 | |||
| 788 | |||
| 789 | def captured_stdout(): | ||
| 790 | """Capture the output of sys.stdout: | ||
| 791 | |||
| 792 | with captured_stdout() as stdout: | ||
| 793 | print('hello') | ||
| 794 | self.assertEqual(stdout.getvalue(), 'hello\n') | ||
| 795 | |||
| 796 | Taken from Lib/support/__init__.py in the CPython repo. | ||
| 797 | """ | ||
| 798 | return captured_output('stdout') | ||
| 799 | |||
| 800 | |||
| 801 | class cached_property(object): | ||
| 802 | """A property that is only computed once per instance and then replaces | ||
| 803 | itself with an ordinary attribute. Deleting the attribute resets the | ||
| 804 | property. | ||
| 805 | |||
| 806 | Source: https://github.com/bottlepy/bottle/blob/0.11.5/bottle.py#L175 | ||
| 807 | """ | ||
| 808 | |||
| 809 | def __init__(self, func): | ||
| 810 | self.__doc__ = getattr(func, '__doc__') | ||
| 811 | self.func = func | ||
| 812 | |||
| 813 | def __get__(self, obj, cls): | ||
| 814 | if obj is None: | ||
| 815 | # We're being accessed from the class itself, not from an object | ||
| 816 | return self | ||
| 817 | value = obj.__dict__[self.func.__name__] = self.func(obj) | ||
| 818 | return value | ||
| 819 | |||
| 820 | |||
| 821 | def get_installed_version(dist_name, lookup_dirs=None): | ||
| 822 | """Get the installed version of dist_name avoiding pkg_resources cache""" | ||
| 823 | # Create a requirement that we'll look for inside of setuptools. | ||
| 824 | req = pkg_resources.Requirement.parse(dist_name) | ||
| 825 | |||
| 826 | # We want to avoid having this cached, so we need to construct a new | ||
| 827 | # working set each time. | ||
| 828 | if lookup_dirs is None: | ||
| 829 | working_set = pkg_resources.WorkingSet() | ||
| 830 | else: | ||
| 831 | working_set = pkg_resources.WorkingSet(lookup_dirs) | ||
| 832 | |||
| 833 | # Get the installed distribution from our working set | ||
| 834 | dist = working_set.find(req) | ||
| 835 | |||
| 836 | # Check to see if we got an installed distribution or not, if we did | ||
| 837 | # we want to return it's version. | ||
| 838 | return dist.version if dist else None | ||
| 839 | |||
| 840 | |||
| 841 | def consume(iterator): | ||
| 842 | """Consume an iterable at C speed.""" | ||
| 843 | deque(iterator, maxlen=0) | ||
| 844 | |||
| 845 | |||
| 846 | # Simulates an enum | ||
| 847 | def enum(*sequential, **named): | ||
| 848 | enums = dict(zip(sequential, range(len(sequential))), **named) | ||
| 849 | reverse = {value: key for key, value in enums.items()} | ||
| 850 | enums['reverse_mapping'] = reverse | ||
| 851 | return type('Enum', (), enums) | ||
