Skip to content

Commit b0b4a39

Browse files
abnfinswimmer
authored andcommitted
provider: ensure ony activated extras are used
Resolves: #3022
1 parent e200a28 commit b0b4a39

File tree

2 files changed

+164
-7
lines changed

2 files changed

+164
-7
lines changed

Diff for: poetry/puzzle/provider.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ def complete_package(
432432
self._pool.package(
433433
package.name,
434434
package.version.text,
435-
extras=package.dependency.extras,
435+
extras=list(package.dependency.extras),
436436
repository=package.dependency.source_name,
437437
),
438438
)
@@ -478,12 +478,12 @@ def complete_package(
478478
if self._env and not dep.marker.validate(self._env.marker_env):
479479
continue
480480

481-
if (
482-
dep.is_optional()
483-
and dep.name not in optional_dependencies
484-
and not package.is_root()
485-
):
486-
continue
481+
if not package.is_root():
482+
if (dep.is_optional() and dep.name not in optional_dependencies) or (
483+
dep.in_extras
484+
and not set(dep.in_extras).intersection(package.dependency.extras)
485+
):
486+
continue
487487

488488
_dependencies.append(dep)
489489

Diff for: tests/puzzle/test_solver.py

+157
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,163 @@ def test_solver_returns_extras_if_requested(solver, repo, package):
449449
assert ops[0].package.marker.is_any()
450450

451451

452+
@pytest.mark.parametrize(("enabled_extra",), [("one",), ("two",), (None,)])
453+
def test_solver_returns_extras_only_requested(solver, repo, package, enabled_extra):
454+
extras = [enabled_extra] if enabled_extra is not None else []
455+
456+
package.add_dependency(Factory.create_dependency("A", "*"))
457+
package.add_dependency(
458+
Factory.create_dependency("B", {"version": "*", "extras": extras})
459+
)
460+
461+
package_a = get_package("A", "1.0")
462+
package_b = get_package("B", "1.0")
463+
package_c10 = get_package("C", "1.0")
464+
package_c20 = get_package("C", "2.0")
465+
466+
dep10 = get_dependency("C", "1.0", optional=True)
467+
dep10._in_extras.append("one")
468+
dep10.marker = parse_marker("extra == 'one'")
469+
470+
dep20 = get_dependency("C", "2.0", optional=True)
471+
dep20._in_extras.append("two")
472+
dep20.marker = parse_marker("extra == 'two'")
473+
474+
package_b.extras = {"one": [dep10], "two": [dep20]}
475+
476+
package_b.requires.append(dep10)
477+
package_b.requires.append(dep20)
478+
479+
repo.add_package(package_a)
480+
repo.add_package(package_b)
481+
repo.add_package(package_c10)
482+
repo.add_package(package_c20)
483+
484+
ops = solver.solve()
485+
486+
expected = [
487+
{"job": "install", "package": package_a},
488+
{"job": "install", "package": package_b},
489+
]
490+
491+
if enabled_extra is not None:
492+
expected.insert(
493+
0,
494+
{
495+
"job": "install",
496+
"package": package_c10 if enabled_extra == "one" else package_c20,
497+
},
498+
)
499+
500+
check_solver_result(
501+
ops, expected,
502+
)
503+
504+
assert ops[-1].package.marker.is_any()
505+
assert ops[0].package.marker.is_any()
506+
507+
508+
@pytest.mark.parametrize(("enabled_extra",), [("one",), ("two",), (None,)])
509+
def test_solver_returns_extras_when_multiple_extras_use_same_dependency(
510+
solver, repo, package, enabled_extra
511+
):
512+
package.add_dependency(Factory.create_dependency("A", "*"))
513+
514+
package_a = get_package("A", "1.0")
515+
package_b = get_package("B", "1.0")
516+
package_c = get_package("C", "1.0")
517+
518+
dep = get_dependency("C", "*", optional=True)
519+
dep._in_extras.append("one")
520+
dep._in_extras.append("two")
521+
522+
package_b.extras = {"one": [dep], "two": [dep]}
523+
524+
package_b.requires.append(dep)
525+
526+
extras = [enabled_extra] if enabled_extra is not None else []
527+
package_a.add_dependency(
528+
Factory.create_dependency("B", {"version": "*", "extras": extras})
529+
)
530+
531+
repo.add_package(package_a)
532+
repo.add_package(package_b)
533+
repo.add_package(package_c)
534+
535+
ops = solver.solve()
536+
537+
expected = [
538+
{"job": "install", "package": package_b},
539+
{"job": "install", "package": package_a},
540+
]
541+
542+
if enabled_extra is not None:
543+
expected.insert(0, {"job": "install", "package": package_c})
544+
545+
check_solver_result(
546+
ops, expected,
547+
)
548+
549+
assert ops[-1].package.marker.is_any()
550+
assert ops[0].package.marker.is_any()
551+
552+
553+
@pytest.mark.parametrize(("enabled_extra",), [("one",), ("two",), (None,)])
554+
def test_solver_returns_extras_only_requested_nested(
555+
solver, repo, package, enabled_extra
556+
):
557+
package.add_dependency(Factory.create_dependency("A", "*"))
558+
559+
package_a = get_package("A", "1.0")
560+
package_b = get_package("B", "1.0")
561+
package_c10 = get_package("C", "1.0")
562+
package_c20 = get_package("C", "2.0")
563+
564+
dep10 = get_dependency("C", "1.0", optional=True)
565+
dep10._in_extras.append("one")
566+
dep10.marker = parse_marker("extra == 'one'")
567+
568+
dep20 = get_dependency("C", "2.0", optional=True)
569+
dep20._in_extras.append("two")
570+
dep20.marker = parse_marker("extra == 'two'")
571+
572+
package_b.extras = {"one": [dep10], "two": [dep20]}
573+
574+
package_b.requires.append(dep10)
575+
package_b.requires.append(dep20)
576+
577+
extras = [enabled_extra] if enabled_extra is not None else []
578+
package_a.add_dependency(
579+
Factory.create_dependency("B", {"version": "*", "extras": extras})
580+
)
581+
582+
repo.add_package(package_a)
583+
repo.add_package(package_b)
584+
repo.add_package(package_c10)
585+
repo.add_package(package_c20)
586+
587+
ops = solver.solve()
588+
589+
expected = [
590+
{"job": "install", "package": package_b},
591+
{"job": "install", "package": package_a},
592+
]
593+
594+
if enabled_extra is not None:
595+
expected.insert(
596+
0,
597+
{
598+
"job": "install",
599+
"package": package_c10 if enabled_extra == "one" else package_c20,
600+
},
601+
)
602+
603+
check_solver_result(ops, expected)
604+
605+
assert ops[-1].package.marker.is_any()
606+
assert ops[0].package.marker.is_any()
607+
608+
452609
def test_solver_returns_prereleases_if_requested(solver, repo, package):
453610
package.add_dependency(Factory.create_dependency("A", "*"))
454611
package.add_dependency(Factory.create_dependency("B", "*"))

0 commit comments

Comments
 (0)