Skip to content

Commit 0e62626

Browse files
committed
fix(solver): do not choose a (locked) package from an explicit source for a dependency that does not allow an explicit source
1 parent 7adbf4a commit 0e62626

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

src/poetry/puzzle/provider.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from poetry.packages.direct_origin import DirectOrigin
3131
from poetry.packages.package_collection import PackageCollection
3232
from poetry.puzzle.exceptions import OverrideNeededError
33+
from poetry.repositories.repository_pool import Priority
3334
from poetry.utils.helpers import get_file_hash
3435

3536

@@ -753,6 +754,14 @@ def get_locked(self, dependency: Dependency) -> DependencyPackage | None:
753754
if package.satisfies(dependency):
754755
if explicit_source := self._explicit_sources.get(dependency.name):
755756
dependency.source_name = explicit_source
757+
elif (
758+
not dependency.source_name
759+
and package.source_type == "legacy"
760+
and package.source_reference
761+
and self._pool.get_priority(package.source_reference)
762+
== Priority.EXPLICIT
763+
):
764+
continue
756765
return DependencyPackage(dependency, package)
757766
return None
758767

tests/puzzle/test_solver.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3776,6 +3776,83 @@ def test_multiple_constraints_explicit_source_transitive_locked_use_latest(
37763776
assert ops[2].package.source_reference == "explicit2"
37773777

37783778

3779+
@pytest.mark.parametrize("locked", [False, True])
3780+
def test_multiple_constraints_incomplete_explicit_source_transitive_locked(
3781+
package: ProjectPackage,
3782+
repo: Repository,
3783+
pool: RepositoryPool,
3784+
io: NullIO,
3785+
locked: bool,
3786+
) -> None:
3787+
"""
3788+
The root package depends on
3789+
* lib == 1.0+cu ; sys_platform == "linux" with source=explicit
3790+
* lib == 1.0 ; sys_platform == "darwin" with no explicit source
3791+
* other >= 1.0
3792+
"other" depends on "lib"
3793+
3794+
Since the source for lib 1.0+cu has the priority "explicit",
3795+
the default source must be chosen for lib 1.0.
3796+
Since the multiple constraints are incomplete - they are only defined for linux
3797+
and darwin, there is another hidden override that also requires lib via other.
3798+
In this hidden override lib 1.0 from the default source must be chosen
3799+
(because the other source has the priority "explicit").
3800+
"""
3801+
package.add_dependency(
3802+
Factory.create_dependency(
3803+
"lib",
3804+
{
3805+
"version": "1.0+cu",
3806+
"source": "explicit",
3807+
"markers": "sys_platform == 'linux'",
3808+
},
3809+
)
3810+
)
3811+
package.add_dependency(
3812+
Factory.create_dependency(
3813+
"lib",
3814+
{
3815+
"version": "1.0",
3816+
"markers": "sys_platform == 'darwin'",
3817+
},
3818+
)
3819+
)
3820+
package.add_dependency(Factory.create_dependency("other", {"version": ">=1.0"}))
3821+
3822+
explicit_repo = Repository("explicit")
3823+
pool.add_repository(explicit_repo, priority=Priority.EXPLICIT)
3824+
3825+
package_lib_explicit = Package(
3826+
"lib", "1.0+cu", source_type="legacy", source_reference="explicit"
3827+
)
3828+
explicit_repo.add_package(package_lib_explicit)
3829+
package_lib_default = Package("lib", "1.0")
3830+
repo.add_package(package_lib_default)
3831+
3832+
package_other = Package("other", "1.5")
3833+
package_other.add_dependency(Factory.create_dependency("lib", ">=1.0"))
3834+
repo.add_package(package_other)
3835+
3836+
if locked:
3837+
# order does not matter because packages are sorted in the provicer
3838+
# (latest first) so that the package from the explicit source is preferred
3839+
locked_packages = [package_lib_default, package_lib_explicit, package_other]
3840+
else:
3841+
locked_packages = []
3842+
solver = Solver(package, pool, [], locked_packages, io)
3843+
3844+
transaction = solver.solve()
3845+
3846+
check_solver_result(
3847+
transaction,
3848+
[
3849+
{"job": "install", "package": package_lib_default},
3850+
{"job": "install", "package": package_lib_explicit},
3851+
{"job": "install", "package": package_other},
3852+
],
3853+
)
3854+
3855+
37793856
def test_solver_discards_packages_with_empty_markers(
37803857
package: ProjectPackage,
37813858
repo: Repository,

0 commit comments

Comments
 (0)