From cb9366eda584fde2421140adf994eadc5bb6b943 Mon Sep 17 00:00:00 2001 From: dirkf Date: Wed, 3 May 2023 10:54:52 +0100 Subject: [PATCH] [utils] Minor updates (merge_dicts, T) A couple of mods to ease yt-dlp back-ports: * add kwargs to merge_dicts: `unblank=True` (disallow empty string), `rev=False` (reverse the merge list) * add `T(x)` shortcut for `{x}`, unsupported in Py2.6 --- youtube_dl/utils.py | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index b05f65283..0cbbec0f3 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -4269,7 +4269,8 @@ def variadic(x, allowed_types=NO_DEFAULT): def dict_get(d, key_or_keys, default=None, skip_false_values=True): exp = (lambda x: x or None) if skip_false_values else IDENTITY - return traverse_obj(d, *variadic(key_or_keys), expected_type=exp, default=default) + return traverse_obj(d, *variadic(key_or_keys), expected_type=exp, + default=default, get_all=False) def try_call(*funcs, **kwargs): @@ -4302,16 +4303,38 @@ def try_get(src, getter, expected_type=None): return v -def merge_dicts(*dicts): +def merge_dicts(*dicts, **kwargs): + """ + Merge the `dict`s in `dicts` using the first valid value for each key. + Normally valid: not None and not an empty string + + Keyword-only args: + unblank: allow empty string if False (default True) + rev: merge dicts in reverse order (default False) + + merge_dicts(dct1, dct2, ..., unblank=False, rev=True) + matches {**dct1, **dct2, ...} + + However, merge_dicts(dct1, dct2, ..., rev=True) may often be better. + """ + + unblank = kwargs.get('unblank', True) + rev = kwargs.get('rev', False) + + if unblank: + def can_merge_str(k, v, to_dict): + return (isinstance(v, compat_str) and v + and isinstance(to_dict[k], compat_str) + and not to_dict[k]) + else: + can_merge_str = lambda k, v, to_dict: False + merged = {} - for a_dict in dicts: + for a_dict in reversed(dicts) if rev else dicts: for k, v in a_dict.items(): if v is None: continue - if (k not in merged - or (isinstance(v, compat_str) and v - and isinstance(merged[k], compat_str) - and not merged[k])): + if (k not in merged) or can_merge_str(k, v, merged): merged[k] = v return merged