Skip to content

Commit

Permalink
Avoid issues related with pins persistence (#355)
Browse files Browse the repository at this point in the history
  • Loading branch information
jaimergp authored Nov 6, 2023
1 parent 20c548c commit 671b9c1
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 5 deletions.
12 changes: 7 additions & 5 deletions conda_libmamba_solver/solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ def _solving_loop(
for attempt in range(1, max_attempts):
log.debug("Starting solver attempt %s", attempt)
try:
solved = self._solve_attempt(in_state, out_state, index)
solved = self._solve_attempt(in_state, out_state, index, attempt=attempt)
if solved:
break
except (UnsatisfiableError, PackagesNotFoundError):
Expand Down Expand Up @@ -345,10 +345,11 @@ def _solve_attempt(
in_state: SolverInputState,
out_state: SolverOutputState,
index: LibMambaIndexHelper,
attempt: int = 1,
):
self._setup_solver(index)

log.debug("New solver attempt")
log.debug("New solver attempt: #%d", attempt)
log.debug("Current conflicts (including learnt ones): %s", out_state.conflicts)

# ## First, we need to obtain the list of specs ###
Expand All @@ -365,12 +366,13 @@ def _solve_attempt(
log.debug("Computed specs: %s", out_state.specs)

# ## Convert to tasks
out_state.pins.clear()
n_pins = 0
tasks = self._specs_to_tasks(in_state, out_state)
for (task_name, task_type), specs in tasks.items():
log.debug("Adding task %s with specs %s", task_name, specs)
if task_name == "ADD_PIN":
if task_name == "ADD_PIN" and attempt == 1:
# pins only need to be added once; since they persist in the pool
# adding them more times results in issues like #354
for spec in specs:
n_pins += 1
self.solver.add_pin(spec)
Expand All @@ -393,7 +395,7 @@ def _solve_attempt(
new_conflicts = self._maybe_raise_for_problems(
problems, old_conflicts, out_state.pins, index._channels
)
log.debug("Attempt failed with %s conflicts", len(new_conflicts))
log.debug("Attempt %d failed with %s conflicts", attempt, len(new_conflicts))
out_state.conflicts.update(new_conflicts.items(), reason="New conflict found")
return False

Expand Down
19 changes: 19 additions & 0 deletions news/355-pins-persistence-issues
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
### Enhancements

* <news item>

### Bug fixes

* Configure pinned specs just once to avoid solver bugs related with their persistence (i.e. inability to downgrade environments if pinned specs are present and a transient dependency needs to be removed). (#354 via #355)

### Deprecations

* <news item>

### Docs

* <news item>

### Other

* <news item>
38 changes: 38 additions & 0 deletions tests/test_solvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,3 +458,41 @@ def test_python_update_should_not_uninstall_history():
"--dry-run",
no_capture=True,
)


def test_python_downgrade_with_pins_removes_truststore():
"""
https://github.com/conda/conda-libmamba-solver/issues/354
"""
channels = "--override-channels", "-c", "conda-forge"
solver = "--solver", "libmamba"
with make_temp_env("python=3.10", "conda", *channels, *solver) as prefix:
zstd_version = PrefixData(prefix).get("zstd").version
for pin in (None, "zstd", f"zstd={zstd_version}"):
env = os.environ.copy()
if pin:
env["CONDA_PINNED_PACKAGES"] = pin
p = conda_subprocess(
Commands.INSTALL,
"-p",
prefix,
*channels,
*solver,
"--dry-run",
"--json",
"python=3.9",
env=env,
)
assert p.returncode == 0
data = json.loads(p.stdout)
assert data.get("success")
assert data.get("dry_run")
assertions = 0
link_dict = {pkg["name"]: pkg for pkg in data["actions"]["LINK"]}
unlink_dict = {pkg["name"]: pkg for pkg in data["actions"]["UNLINK"]}
assert link_dict["python"]["version"].startswith("3.9.")
assert "truststore" in unlink_dict
if pin:
# shouldn't have changed!
assert "zstd" not in link_dict
assert "zstd" not in unlink_dict

0 comments on commit 671b9c1

Please sign in to comment.