diff --git a/piptools/exceptions.py b/piptools/exceptions.py index 66df316fa..77c5bd404 100644 --- a/piptools/exceptions.py +++ b/piptools/exceptions.py @@ -3,22 +3,44 @@ class PipToolsError(Exception): class NoCandidateFound(PipToolsError): - def __init__(self, ireq, candidates_tried, index_urls): + def __init__(self, ireq, candidates_tried, finder): self.ireq = ireq self.candidates_tried = candidates_tried - self.index_urls = index_urls + self.finder = finder def __str__(self): - sorted_versions = sorted(c.version for c in self.candidates_tried) + versions = [] + pre_versions = [] + + for candidate in sorted(self.candidates_tried): + version = str(candidate.version) + if candidate.version.is_prerelease: + pre_versions.append(version) + else: + versions.append(version) + lines = [ 'Could not find a version that matches {}'.format(self.ireq), - 'Tried: {}'.format(', '.join(str(version) for version in sorted_versions) or '(no version found at all)') ] - if sorted_versions: + + if versions: + lines.append('Tried: {}'.format(', '.join(versions))) + + if pre_versions: + if self.finder.allow_all_prereleases: + line = 'Tried' + else: + line = 'Skipped' + + line += ' pre-versions: {}'.format(', '.join(pre_versions)) + lines.append(line) + + if versions or pre_versions: lines.append('There are incompatible versions in the resolved dependencies.') else: + lines.append('No versions found') lines.append('{} {} reachable?'.format( - 'Were' if len(self.index_urls) > 1 else 'Was', ' or '.join(self.index_urls)) + 'Were' if len(self.finder.index_urls) > 1 else 'Was', ' or '.join(self.finder.index_urls)) ) return '\n'.join(lines) diff --git a/piptools/repositories/pypi.py b/piptools/repositories/pypi.py index d3b7fe75a..1d42c2806 100644 --- a/piptools/repositories/pypi.py +++ b/piptools/repositories/pypi.py @@ -104,7 +104,7 @@ def find_best_match(self, ireq, prereleases=None): # Reuses pip's internal candidate sort key to sort matching_candidates = [candidates_by_version[ver] for ver in matching_versions] if not matching_candidates: - raise NoCandidateFound(ireq, all_candidates, self.finder.index_urls) + raise NoCandidateFound(ireq, all_candidates, self.finder) best_candidate = max(matching_candidates, key=self.finder._candidate_sort_key) # Turn the candidate into a pinned InstallRequirement diff --git a/tests/test_cli.py b/tests/test_cli.py index 62132e81c..c590a9bfd 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -366,3 +366,27 @@ def test_filter_pip_markes(): assert '--output-file requirements.txt' in out.output assert 'six==1.10.0' in out.output assert 'unknown_package' not in out.output + + +def test_no_candidates(): + runner = CliRunner() + with runner.isolated_filesystem(): + with open('requirements', 'w') as req_in: + req_in.write('six>1.0b0,<1.0b0') + + out = runner.invoke(cli, ['-n', 'requirements']) + + assert out.exit_code == 2 + assert 'Skipped pre-versions:' in out.output + + +def test_no_candidates_pre(): + runner = CliRunner() + with runner.isolated_filesystem(): + with open('requirements', 'w') as req_in: + req_in.write('six>1.0b0,<1.0b0') + + out = runner.invoke(cli, ['-n', 'requirements', '--pre']) + + assert out.exit_code == 2 + assert 'Tried pre-versions:' in out.output diff --git a/tox.ini b/tox.ini index f2fa8405f..97e0c1e76 100644 --- a/tox.ini +++ b/tox.ini @@ -3,6 +3,7 @@ envlist = py{27,34,35,36,py} flake8 readme +skip_missing_interpreters = True [testenv] deps =