@@ -4322,3 +4322,91 @@ def test_update_with_use_latest_vs_lock(
4322
4322
{"job" : "install" , "package" : package_a1 },
4323
4323
],
4324
4324
)
4325
+
4326
+
4327
+ @pytest .mark .parametrize ("with_extra" , [False , True ])
4328
+ def test_solver_resolves_duplicate_dependency_in_extra (
4329
+ package : ProjectPackage ,
4330
+ pool : RepositoryPool ,
4331
+ repo : Repository ,
4332
+ io : NullIO ,
4333
+ with_extra : bool ,
4334
+ ) -> None :
4335
+ """
4336
+ Without extras, a newer version of B can be chosen than with extras.
4337
+ See https://github.com/python-poetry/poetry/issues/8380.
4338
+ """
4339
+ constraint : dict [str , Any ] = {"version" : "*" }
4340
+ if with_extra :
4341
+ constraint ["extras" ] = ["foo" ]
4342
+ package .add_dependency (Factory .create_dependency ("A" , constraint ))
4343
+
4344
+ package_a = get_package ("A" , "1.0" )
4345
+ package_b1 = get_package ("B" , "1.0" )
4346
+ package_b2 = get_package ("B" , "2.0" )
4347
+
4348
+ dep = get_dependency ("B" , ">=1.0" )
4349
+ package_a .add_dependency (dep )
4350
+
4351
+ dep_extra = get_dependency ("B" , "^1.0" , optional = True )
4352
+ dep_extra .marker = parse_marker ("extra == 'foo'" )
4353
+ package_a .extras = {canonicalize_name ("foo" ): [dep_extra ]}
4354
+ package_a .add_dependency (dep_extra )
4355
+
4356
+ repo .add_package (package_a )
4357
+ repo .add_package (package_b1 )
4358
+ repo .add_package (package_b2 )
4359
+
4360
+ solver = Solver (package , pool , [], [], io )
4361
+ transaction = solver .solve ()
4362
+
4363
+ check_solver_result (
4364
+ transaction ,
4365
+ (
4366
+ [
4367
+ {"job" : "install" , "package" : package_b1 if with_extra else package_b2 },
4368
+ {"job" : "install" , "package" : package_a },
4369
+ ]
4370
+ ),
4371
+ )
4372
+
4373
+
4374
+ def test_solver_resolves_duplicate_dependencies_with_restricted_extras (
4375
+ package : ProjectPackage ,
4376
+ pool : RepositoryPool ,
4377
+ repo : Repository ,
4378
+ io : NullIO ,
4379
+ ) -> None :
4380
+ package .add_dependency (
4381
+ Factory .create_dependency ("A" , {"version" : "*" , "extras" : ["foo" ]})
4382
+ )
4383
+
4384
+ package_a = get_package ("A" , "1.0" )
4385
+ package_b1 = get_package ("B" , "1.0" )
4386
+ package_b2 = get_package ("B" , "2.0" )
4387
+
4388
+ dep1 = get_dependency ("B" , "^1.0" , optional = True )
4389
+ dep1 .marker = parse_marker ("sys_platform == 'win32' and extra == 'foo'" )
4390
+ dep2 = get_dependency ("B" , "^2.0" , optional = True )
4391
+ dep2 .marker = parse_marker ("sys_platform == 'linux' and extra == 'foo'" )
4392
+ package_a .extras = {canonicalize_name ("foo" ): [dep1 , dep2 ]}
4393
+ package_a .add_dependency (dep1 )
4394
+ package_a .add_dependency (dep2 )
4395
+
4396
+ repo .add_package (package_a )
4397
+ repo .add_package (package_b1 )
4398
+ repo .add_package (package_b2 )
4399
+
4400
+ solver = Solver (package , pool , [], [], io )
4401
+ transaction = solver .solve ()
4402
+
4403
+ check_solver_result (
4404
+ transaction ,
4405
+ (
4406
+ [
4407
+ {"job" : "install" , "package" : package_b1 },
4408
+ {"job" : "install" , "package" : package_b2 },
4409
+ {"job" : "install" , "package" : package_a },
4410
+ ]
4411
+ ),
4412
+ )
0 commit comments