resolve#

Low-level SAT solver wrapper/interface for the classic solver.

See conda.core.solver.Solver for the high-level API.

Classes#

Resolve

Functions#

_get_sat_solver_cls([sat_solver_choice])

exactness_and_number_of_deps(resolve_obj, ms)

Sorting key to emphasize packages that have more strict

Attributes#

stdoutlog

Unsatisfiable

ResolvePackageNotFound

_sat_solvers

stdoutlog#
Unsatisfiable#
ResolvePackageNotFound#
_sat_solvers#
_get_sat_solver_cls(sat_solver_choice=SatSolverChoice.PYCOSAT)#
exactness_and_number_of_deps(resolve_obj, ms)#

Sorting key to emphasize packages that have more strict requirements. More strict means the reduced index can be reduced more, so we want to consider these more constrained deps earlier in reducing the index.

class Resolve(index, processed=False, channels=())#
__hash__()#

Return hash(self).

default_filter(features=None, filter=None)#
valid(spec_or_prec, filter, optional=True)#

Tests if a package, MatchSpec, or a list of both has satisfiable dependencies, assuming cyclic dependencies are always valid.

Parameters:
  • spec_or_prec -- a package record, a MatchSpec, or an iterable of these.

  • filter -- a dictionary of (fkey,valid) pairs, used to consider a subset of dependencies, and to eliminate repeated searches.

  • optional -- if True (default), do not enforce optional specifications when considering validity. If False, enforce them.

Returns:

True if the full set of dependencies can be satisfied; False otherwise. If filter is supplied and update is True, it will be updated with the search results.

valid2(spec_or_prec, filter_out, optional=True)#
invalid_chains(spec, filter, optional=True)#

Constructs a set of 'dependency chains' for invalid specs.

A dependency chain is a tuple of MatchSpec objects, starting with the requested spec, proceeding down the dependency tree, ending at a specification that cannot be satisfied.

Parameters:
  • spec -- a package key or MatchSpec

  • filter -- a dictionary of (prec, valid) pairs to be used when testing for package validity.

Returns:

A tuple of tuples, empty if the MatchSpec is valid.

verify_specs(specs)#

Perform a quick verification that specs and dependencies are reasonable.

Parameters:

specs -- An iterable of strings or MatchSpec objects to be tested.

Returns:

Nothing, but if there is a conflict, an error is thrown.

Note that this does not attempt to resolve circular dependencies.

_classify_bad_deps(bad_deps, specs_to_add, history_specs, strict_channel_priority)#
find_matches_with_strict(ms, strict_channel_priority)#
find_conflicts(specs, specs_to_add=None, history_specs=None)#
breadth_first_search_for_dep_graph(root_spec, target_name, dep_graph, num_targets=1)#

Return shorted path from root_spec to target_name

build_graph_of_deps(spec)#
build_conflict_map(specs, specs_to_add=None, history_specs=None)#

Perform a deeper analysis on conflicting specifications, by attempting to find the common dependencies that might be the cause of conflicts.

Parameters:
  • specs -- An iterable of strings or MatchSpec objects to be tested.

  • conflict. (It is assumed that the specs)

Returns:

A list of lists of bad deps

Return type:

bad_deps

Strategy:

If we're here, we know that the specs conflict. This could be because: - One spec conflicts with another; e.g.

['numpy 1.5*', 'numpy >=1.6']

  • One spec conflicts with a dependency of another; e.g.

    ['numpy 1.5*', 'scipy 0.12.0b1']

  • Each spec depends on the same package but in a different way; e.g.,

    ['A', 'B'] where A depends on numpy 1.5, and B on numpy 1.6.

Technically, all three of these cases can be boiled down to the last one if we treat the spec itself as one of the "dependencies". There might be more complex reasons for a conflict, but this code only considers the ones above.

The purpose of this code, then, is to identify packages (like numpy above) that all of the specs depend on but in different ways. We then identify the dependency chains that lead to those packages.

_get_strict_channel(package_name)#
_broader(ms, specs_by_name)#

Prevent introduction of matchspecs that broaden our selection of choices.

_get_package_pool(specs)#
get_reduced_index(explicit_specs, sort_by_exactness=True, exit_on_conflict=False)#
match_any(mss, prec)#
find_matches(spec: conda.models.match_spec.MatchSpec) tuple[conda.models.records.PackageRecord]#
ms_depends(prec: conda.models.records.PackageRecord) list[conda.models.match_spec.MatchSpec]#
version_key(prec, vtype=None)#
static _make_channel_priorities(channels)#
get_pkgs(ms, emptyok=False)#
static to_sat_name(val)#
static to_feature_metric_id(prec_dist_str, feat)#
push_MatchSpec(C, spec)#
gen_clauses()#
generate_spec_constraints(C, specs)#
generate_feature_count(C)#
generate_update_count(C, specs)#
generate_feature_metric(C)#
generate_removal_count(C, specs)#
generate_install_count(C, specs)#
generate_package_count(C, missing)#
generate_version_metrics(C, specs, include0=False)#
dependency_sort(must_have: dict[str, conda.models.records.PackageRecord]) list[conda.models.records.PackageRecord]#
environment_is_consistent(installed)#
get_conflicting_specs(specs, explicit_specs)#
bad_installed(installed, new_specs)#
restore_bad(pkgs, preserve)#
install_specs(specs, installed, update_deps=True)#
install(specs, installed=None, update_deps=True, returnall=False)#
remove_specs(specs, installed)#
remove(specs, installed)#
solve(specs: list, returnall: bool = False, _remove=False, specs_to_add=None, history_specs=None, should_retry_solve=False) list[conda.models.records.PackageRecord]#