Commit b7acf884 by Arun Babu Neelicattu

provider: do not merge deps from different sources

This change ensures that the provider is less eager when merging
duplicate dependencies for a package. In particular, takes into
consideration source type, url and reference if available.
parent f9e7f0d1
...@@ -550,19 +550,33 @@ class Provider: ...@@ -550,19 +550,33 @@ class Provider:
# An example of this is: # An example of this is:
# - pypiwin32 (220); sys_platform == "win32" and python_version >= "3.6" # - pypiwin32 (220); sys_platform == "win32" and python_version >= "3.6"
# - pypiwin32 (219); sys_platform == "win32" and python_version < "3.6" # - pypiwin32 (219); sys_platform == "win32" and python_version < "3.6"
duplicates: dict[str, list[Dependency]] = {} #
# Additional care has to be taken to ensure that hidden constraints like that
# of source type, reference etc. are taking into consideration when duplicates
# are identified.
duplicates: dict[
tuple[str, str | None, str | None, str | None], list[Dependency]
] = {}
for dep in dependencies: for dep in dependencies:
if dep.complete_name not in duplicates: key = (
duplicates[dep.complete_name] = [] dep.complete_name,
dep.source_type,
duplicates[dep.complete_name].append(dep) dep.source_url,
dep.source_reference,
)
if key not in duplicates:
duplicates[key] = []
duplicates[key].append(dep)
dependencies = [] dependencies = []
for dep_name, deps in duplicates.items(): for key, deps in duplicates.items():
if len(deps) == 1: if len(deps) == 1:
dependencies.append(deps[0]) dependencies.append(deps[0])
continue continue
extra_keys = ", ".join(k for k in key[1:] if k is not None)
dep_name = f"{key[0]} ({extra_keys})" if extra_keys else key[0]
self.debug(f"<debug>Duplicate dependencies for {dep_name}</debug>") self.debug(f"<debug>Duplicate dependencies for {dep_name}</debug>")
deps = self._merge_dependencies_by_marker(deps) deps = self._merge_dependencies_by_marker(deps)
......
...@@ -14,6 +14,7 @@ from poetry.core.packages.vcs_dependency import VCSDependency ...@@ -14,6 +14,7 @@ from poetry.core.packages.vcs_dependency import VCSDependency
from poetry.core.version.markers import parse_marker from poetry.core.version.markers import parse_marker
from poetry.factory import Factory from poetry.factory import Factory
from poetry.packages import DependencyPackage
from poetry.puzzle import Solver from poetry.puzzle import Solver
from poetry.puzzle.exceptions import SolverProblemError from poetry.puzzle.exceptions import SolverProblemError
from poetry.puzzle.provider import Provider as BaseProvider from poetry.puzzle.provider import Provider as BaseProvider
...@@ -1337,6 +1338,67 @@ def test_solver_duplicate_dependencies_different_constraints_merge_by_marker( ...@@ -1337,6 +1338,67 @@ def test_solver_duplicate_dependencies_different_constraints_merge_by_marker(
) )
def test_solver_duplicate_dependencies_different_sources_types_are_preserved(
solver: Solver, repo: Repository, package: Package
):
pendulum = get_package("pendulum", "2.0.3")
repo.add_package(pendulum)
repo.add_package(get_package("cleo", "1.0.0"))
repo.add_package(get_package("demo", "0.1.0"))
dependency_pypi = Factory.create_dependency("demo", ">=0.1.0")
dependency_git = Factory.create_dependency(
"demo", {"git": "https://github.com/demo/demo.git"}, groups=["dev"]
)
package.add_dependency(dependency_git)
package.add_dependency(dependency_pypi)
demo = Package(
"demo",
"0.1.2",
source_type="git",
source_url="https://github.com/demo/demo.git",
source_reference=DEFAULT_SOURCE_REF,
source_resolved_reference="9cf87a285a2d3fbb0b9fa621997b3acc3631ed24",
)
transaction = solver.solve()
ops = check_solver_result(
transaction,
[{"job": "install", "package": pendulum}, {"job": "install", "package": demo}],
)
op = ops[1]
assert op.package.source_type == demo.source_type
assert op.package.source_reference == DEFAULT_SOURCE_REF
assert op.package.source_resolved_reference.startswith(
demo.source_resolved_reference
)
complete_package = solver.provider.complete_package(
DependencyPackage(package.to_dependency(), package)
)
assert len(complete_package.all_requires) == 2
pypi, git = complete_package.all_requires
assert isinstance(pypi, Dependency)
assert pypi == dependency_pypi
assert isinstance(git, VCSDependency)
assert git.constraint
assert git.constraint != dependency_git.constraint
assert (git.name, git.source_type, git.source_url, git.source_reference) == (
dependency_git.name,
dependency_git.source_type,
dependency_git.source_url,
DEFAULT_SOURCE_REF,
)
def test_solver_duplicate_dependencies_different_constraints_merge_no_markers( def test_solver_duplicate_dependencies_different_constraints_merge_no_markers(
solver: Solver, repo: Repository, package: Package solver: Solver, repo: Repository, package: Package
): ):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment