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:
# An example of this is:
# - pypiwin32 (220); 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:
if dep.complete_name not in duplicates:
duplicates[dep.complete_name] = []
duplicates[dep.complete_name].append(dep)
key = (
dep.complete_name,
dep.source_type,
dep.source_url,
dep.source_reference,
)
if key not in duplicates:
duplicates[key] = []
duplicates[key].append(dep)
dependencies = []
for dep_name, deps in duplicates.items():
for key, deps in duplicates.items():
if len(deps) == 1:
dependencies.append(deps[0])
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>")
deps = self._merge_dependencies_by_marker(deps)
......
......@@ -14,6 +14,7 @@ from poetry.core.packages.vcs_dependency import VCSDependency
from poetry.core.version.markers import parse_marker
from poetry.factory import Factory
from poetry.packages import DependencyPackage
from poetry.puzzle import Solver
from poetry.puzzle.exceptions import SolverProblemError
from poetry.puzzle.provider import Provider as BaseProvider
......@@ -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(
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