-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enh/missing constraints #156
Merged
Merged
Changes from 5 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
ffd65fb
ENH: add RuleType.package_broken
johntyree e7127df
ENH: add strict keyword to rules gen
johntyree 9159dde
ENH: gracefully prevent installation of packages with broken dependen…
johntyree ea1f0dd
ENH: gracefully ignore packages' broken conflicts
johntyree e89b40a
ENH: honor 'strict' parameter when ignoring broken packages
johntyree 8308f64
Merge branch 'master' into enh/missing-constraints
johntyree e8c853c
MAINT: make timed_context more uniform
johntyree 5b45445
MAINT: enable logging with solve.py --debug
johntyree 0b7e81c
MAINT: broken package error message supports normal PackageMetadata
johntyree a76a854
STY: flake8 fix
johntyree 1ec8ace
MAINT: fix docstring for MiniSat.enque
johntyree c58bfbe
BUG: die if conflict found during initialization
johntyree c0e9470
TST: test that we die on error during init
johntyree c06564e
ENH: expose strict errors in DependencySolver
johntyree 6c6cea0
ENH: expose --strict option to scripts/solve.py
johntyree 7218fbc
TST: add scenarios for missing conflict and install_requires
johntyree 3b85e49
MAINT: expand comment about detecting a job
johntyree File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,16 @@ | ||
import collections | ||
import enum | ||
import logging | ||
|
||
from .constraints import Requirement | ||
from .errors import NoPackageFound, SolverException | ||
from .errors import ( | ||
MissingConflicts, MissingInstallRequires, NoPackageFound, SolverException | ||
) | ||
from .request import JobType | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
|
||
INDENT = 4 | ||
|
||
|
||
|
@@ -19,6 +24,7 @@ class RuleType(enum.Enum): | |
package_same_name = 10 | ||
package_implicit_obsoletes = 11 | ||
package_installed = 12 | ||
package_broken = 100 | ||
|
||
internal = 256 | ||
|
||
|
@@ -113,6 +119,12 @@ def to_string(self, pool, unique=False): | |
left = pool.id_to_string(abs(left_id))[1:] | ||
right = pool.id_to_string(abs(right_id)) | ||
rule_desc = "{} conflicts with {}".format(left, right) | ||
elif self._reason == RuleType.package_broken: | ||
package_id = self.literals[0] | ||
# Trim the sign | ||
package_str = pool.id_to_string(abs(package_id)) | ||
msg = "{} was ignored because it depends on missing packages" | ||
rule_desc = msg.format(package_str) | ||
else: | ||
rule_desc = s | ||
|
||
|
@@ -135,13 +147,14 @@ def __hash__(self): | |
|
||
|
||
class RulesGenerator(object): | ||
def __init__(self, pool, request, installed_map=None): | ||
def __init__(self, pool, request, installed_map=None, strict=False): | ||
self._rules_set = collections.OrderedDict() | ||
self._pool = pool | ||
|
||
self.request = request | ||
self.installed_map = installed_map or collections.OrderedDict() | ||
self.added_package_ids = set() | ||
self.strict = strict | ||
|
||
def iter_rules(self): | ||
""" | ||
|
@@ -284,6 +297,7 @@ def _add_rule(self, rule, rule_type): | |
self._rules_set[rule] = None | ||
|
||
def _add_install_requires_rules(self, package, work_queue, requirements): | ||
all_dependency_candidates = [] | ||
for constraints in package.install_requires: | ||
pkg_requirement = Requirement.from_constraints(constraints) | ||
dependency_candidates = self._pool.what_provides(pkg_requirement) | ||
|
@@ -296,20 +310,42 @@ def _add_install_requires_rules(self, package, work_queue, requirements): | |
else None) | ||
|
||
if not dependency_candidates: | ||
msg = ("No candidates found for requirement {0!r}, needed for " | ||
"dependency {1!r}") | ||
raise NoPackageFound( | ||
pkg_requirement, | ||
msg.format(pkg_requirement.name, package), | ||
pkg_msg = ("'{0.name} {0.version}' from" | ||
" '{0.repository_info.name}'") | ||
pkg_str = pkg_msg.format(package) | ||
req_str = str(pkg_requirement) | ||
msg = ("Blocking package {0!s}: no candidates found for" | ||
" dependency {1!r}").format(pkg_str, req_str) | ||
if self.strict: | ||
# We only raise an exception if this comes directly from a | ||
# job requirement. Unfortunately, we don't track that | ||
# explicitly because we push all of the work through a | ||
# queue. As a proxy, we can examine the associated | ||
# requirements directly. | ||
if len(requirements) == 1: | ||
raise MissingInstallRequires(pkg_requirement, msg) | ||
else: | ||
logger.warning(msg) | ||
else: | ||
logger.info(msg) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nevermind, it's down below. We have to make our rule preventing installation first. |
||
|
||
rule = self._create_remove_rule( | ||
package, RuleType.package_broken, | ||
requirements=combined_requirements, | ||
) | ||
self._add_rule(rule, "package") | ||
return | ||
|
||
rule = self._create_dependency_rule( | ||
package, dependency_candidates, RuleType.package_requires, | ||
combined_requirements) | ||
self._add_rule(rule, "package") | ||
|
||
for candidate in dependency_candidates: | ||
work_queue.append((candidate, combined_requirements)) | ||
# We're "buffering" this so that we don't queue up any dependencies | ||
# unless they are all successfully processed | ||
all_dependency_candidates.extend( | ||
(candidate, combined_requirements) | ||
for candidate in dependency_candidates) | ||
work_queue.extend(all_dependency_candidates) | ||
|
||
def _add_conflicts_rules(self, package, requirements): | ||
""" | ||
|
@@ -345,12 +381,26 @@ def _add_conflicts_rules(self, package, requirements): | |
else None) | ||
|
||
if not conflict_providers: | ||
msg = ("No candidates found for requirement {0!r}, needed for " | ||
"conflict {1!r}") | ||
raise NoPackageFound( | ||
pkg_requirement, | ||
msg.format(pkg_requirement.name, package), | ||
) | ||
pkg_msg = ("'{0.name} {0.version}' from" | ||
" '{0.repository_info.name}'") | ||
pkg_str = pkg_msg.format(package) | ||
req_str = str(pkg_requirement) | ||
msg = ("No candidates found for requirement {0!r}, needed" | ||
" for conflict with {1!s}").format(req_str, pkg_str) | ||
if self.strict: | ||
# We only raise an exception if this comes directly from a | ||
# job requirement. Unfortunately, we don't track that | ||
# explicitly because we push all of the work through a | ||
# queue. As a proxy, we can examine the associated | ||
# requirements directly. | ||
if len(requirements) == 1: | ||
raise MissingConflicts(pkg_requirement, msg) | ||
else: | ||
logger.warning(msg) | ||
else: | ||
# We just ignore missing constraints. They don't break | ||
# anything. | ||
logger.info(msg) | ||
|
||
for provider in conflict_providers: | ||
rule = self._create_conflicts_rule( | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand the logic behind testing for
len(requirements) == 1
?