Skip to content

Commit c92f55f

Browse files
committed
Implement constraints
1 parent 5186f05 commit c92f55f

File tree

3 files changed

+36
-13
lines changed

3 files changed

+36
-13
lines changed

src/pip/_internal/resolution/resolvelib/factory.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
)
2222

2323
if MYPY_CHECK_RUNNING:
24-
from typing import Dict, Iterator, Optional, Set, Tuple, TypeVar
24+
from typing import Dict, Iterator, List, Optional, Set, Tuple, TypeVar
2525

2626
from pip._vendor.packaging.specifiers import SpecifierSet
2727
from pip._vendor.packaging.version import _BaseVersion
@@ -71,6 +71,8 @@ def __init__(
7171
else:
7272
self._installed_dists = {}
7373

74+
self._constraints = {} # type: Dict[str,List[SpecifierSet]]
75+
7476
def _make_candidate_from_dist(
7577
self,
7678
dist, # type: Distribution
@@ -154,7 +156,7 @@ def make_requirement_from_install_req(self, ireq):
154156
cand = self._make_candidate_from_link(
155157
ireq.link, extras=set(), parent=ireq,
156158
)
157-
return ExplicitRequirement(cand)
159+
return ExplicitRequirement(cand, factory=self)
158160
return SpecifierRequirement(ireq, factory=self)
159161

160162
def make_requirement_from_spec(self, specifier, comes_from):

src/pip/_internal/resolution/resolvelib/requirements.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from pip._vendor.packaging.utils import canonicalize_name
22

3+
from pip._internal.exceptions import InstallationError
34
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
45

56
from .base import Requirement, format_name
@@ -16,9 +17,10 @@
1617

1718

1819
class ExplicitRequirement(Requirement):
19-
def __init__(self, candidate):
20-
# type: (Candidate) -> None
20+
def __init__(self, candidate, factory):
21+
# type: (Candidate, Factory) -> None
2122
self.candidate = candidate
23+
self._factory = factory
2224

2325
def __repr__(self):
2426
# type: () -> str
@@ -35,6 +37,12 @@ def name(self):
3537

3638
def find_matches(self):
3739
# type: () -> Sequence[Candidate]
40+
if self.name in self._factory._constraints:
41+
raise InstallationError(
42+
"Could not satisfy constraints for '{}': "
43+
"installation from path or url cannot be "
44+
"constrained to a version".format(self.name)
45+
)
3846
return [self.candidate]
3947

4048
def is_satisfied_by(self, candidate):
@@ -70,7 +78,11 @@ def name(self):
7078
def find_matches(self):
7179
# type: () -> Sequence[Candidate]
7280
it = self._factory.iter_found_candidates(self._ireq, self.extras)
73-
return list(it)
81+
constraints = self._factory._constraints.get(self.name, [])
82+
lit = [c for c in it if all(
83+
s.contains(c.version, prereleases=True) for s in constraints
84+
)]
85+
return lit
7486

7587
def is_satisfied_by(self, candidate):
7688
# type: (Candidate) -> bool

src/pip/_internal/resolution/resolvelib/resolver.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import functools
22
import logging
3+
from collections import defaultdict
34

45
from pip._vendor import six
56
from pip._vendor.packaging.utils import canonicalize_name
@@ -17,6 +18,7 @@
1718
if MYPY_CHECK_RUNNING:
1819
from typing import Dict, List, Optional, Tuple
1920

21+
from pip._vendor.packaging.specifiers import SpecifierSet
2022
from pip._vendor.resolvelib.resolvers import Result
2123

2224
from pip._internal.cache import WheelCache
@@ -60,9 +62,21 @@ def __init__(
6062
def resolve(self, root_reqs, check_supported_wheels):
6163
# type: (List[InstallRequirement], bool) -> RequirementSet
6264

63-
# FIXME: Implement constraints.
64-
if any(r.constraint for r in root_reqs):
65-
raise InstallationError("Constraints are not yet supported.")
65+
constraints = defaultdict(list) # type: Dict[str,List[SpecifierSet]]
66+
requirements = []
67+
for req in root_reqs:
68+
if req.constraint:
69+
assert req.name
70+
assert req.specifier
71+
name = canonicalize_name(req.name)
72+
constraints[name].append(req.specifier)
73+
else:
74+
requirements.append(
75+
self.factory.make_requirement_from_install_req(req)
76+
)
77+
78+
# TODO: Refactor this, it's just for proof of concept
79+
self.factory._constraints = constraints
6680

6781
provider = PipProvider(
6882
factory=self.factory,
@@ -71,11 +85,6 @@ def resolve(self, root_reqs, check_supported_wheels):
7185
reporter = BaseReporter()
7286
resolver = RLResolver(provider, reporter)
7387

74-
requirements = [
75-
self.factory.make_requirement_from_install_req(r)
76-
for r in root_reqs
77-
]
78-
7988
try:
8089
self._result = resolver.resolve(requirements)
8190

0 commit comments

Comments
 (0)