This commit is contained in:
Sander Van Balen 2023-06-22 14:42:05 +02:00
parent 5f8f40eb1d
commit d09431feb5
3 changed files with 35 additions and 6 deletions

View File

@ -8,10 +8,11 @@ These are meant to be used elsewhere within pip to create instances of
InstallRequirement.
"""
import copy
import logging
import os
import re
from typing import Dict, List, Optional, Set, Tuple, Union
from typing import Collection, Dict, List, Optional, Set, Tuple, Union
from pip._vendor.packaging.markers import Marker
from pip._vendor.packaging.requirements import InvalidRequirement, Requirement
@ -512,7 +513,6 @@ def install_req_without(
without_extras: bool = False,
without_specifier: bool = False,
) -> InstallRequirement:
# TODO: clean up hack
req = Requirement(str(ireq.req))
if without_extras:
req.extras = {}
@ -535,3 +535,19 @@ def install_req_without(
user_supplied=ireq.user_supplied,
permit_editable_wheels=ireq.permit_editable_wheels,
)
def install_req_extend_extras(
ireq: InstallRequirement,
extras: Collection[str],
) -> InstallRequirement:
"""
Returns a copy of an installation requirement with some additional extras.
Makes a shallow copy of the ireq object.
"""
result = copy.copy(ireq)
req = Requirement(str(ireq.req))
req.extras.update(extras)
result.req = req
result.extras = {*ireq.extras, *extras}
return result

View File

@ -1,3 +1,4 @@
import contextlib
import functools
import logging
import os
@ -11,6 +12,7 @@ from pip._vendor.resolvelib.structs import DirectedGraph
from pip._internal.cache import WheelCache
from pip._internal.index.package_finder import PackageFinder
from pip._internal.operations.prepare import RequirementPreparer
from pip._internal.req.constructors import install_req_extend_extras
from pip._internal.req.req_install import InstallRequirement
from pip._internal.req.req_set import RequirementSet
from pip._internal.resolution.base import BaseResolver, InstallRequirementProvider
@ -19,6 +21,7 @@ from pip._internal.resolution.resolvelib.reporter import (
PipDebuggingReporter,
PipReporter,
)
from pip._internal.utils.packaging import get_requirement
from .base import Candidate, Requirement
from .factory import Factory
@ -101,9 +104,19 @@ class Resolver(BaseResolver):
raise error from e
req_set = RequirementSet(check_supported_wheels=check_supported_wheels)
for candidate in result.mapping.values():
# sort to ensure base candidates come before candidates with extras
for candidate in sorted(result.mapping.values(), key=lambda c: c.name):
ireq = candidate.get_install_requirement()
if ireq is None:
if candidate.name != candidate.project_name:
# extend existing req's extras
with contextlib.suppress(KeyError):
req = req_set.get_requirement(candidate.project_name)
req_set.add_named_requirement(
install_req_extend_extras(
req, get_requirement(candidate.name).extras
)
)
continue
# Check if there is already an installation under the same name,

View File

@ -2465,6 +2465,6 @@ def test_install_pip_prints_req_chain_pypi(script: PipTestEnvironment) -> None:
)
assert (
f"Collecting python-openid "
f"(from Paste[openid]==1.7.5.1->-r {req_path} (line 1))" in result.stdout
)
"Collecting python-openid "
f"(from Paste[openid]->Paste[openid]==1.7.5.1->-r {req_path} (line 1))"
) in result.stdout