Skip to content

Commit

Permalink
working Windows channel priority integration test
Browse files Browse the repository at this point in the history
Signed-off-by: Kale Franz <[email protected]>
  • Loading branch information
kalefranz committed Sep 4, 2018
1 parent 4053096 commit 79bcfee
Show file tree
Hide file tree
Showing 7 changed files with 26 additions and 21 deletions.
2 changes: 1 addition & 1 deletion conda/cli/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def install(args, parser, command='install'):
platform=None,
use_local=index_args['use_local'],
))
raise PackagesNotFoundError(e.bad_deps, channels_urls)
raise PackagesNotFoundError(e._formatted_chains, channels_urls)

except (UnsatisfiableError, SystemExit) as e:
# Unsatisfiable package specifications/no such revision/import error
Expand Down
8 changes: 2 additions & 6 deletions conda/core/solve.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,8 +440,6 @@ def _run_sat(self, ssc):
ssc.pinned_specs,
))

strict_channel_priority = context.channel_priority == ChannelPriority.STRICT

# We've previously checked `solution` for consistency (which at that point was the
# pre-solve state of the environment). Now we check our compiled set of
# `final_environment_specs` for the possibility of a solution. If there are conflicts,
Expand All @@ -453,8 +451,7 @@ def _run_sat(self, ssc):
# get_conflicting_specs() returns a "minimal unsatisfiable subset" which
# may not be the only unsatisfiable subset. We may have to call get_conflicting_specs()
# several times, each time making modifications to loosen constraints.
conflicting_specs = ssc.r.get_conflicting_specs(tuple(final_environment_specs),
strict_channel_priority)
conflicting_specs = ssc.r.get_conflicting_specs(tuple(final_environment_specs))
while conflicting_specs:
specs_modified = False
if log.isEnabledFor(DEBUG):
Expand Down Expand Up @@ -489,8 +486,7 @@ def _run_sat(self, ssc):
if log.isEnabledFor(DEBUG):
log.debug("final specs to add: %s",
dashlist(sorted(text_type(s) for s in final_environment_specs)))
ssc.solution_precs = ssc.r.solve(tuple(final_environment_specs),
strict_channel_priority=strict_channel_priority)
ssc.solution_precs = ssc.r.solve(tuple(final_environment_specs))

# add back inconsistent packages to solution
if ssc.add_back_map:
Expand Down
5 changes: 4 additions & 1 deletion conda/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@
class ResolvePackageNotFound(CondaError):
def __init__(self, bad_deps):
# bad_deps is a list of lists
# bad_deps should really be named 'invalid_chains'
self.bad_deps = tuple(dep for deps in bad_deps for dep in deps if dep)
message = '\n' + '\n'.join((' - %s' % dep) for dep in self.bad_deps)
formatted_chains = tuple(" -> ".join(map(str, bad_chain)) for bad_chain in bad_deps)
self._formatted_chains = formatted_chains
message = '\n' + '\n'.join((' - %s' % bad_chain) for bad_chain in formatted_chains)
super(ResolvePackageNotFound, self).__init__(message)
NoPackagesFound = NoPackagesFoundError = ResolvePackageNotFound # NOQA

Expand Down
9 changes: 6 additions & 3 deletions conda/models/records.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ def box(self, instance, instance_type, val):

class TimestampField(NumberField):

def __init__(self):
super(TimestampField, self).__init__(default=0, required=False, default_in_dump=False)

@staticmethod
def _make_seconds(val):
if val:
Expand Down Expand Up @@ -77,8 +80,8 @@ def __get__(self, instance, instance_type):
except AttributeError:
try:
return int(dt_to_timestamp(isoparse(instance.date)))
except ValueError:
raise AttributeError()
except (AttributeError, ValueError):
return 0


class Link(DictSafeMixin, Entity):
Expand Down Expand Up @@ -299,7 +302,7 @@ def dist_fields_dump(self):
def is_unmanageable(self):
return self.package_type in PackageType.unmanageable_package_types()

