diff --git a/src/pip/_internal/cli/req_command.py b/src/pip/_internal/cli/req_command.py index 104b033281f..deb105cac27 100644 --- a/src/pip/_internal/cli/req_command.py +++ b/src/pip/_internal/cli/req_command.py @@ -314,7 +314,7 @@ def get_requirements( parsed_req, isolated=options.isolated_mode, ) - req_to_add.is_direct = True + req_to_add.is_direct = False requirement_set.add_requirement(req_to_add) for req in args: diff --git a/src/pip/_internal/req/req_set.py b/src/pip/_internal/req/req_set.py index f168ce17abd..7d6ad182eec 100644 --- a/src/pip/_internal/req/req_set.py +++ b/src/pip/_internal/req/req_set.py @@ -110,9 +110,8 @@ def add_requirement( ) # This next bit is really a sanity check. - assert install_req.is_direct == (parent_req_name is None), ( - "a direct req shouldn't have a parent and also, " - "a non direct req should have a parent" + assert not install_req.is_direct or parent_req_name is None, ( + "a direct req shouldn't have a parent" ) # Unnamed requirements are scanned again and the requirement won't be @@ -167,6 +166,10 @@ def add_requirement( # If we're now installing a constraint, mark the existing # object for real installation. existing_req.constraint = False + # If we're now installing a top level requirement, mark the existing + # object as top level. + if install_req.is_direct: + existing_req.is_direct = True existing_req.extras = tuple(sorted( set(existing_req.extras) | set(install_req.extras) )) diff --git a/src/pip/_internal/resolution/legacy/resolver.py b/src/pip/_internal/resolution/legacy/resolver.py index cdb44d19dbe..977cb6a57f8 100644 --- a/src/pip/_internal/resolution/legacy/resolver.py +++ b/src/pip/_internal/resolution/legacy/resolver.py @@ -194,7 +194,7 @@ def _is_upgrade_allowed(self, req): return True else: assert self.upgrade_strategy == "only-if-needed" - return req.is_direct + return req.is_direct or req.constraint def _set_req_to_reinstall(self, req): # type: (InstallRequirement) -> None