[BUGFIX] Fix nested parents with multiple parents (#255)
This commit is contained in:
parent
06dffdb763
commit
4b6add06e1
2 changed files with 53 additions and 33 deletions
|
|
@ -277,46 +277,60 @@ class Preset(StrictDictValidator):
|
|||
for validator_value in validator.dict.values():
|
||||
self.__validate_override_string_formatter_validator(validator_value)
|
||||
|
||||
def _get_presets_to_merge(
|
||||
self, parent_presets: str | List[str], seen_presets: List[str], config: ConfigFile
|
||||
) -> List[Dict]:
|
||||
presets_to_merge: List[Dict] = []
|
||||
|
||||
if isinstance(parent_presets, str):
|
||||
parent_presets = [parent_presets]
|
||||
|
||||
for parent_preset in reversed(parent_presets):
|
||||
# Make sure we do not hit an infinite loop
|
||||
if parent_preset in seen_presets:
|
||||
raise self._validation_exception(
|
||||
f"preset loop detected with the preset '{parent_preset}'"
|
||||
)
|
||||
|
||||
# Make sure the parent preset actually exists
|
||||
if parent_preset not in config.presets.keys:
|
||||
raise self._validation_exception(
|
||||
f"preset '{parent_preset}' does not exist in the provided config. "
|
||||
f"Available presets: {', '.join(config.presets.keys)}"
|
||||
)
|
||||
|
||||
parent_preset_dict = copy.deepcopy(config.presets.dict[parent_preset])
|
||||
presets_to_merge.append(parent_preset_dict)
|
||||
|
||||
if "preset" in parent_preset_dict:
|
||||
presets_to_merge.extend(
|
||||
self._get_presets_to_merge(
|
||||
parent_presets=parent_preset_dict["preset"],
|
||||
seen_presets=seen_presets + [parent_preset],
|
||||
config=config,
|
||||
)
|
||||
)
|
||||
|
||||
return presets_to_merge
|
||||
|
||||
def __merge_parent_preset_dicts_if_present(self, config: ConfigFile):
|
||||
parent_preset_validator = self._validate_key_if_present(
|
||||
key="preset", validator=StringListValidator
|
||||
)
|
||||
|
||||
if parent_preset_validator is None:
|
||||
return
|
||||
|
||||
presets_to_merge: List[Dict] = []
|
||||
for parent_preset in [preset.value for preset in parent_preset_validator.list]:
|
||||
sub_parent_presets: Dict[str, Dict] = {}
|
||||
|
||||
while parent_preset:
|
||||
# Make sure the parent preset actually exists
|
||||
if parent_preset not in config.presets.keys:
|
||||
raise self._validation_exception(
|
||||
f"preset '{parent_preset}' does not exist in the provided config. "
|
||||
f"Available presets: {', '.join(config.presets.keys)}"
|
||||
)
|
||||
|
||||
# Make sure we do not hit an infinite loop
|
||||
if parent_preset in sub_parent_presets:
|
||||
raise self._validation_exception(
|
||||
f"preset loop detected with the preset '{parent_preset}'"
|
||||
)
|
||||
|
||||
parent_preset_dict = copy.deepcopy(config.presets.dict[parent_preset])
|
||||
|
||||
sub_parent_presets[parent_preset] = parent_preset_dict
|
||||
parent_preset = parent_preset_dict.get("preset")
|
||||
|
||||
# Extend reversed, so top-most parents are first
|
||||
if sub_parent_presets:
|
||||
presets_to_merge.extend(reversed(sub_parent_presets.values()))
|
||||
|
||||
# Append this preset (the subscription) last
|
||||
presets_to_merge.append(copy.deepcopy(self._value))
|
||||
# Get list of all parent presets in depth-first search order, beginning with this preset
|
||||
presets_to_merge: List[Dict] = [copy.deepcopy(self._value)] + self._get_presets_to_merge(
|
||||
parent_presets=[preset.value for preset in parent_preset_validator.list],
|
||||
seen_presets=[],
|
||||
config=config,
|
||||
)
|
||||
|
||||
# Merge all presets
|
||||
self._value = mergedeep.merge({}, *presets_to_merge, strategy=mergedeep.Strategy.ADDITIVE)
|
||||
self._value = mergedeep.merge(
|
||||
{}, *reversed(presets_to_merge), strategy=mergedeep.Strategy.ADDITIVE
|
||||
)
|
||||
|
||||
def __init__(self, config: ConfigFile, name: str, value: Any):
|
||||
super().__init__(name=name, value=value)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ def config_file() -> ConfigFile:
|
|||
"tags": {"key-2": "preset_2", "key-3": "preset_2"},
|
||||
}
|
||||
},
|
||||
"parent_preset_3": {"preset": ["parent_preset_1", "parent_preset_2"]},
|
||||
"preset_self_loop": {"preset": "preset_self_loop"},
|
||||
"preset_loop_0": {"preset": "preset_loop_1"},
|
||||
"preset_loop_1": {"preset": "preset_loop_0"},
|
||||
|
|
@ -113,12 +114,17 @@ class TestPreset:
|
|||
|
||||
assert tags_string_dict == {"key-1": "preset_0", "key-2": "this-preset"}
|
||||
|
||||
def test_preset_multiple_parents(self, config_file, output_options, youtube_video):
|
||||
@pytest.mark.parametrize(
|
||||
"preset_value", [["parent_preset_1", "parent_preset_2"], "parent_preset_3"]
|
||||
)
|
||||
def test_preset_multiple_parents(
|
||||
self, config_file, output_options, youtube_video, preset_value
|
||||
):
|
||||
preset = Preset(
|
||||
config=config_file,
|
||||
name="test",
|
||||
value={
|
||||
"preset": ["parent_preset_1", "parent_preset_2"],
|
||||
"preset": preset_value,
|
||||
"youtube": youtube_video,
|
||||
"output_options": output_options,
|
||||
"nfo_tags": {"tags": {"key-3": "this-preset"}},
|
||||
|
|
|
|||
Loading…
Reference in a new issue