timestamp = TimestampField(required=False)
timestamp = TimestampField()

@property
def combined_depends(self):
Expand Down
14 changes: 8 additions & 6 deletions conda/resolve.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,10 +305,12 @@ def _get_strict_channel(self, package_name):
return channel_name

@time_recorder(module_name=__name__)
def get_reduced_index(self, specs, strict_channel_priority=False):
def get_reduced_index(self, specs):
# TODO: fix this import; this is bad
from .core.subdir_data import make_feature_record

strict_channel_priority = context.channel_priority == ChannelPriority.STRICT

cache_key = strict_channel_priority, frozenset(specs)
if cache_key in self._reduced_index_cache:
return self._reduced_index_cache[cache_key]
Expand Down Expand Up @@ -418,7 +420,7 @@ def filter_group(_specs):
# Messaging to users should be more descriptive.
# 1. Are there no direct matches?
# 2. Are there no matches for first-level dependencies?
# 3. Have the first level depedendencies been invalidated?
# 3. Have the first level dependencies been invalidated?
break

# Determine all valid packages in the dependency graph
Expand Down Expand Up @@ -758,10 +760,10 @@ def environment_is_consistent(self, installed):
solution = C.sat(constraints)
return bool(solution)

def get_conflicting_specs(self, specs, strict_channel_priority=False):
def get_conflicting_specs(self, specs):
if not specs:
return ()
reduced_index = self.get_reduced_index(specs, strict_channel_priority)
reduced_index = self.get_reduced_index(specs)

# Check if satisfiable
def mysat(specs, add_if=False):
Expand Down Expand Up @@ -911,15 +913,15 @@ def remove(self, specs, installed):
return pkgs

@time_recorder(module_name=__name__)
def solve(self, specs, returnall=False, _remove=False, strict_channel_priority=False):
def solve(self, specs, returnall=False, _remove=False):
# type: (List[str], bool) -> List[PackageRecord]
if log.isEnabledFor(DEBUG):
log.debug('Solving for: %s', dashlist(sorted(text_type(s) for s in specs)))

# Find the compliant packages
len0 = len(specs)
specs = tuple(map(MatchSpec, specs))
reduced_index = self.get_reduced_index(specs, strict_channel_priority)
reduced_index = self.get_reduced_index(specs)
if not reduced_index:
return False if reduced_index is None else ([[]] if returnall else [])

Expand Down
7 changes: 4 additions & 3 deletions tests/test_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -569,13 +569,14 @@ def test_strict_channel_priority(self):
with env_var("CONDA_CHANNEL_PRIORITY", "strict", reset_context):
stdout, stderr = run_command(
Commands.CREATE, "/",
"-c conda-forge -c defaults python=3.6 geopandas --dry-run --json",
"-c conda-forge -c defaults python=3.6 fiona --strict-channel-priority --dry-run --json",
use_exception_handler=True
)
assert not stderr
json_obj = json_loads(stdout)
channels = set(dist["channel"] for dist in json_obj["actions"]["LINK"])
assert channels == {"conda-forge"}
channel_groups = groupby("channel",json_obj["actions"]["LINK"])
# conda-forge should be the only channel in the solution on unix
assert list(channel_groups) == ["conda-forge"]

def test_strict_resolve_get_reduced_index(self):
channels = (Channel("defaults"),)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_resolve.py
Original file line number Diff line number Diff line change
Expand Up @@ -1355,7 +1355,7 @@ def test_channel_priority_2():

# setting strict actually doesn't do anything here; just ensures it's not 'disabled'
with env_var("CONDA_CHANNEL_PRIORITY", "strict", reset_context):
dists = this_r.get_reduced_index(spec, strict_channel_priority=True)
dists = this_r.get_reduced_index(spec)
r2 = Resolve(dists, True, True, channels=channels)
C = r2.gen_clauses()
eqc, eqv, eqb, eqt = r2.generate_version_metrics(C, list(r2.groups.keys()))
Expand Down

0 comments on commit 79bcfee

Please sign in to comment.