diff --git a/src/pip/_internal/req/req_install.py b/src/pip/_internal/req/req_install.py index acf9045847b..52c8deb1952 100644 --- a/src/pip/_internal/req/req_install.py +++ b/src/pip/_internal/req/req_install.py @@ -254,6 +254,13 @@ def match_markers(self, extras_requested: Optional[Iterable[str]] = None) -> boo else: return True + @property + def has_ignore_dependencies(self) -> bool: + if isinstance(self.comes_from, InstallRequirement): + return self.comes_from.ignore_dependencies + else: + return self.ignore_dependencies + @property def has_hash_options(self) -> bool: """Return whether any known-good hashes are specified as options. diff --git a/src/pip/_internal/resolution/resolvelib/candidates.py b/src/pip/_internal/resolution/resolvelib/candidates.py index f96ffc5d25a..40cb7a80337 100644 --- a/src/pip/_internal/resolution/resolvelib/candidates.py +++ b/src/pip/_internal/resolution/resolvelib/candidates.py @@ -37,6 +37,16 @@ REQUIRES_PYTHON_IDENTIFIER = cast(NormalizedName, "") +def has_ignore_dependencies(candidate: Candidate) -> bool: + ireq = candidate.get_install_requirement() + if ireq: + return ireq.has_ignore_dependencies + elif isinstance(candidate, AlreadyInstalledCandidate): + return candidate._ireq.has_ignore_dependencies + else: + return False + + def as_base_candidate(candidate: Candidate) -> Optional[BaseCandidate]: """The runtime version of BaseCandidate.""" base_candidate_classes = ( diff --git a/src/pip/_internal/resolution/resolvelib/provider.py b/src/pip/_internal/resolution/resolvelib/provider.py index b0302473819..a52f54a1c6e 100644 --- a/src/pip/_internal/resolution/resolvelib/provider.py +++ b/src/pip/_internal/resolution/resolvelib/provider.py @@ -13,10 +13,8 @@ from pip._vendor.resolvelib.providers import AbstractProvider -from pip._internal.req import InstallRequirement - from .base import Candidate, Constraint, Requirement -from .candidates import REQUIRES_PYTHON_IDENTIFIER, AlreadyInstalledCandidate +from .candidates import REQUIRES_PYTHON_IDENTIFIER, has_ignore_dependencies from .factory import Factory if TYPE_CHECKING: @@ -235,15 +233,9 @@ def is_satisfied_by(self, requirement: Requirement, candidate: Candidate) -> boo return requirement.is_satisfied_by(candidate) def get_dependencies(self, candidate: Candidate) -> Sequence[Requirement]: - ireq = candidate.get_install_requirement() - with_requires = not self._ignore_dependencies - if ireq and with_requires: - if ireq.comes_from and isinstance(ireq.comes_from, InstallRequirement): - with_requires = not ireq.comes_from.ignore_dependencies - else: - with_requires = not ireq.ignore_dependencies - elif isinstance(candidate, AlreadyInstalledCandidate): - with_requires = not candidate._ireq.ignore_dependencies + with_requires = not ( + self._ignore_dependencies or has_ignore_dependencies(candidate) + ) return [r for r in candidate.iter_dependencies(with_requires) if r is not None] @staticmethod diff --git a/tests/functional/test_install_reqs.py b/tests/functional/test_install_reqs.py index a7f2f46be94..943c8a25b33 100644 --- a/tests/functional/test_install_reqs.py +++ b/tests/functional/test_install_reqs.py @@ -816,3 +816,23 @@ def test_location_related_install_option_fails(script: PipTestEnvironment) -> No expect_error=True, ) assert "['--home'] from simple" in result.stderr + + +def test_install_options_no_deps(script: PipTestEnvironment) -> None: + create_basic_wheel_for_package(script, "A", "0.1.0", depends=["B==0.1.0"]) + create_basic_wheel_for_package(script, "B", "0.1.0") + + requirements_txt = script.scratch_path / "requirements.txt" + requirements_txt.write_text("A --no-deps") + + script.pip( + "install", + "--no-cache-dir", + "--find-links", + script.scratch_path, + "-r", + requirements_txt, + "--only-binary=:all:", + ) + script.assert_installed(A="0.1.0") + script.assert_not_installed("B")