1
1
from __future__ import annotations
2
2
3
+ import collections
3
4
import functools
4
5
import time
5
6
@@ -94,7 +95,9 @@ def __init__(self, root: ProjectPackage, provider: Provider) -> None:
94
95
self ._provider = provider
95
96
self ._dependency_cache = DependencyCache (provider )
96
97
self ._incompatibilities : dict [str , list [Incompatibility ]] = {}
97
- self ._contradicted_incompatibilities : set [Incompatibility ] = set ()
98
+ self ._contradicted_incompatibilities : dict [int , set [Incompatibility ]] = (
99
+ collections .defaultdict (set )
100
+ )
98
101
self ._solution = PartialSolution ()
99
102
100
103
@property
@@ -143,7 +146,10 @@ def _propagate(self, package: str) -> None:
143
146
# we can derive stronger assignments sooner and more eagerly find
144
147
# conflicts.
145
148
for incompatibility in reversed (self ._incompatibilities [package ]):
146
- if incompatibility in self ._contradicted_incompatibilities :
149
+ if any (
150
+ incompatibility in c
151
+ for c in self ._contradicted_incompatibilities .values ()
152
+ ):
147
153
continue
148
154
149
155
result = self ._propagate_incompatibility (incompatibility )
@@ -192,7 +198,9 @@ def _propagate_incompatibility(
192
198
# If term is already contradicted by _solution, then
193
199
# incompatibility is contradicted as well and there's nothing new we
194
200
# can deduce from it.
195
- self ._contradicted_incompatibilities .add (incompatibility )
201
+ self ._contradicted_incompatibilities [self ._solution .decision_level ].add (
202
+ incompatibility
203
+ )
196
204
return None
197
205
elif relation == SetRelation .OVERLAPPING :
198
206
# If more than one term is inconclusive, we can't deduce anything about
@@ -210,7 +218,9 @@ def _propagate_incompatibility(
210
218
if unsatisfied is None :
211
219
return _conflict
212
220
213
- self ._contradicted_incompatibilities .add (incompatibility )
221
+ self ._contradicted_incompatibilities [self ._solution .decision_level ].add (
222
+ incompatibility
223
+ )
214
224
215
225
adverb = "not " if unsatisfied .is_positive () else ""
216
226
self ._log (f"derived: { adverb } { unsatisfied .dependency } " )
@@ -304,8 +314,12 @@ def _resolve_conflict(self, incompatibility: Incompatibility) -> Incompatibility
304
314
previous_satisfier_level < most_recent_satisfier .decision_level
305
315
or most_recent_satisfier .cause is None
306
316
):
317
+ for level in range (
318
+ self ._solution .decision_level , previous_satisfier_level , - 1
319
+ ):
320
+ self ._contradicted_incompatibilities .pop (level , None )
321
+
307
322
self ._solution .backtrack (previous_satisfier_level )
308
- self ._contradicted_incompatibilities .clear ()
309
323
self ._dependency_cache .clear ()
310
324
if new_incompatibility :
311
325
self ._add_incompatibility (incompatibility )
0 commit comments