mirror of https://github.com/pypa/pip
Tidy up handling of unexpected forms of constraint
This commit is contained in:
parent
d911a9fcb8
commit
6fcaf49cb0
|
@ -2,6 +2,7 @@ import functools
|
|||
import logging
|
||||
|
||||
from pip._vendor import six
|
||||
from pip._vendor.packaging.specifiers import SpecifierSet
|
||||
from pip._vendor.packaging.utils import canonicalize_name
|
||||
from pip._vendor.resolvelib import BaseReporter, ResolutionImpossible
|
||||
from pip._vendor.resolvelib import Resolver as RLResolver
|
||||
|
@ -17,7 +18,6 @@ from .factory import Factory
|
|||
if MYPY_CHECK_RUNNING:
|
||||
from typing import Dict, List, Optional, Set, Tuple
|
||||
|
||||
from pip._vendor.packaging.specifiers import SpecifierSet
|
||||
from pip._vendor.resolvelib.resolvers import Result
|
||||
from pip._vendor.resolvelib.structs import Graph
|
||||
|
||||
|
@ -74,13 +74,29 @@ class Resolver(BaseResolver):
|
|||
requirements = []
|
||||
for req in root_reqs:
|
||||
if req.constraint:
|
||||
assert req.name
|
||||
assert req.specifier
|
||||
# TODO: Add warnings to accompany these errors, explaining
|
||||
# that these were undocumented behaviour of the old resolver
|
||||
# and will be removed in the new resolver. We need to consider
|
||||
# how we remember to remove these warnings when the new
|
||||
# resolver becomes the default...
|
||||
if not req.name:
|
||||
raise InstallationError(
|
||||
"Unnamed requirements are not allowed as constraints"
|
||||
)
|
||||
if req.link:
|
||||
raise InstallationError(
|
||||
"Links are not allowed as constraints"
|
||||
)
|
||||
if req.extras:
|
||||
raise InstallationError(
|
||||
"Constraints cannot have extras"
|
||||
)
|
||||
specifier = req.specifier or SpecifierSet()
|
||||
name = canonicalize_name(req.name)
|
||||
if name in constraints:
|
||||
constraints[name] = constraints[name] & req.specifier
|
||||
constraints[name] = constraints[name] & specifier
|
||||
else:
|
||||
constraints[name] = req.specifier
|
||||
constraints[name] = specifier
|
||||
else:
|
||||
requirements.append(
|
||||
self.factory.make_requirement_from_install_req(req)
|
||||
|
|
|
@ -548,6 +548,54 @@ def test_new_resolver_constraints(script):
|
|||
assert_not_installed(script, "constraint_only")
|
||||
|
||||
|
||||
def test_new_resolver_constraint_no_specifier(script):
|
||||
"It's allowed (but useless...) for a constraint to have no specifier"
|
||||
create_basic_wheel_for_package(script, "pkg", "1.0")
|
||||
constraints_file = script.scratch_path / "constraints.txt"
|
||||
constraints_file.write_text("pkg")
|
||||
script.pip(
|
||||
"install", "--unstable-feature=resolver",
|
||||
"--no-cache-dir", "--no-index",
|
||||
"--find-links", script.scratch_path,
|
||||
"-c", constraints_file,
|
||||
"pkg"
|
||||
)
|
||||
assert_installed(script, pkg="1.0")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"constraint, error",
|
||||
[
|
||||
(
|
||||
"dist.zip",
|
||||
"Unnamed requirements are not allowed as constraints",
|
||||
),
|
||||
(
|
||||
"req @ https://example.com/dist.zip",
|
||||
"Links are not allowed as constraints",
|
||||
),
|
||||
(
|
||||
"pkg[extra]",
|
||||
"Constraints cannot have extras",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_new_resolver_constraint_reject_invalid(script, constraint, error):
|
||||
create_basic_wheel_for_package(script, "pkg", "1.0")
|
||||
constraints_file = script.scratch_path / "constraints.txt"
|
||||
constraints_file.write_text(constraint)
|
||||
result = script.pip(
|
||||
"install", "--unstable-feature=resolver",
|
||||
"--no-cache-dir", "--no-index",
|
||||
"--find-links", script.scratch_path,
|
||||
"-c", constraints_file,
|
||||
"pkg",
|
||||
expect_error=True,
|
||||
expect_stderr=True,
|
||||
)
|
||||
assert error in result.stderr, str(result)
|
||||
|
||||
|
||||
def test_new_resolver_constraint_on_dependency(script):
|
||||
create_basic_wheel_for_package(script, "base", "1.0", depends=["dep"])
|
||||
create_basic_wheel_for_package(script, "dep", "1.0")
|
||||
|
|
Loading…
Reference in New Issue