PageRenderTime 57ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/env/lib/python3.3/site-packages/pip/util.py

https://github.com/wantsomechocolate/MosaicMaker
Python | 693 lines | 648 code | 15 blank | 30 comment | 21 complexity | 77a16db0915d5a6eb5eb41ba5ce2cf79 MD5 | raw file
  1. import sys
  2. import shutil
  3. import os
  4. import stat
  5. import re
  6. import posixpath
  7. import pkg_resources
  8. import zipfile
  9. import tarfile
  10. import subprocess
  11. import textwrap
  12. from pip.exceptions import InstallationError, BadCommand, PipError
  13. from pip.backwardcompat import(WindowsError, string_types, raw_input,
  14. console_to_str, user_site, PermissionError)
  15. from pip.locations import site_packages, running_under_virtualenv, virtualenv_no_global
  16. from pip.log import logger
  17. from pip.vendor.distlib import version
  18. __all__ = ['rmtree', 'display_path', 'backup_dir',
  19. 'find_command', 'ask', 'Inf',
  20. 'normalize_name', 'splitext',
  21. 'format_size', 'is_installable_dir',
  22. 'is_svn_page', 'file_contents',
  23. 'split_leading_dir', 'has_leading_dir',
  24. 'make_path_relative', 'normalize_path',
  25. 'renames', 'get_terminal_size', 'get_prog',
  26. 'unzip_file', 'untar_file', 'create_download_cache_folder',
  27. 'cache_download', 'unpack_file', 'call_subprocess']
  28. def get_prog():
  29. try:
  30. if os.path.basename(sys.argv[0]) in ('__main__.py', '-c'):
  31. return "%s -m pip" % sys.executable
  32. except (AttributeError, TypeError, IndexError):
  33. pass
  34. return 'pip'
  35. def rmtree(dir, ignore_errors=False):
  36. shutil.rmtree(dir, ignore_errors=ignore_errors,
  37. onerror=rmtree_errorhandler)
  38. def rmtree_errorhandler(func, path, exc_info):
  39. """On Windows, the files in .svn are read-only, so when rmtree() tries to
  40. remove them, an exception is thrown. We catch that here, remove the
  41. read-only attribute, and hopefully continue without problems."""
  42. exctype, value = exc_info[:2]
  43. if not ((exctype is WindowsError and value.args[0] == 5) or #others
  44. (exctype is OSError and value.args[0] == 13) or #python2.4
  45. (exctype is PermissionError and value.args[3] == 5) #python3.3
  46. ):
  47. raise
  48. # file type should currently be read only
  49. if ((os.stat(path).st_mode & stat.S_IREAD) != stat.S_IREAD):
  50. raise
  51. # convert to read/write
  52. os.chmod(path, stat.S_IWRITE)
  53. # use the original function to repeat the operation
  54. func(path)
  55. def display_path(path):
  56. """Gives the display value for a given path, making it relative to cwd
  57. if possible."""
  58. path = os.path.normcase(os.path.abspath(path))
  59. if path.startswith(os.getcwd() + os.path.sep):
  60. path = '.' + path[len(os.getcwd()):]
  61. return path
  62. def backup_dir(dir, ext='.bak'):
  63. """Figure out the name of a directory to back up the given dir to
  64. (adding .bak, .bak2, etc)"""
  65. n = 1
  66. extension = ext
  67. while os.path.exists(dir + extension):
  68. n += 1
  69. extension = ext + str(n)
  70. return dir + extension
  71. def find_command(cmd, paths=None, pathext=None):
  72. """Searches the PATH for the given command and returns its path"""
  73. if paths is None:
  74. paths = os.environ.get('PATH', '').split(os.pathsep)
  75. if isinstance(paths, string_types):
  76. paths = [paths]
  77. # check if there are funny path extensions for executables, e.g. Windows
  78. if pathext is None:
  79. pathext = get_pathext()
  80. pathext = [ext for ext in pathext.lower().split(os.pathsep) if len(ext)]
  81. # don't use extensions if the command ends with one of them
  82. if os.path.splitext(cmd)[1].lower() in pathext:
  83. pathext = ['']
  84. # check if we find the command on PATH
  85. for path in paths:
  86. # try without extension first
  87. cmd_path = os.path.join(path, cmd)
  88. for ext in pathext:
  89. # then including the extension
  90. cmd_path_ext = cmd_path + ext
  91. if os.path.isfile(cmd_path_ext):
  92. return cmd_path_ext
  93. if os.path.isfile(cmd_path):
  94. return cmd_path
  95. raise BadCommand('Cannot find command %r' % cmd)
  96. def get_pathext(default_pathext=None):
  97. """Returns the path extensions from environment or a default"""
  98. if default_pathext is None:
  99. default_pathext = os.pathsep.join(['.COM', '.EXE', '.BAT', '.CMD'])
  100. pathext = os.environ.get('PATHEXT', default_pathext)
  101. return pathext
  102. def ask_path_exists(message, options):
  103. for action in os.environ.get('PIP_EXISTS_ACTION', ''):
  104. if action in options:
  105. return action
  106. return ask(message, options)
  107. def ask(message, options):
  108. """Ask the message interactively, with the given possible responses"""
  109. while 1:
  110. if os.environ.get('PIP_NO_INPUT'):
  111. raise Exception('No input was expected ($PIP_NO_INPUT set); question: %s' % message)
  112. response = raw_input(message)
  113. response = response.strip().lower()
  114. if response not in options:
  115. print('Your response (%r) was not one of the expected responses: %s' % (
  116. response, ', '.join(options)))
  117. else:
  118. return response
  119. class _Inf(object):
  120. """I am bigger than everything!"""
  121. def __eq__(self, other):
  122. if self is other:
  123. return True
  124. else:
  125. return False
  126. def __ne__(self, other):
  127. return not self.__eq__(other)
  128. def __lt__(self, other):
  129. return False
  130. def __le__(self, other):
  131. return False
  132. def __gt__(self, other):
  133. return True
  134. def __ge__(self, other):
  135. return True
  136. def __repr__(self):
  137. return 'Inf'
  138. Inf = _Inf() #this object is not currently used as a sortable in our code
  139. del _Inf
  140. _normalize_re = re.compile(r'[^a-z]', re.I)
  141. def normalize_name(name):
  142. return _normalize_re.sub('-', name.lower())
  143. def format_size(bytes):
  144. if bytes > 1000*1000:
  145. return '%.1fMB' % (bytes/1000.0/1000)
  146. elif bytes > 10*1000:
  147. return '%ikB' % (bytes/1000)
  148. elif bytes > 1000:
  149. return '%.1fkB' % (bytes/1000.0)
  150. else:
  151. return '%ibytes' % bytes
  152. def is_installable_dir(path):
  153. """Return True if `path` is a directory containing a setup.py file."""
  154. if not os.path.isdir(path):
  155. return False
  156. setup_py = os.path.join(path, 'setup.py')
  157. if os.path.isfile(setup_py):
  158. return True
  159. return False
  160. def is_svn_page(html):
  161. """Returns true if the page appears to be the index page of an svn repository"""
  162. return (re.search(r'<title>[^<]*Revision \d+:', html)
  163. and re.search(r'Powered by (?:<a[^>]*?>)?Subversion', html, re.I))
  164. def file_contents(filename):
  165. fp = open(filename, 'rb')
  166. try:
  167. return fp.read().decode('utf-8')
  168. finally:
  169. fp.close()
  170. def split_leading_dir(path):
  171. path = str(path)
  172. path = path.lstrip('/').lstrip('\\')
  173. if '/' in path and (('\\' in path and path.find('/') < path.find('\\'))
  174. or '\\' not in path):
  175. return path.split('/', 1)
  176. elif '\\' in path:
  177. return path.split('\\', 1)
  178. else:
  179. return path, ''
  180. def has_leading_dir(paths):
  181. """Returns true if all the paths have the same leading path name
  182. (i.e., everything is in one subdirectory in an archive)"""
  183. common_prefix = None
  184. for path in paths:
  185. prefix, rest = split_leading_dir(path)
  186. if not prefix:
  187. return False
  188. elif common_prefix is None:
  189. common_prefix = prefix
  190. elif prefix != common_prefix:
  191. return False
  192. return True
  193. def make_path_relative(path, rel_to):
  194. """
  195. Make a filename relative, where the filename path, and it is
  196. relative to rel_to
  197. >>> make_relative_path('/usr/share/something/a-file.pth',
  198. ... '/usr/share/another-place/src/Directory')
  199. '../../../something/a-file.pth'
  200. >>> make_relative_path('/usr/share/something/a-file.pth',
  201. ... '/home/user/src/Directory')
  202. '../../../usr/share/something/a-file.pth'
  203. >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/')
  204. 'a-file.pth'
  205. """
  206. path_filename = os.path.basename(path)
  207. path = os.path.dirname(path)
  208. path = os.path.normpath(os.path.abspath(path))
  209. rel_to = os.path.normpath(os.path.abspath(rel_to))
  210. path_parts = path.strip(os.path.sep).split(os.path.sep)
  211. rel_to_parts = rel_to.strip(os.path.sep).split(os.path.sep)
  212. while path_parts and rel_to_parts and path_parts[0] == rel_to_parts[0]:
  213. path_parts.pop(0)
  214. rel_to_parts.pop(0)
  215. full_parts = ['..']*len(rel_to_parts) + path_parts + [path_filename]
  216. if full_parts == ['']:
  217. return '.' + os.path.sep
  218. return os.path.sep.join(full_parts)
  219. def normalize_path(path):
  220. """
  221. Convert a path to its canonical, case-normalized, absolute version.
  222. """
  223. return os.path.normcase(os.path.realpath(path))
  224. def splitext(path):
  225. """Like os.path.splitext, but take off .tar too"""
  226. base, ext = posixpath.splitext(path)
  227. if base.lower().endswith('.tar'):
  228. ext = base[-4:] + ext
  229. base = base[:-4]
  230. return base, ext
  231. def renames(old, new):
  232. """Like os.renames(), but handles renaming across devices."""
  233. # Implementation borrowed from os.renames().
  234. head, tail = os.path.split(new)
  235. if head and tail and not os.path.exists(head):
  236. os.makedirs(head)
  237. shutil.move(old, new)
  238. head, tail = os.path.split(old)
  239. if head and tail:
  240. try:
  241. os.removedirs(head)
  242. except OSError:
  243. pass
  244. def is_local(path):
  245. """
  246. Return True if path is within sys.prefix, if we're running in a virtualenv.
  247. If we're not in a virtualenv, all paths are considered "local."
  248. """
  249. if not running_under_virtualenv():
  250. return True
  251. return normalize_path(path).startswith(normalize_path(sys.prefix))
  252. def dist_is_local(dist):
  253. """
  254. Return True if given Distribution object is installed locally
  255. (i.e. within current virtualenv).
  256. Always True if we're not in a virtualenv.
  257. """
  258. return is_local(dist_location(dist))
  259. def dist_in_usersite(dist):
  260. """
  261. Return True if given Distribution is installed in user site.
  262. """
  263. if user_site:
  264. return normalize_path(dist_location(dist)).startswith(normalize_path(user_site))
  265. else:
  266. return False
  267. def dist_in_site_packages(dist):
  268. """
  269. Return True if given Distribution is installed in distutils.sysconfig.get_python_lib().
  270. """
  271. return normalize_path(dist_location(dist)).startswith(normalize_path(site_packages))
  272. def dist_is_editable(dist):
  273. """Is distribution an editable install?"""
  274. #TODO: factor out determining editableness out of FrozenRequirement
  275. from pip import FrozenRequirement
  276. req = FrozenRequirement.from_dist(dist, [])
  277. return req.editable
  278. def get_installed_distributions(local_only=True,
  279. skip=('setuptools', 'pip', 'python'),
  280. include_editables=True,
  281. editables_only=False):
  282. """
  283. Return a list of installed Distribution objects.
  284. If ``local_only`` is True (default), only return installations
  285. local to the current virtualenv, if in a virtualenv.
  286. ``skip`` argument is an iterable of lower-case project names to
  287. ignore; defaults to ('setuptools', 'pip', 'python'). [FIXME also
  288. skip virtualenv?]
  289. If ``editables`` is False, don't report editables.
  290. If ``editables_only`` is True , only report editables.
  291. """
  292. if local_only:
  293. local_test = dist_is_local
  294. else:
  295. local_test = lambda d: True
  296. if include_editables:
  297. editable_test = lambda d: True
  298. else:
  299. editable_test = lambda d: not dist_is_editable(d)
  300. if editables_only:
  301. editables_only_test = lambda d: dist_is_editable(d)
  302. else:
  303. editables_only_test = lambda d: True
  304. return [d for d in pkg_resources.working_set
  305. if local_test(d)
  306. and d.key not in skip
  307. and editable_test(d)
  308. and editables_only_test(d)
  309. ]
  310. def egg_link_path(dist):
  311. """
  312. Return the path for the .egg-link file if it exists, otherwise, None.
  313. There's 3 scenarios:
  314. 1) not in a virtualenv
  315. try to find in site.USER_SITE, then site_packages
  316. 2) in a no-global virtualenv
  317. try to find in site_packages
  318. 3) in a yes-global virtualenv
  319. try to find in site_packages, then site.USER_SITE (don't look in global location)
  320. For #1 and #3, there could be odd cases, where there's an egg-link in 2 locations.
  321. This method will just return the first one found.
  322. """
  323. sites = []
  324. if running_under_virtualenv():
  325. if virtualenv_no_global():
  326. sites.append(site_packages)
  327. else:
  328. sites.append(site_packages)
  329. if user_site:
  330. sites.append(user_site)
  331. else:
  332. if user_site:
  333. sites.append(user_site)
  334. sites.append(site_packages)
  335. for site in sites:
  336. egglink = os.path.join(site, dist.project_name) + '.egg-link'
  337. if os.path.isfile(egglink):
  338. return egglink
  339. def dist_location(dist):
  340. """
  341. Get the site-packages location of this distribution. Generally
  342. this is dist.location, except in the case of develop-installed
  343. packages, where dist.location is the source code location, and we
  344. want to know where the egg-link file is.
  345. """
  346. egg_link = egg_link_path(dist)
  347. if egg_link:
  348. return egg_link
  349. return dist.location
  350. def get_terminal_size():
  351. """Returns a tuple (x, y) representing the width(x) and the height(x)
  352. in characters of the terminal window."""
  353. def ioctl_GWINSZ(fd):
  354. try:
  355. import fcntl
  356. import termios
  357. import struct
  358. cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,
  359. '1234'))
  360. except:
  361. return None
  362. if cr == (0, 0):
  363. return None
  364. if cr == (0, 0):
  365. return None
  366. return cr
  367. cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
  368. if not cr:
  369. try:
  370. fd = os.open(os.ctermid(), os.O_RDONLY)
  371. cr = ioctl_GWINSZ(fd)
  372. os.close(fd)
  373. except:
  374. pass
  375. if not cr:
  376. cr = (os.environ.get('LINES', 25), os.environ.get('COLUMNS', 80))
  377. return int(cr[1]), int(cr[0])
  378. def unzip_file(filename, location, flatten=True):
  379. """Unzip the file (zip file located at filename) to the destination
  380. location"""
  381. if not os.path.exists(location):
  382. os.makedirs(location)
  383. zipfp = open(filename, 'rb')
  384. try:
  385. zip = zipfile.ZipFile(zipfp)
  386. leading = has_leading_dir(zip.namelist()) and flatten
  387. for info in zip.infolist():
  388. name = info.filename
  389. data = zip.read(name)
  390. fn = name
  391. if leading:
  392. fn = split_leading_dir(name)[1]
  393. fn = os.path.join(location, fn)
  394. dir = os.path.dirname(fn)
  395. if not os.path.exists(dir):
  396. os.makedirs(dir)
  397. if fn.endswith('/') or fn.endswith('\\'):
  398. # A directory
  399. if not os.path.exists(fn):
  400. os.makedirs(fn)
  401. else:
  402. fp = open(fn, 'wb')
  403. try:
  404. fp.write(data)
  405. finally:
  406. fp.close()
  407. unix_attributes = info.external_attr >> 16
  408. if unix_attributes:
  409. os.chmod(fn, unix_attributes)
  410. finally:
  411. zipfp.close()
  412. def untar_file(filename, location):
  413. """Untar the file (tar file located at filename) to the destination location"""
  414. if not os.path.exists(location):
  415. os.makedirs(location)
  416. if filename.lower().endswith('.gz') or filename.lower().endswith('.tgz'):
  417. mode = 'r:gz'
  418. elif filename.lower().endswith('.bz2') or filename.lower().endswith('.tbz'):
  419. mode = 'r:bz2'
  420. elif filename.lower().endswith('.tar'):
  421. mode = 'r'
  422. else:
  423. logger.warn('Cannot determine compression type for file %s' % filename)
  424. mode = 'r:*'
  425. tar = tarfile.open(filename, mode)
  426. try:
  427. # note: python<=2.5 doesnt seem to know about pax headers, filter them
  428. leading = has_leading_dir([
  429. member.name for member in tar.getmembers()
  430. if member.name != 'pax_global_header'
  431. ])
  432. for member in tar.getmembers():
  433. fn = member.name
  434. if fn == 'pax_global_header':
  435. continue
  436. if leading:
  437. fn = split_leading_dir(fn)[1]
  438. path = os.path.join(location, fn)
  439. if member.isdir():
  440. if not os.path.exists(path):
  441. os.makedirs(path)
  442. elif member.issym():
  443. try:
  444. tar._extract_member(member, path)
  445. except:
  446. e = sys.exc_info()[1]
  447. # Some corrupt tar files seem to produce this
  448. # (specifically bad symlinks)
  449. logger.warn(
  450. 'In the tar file %s the member %s is invalid: %s'
  451. % (filename, member.name, e))
  452. continue
  453. else:
  454. try:
  455. fp = tar.extractfile(member)
  456. except (KeyError, AttributeError):
  457. e = sys.exc_info()[1]
  458. # Some corrupt tar files seem to produce this
  459. # (specifically bad symlinks)
  460. logger.warn(
  461. 'In the tar file %s the member %s is invalid: %s'
  462. % (filename, member.name, e))
  463. continue
  464. if not os.path.exists(os.path.dirname(path)):
  465. os.makedirs(os.path.dirname(path))
  466. destfp = open(path, 'wb')
  467. try:
  468. shutil.copyfileobj(fp, destfp)
  469. finally:
  470. destfp.close()
  471. fp.close()
  472. finally:
  473. tar.close()
  474. def create_download_cache_folder(folder):
  475. logger.indent -= 2
  476. logger.notify('Creating supposed download cache at %s' % folder)
  477. logger.indent += 2
  478. os.makedirs(folder)
  479. def cache_download(target_file, temp_location, content_type):
  480. logger.notify('Storing download in cache at %s' % display_path(target_file))
  481. shutil.copyfile(temp_location, target_file)
  482. fp = open(target_file+'.content-type', 'w')
  483. fp.write(content_type)
  484. fp.close()
  485. def unpack_file(filename, location, content_type, link):
  486. filename = os.path.realpath(filename)
  487. if (content_type == 'application/zip'
  488. or filename.endswith('.zip')
  489. or filename.endswith('.pybundle')
  490. or filename.endswith('.whl')
  491. or zipfile.is_zipfile(filename)):
  492. unzip_file(filename, location, flatten=not filename.endswith(('.pybundle', '.whl')))
  493. elif (content_type == 'application/x-gzip'
  494. or tarfile.is_tarfile(filename)
  495. or splitext(filename)[1].lower() in ('.tar', '.tar.gz', '.tar.bz2', '.tgz', '.tbz')):
  496. untar_file(filename, location)
  497. elif (content_type and content_type.startswith('text/html')
  498. and is_svn_page(file_contents(filename))):
  499. # We don't really care about this
  500. from pip.vcs.subversion import Subversion
  501. Subversion('svn+' + link.url).unpack(location)
  502. else:
  503. ## FIXME: handle?
  504. ## FIXME: magic signatures?
  505. logger.fatal('Cannot unpack file %s (downloaded from %s, content-type: %s); cannot detect archive format'
  506. % (filename, location, content_type))
  507. raise InstallationError('Cannot determine archive format of %s' % location)
  508. def call_subprocess(cmd, show_stdout=True,
  509. filter_stdout=None, cwd=None,
  510. raise_on_returncode=True,
  511. command_level=logger.DEBUG, command_desc=None,
  512. extra_environ=None):
  513. if command_desc is None:
  514. cmd_parts = []
  515. for part in cmd:
  516. if ' ' in part or '\n' in part or '"' in part or "'" in part:
  517. part = '"%s"' % part.replace('"', '\\"')
  518. cmd_parts.append(part)
  519. command_desc = ' '.join(cmd_parts)
  520. if show_stdout:
  521. stdout = None
  522. else:
  523. stdout = subprocess.PIPE
  524. logger.log(command_level, "Running command %s" % command_desc)
  525. env = os.environ.copy()
  526. if extra_environ:
  527. env.update(extra_environ)
  528. try:
  529. proc = subprocess.Popen(
  530. cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout,
  531. cwd=cwd, env=env)
  532. except Exception:
  533. e = sys.exc_info()[1]
  534. logger.fatal(
  535. "Error %s while executing command %s" % (e, command_desc))
  536. raise
  537. all_output = []
  538. if stdout is not None:
  539. stdout = proc.stdout
  540. while 1:
  541. line = console_to_str(stdout.readline())
  542. if not line:
  543. break
  544. line = line.rstrip()
  545. all_output.append(line + '\n')
  546. if filter_stdout:
  547. level = filter_stdout(line)
  548. if isinstance(level, tuple):
  549. level, line = level
  550. logger.log(level, line)
  551. if not logger.stdout_level_matches(level):
  552. logger.show_progress()
  553. else:
  554. logger.info(line)
  555. else:
  556. returned_stdout, returned_stderr = proc.communicate()
  557. all_output = [returned_stdout or '']
  558. proc.wait()
  559. if proc.returncode:
  560. if raise_on_returncode:
  561. if all_output:
  562. logger.notify('Complete output from command %s:' % command_desc)
  563. logger.notify('\n'.join(all_output) + '\n----------------------------------------')
  564. raise InstallationError(
  565. "Command %s failed with error code %s in %s"
  566. % (command_desc, proc.returncode, cwd))
  567. else:
  568. logger.warn(
  569. "Command %s had error code %s in %s"
  570. % (command_desc, proc.returncode, cwd))
  571. if stdout is not None:
  572. return ''.join(all_output)
  573. def is_prerelease(vers):
  574. """
  575. Attempt to determine if this is a pre-release using PEP386/PEP426 rules.
  576. Will return True if it is a pre-release and False if not. Versions are
  577. assumed to be a pre-release if they cannot be parsed.
  578. """
  579. normalized = version.suggest_normalized_version(vers)
  580. if normalized is None:
  581. # Cannot normalize, assume it is a pre-release
  582. return True
  583. parsed = version.normalized_key(normalized)
  584. return any([any([y in set(["a", "b", "c", "rc", "dev"]) for y in x]) for x in parsed])