PageRenderTime 53ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/manage/easy_install.py

https://github.com/sgammon/tipfy
Python | 1286 lines | 916 code | 141 blank | 229 comment | 202 complexity | 7aebc7d6774e1c004160a5922eaf03aa MD5 | raw file
  1. #############################################################################
  2. #
  3. # Copyright (c) 2005 Zope Corporation and Contributors.
  4. # All Rights Reserved.
  5. #
  6. # This software is subject to the provisions of the Zope Public License,
  7. # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
  8. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
  9. # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  10. # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
  11. # FOR A PARTICULAR PURPOSE.
  12. #
  13. ##############################################################################
  14. """Python easy_install API
  15. This module provides a high-level Python API for installing packages.
  16. It doesn't install scripts. It uses setuptools and requires it to be
  17. installed.
  18. """
  19. import distutils.errors
  20. import fnmatch
  21. import glob
  22. import logging
  23. import os
  24. import pkg_resources
  25. import py_compile
  26. import re
  27. import setuptools.archive_util
  28. import setuptools.command.setopt
  29. import setuptools.package_index
  30. import shutil
  31. import subprocess
  32. import sys
  33. import tempfile
  34. import warnings
  35. #import zc.buildout
  36. import zipimport
  37. _oprp = getattr(os.path, 'realpath', lambda path: path)
  38. def realpath(path):
  39. return os.path.normcase(os.path.abspath(_oprp(path)))
  40. default_index_url = os.environ.get(
  41. 'buildout-testing-index-url',
  42. 'http://pypi.python.org/simple',
  43. )
  44. logger = logging.getLogger('easy_install')
  45. url_match = re.compile('[a-z0-9+.-]+://').match
  46. is_win32 = sys.platform == 'win32'
  47. is_jython = sys.platform.startswith('java')
  48. is_distribute = (
  49. pkg_resources.Requirement.parse('setuptools').key=='distribute')
  50. BROKEN_DASH_S_WARNING = (
  51. 'Buildout has been asked to exclude or limit site-packages so that '
  52. 'builds can be repeatable when using a system Python. However, '
  53. 'the chosen Python executable has a broken implementation of -S (see '
  54. 'https://bugs.launchpad.net/virtualenv/+bug/572545 for an example '
  55. "problem) and this breaks buildout's ability to isolate site-packages. "
  56. "If the executable already has a clean site-packages (e.g., "
  57. "using virtualenv's ``--no-site-packages`` option) you may be getting "
  58. 'equivalent repeatability. To silence this warning, use the -s argument '
  59. 'to the buildout script. Alternatively, use a Python executable with a '
  60. 'working -S (such as a standard Python binary).')
  61. if is_jython:
  62. import java.lang.System
  63. jython_os_name = (java.lang.System.getProperties()['os.name']).lower()
  64. setuptools_loc = pkg_resources.working_set.find(
  65. pkg_resources.Requirement.parse('setuptools')
  66. ).location
  67. # Include buildout and setuptools eggs in paths. We prevent dupes just to
  68. # keep from duplicating any log messages about them.
  69. #buildout_loc = pkg_resources.working_set.find(
  70. # pkg_resources.Requirement.parse('zc.buildout')).location
  71. buildout_and_setuptools_path = [setuptools_loc]
  72. if os.path.normpath(setuptools_loc) != os.path.normpath(buildout_loc):
  73. buildout_and_setuptools_path.append(buildout_loc)
  74. def _has_broken_dash_S(executable):
  75. """Detect https://bugs.launchpad.net/virtualenv/+bug/572545 ."""
  76. # The first attempt here was to simply have the executable attempt to import
  77. # ConfigParser and return the return code. That worked except for tests on
  78. # Windows, where the return code was wrong for the fake Python executable
  79. # generated by the virtualenv.txt test, apparently because setuptools' .exe
  80. # file does not pass the -script.py's returncode back properly, at least in
  81. # some circumstances. Therefore...print statements.
  82. stdout, stderr = subprocess.Popen(
  83. [executable, '-Sc',
  84. 'try:\n'
  85. ' import ConfigParser\n'
  86. 'except ImportError:\n'
  87. ' print 1\n'
  88. 'else:\n'
  89. ' print 0\n'],
  90. stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
  91. return bool(int(stdout.strip()))
  92. def _get_system_paths(executable):
  93. """Return lists of standard lib and site paths for executable.
  94. """
  95. # We want to get a list of the site packages, which is not easy.
  96. # The canonical way to do this is to use
  97. # distutils.sysconfig.get_python_lib(), but that only returns a
  98. # single path, which does not reflect reality for many system
  99. # Pythons, which have multiple additions. Instead, we start Python
  100. # with -S, which does not import site.py and set up the extra paths
  101. # like site-packages or (Ubuntu/Debian) dist-packages and
  102. # python-support. We then compare that sys.path with the normal one
  103. # (minus user packages if this is Python 2.6, because we don't
  104. # support those (yet?). The set of the normal one minus the set of
  105. # the ones in ``python -S`` is the set of packages that are
  106. # effectively site-packages.
  107. #
  108. # The given executable might not be the current executable, so it is
  109. # appropriate to do another subprocess to figure out what the
  110. # additional site-package paths are. Moreover, even if this
  111. # executable *is* the current executable, this code might be run in
  112. # the context of code that has manipulated the sys.path--for
  113. # instance, to add local zc.buildout or setuptools eggs.
  114. def get_sys_path(*args, **kwargs):
  115. cmd = [executable]
  116. cmd.extend(args)
  117. cmd.extend([
  118. "-c", "import sys, os;"
  119. "print repr([os.path.normpath(p) for p in sys.path if p])"])
  120. # Windows needs some (as yet to be determined) part of the real env.
  121. env = os.environ.copy()
  122. # We need to make sure that PYTHONPATH, which will often be set
  123. # to include a custom buildout-generated site.py, is not set, or
  124. # else we will not get an accurate sys.path for the executable.
  125. env.pop('PYTHONPATH', None)
  126. env.update(kwargs)
  127. _proc = subprocess.Popen(
  128. cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
  129. stdout, stderr = _proc.communicate();
  130. if _proc.returncode:
  131. raise RuntimeError(
  132. 'error trying to get system packages:\n%s' % (stderr,))
  133. res = eval(stdout.strip())
  134. try:
  135. res.remove('.')
  136. except ValueError:
  137. pass
  138. return res
  139. stdlib = get_sys_path('-S') # stdlib only
  140. no_user_paths = get_sys_path(PYTHONNOUSERSITE='x')
  141. site_paths = [p for p in no_user_paths if p not in stdlib]
  142. return (stdlib, site_paths)
  143. def _get_version_info(executable):
  144. cmd = [executable, '-Sc',
  145. 'import sys; print(repr(tuple(x for x in sys.version_info)))']
  146. _proc = subprocess.Popen(
  147. cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  148. stdout, stderr = _proc.communicate();
  149. if _proc.returncode:
  150. raise RuntimeError(
  151. 'error trying to get system packages:\n%s' % (stderr,))
  152. return eval(stdout.strip())
  153. _versions = {sys.executable: '%d.%d' % sys.version_info[:2]}
  154. def _get_version(executable):
  155. try:
  156. return _versions[executable]
  157. except KeyError:
  158. cmd = _safe_arg(executable) + ' -V'
  159. p = subprocess.Popen(cmd,
  160. shell=True,
  161. stdin=subprocess.PIPE,
  162. stdout=subprocess.PIPE,
  163. stderr=subprocess.STDOUT,
  164. close_fds=not is_win32)
  165. i, o = (p.stdin, p.stdout)
  166. i.close()
  167. version = o.read().strip()
  168. o.close()
  169. pystring, version = version.split()
  170. assert pystring == 'Python'
  171. version = re.match('(\d[.]\d)([.].*\d)?$', version).group(1)
  172. _versions[executable] = version
  173. return version
  174. FILE_SCHEME = re.compile('file://', re.I).match
  175. class AllowHostsPackageIndex(setuptools.package_index.PackageIndex):
  176. """Will allow urls that are local to the system.
  177. No matter what is allow_hosts.
  178. """
  179. def url_ok(self, url, fatal=False):
  180. if FILE_SCHEME(url):
  181. return True
  182. return setuptools.package_index.PackageIndex.url_ok(self, url, False)
  183. _indexes = {}
  184. def _get_index(executable, index_url, find_links, allow_hosts=('*',),
  185. path=None):
  186. # If path is None, the index will use sys.path. If you provide an empty
  187. # path ([]), it will complain uselessly about missing index pages for
  188. # packages found in the paths that you expect to use. Therefore, this path
  189. # is always the same as the _env path in the Installer.
  190. key = executable, index_url, tuple(find_links)
  191. index = _indexes.get(key)
  192. if index is not None:
  193. return index
  194. if index_url is None:
  195. index_url = default_index_url
  196. index = AllowHostsPackageIndex(
  197. index_url, hosts=allow_hosts, search_path=path,
  198. python=_get_version(executable)
  199. )
  200. if find_links:
  201. index.add_find_links(find_links)
  202. _indexes[key] = index
  203. return index
  204. clear_index_cache = _indexes.clear
  205. if is_win32:
  206. # work around spawn lamosity on windows
  207. # XXX need safe quoting (see the subprocess.list2cmdline) and test
  208. def _safe_arg(arg):
  209. return '"%s"' % arg
  210. else:
  211. _safe_arg = str
  212. # The following string is used to run easy_install in
  213. # Installer._call_easy_install. It is usually started with python -S
  214. # (that is, don't import site at start). That flag, and all of the code
  215. # in this snippet above the last two lines, exist to work around a
  216. # relatively rare problem. If
  217. #
  218. # - your buildout configuration is trying to install a package that is within
  219. # a namespace package, and
  220. #
  221. # - you use a Python that has a different version of this package
  222. # installed in in its site-packages using
  223. # --single-version-externally-managed (that is, using the mechanism
  224. # sometimes used by system packagers:
  225. # http://peak.telecommunity.com/DevCenter/setuptools#install-command ), and
  226. #
  227. # - the new package tries to do sys.path tricks in the setup.py to get a
  228. # __version__,
  229. #
  230. # then the older package will be loaded first, making the setup version
  231. # the wrong number. While very arguably packages simply shouldn't do
  232. # the sys.path tricks, some do, and we don't want buildout to fall over
  233. # when they do.
  234. #
  235. # The namespace packages installed in site-packages with
  236. # --single-version-externally-managed use a mechanism that cause them to
  237. # be processed when site.py is imported (see
  238. # http://mail.python.org/pipermail/distutils-sig/2009-May/011730.html
  239. # for another description of the problem). Simply starting Python with
  240. # -S addresses the problem in Python 2.4 and 2.5, but Python 2.6's
  241. # distutils imports a value from the site module, so we unfortunately
  242. # have to do more drastic surgery in the _easy_install_preface code below.
  243. #
  244. # Here's an example of the .pth files created by setuptools when using that
  245. # flag:
  246. #
  247. # import sys,new,os;
  248. # p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('<NAMESPACE>',));
  249. # ie = os.path.exists(os.path.join(p,'__init__.py'));
  250. # m = not ie and sys.modules.setdefault('<NAMESPACE>',new.module('<NAMESPACE>'));
  251. # mp = (m or []) and m.__dict__.setdefault('__path__',[]);
  252. # (p not in mp) and mp.append(p)
  253. #
  254. # The code, below, then, runs under -S, indicating that site.py should
  255. # not be loaded initially. It gets the initial sys.path under these
  256. # circumstances, and then imports site (because Python 2.6's distutils
  257. # will want it, as mentioned above). It then reinstates the old sys.path
  258. # value. Then it removes namespace packages (created by the setuptools
  259. # code above) from sys.modules. It identifies namespace packages by
  260. # iterating over every loaded module. It first looks if there is a
  261. # __path__, so it is a package; and then it sees if that __path__ does
  262. # not have an __init__.py. (Note that PEP 382,
  263. # http://www.python.org/dev/peps/pep-0382, makes it possible to have a
  264. # namespace package that has an __init__.py, but also should make it
  265. # unnecessary for site.py to preprocess these packages, so it should be
  266. # fine, as far as can be guessed as of this writing.) Finally, it
  267. # imports easy_install and runs it.
  268. _easy_install_preface = '''\
  269. import sys,os;\
  270. p = sys.path[:];\
  271. import site;\
  272. sys.path[:] = p;\
  273. [sys.modules.pop(k) for k, v in sys.modules.items()\
  274. if hasattr(v, '__path__') and len(v.__path__)==1 and\
  275. not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))];'''
  276. _easy_install_cmd = (
  277. 'from setuptools.command.easy_install import main;main()')
  278. class Installer:
  279. _versions = {}
  280. _download_cache = None
  281. _install_from_cache = False
  282. _prefer_final = True
  283. _use_dependency_links = True
  284. _allow_picked_versions = True
  285. _always_unzip = False
  286. _include_site_packages = True
  287. _allowed_eggs_from_site_packages = ('*',)
  288. def __init__(self,
  289. dest=None,
  290. links=(),
  291. index=None,
  292. executable=sys.executable,
  293. always_unzip=None,
  294. path=None,
  295. newest=True,
  296. versions=None,
  297. use_dependency_links=None,
  298. allow_hosts=('*',),
  299. include_site_packages=None,
  300. allowed_eggs_from_site_packages=None,
  301. prefer_final=None,
  302. ):
  303. self._dest = dest
  304. self._allow_hosts = allow_hosts
  305. if self._install_from_cache:
  306. if not self._download_cache:
  307. raise ValueError("install_from_cache set to true with no"
  308. " download cache")
  309. links = ()
  310. index = 'file://' + self._download_cache
  311. if use_dependency_links is not None:
  312. self._use_dependency_links = use_dependency_links
  313. if prefer_final is not None:
  314. self._prefer_final = prefer_final
  315. self._links = links = list(_fix_file_links(links))
  316. if self._download_cache and (self._download_cache not in links):
  317. links.insert(0, self._download_cache)
  318. self._index_url = index
  319. self._executable = executable
  320. self._has_broken_dash_S = _has_broken_dash_S(self._executable)
  321. if always_unzip is not None:
  322. self._always_unzip = always_unzip
  323. path = (path and path[:] or [])
  324. if include_site_packages is not None:
  325. self._include_site_packages = include_site_packages
  326. if allowed_eggs_from_site_packages is not None:
  327. self._allowed_eggs_from_site_packages = tuple(
  328. allowed_eggs_from_site_packages)
  329. if self._has_broken_dash_S:
  330. if (not self._include_site_packages or
  331. self._allowed_eggs_from_site_packages != ('*',)):
  332. # We can't do this if the executable has a broken -S.
  333. warnings.warn(BROKEN_DASH_S_WARNING)
  334. self._include_site_packages = True
  335. self._allowed_eggs_from_site_packages = ('*',)
  336. self._easy_install_cmd = _easy_install_cmd
  337. else:
  338. self._easy_install_cmd = _easy_install_preface + _easy_install_cmd
  339. self._easy_install_cmd = _safe_arg(self._easy_install_cmd)
  340. stdlib, self._site_packages = _get_system_paths(executable)
  341. version_info = _get_version_info(executable)
  342. if version_info == sys.version_info:
  343. # Maybe we can add the buildout and setuptools path. If we
  344. # are including site_packages, we only have to include the extra
  345. # bits here, so we don't duplicate. On the other hand, if we
  346. # are not including site_packages, we only want to include the
  347. # parts that are not in site_packages, so the code is the same.
  348. path.extend(
  349. set(buildout_and_setuptools_path).difference(
  350. self._site_packages))
  351. if self._include_site_packages:
  352. path.extend(self._site_packages)
  353. if dest is not None and dest not in path:
  354. path.insert(0, dest)
  355. self._path = path
  356. if self._dest is None:
  357. newest = False
  358. self._newest = newest
  359. self._env = pkg_resources.Environment(path,
  360. python=_get_version(executable))
  361. self._index = _get_index(executable, index, links, self._allow_hosts,
  362. self._path)
  363. if versions is not None:
  364. self._versions = versions
  365. _allowed_eggs_from_site_packages_regex = None
  366. def allow_site_package_egg(self, name):
  367. if (not self._include_site_packages or
  368. not self._allowed_eggs_from_site_packages):
  369. # If the answer is a blanket "no," perform a shortcut.
  370. return False
  371. if self._allowed_eggs_from_site_packages_regex is None:
  372. pattern = '(%s)' % (
  373. '|'.join(
  374. fnmatch.translate(name)
  375. for name in self._allowed_eggs_from_site_packages),
  376. )
  377. self._allowed_eggs_from_site_packages_regex = re.compile(pattern)
  378. return bool(self._allowed_eggs_from_site_packages_regex.match(name))
  379. def _satisfied(self, req, source=None):
  380. # We get all distributions that match the given requirement. If we are
  381. # not supposed to include site-packages for the given egg, we also
  382. # filter those out. Even if include_site_packages is False and so we
  383. # have excluded site packages from the _env's paths (see
  384. # Installer.__init__), we need to do the filtering here because an
  385. # .egg-link, such as one for setuptools or zc.buildout installed by
  386. # zc.buildout.buildout.Buildout.bootstrap, can indirectly include a
  387. # path in our _site_packages.
  388. dists = [dist for dist in self._env[req.project_name] if (
  389. dist in req and (
  390. dist.location not in self._site_packages or
  391. self.allow_site_package_egg(dist.project_name))
  392. )
  393. ]
  394. if not dists:
  395. logger.debug('We have no distributions for %s that satisfies %r.',
  396. req.project_name, str(req))
  397. return None, self._obtain(req, source)
  398. # Note that dists are sorted from best to worst, as promised by
  399. # env.__getitem__
  400. for dist in dists:
  401. if (dist.precedence == pkg_resources.DEVELOP_DIST and
  402. dist.location not in self._site_packages):
  403. # System eggs are sometimes installed as develop eggs.
  404. # Those are not the kind of develop eggs we are looking for
  405. # here: we want ones that the buildout itself has locally as
  406. # develop eggs.
  407. logger.debug('We have a develop egg: %s', dist)
  408. return dist, None
  409. # Special common case, we have a specification for a single version:
  410. specs = req.specs
  411. if len(specs) == 1 and specs[0][0] == '==':
  412. logger.debug('We have the distribution that satisfies %r.',
  413. str(req))
  414. return dists[0], None
  415. if self._prefer_final:
  416. fdists = [dist for dist in dists
  417. if _final_version(dist.parsed_version)
  418. ]
  419. if fdists:
  420. # There are final dists, so only use those
  421. dists = fdists
  422. if not self._newest:
  423. # We don't need the newest, so we'll use the newest one we
  424. # find, which is the first returned by
  425. # Environment.__getitem__.
  426. return dists[0], None
  427. best_we_have = dists[0] # Because dists are sorted from best to worst
  428. # We have some installed distros. There might, theoretically, be
  429. # newer ones. Let's find out which ones are available and see if
  430. # any are newer. We only do this if we're willing to install
  431. # something, which is only true if dest is not None:
  432. if self._dest is not None:
  433. best_available = self._obtain(req, source)
  434. else:
  435. best_available = None
  436. if best_available is None:
  437. # That's a bit odd. There aren't any distros available.
  438. # We should use the best one we have that meets the requirement.
  439. logger.debug(
  440. 'There are no distros available that meet %r.\n'
  441. 'Using our best, %s.',
  442. str(req), best_available)
  443. return best_we_have, None
  444. if self._prefer_final:
  445. if _final_version(best_available.parsed_version):
  446. if _final_version(best_we_have.parsed_version):
  447. if (best_we_have.parsed_version
  448. <
  449. best_available.parsed_version
  450. ):
  451. return None, best_available
  452. else:
  453. return None, best_available
  454. else:
  455. if (not _final_version(best_we_have.parsed_version)
  456. and
  457. (best_we_have.parsed_version
  458. <
  459. best_available.parsed_version
  460. )
  461. ):
  462. return None, best_available
  463. else:
  464. if (best_we_have.parsed_version
  465. <
  466. best_available.parsed_version
  467. ):
  468. return None, best_available
  469. logger.debug(
  470. 'We have the best distribution that satisfies %r.',
  471. str(req))
  472. return best_we_have, None
  473. def _load_dist(self, dist):
  474. dists = pkg_resources.Environment(
  475. dist.location,
  476. python=_get_version(self._executable),
  477. )[dist.project_name]
  478. assert len(dists) == 1
  479. return dists[0]
  480. def _call_easy_install(self, spec, ws, dest, dist):
  481. tmp = tempfile.mkdtemp(dir=dest)
  482. try:
  483. path = setuptools_loc
  484. args = ('-c', self._easy_install_cmd, '-mUNxd', _safe_arg(tmp))
  485. if not self._has_broken_dash_S:
  486. args = ('-S',) + args
  487. if self._always_unzip:
  488. args += ('-Z', )
  489. level = logger.getEffectiveLevel()
  490. if level > 0:
  491. args += ('-q', )
  492. elif level < 0:
  493. args += ('-v', )
  494. args += (_safe_arg(spec), )
  495. if level <= logging.DEBUG:
  496. logger.debug('Running easy_install:\n%s "%s"\npath=%s\n',
  497. self._executable, '" "'.join(args), path)
  498. if is_jython:
  499. extra_env = dict(os.environ, PYTHONPATH=path)
  500. else:
  501. args += (dict(os.environ, PYTHONPATH=path), )
  502. sys.stdout.flush() # We want any pending output first
  503. if is_jython:
  504. exit_code = subprocess.Popen(
  505. [_safe_arg(self._executable)] + list(args),
  506. env=extra_env).wait()
  507. else:
  508. exit_code = os.spawnle(
  509. os.P_WAIT, self._executable, _safe_arg (self._executable),
  510. *args)
  511. dists = []
  512. env = pkg_resources.Environment(
  513. [tmp],
  514. python=_get_version(self._executable),
  515. )
  516. for project in env:
  517. dists.extend(env[project])
  518. if exit_code:
  519. logger.error(
  520. "An error occurred when trying to install %s. "
  521. "Look above this message for any errors that "
  522. "were output by easy_install.",
  523. dist)
  524. if not dists:
  525. raise UserError("Couldn't install: %s" % dist)
  526. if len(dists) > 1:
  527. logger.warn("Installing %s\n"
  528. "caused multiple distributions to be installed:\n"
  529. "%s\n",
  530. dist, '\n'.join(map(str, dists)))
  531. else:
  532. d = dists[0]
  533. if d.project_name != dist.project_name:
  534. logger.warn("Installing %s\n"
  535. "Caused installation of a distribution:\n"
  536. "%s\n"
  537. "with a different project name.",
  538. dist, d)
  539. if d.version != dist.version:
  540. logger.warn("Installing %s\n"
  541. "Caused installation of a distribution:\n"
  542. "%s\n"
  543. "with a different version.",
  544. dist, d)
  545. result = []
  546. for d in dists:
  547. newloc = os.path.join(dest, os.path.basename(d.location))
  548. if os.path.exists(newloc):
  549. if os.path.isdir(newloc):
  550. shutil.rmtree(newloc)
  551. else:
  552. os.remove(newloc)
  553. os.rename(d.location, newloc)
  554. [d] = pkg_resources.Environment(
  555. [newloc],
  556. python=_get_version(self._executable),
  557. )[d.project_name]
  558. result.append(d)
  559. return result
  560. finally:
  561. shutil.rmtree(tmp)
  562. def _obtain(self, requirement, source=None):
  563. # initialize out index for this project:
  564. index = self._index
  565. if index.obtain(requirement) is None:
  566. # Nothing is available.
  567. return None
  568. # Filter the available dists for the requirement and source flag. If
  569. # we are not supposed to include site-packages for the given egg, we
  570. # also filter those out. Even if include_site_packages is False and so
  571. # we have excluded site packages from the _env's paths (see
  572. # Installer.__init__), we need to do the filtering here because an
  573. # .egg-link, such as one for setuptools or zc.buildout installed by
  574. # zc.buildout.buildout.Buildout.bootstrap, can indirectly include a
  575. # path in our _site_packages.
  576. dists = [dist for dist in index[requirement.project_name] if (
  577. dist in requirement and (
  578. dist.location not in self._site_packages or
  579. self.allow_site_package_egg(dist.project_name))
  580. and (
  581. (not source) or
  582. (dist.precedence == pkg_resources.SOURCE_DIST))
  583. )
  584. ]
  585. # If we prefer final dists, filter for final and use the
  586. # result if it is non empty.
  587. if self._prefer_final:
  588. fdists = [dist for dist in dists
  589. if _final_version(dist.parsed_version)
  590. ]
  591. if fdists:
  592. # There are final dists, so only use those
  593. dists = fdists
  594. # Now find the best one:
  595. best = []
  596. bestv = ()
  597. for dist in dists:
  598. distv = dist.parsed_version
  599. if distv > bestv:
  600. best = [dist]
  601. bestv = distv
  602. elif distv == bestv:
  603. best.append(dist)
  604. if not best:
  605. return None
  606. if len(best) == 1:
  607. return best[0]
  608. if self._download_cache:
  609. for dist in best:
  610. if (realpath(os.path.dirname(dist.location))
  611. ==
  612. self._download_cache
  613. ):
  614. return dist
  615. best.sort()
  616. return best[-1]
  617. def _fetch(self, dist, tmp, download_cache):
  618. if (download_cache
  619. and (realpath(os.path.dirname(dist.location)) == download_cache)
  620. ):
  621. return dist
  622. new_location = self._index.download(dist.location, tmp)
  623. if (download_cache
  624. and (realpath(new_location) == realpath(dist.location))
  625. and os.path.isfile(new_location)
  626. ):
  627. # setuptools avoids making extra copies, but we want to copy
  628. # to the download cache
  629. shutil.copy2(new_location, tmp)
  630. new_location = os.path.join(tmp, os.path.basename(new_location))
  631. return dist.clone(location=new_location)
  632. def _get_dist(self, requirement, ws, always_unzip):
  633. __doing__ = 'Getting distribution for %r.', str(requirement)
  634. # Maybe an existing dist is already the best dist that satisfies the
  635. # requirement
  636. dist, avail = self._satisfied(requirement)
  637. if dist is None:
  638. if self._dest is not None:
  639. logger.info(*__doing__)
  640. # Retrieve the dist:
  641. if avail is None:
  642. raise MissingDistribution(requirement, ws)
  643. # We may overwrite distributions, so clear importer
  644. # cache.
  645. sys.path_importer_cache.clear()
  646. tmp = self._download_cache
  647. if tmp is None:
  648. tmp = tempfile.mkdtemp('get_dist')
  649. try:
  650. dist = self._fetch(avail, tmp, self._download_cache)
  651. if dist is None:
  652. raise UserError(
  653. "Couldn't download distribution %s." % avail)
  654. if dist.precedence == pkg_resources.EGG_DIST:
  655. # It's already an egg, just fetch it into the dest
  656. newloc = os.path.join(
  657. self._dest, os.path.basename(dist.location))
  658. if os.path.isdir(dist.location):
  659. # we got a directory. It must have been
  660. # obtained locally. Just copy it.
  661. shutil.copytree(dist.location, newloc)
  662. else:
  663. if self._always_unzip:
  664. should_unzip = True
  665. else:
  666. metadata = pkg_resources.EggMetadata(
  667. zipimport.zipimporter(dist.location)
  668. )
  669. should_unzip = (
  670. metadata.has_metadata('not-zip-safe')
  671. or
  672. not metadata.has_metadata('zip-safe')
  673. )
  674. if should_unzip:
  675. setuptools.archive_util.unpack_archive(
  676. dist.location, newloc)
  677. else:
  678. shutil.copyfile(dist.location, newloc)
  679. redo_pyc(newloc)
  680. # Getting the dist from the environment causes the
  681. # distribution meta data to be read. Cloning isn't
  682. # good enough.
  683. dists = pkg_resources.Environment(
  684. [newloc],
  685. python=_get_version(self._executable),
  686. )[dist.project_name]
  687. else:
  688. # It's some other kind of dist. We'll let easy_install
  689. # deal with it:
  690. dists = self._call_easy_install(
  691. dist.location, ws, self._dest, dist)
  692. for dist in dists:
  693. redo_pyc(dist.location)
  694. finally:
  695. if tmp != self._download_cache:
  696. shutil.rmtree(tmp)
  697. self._env.scan([self._dest])
  698. dist = self._env.best_match(requirement, ws)
  699. logger.info("Got %s.", dist)
  700. else:
  701. dists = [dist]
  702. for dist in dists:
  703. if (dist.has_metadata('dependency_links.txt')
  704. and not self._install_from_cache
  705. and self._use_dependency_links
  706. ):
  707. for link in dist.get_metadata_lines('dependency_links.txt'):
  708. link = link.strip()
  709. if link not in self._links:
  710. logger.debug('Adding find link %r from %s', link, dist)
  711. self._links.append(link)
  712. self._index = _get_index(self._executable,
  713. self._index_url, self._links,
  714. self._allow_hosts, self._path)
  715. for dist in dists:
  716. # Check whether we picked a version and, if we did, report it:
  717. if not (
  718. dist.precedence == pkg_resources.DEVELOP_DIST
  719. or
  720. (len(requirement.specs) == 1
  721. and
  722. requirement.specs[0][0] == '==')
  723. ):
  724. logger.debug('Picked: %s = %s',
  725. dist.project_name, dist.version)
  726. if not self._allow_picked_versions:
  727. raise UserError(
  728. 'Picked: %s = %s' % (dist.project_name, dist.version)
  729. )
  730. return dists
  731. def _maybe_add_setuptools(self, ws, dist):
  732. if dist.has_metadata('namespace_packages.txt'):
  733. for r in dist.requires():
  734. if r.project_name in ('setuptools', 'distribute'):
  735. break
  736. else:
  737. # We have a namespace package but no requirement for setuptools
  738. if dist.precedence == pkg_resources.DEVELOP_DIST:
  739. logger.warn(
  740. "Develop distribution: %s\n"
  741. "uses namespace packages but the distribution "
  742. "does not require setuptools.",
  743. dist)
  744. requirement = self._constrain(
  745. pkg_resources.Requirement.parse('setuptools')
  746. )
  747. if ws.find(requirement) is None:
  748. for dist in self._get_dist(requirement, ws, False):
  749. ws.add(dist)
  750. def _constrain(self, requirement):
  751. if is_distribute and requirement.key == 'setuptools':
  752. requirement = pkg_resources.Requirement.parse('distribute')
  753. version = self._versions.get(requirement.project_name)
  754. if version:
  755. if version not in requirement:
  756. logger.error("The version, %s, is not consistent with the "
  757. "requirement, %r.", version, str(requirement))
  758. raise IncompatibleVersionError("Bad version", version)
  759. requirement = pkg_resources.Requirement.parse(
  760. "%s[%s] ==%s" % (requirement.project_name,
  761. ','.join(requirement.extras),
  762. version))
  763. return requirement
  764. def install(self, specs, working_set=None):
  765. logger.debug('Installing %s.', repr(specs)[1:-1])
  766. path = self._path
  767. destination = self._dest
  768. if destination is not None and destination not in path:
  769. path.insert(0, destination)
  770. requirements = [self._constrain(pkg_resources.Requirement.parse(spec))
  771. for spec in specs]
  772. if working_set is None:
  773. ws = pkg_resources.WorkingSet([])
  774. else:
  775. ws = working_set
  776. for requirement in requirements:
  777. for dist in self._get_dist(requirement, ws, self._always_unzip):
  778. ws.add(dist)
  779. self._maybe_add_setuptools(ws, dist)
  780. # OK, we have the requested distributions and they're in the working
  781. # set, but they may have unmet requirements. We'll resolve these
  782. # requirements. This is code modified from
  783. # pkg_resources.WorkingSet.resolve. We can't reuse that code directly
  784. # because we have to constrain our requirements (see
  785. # versions_section_ignored_for_dependency_in_favor_of_site_packages in
  786. # zc.buildout.tests).
  787. requirements.reverse() # Set up the stack.
  788. processed = {} # This is a set of processed requirements.
  789. best = {} # This is a mapping of key -> dist.
  790. # Note that we don't use the existing environment, because we want
  791. # to look for new eggs unless what we have is the best that
  792. # matches the requirement.
  793. env = pkg_resources.Environment(ws.entries)
  794. while requirements:
  795. # Process dependencies breadth-first.
  796. req = self._constrain(requirements.pop(0))
  797. if req in processed:
  798. # Ignore cyclic or redundant dependencies.
  799. continue
  800. dist = best.get(req.key)
  801. if dist is None:
  802. # Find the best distribution and add it to the map.
  803. dist = ws.by_key.get(req.key)
  804. if dist is None:
  805. try:
  806. dist = best[req.key] = env.best_match(req, ws)
  807. except pkg_resources.VersionConflict, err:
  808. raise VersionConflict(err, ws)
  809. if dist is None or (
  810. dist.location in self._site_packages and not
  811. self.allow_site_package_egg(dist.project_name)):
  812. # If we didn't find a distribution in the
  813. # environment, or what we found is from site
  814. # packages and not allowed to be there, try
  815. # again.
  816. if destination:
  817. logger.debug('Getting required %r', str(req))
  818. else:
  819. logger.debug('Adding required %r', str(req))
  820. _log_requirement(ws, req)
  821. for dist in self._get_dist(req,
  822. ws, self._always_unzip):
  823. ws.add(dist)
  824. self._maybe_add_setuptools(ws, dist)
  825. if dist not in req:
  826. # Oops, the "best" so far conflicts with a dependency.
  827. raise VersionConflict(
  828. pkg_resources.VersionConflict(dist, req), ws)
  829. requirements.extend(dist.requires(req.extras)[::-1])
  830. processed[req] = True
  831. if dist.location in self._site_packages:
  832. logger.debug('Egg from site-packages: %s', dist)
  833. return ws
  834. def build(self, spec, build_ext):
  835. requirement = self._constrain(pkg_resources.Requirement.parse(spec))
  836. dist, avail = self._satisfied(requirement, 1)
  837. if dist is not None:
  838. return [dist.location]
  839. # Retrieve the dist:
  840. if avail is None:
  841. raise UserError(
  842. "Couldn't find a source distribution for %r."
  843. % str(requirement))
  844. logger.debug('Building %r', spec)
  845. tmp = self._download_cache
  846. if tmp is None:
  847. tmp = tempfile.mkdtemp('get_dist')
  848. try:
  849. dist = self._fetch(avail, tmp, self._download_cache)
  850. build_tmp = tempfile.mkdtemp('build')
  851. try:
  852. setuptools.archive_util.unpack_archive(dist.location,
  853. build_tmp)
  854. if os.path.exists(os.path.join(build_tmp, 'setup.py')):
  855. base = build_tmp
  856. else:
  857. setups = glob.glob(
  858. os.path.join(build_tmp, '*', 'setup.py'))
  859. if not setups:
  860. raise distutils.errors.DistutilsError(
  861. "Couldn't find a setup script in %s"
  862. % os.path.basename(dist.location)
  863. )
  864. if len(setups) > 1:
  865. raise distutils.errors.DistutilsError(
  866. "Multiple setup scripts in %s"
  867. % os.path.basename(dist.location)
  868. )
  869. base = os.path.dirname(setups[0])
  870. setup_cfg = os.path.join(base, 'setup.cfg')
  871. if not os.path.exists(setup_cfg):
  872. f = open(setup_cfg, 'w')
  873. f.close()
  874. setuptools.command.setopt.edit_config(
  875. setup_cfg, dict(build_ext=build_ext))
  876. dists = self._call_easy_install(
  877. base, pkg_resources.WorkingSet(),
  878. self._dest, dist)
  879. for dist in dists:
  880. redo_pyc(dist.location)
  881. return [dist.location for dist in dists]
  882. finally:
  883. shutil.rmtree(build_tmp)
  884. finally:
  885. if tmp != self._download_cache:
  886. shutil.rmtree(tmp)
  887. def default_versions(versions=None):
  888. old = Installer._versions
  889. if versions is not None:
  890. Installer._versions = versions
  891. return old
  892. def download_cache(path=-1):
  893. old = Installer._download_cache
  894. if path != -1:
  895. if path:
  896. path = realpath(path)
  897. Installer._download_cache = path
  898. return old
  899. def install_from_cache(setting=None):
  900. old = Installer._install_from_cache
  901. if setting is not None:
  902. Installer._install_from_cache = bool(setting)
  903. return old
  904. def prefer_final(setting=None):
  905. old = Installer._prefer_final
  906. if setting is not None:
  907. Installer._prefer_final = bool(setting)
  908. return old
  909. def include_site_packages(setting=None):
  910. old = Installer._include_site_packages
  911. if setting is not None:
  912. Installer._include_site_packages = bool(setting)
  913. return old
  914. def allowed_eggs_from_site_packages(setting=None):
  915. old = Installer._allowed_eggs_from_site_packages
  916. if setting is not None:
  917. Installer._allowed_eggs_from_site_packages = tuple(setting)
  918. return old
  919. def use_dependency_links(setting=None):
  920. old = Installer._use_dependency_links
  921. if setting is not None:
  922. Installer._use_dependency_links = bool(setting)
  923. return old
  924. def allow_picked_versions(setting=None):
  925. old = Installer._allow_picked_versions
  926. if setting is not None:
  927. Installer._allow_picked_versions = bool(setting)
  928. return old
  929. def always_unzip(setting=None):
  930. old = Installer._always_unzip
  931. if setting is not None:
  932. Installer._always_unzip = bool(setting)
  933. return old
  934. def install(specs, dest,
  935. links=(), index=None,
  936. executable=sys.executable, always_unzip=None,
  937. path=None, working_set=None, newest=True, versions=None,
  938. use_dependency_links=None, allow_hosts=('*',),
  939. include_site_packages=None, allowed_eggs_from_site_packages=None,
  940. prefer_final=None):
  941. installer = Installer(
  942. dest, links, index, executable, always_unzip, path, newest,
  943. versions, use_dependency_links, allow_hosts=allow_hosts,
  944. include_site_packages=include_site_packages,
  945. allowed_eggs_from_site_packages=allowed_eggs_from_site_packages,
  946. prefer_final=prefer_final)
  947. return installer.install(specs, working_set)
  948. def build(spec, dest, build_ext,
  949. links=(), index=None,
  950. executable=sys.executable,
  951. path=None, newest=True, versions=None, allow_hosts=('*',),
  952. include_site_packages=None, allowed_eggs_from_site_packages=None):
  953. installer = Installer(
  954. dest, links, index, executable, True, path, newest, versions,
  955. allow_hosts=allow_hosts,
  956. include_site_packages=include_site_packages,
  957. allowed_eggs_from_site_packages=allowed_eggs_from_site_packages)
  958. return installer.build(spec, build_ext)
  959. def _rm(*paths):
  960. for path in paths:
  961. if os.path.isdir(path):
  962. shutil.rmtree(path)
  963. elif os.path.exists(path):
  964. os.remove(path)
  965. def _copyeggs(src, dest, suffix, undo):
  966. result = []
  967. undo.append(lambda : _rm(*result))
  968. for name in os.listdir(src):
  969. if name.endswith(suffix):
  970. new = os.path.join(dest, name)
  971. _rm(new)
  972. os.rename(os.path.join(src, name), new)
  973. result.append(new)
  974. assert len(result) == 1, str(result)
  975. undo.pop()
  976. return result[0]
  977. def develop(setup, dest,
  978. build_ext=None,
  979. executable=sys.executable):
  980. if os.path.isdir(setup):
  981. directory = setup
  982. setup = os.path.join(directory, 'setup.py')
  983. else:
  984. directory = os.path.dirname(setup)
  985. undo = []
  986. try:
  987. if build_ext:
  988. setup_cfg = os.path.join(directory, 'setup.cfg')
  989. if os.path.exists(setup_cfg):
  990. os.rename(setup_cfg, setup_cfg+'-develop-aside')
  991. def restore_old_setup():
  992. if os.path.exists(setup_cfg):
  993. os.remove(setup_cfg)
  994. os.rename(setup_cfg+'-develop-aside', setup_cfg)
  995. undo.append(restore_old_setup)
  996. else:
  997. open(setup_cfg, 'w')
  998. undo.append(lambda: os.remove(setup_cfg))
  999. setuptools.command.setopt.edit_config(
  1000. setup_cfg, dict(build_ext=build_ext))
  1001. fd, tsetup = tempfile.mkstemp()
  1002. undo.append(lambda: os.remove(tsetup))
  1003. undo.append(lambda: os.close(fd))
  1004. os.write(fd, runsetup_template % dict(
  1005. setuptools=setuptools_loc,
  1006. setupdir=directory,
  1007. setup=setup,
  1008. __file__ = setup,
  1009. ))
  1010. tmp3 = tempfile.mkdtemp('build', dir=dest)
  1011. undo.append(lambda : shutil.rmtree(tmp3))
  1012. args = [
  1013. _safe_arg(tsetup),
  1014. '-q', 'develop', '-mxN',
  1015. '-d', _safe_arg(tmp3),
  1016. ]
  1017. log_level = logger.getEffectiveLevel()
  1018. if log_level <= 0:
  1019. if log_level == 0:
  1020. del args[1]
  1021. else:
  1022. args[1] == '-v'
  1023. if log_level < logging.DEBUG:
  1024. logger.debug("in: %r\n%s", directory, ' '.join(args))
  1025. if is_jython:
  1026. assert subprocess.Popen([_safe_arg(executable)] + args).wait() == 0
  1027. else:
  1028. assert os.spawnl(os.P_WAIT, executable, _safe_arg(executable),
  1029. *args) == 0
  1030. return _copyeggs(tmp3, dest, '.egg-link', undo)
  1031. finally:
  1032. undo.reverse()
  1033. [f() for f in undo]
  1034. def working_set(specs, executable, path, include_site_packages=None,
  1035. allowed_eggs_from_site_packages=None, prefer_final=None):
  1036. return install(
  1037. specs, None, executable=executable, path=path,
  1038. include_site_packages=include_site_packages,
  1039. allowed_eggs_from_site_packages=allowed_eggs_from_site_packages,
  1040. prefer_final=prefer_final)
  1041. ############################################################################
  1042. # Script generation functions
  1043. def scripts(
  1044. reqs, working_set, executable, dest,
  1045. scripts=None,
  1046. extra_paths=(),
  1047. arguments='',
  1048. interpreter=None,
  1049. initialization='',
  1050. relative_paths=False,
  1051. ):
  1052. """Generate scripts and/or an interpreter.
  1053. See sitepackage_safe_scripts for a version that can be used with a Python
  1054. that has code installed in site-packages. It has more options and a
  1055. different approach.
  1056. """
  1057. path = _get_path(working_set, extra_paths)
  1058. if initialization:
  1059. initialization = '\n'+initialization+'\n'
  1060. generated = _generate_scripts(
  1061. reqs, working_set, dest, path, scripts, relative_paths,
  1062. initialization, executable, arguments)
  1063. if interpreter:
  1064. sname = os.path.join(dest, interpreter)
  1065. spath, rpsetup = _relative_path_and_setup(sname, path, relative_paths)
  1066. generated.extend(
  1067. _pyscript(spath, sname, executable, rpsetup))
  1068. return generated
  1069. # We need to give an alternate name to the ``scripts`` function so that it
  1070. # can be referenced within sitepackage_safe_scripts, which uses ``scripts``
  1071. # as an argument name.
  1072. _original_scripts_function = scripts
  1073. def sitepackage_safe_scripts(
  1074. dest, working_set, executable, site_py_dest,
  1075. reqs=(),
  1076. scripts=None,
  1077. interpreter=None,
  1078. extra_paths=(),
  1079. initialization='',
  1080. include_site_packages=False,
  1081. exec_sitecustomize=False,
  1082. relative_paths=False,
  1083. script_arguments='',
  1084. script_initialization='',
  1085. ):
  1086. """Generate scripts and/or an interpreter from a system Python.
  1087. This accomplishes the same job as the ``scripts`` function, above,
  1088. but it does so in an alternative way that allows safely including
  1089. Python site packages, if desired, and choosing to execute the Python's
  1090. sitecustomize.
  1091. """
  1092. if _has_broken_dash_S(executable):
  1093. if not include_site_packages:
  1094. warnings.warn(BROKEN_DASH_S_WARNING)
  1095. return _original_scripts_function(
  1096. reqs, working_set, executable, dest, scripts, extra_paths,
  1097. script_arguments, interpreter, initialization, relative_paths)
  1098. generated = []
  1099. generated.append(_generate_sitecustomize(
  1100. site_py_dest, executable, initialization, exec_sitecustomize))
  1101. generated.append(_generate_site(
  1102. site_py_dest, working_set, executable, extra_paths,
  1103. include_site_packages, relative_paths))
  1104. script_initialization = _script_initialization_template % dict(
  1105. site_py_dest=site_py_dest,
  1106. script_initialization=script_initialization)
  1107. if not script_initialization.endswith('\n'):
  1108. script_initialization += '\n'
  1109. generated.extend(_generate_scripts(
  1110. reqs, working_set, dest, [site_py_dest], scripts, relative_paths,
  1111. script_initialization, executable, script_arguments, block_site=True))
  1112. if interpreter:
  1113. generated.extend(_generate_interpreter(
  1114. interpreter, dest, executable, site_py_dest, relative_paths))
  1115. return generated
  1116. _script_initialization_template = '''
  1117. import os
  1118. path = sys.path[0]
  1119. if os.environ.get('PYTHONPATH'):
  1120. path = os.pathsep.join([path, os.environ['PYTHONPATH