From f7dd4ed84fd996cb8d9f113a9817b878e9dd773e Mon Sep 17 00:00:00 2001 From: danpetry Date: Thu, 2 Nov 2023 13:57:57 -0500 Subject: [PATCH] Avoid clobbering variants from higher priority cbc.yaml (#5039) * Add record of previously checked config entries, to avoid clobbering by lower priority entries. * Add test for clobbering. --------- Co-authored-by: Ken Odegard Co-authored-by: Jean-Christophe Morin <38703886+JeanChristopheMorinPerso@users.noreply.github.com> --- conda_build/variants.py | 7 ++++- news/5039-dont-clobber-multiple-config | 19 ++++++++++++ tests/test_variants.py | 43 ++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 news/5039-dont-clobber-multiple-config diff --git a/conda_build/variants.py b/conda_build/variants.py index d7c6841238..319ace7fea 100644 --- a/conda_build/variants.py +++ b/conda_build/variants.py @@ -679,9 +679,13 @@ def filter_combined_spec_to_used_keys(combined_spec, specs): # TODO: act here? combined_spec = explode_variants(combined_spec) + # seen_keys makes sure that a setting from a lower-priority spec doesn't clobber + # the same setting that has been redefined in a higher-priority spec. + seen_keys = set() + # The specs are checked from high to low priority order. for source, source_specs in reversed(specs.items()): for k, vs in source_specs.items(): - if k not in extend_keys: + if k not in extend_keys and k not in seen_keys: # when filtering ends up killing off all variants, we just ignore that. Generally, # this arises when a later variant config overrides, rather than selects a # subspace of earlier configs @@ -689,6 +693,7 @@ def filter_combined_spec_to_used_keys(combined_spec, specs): filter_by_key_value(combined_spec, k, vs, source_name=source) or combined_spec ) + seen_keys.add(k) return combined_spec diff --git a/news/5039-dont-clobber-multiple-config b/news/5039-dont-clobber-multiple-config new file mode 100644 index 0000000000..630868093d --- /dev/null +++ b/news/5039-dont-clobber-multiple-config @@ -0,0 +1,19 @@ +### Enhancements + +* + +### Bug fixes + +* Avoid clobbering of variants in high priority cbc.yaml entries when they aren't present in lower priority cbc.yamls. (#5039) + +### Deprecations + +* + +### Docs + +* + +### Other + +* diff --git a/tests/test_variants.py b/tests/test_variants.py index 3e7ba621a5..819f39d793 100644 --- a/tests/test_variants.py +++ b/tests/test_variants.py @@ -16,6 +16,7 @@ from conda_build.variants import ( combine_specs, dict_of_lists_to_list_of_dicts, + filter_combined_spec_to_used_keys, get_package_variants, validate_spec, ) @@ -657,3 +658,45 @@ def test_variant_subkeys_retained(): m.final = False outputs = m.get_output_metadata_set(permit_unsatisfiable_variants=False) get_all_replacements(outputs[0][1].config.variant) + + +@pytest.mark.parametrize( + "internal_defaults, low_prio_config, high_prio_config, expected", + [ + pytest.param( + {"pkg_1": "1.0"}, + {"pkg_1": "1.1"}, + {"pkg_1": ["1.1", "1.2"], "pkg_2": ["1.1"]}, + [{"pkg_1": "1.1", "pkg_2": "1.1"}, {"pkg_1": "1.2", "pkg_2": "1.1"}], + id="basic", + ), + pytest.param( + {"pkg_1": "1.0"}, + {"pkg_1": "1.1"}, + { + "pkg_1": ["1.1", "1.2"], + "pkg_2": ["1.1", "1.2"], + "zip_keys": [["pkg_1", "pkg_2"]], + }, + [ + {"pkg_1": "1.1", "pkg_2": "1.1", "zip_keys": [["pkg_1", "pkg_2"]]}, + {"pkg_1": "1.2", "pkg_2": "1.2", "zip_keys": [["pkg_1", "pkg_2"]]}, + ], + id="zip_keys", + ), + ], +) +def test_zip_key_filtering( + internal_defaults, low_prio_config, high_prio_config, expected +): + combined_spec = { + **low_prio_config, + **high_prio_config, + } + specs = { + "internal_defaults": internal_defaults, + "low_prio_config": low_prio_config, + "high_prio_config": high_prio_config, + } + + assert filter_combined_spec_to_used_keys(combined_spec, specs=specs) == expected