Skip to content

Commit fee8777

Browse files
committed
Reapply "Fix transitive subpackage dependency resolution (conda#5603)" (conda#5647)
This reverts commit 19251f4.
1 parent 19251f4 commit fee8777

File tree

4 files changed

+49
-13
lines changed

4 files changed

+49
-13
lines changed

conda_build/build.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2440,7 +2440,7 @@ def build(
24402440
exclude_pattern = re.compile(
24412441
r"|".join(rf"(?:^{exc}(?:\s|$|\Z))" for exc in excludes)
24422442
)
2443-
add_upstream_pins(m, False, exclude_pattern)
2443+
add_upstream_pins(m, False, exclude_pattern, [])
24442444

24452445
create_build_envs(top_level_pkg, notest)
24462446

conda_build/render.py

+48-5
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ def get_env_dependencies(
130130
exclude_pattern=None,
131131
permit_unsatisfiable_variants=False,
132132
merge_build_host_on_same_platform=True,
133+
extra_specs=None,
133134
):
134135
specs = m.get_depends_top_and_out(env)
135136
# replace x.x with our variant's numpy version, or else conda tries to literally go get x.x
@@ -148,6 +149,8 @@ def get_env_dependencies(
148149
)
149150

150151
dependencies = set(dependencies)
152+
if extra_specs:
153+
dependencies |= set(extra_specs)
151154
unsat = None
152155
random_string = "".join(
153156
random.choice(string.ascii_uppercase + string.digits) for _ in range(10)
@@ -183,7 +186,7 @@ def get_env_dependencies(
183186
specs = [package_record_to_requirement(prec) for prec in precs]
184187
return (
185188
utils.ensure_list(
186-
(specs + subpackages + pass_through_deps)
189+
(specs + subpackages + pass_through_deps + (extra_specs or []))
187190
or m.get_value(f"requirements/{env}", [])
188191
),
189192
precs,
@@ -441,13 +444,15 @@ def _read_upstream_pin_files(
441444
env,
442445
permit_unsatisfiable_variants,
443446
exclude_pattern,
447+
extra_specs,
444448
):
445449
deps, precs, unsat = get_env_dependencies(
446450
m,
447451
env,
448452
m.config.variant,
449453
exclude_pattern,
450454
permit_unsatisfiable_variants=permit_unsatisfiable_variants,
455+
extra_specs=extra_specs,
451456
)
452457
# extend host deps with strong build run exports. This is important for things like
453458
# vc feature activation to work correctly in the host env.
@@ -459,12 +464,18 @@ def _read_upstream_pin_files(
459464
)
460465

461466

462-
def add_upstream_pins(m: MetaData, permit_unsatisfiable_variants, exclude_pattern):
467+
def add_upstream_pins(
468+
m: MetaData, permit_unsatisfiable_variants, exclude_pattern, extra_specs
469+
):
463470
"""Applies run_exports from any build deps to host and run sections"""
464471
# if we have host deps, they're more important than the build deps.
465472
requirements = m.get_section("requirements")
466473
build_deps, build_unsat, extra_run_specs_from_build = _read_upstream_pin_files(
467-
m, "build", permit_unsatisfiable_variants, exclude_pattern
474+
m,
475+
"build",
476+
permit_unsatisfiable_variants,
477+
exclude_pattern,
478+
[] if m.is_cross else extra_specs,
468479
)
469480

470481
# is there a 'host' section?
@@ -490,7 +501,7 @@ def add_upstream_pins(m: MetaData, permit_unsatisfiable_variants, exclude_patter
490501
host_reqs.extend(extra_run_specs_from_build.get("strong", []))
491502

492503
host_deps, host_unsat, extra_run_specs_from_host = _read_upstream_pin_files(
493-
m, "host", permit_unsatisfiable_variants, exclude_pattern
504+
m, "host", permit_unsatisfiable_variants, exclude_pattern, extra_specs
494505
)
495506
if m.noarch or m.noarch_python:
496507
extra_run_specs = set(extra_run_specs_from_host.get("noarch", []))
@@ -647,9 +658,40 @@ def finalize_metadata(
647658
utils.insert_variant_versions(requirements, m.config.variant, "build")
648659
utils.insert_variant_versions(requirements, m.config.variant, "host")
649660

661+
host_requirements = requirements.get("host" if m.is_cross else "build", [])
662+
host_requirement_names = [req.split(" ")[0] for req in host_requirements]
663+
extra_specs = []
664+
if output and output_excludes and not is_top_level and host_requirement_names:
665+
reqs = {}
666+
667+
# we first make a mapping of output -> requirements
668+
for (name, _), (_, other_meta) in m.other_outputs.items():
669+
if name == m.name():
670+
continue
671+
other_meta_reqs = other_meta.meta.get("requirements", {}).get("run", [])
672+
reqs[name] = set(other_meta_reqs)
673+
674+
seen = set()
675+
# for each subpackage that is a dependency we add its dependencies
676+
# and transitive dependencies if the dependency of the subpackage
677+
# is a subpackage.
678+
to_process = set(
679+
name for (name, _) in m.other_outputs if name in host_requirement_names
680+
)
681+
while to_process:
682+
name = to_process.pop()
683+
if name == m.name():
684+
continue
685+
for req in reqs[name]:
686+
req_name = req.split(" ")[0]
687+
if req_name not in reqs:
688+
extra_specs.append(req)
689+
elif req_name not in seen:
690+
to_process.add(req_name)
691+
650692
m = parent_metadata.get_output_metadata(m.get_rendered_output(m.name()))
651693
build_unsat, host_unsat = add_upstream_pins(
652-
m, permit_unsatisfiable_variants, exclude_pattern
694+
m, permit_unsatisfiable_variants, exclude_pattern, extra_specs
653695
)
654696
# getting this AFTER add_upstream_pins is important, because that function adds deps
655697
# to the metadata.
@@ -677,6 +719,7 @@ def finalize_metadata(
677719
m.config.variant,
678720
exclude_pattern=exclude_pattern,
679721
permit_unsatisfiable_variants=permit_unsatisfiable_variants,
722+
extra_specs=extra_specs,
680723
)
681724
full_build_dep_versions = {
682725
dep.split()[0]: " ".join(dep.split()[1:]) for dep in full_build_deps

tests/test_api_build.py

-4
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,6 @@ def test_recipe_builds(
137137
pytest.xfail("Issue related to #3754 on conda-build.")
138138
elif recipe.name == "unicode_all_over" and context.solver == "libmamba":
139139
pytest.xfail("Unicode package names not supported in libmamba.")
140-
elif recipe.name == "transitive_subpackage":
141-
pytest.xfail(
142-
"Added as part of #5603, reverted in #5647. Fix needs to be reworked."
143-
)
144140

145141
# These variables are defined solely for testing purposes,
146142
# so they can be checked within build scripts

tests/test_api_render.py

-3
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,6 @@ def test_pin_compatible_semver(testing_config):
122122
assert "zlib >=1.2.11,<2.0a0" in metadata.get_value("requirements/run")
123123

124124

125-
@pytest.mark.xfail(
126-
reason="Added as part of #5603, reverted in #5647. Fix needs to be reworked."
127-
)
128125
def test_transitive_subpackage_dependency(testing_config):
129126
recipe_dir = os.path.join(metadata_dir, "transitive_subpackage")
130127
metadata = api.render(recipe_dir, config=testing_config)[1][0]

0 commit comments

Comments
 (0)