~ubuntu-branches/ubuntu/vivid/python-pex/vivid

« back to all changes in this revision

Viewing changes to pex/iterator.py

  • Committer: Package Import Robot
  • Author(s): Barry Warsaw
  • Date: 2015-02-19 14:13:25 UTC
  • Revision ID: package-import@ubuntu.com-20150219141325-w62bie95l6rawuuv
Tags: upstream-0.8.6
ImportĀ upstreamĀ versionĀ 0.8.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import itertools
 
2
 
 
3
from .crawler import Crawler
 
4
from .fetcher import PyPIFetcher
 
5
from .package import EggPackage, Package, SourcePackage, WheelPackage
 
6
 
 
7
 
 
8
class Iterator(object):
 
9
  """A requirement iterator."""
 
10
 
 
11
  DEFAULT_PACKAGE_PRECEDENCE = (
 
12
      WheelPackage,
 
13
      EggPackage,
 
14
      SourcePackage,
 
15
  )
 
16
 
 
17
  @classmethod
 
18
  def package_type_precedence(cls, package, precedence=DEFAULT_PACKAGE_PRECEDENCE):
 
19
    for rank, package_type in enumerate(reversed(precedence)):
 
20
      if isinstance(package, package_type):
 
21
        return rank
 
22
    # If we do not recognize the package, it gets lowest precedence
 
23
    return -1
 
24
 
 
25
  @classmethod
 
26
  def package_precedence(cls, package, precedence=DEFAULT_PACKAGE_PRECEDENCE):
 
27
    return (
 
28
        package.version,  # highest version
 
29
        cls.package_type_precedence(package, precedence=precedence),  # type preference
 
30
        package.local)  # prefer not fetching over the wire
 
31
 
 
32
  def __init__(self, fetchers=None, crawler=None, precedence=None):
 
33
    self._crawler = crawler or Crawler()
 
34
    self._fetchers = fetchers or [PyPIFetcher()]
 
35
    self._precedence = precedence or self.DEFAULT_PACKAGE_PRECEDENCE
 
36
 
 
37
  def _translate_href(self, href):
 
38
    package = Package.from_href(href)
 
39
    # Restrict this to a package found in the package precedence list, so that users of
 
40
    # obtainers can restrict which distribution formats they support.
 
41
    if any(isinstance(package, package_type) for package_type in self._precedence):
 
42
      return package
 
43
 
 
44
  def iter_requirement_urls(self, req):
 
45
    return itertools.chain.from_iterable(fetcher.urls(req) for fetcher in self._fetchers)
 
46
 
 
47
  def _iter_unordered(self, req, follow_links):
 
48
    url_iterator = self.iter_requirement_urls(req)
 
49
    crawled_url_iterator = self._crawler.crawl(url_iterator, follow_links=follow_links)
 
50
    for package in filter(None, map(self._translate_href, crawled_url_iterator)):
 
51
      if package.satisfies(req):
 
52
        yield package
 
53
 
 
54
  def _sort(self, package_list):
 
55
    key = lambda package: self.package_precedence(package, self._precedence)
 
56
    return sorted(package_list, key=key, reverse=True)
 
57
 
 
58
  def iter(self, req, follow_links=False):
 
59
    """Return a list of packages that satisfy the requirement in best match order."""
 
60
    for package in self._sort(self._iter_unordered(req, follow_links)):
 
61
      yield package