mirror of https://github.com/pypa/pip
Merge 0b854a39c5
into 2a0acb595c
This commit is contained in:
commit
a0dea514be
|
@ -0,0 +1,3 @@
|
|||
Add the ``--ignore-constraint`` option to ``pip install``, ``pip download``
|
||||
and ``pip wheel`` commands to ignore an individual constraint from a
|
||||
constraints file.
|
|
@ -415,6 +415,19 @@ def constraints() -> Option:
|
|||
)
|
||||
|
||||
|
||||
def ignored_constraints() -> Option:
|
||||
return Option(
|
||||
"--ignore-constraint",
|
||||
dest="ignored_constraints",
|
||||
action="append",
|
||||
default=[],
|
||||
metavar="package",
|
||||
help="Ignore constraints for given package. This is commonly used "
|
||||
"during development of a package when using a common constraints "
|
||||
"file. This option be used multiple times.",
|
||||
)
|
||||
|
||||
|
||||
def requirements() -> Option:
|
||||
return Option(
|
||||
"-r",
|
||||
|
|
|
@ -363,10 +363,13 @@ class RequirementCommand(IndexGroupCommand):
|
|||
ignore_requires_python=ignore_requires_python,
|
||||
force_reinstall=force_reinstall,
|
||||
upgrade_strategy=upgrade_strategy,
|
||||
ignored_constraints=options.ignored_constraints,
|
||||
py_version_info=py_version_info,
|
||||
)
|
||||
import pip._internal.resolution.legacy.resolver
|
||||
|
||||
# we intentionally don't pass ignored_constraints to this since the
|
||||
# resolver is deprecated
|
||||
return pip._internal.resolution.legacy.resolver.Resolver(
|
||||
preparer=preparer,
|
||||
finder=finder,
|
||||
|
|
|
@ -37,6 +37,7 @@ class DownloadCommand(RequirementCommand):
|
|||
|
||||
def add_options(self) -> None:
|
||||
self.cmd_opts.add_option(cmdoptions.constraints())
|
||||
self.cmd_opts.add_option(cmdoptions.ignored_constraints())
|
||||
self.cmd_opts.add_option(cmdoptions.requirements())
|
||||
self.cmd_opts.add_option(cmdoptions.no_deps())
|
||||
self.cmd_opts.add_option(cmdoptions.global_options())
|
||||
|
|
|
@ -72,6 +72,7 @@ class InstallCommand(RequirementCommand):
|
|||
def add_options(self) -> None:
|
||||
self.cmd_opts.add_option(cmdoptions.requirements())
|
||||
self.cmd_opts.add_option(cmdoptions.constraints())
|
||||
self.cmd_opts.add_option(cmdoptions.ignored_constraints())
|
||||
self.cmd_opts.add_option(cmdoptions.no_deps())
|
||||
self.cmd_opts.add_option(cmdoptions.pre())
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ class WheelCommand(RequirementCommand):
|
|||
self.cmd_opts.add_option(cmdoptions.no_use_pep517())
|
||||
self.cmd_opts.add_option(cmdoptions.check_build_deps())
|
||||
self.cmd_opts.add_option(cmdoptions.constraints())
|
||||
self.cmd_opts.add_option(cmdoptions.ignored_constraints())
|
||||
self.cmd_opts.add_option(cmdoptions.editable())
|
||||
self.cmd_opts.add_option(cmdoptions.requirements())
|
||||
self.cmd_opts.add_option(cmdoptions.src())
|
||||
|
|
|
@ -84,6 +84,8 @@ class PipProvider(_ProviderBase):
|
|||
:params upgrade_strategy: The user-specified upgrade strategy.
|
||||
:params user_requested: A set of canonicalized package names that the user
|
||||
supplied for pip to install/upgrade.
|
||||
:params ignored_constraints: A list of canonicalized package names that the
|
||||
user has asked us to ignore constraints for.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
|
@ -93,12 +95,14 @@ class PipProvider(_ProviderBase):
|
|||
ignore_dependencies: bool,
|
||||
upgrade_strategy: str,
|
||||
user_requested: Dict[str, int],
|
||||
ignored_constraints: Sequence[str],
|
||||
) -> None:
|
||||
self._factory = factory
|
||||
self._constraints = constraints
|
||||
self._ignore_dependencies = ignore_dependencies
|
||||
self._upgrade_strategy = upgrade_strategy
|
||||
self._user_requested = user_requested
|
||||
self._ignored_constraints = ignored_constraints
|
||||
self._known_depths: Dict[str, float] = collections.defaultdict(lambda: math.inf)
|
||||
|
||||
def identify(self, requirement_or_candidate: Union[Requirement, Candidate]) -> str:
|
||||
|
@ -223,11 +227,15 @@ class PipProvider(_ProviderBase):
|
|||
return user_order is not None
|
||||
return False
|
||||
|
||||
constraint = _get_with_identifier(
|
||||
self._constraints,
|
||||
identifier,
|
||||
default=Constraint.empty(),
|
||||
)
|
||||
if identifier not in self._ignored_constraints:
|
||||
constraint = _get_with_identifier(
|
||||
self._constraints,
|
||||
identifier,
|
||||
default=Constraint.empty(),
|
||||
)
|
||||
else:
|
||||
constraint = Constraint.empty()
|
||||
|
||||
return self._factory.find_candidates(
|
||||
identifier=identifier,
|
||||
requirements=requirements,
|
||||
|
|
|
@ -2,7 +2,7 @@ import contextlib
|
|||
import functools
|
||||
import logging
|
||||
import os
|
||||
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple, cast
|
||||
from typing import TYPE_CHECKING, Dict, List, Optional, Sequence, Set, Tuple, cast
|
||||
|
||||
from pip._vendor.packaging.utils import canonicalize_name
|
||||
from pip._vendor.resolvelib import BaseReporter, ResolutionImpossible
|
||||
|
@ -50,6 +50,7 @@ class Resolver(BaseResolver):
|
|||
ignore_requires_python: bool,
|
||||
force_reinstall: bool,
|
||||
upgrade_strategy: str,
|
||||
ignored_constraints: Sequence[str],
|
||||
py_version_info: Optional[Tuple[int, ...]] = None,
|
||||
):
|
||||
super().__init__()
|
||||
|
@ -68,6 +69,7 @@ class Resolver(BaseResolver):
|
|||
)
|
||||
self.ignore_dependencies = ignore_dependencies
|
||||
self.upgrade_strategy = upgrade_strategy
|
||||
self.ignored_constraints = ignored_constraints
|
||||
self._result: Optional[Result] = None
|
||||
|
||||
def resolve(
|
||||
|
@ -80,6 +82,7 @@ class Resolver(BaseResolver):
|
|||
ignore_dependencies=self.ignore_dependencies,
|
||||
upgrade_strategy=self.upgrade_strategy,
|
||||
user_requested=collected.user_requested,
|
||||
ignored_constraints=self.ignored_constraints,
|
||||
)
|
||||
if "PIP_RESOLVER_DEBUG" in os.environ:
|
||||
reporter: BaseReporter = PipDebuggingReporter()
|
||||
|
|
|
@ -681,6 +681,26 @@ def test_new_resolver_constraints(
|
|||
script.assert_not_installed("constraint_only")
|
||||
|
||||
|
||||
def test_new_resolver_constraint_ignored(script: PipTestEnvironment) -> None:
|
||||
"We can ignore constraints. Useful when hacking on a constrained package."
|
||||
create_basic_wheel_for_package(script, "pkg", "1.1.dev1")
|
||||
constraints_file = script.scratch_path / "constraints.txt"
|
||||
constraints_file.write_text("pkg==1.0")
|
||||
script.pip(
|
||||
"install",
|
||||
"--no-cache-dir",
|
||||
"--no-index",
|
||||
"--find-links",
|
||||
script.scratch_path,
|
||||
"-c",
|
||||
constraints_file,
|
||||
"--ignore-constraint",
|
||||
"pkg",
|
||||
"pkg",
|
||||
)
|
||||
script.assert_installed(pkg="1.1.dev1")
|
||||
|
||||
|
||||
def test_new_resolver_constraint_no_specifier(script: PipTestEnvironment) -> None:
|
||||
"It's allowed (but useless...) for a constraint to have no specifier"
|
||||
create_basic_wheel_for_package(script, "pkg", "1.0")
|
||||
|
|
|
@ -75,4 +75,5 @@ def provider(factory: Factory) -> Iterator[PipProvider]:
|
|||
ignore_dependencies=False,
|
||||
upgrade_strategy="to-satisfy-only",
|
||||
user_requested={},
|
||||
ignored_constraints=[],
|
||||
)
|
||||
|
|
|
@ -36,6 +36,7 @@ def test_provider_known_depths(factory: Factory) -> None:
|
|||
ignore_dependencies=False,
|
||||
upgrade_strategy="to-satisfy-only",
|
||||
user_requested={root_requirement_name: 0},
|
||||
ignored_constraints=[],
|
||||
)
|
||||
|
||||
root_requirement_information = build_requirement_information(
|
||||
|
|
|
@ -29,6 +29,7 @@ def resolver(preparer: RequirementPreparer, finder: PackageFinder) -> Resolver:
|
|||
ignore_requires_python=False,
|
||||
force_reinstall=False,
|
||||
upgrade_strategy="to-satisfy-only",
|
||||
ignored_constraints=[],
|
||||
)
|
||||
return resolver
|
||||
|
||||
|
|
Loading…
Reference in New Issue