@@ -3776,6 +3776,83 @@ def test_multiple_constraints_explicit_source_transitive_locked_use_latest(
3776
3776
assert ops [2 ].package .source_reference == "explicit2"
3777
3777
3778
3778
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
+
3779
3856
def test_solver_discards_packages_with_empty_markers (
3780
3857
package : ProjectPackage ,
3781
3858
repo : Repository ,
0 commit comments