@@ -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+
37793856def test_solver_discards_packages_with_empty_markers (
37803857 package : ProjectPackage ,
37813858 repo : Repository ,
0 commit comments