aboutsummaryrefslogtreecommitdiffstats
path: root/yt_dlp/utils.py
diff options
context:
space:
mode:
authorSimon Sawicki <37424085+Grub4K@users.noreply.github.com>2022-10-09 03:31:37 +0200
committerGitHub <noreply@github.com>2022-10-09 07:01:37 +0530
commit7b0127e1e11186bcbb80a18b1b530d864a5dbada (patch)
tree6fe4dad7c3a043249291c428fdc8cf47567d8280 /yt_dlp/utils.py
parentf99bbfc9838d98d81027dddb18ace0af66acdf6d (diff)
downloadhypervideo-pre-7b0127e1e11186bcbb80a18b1b530d864a5dbada.tar.lz
hypervideo-pre-7b0127e1e11186bcbb80a18b1b530d864a5dbada.tar.xz
hypervideo-pre-7b0127e1e11186bcbb80a18b1b530d864a5dbada.zip
[utils] `traverse_obj`: Allow `re.Match` objects (#5174)
Authored by: Grub4K
Diffstat (limited to 'yt_dlp/utils.py')
-rw-r--r--yt_dlp/utils.py22
1 files changed, 19 insertions, 3 deletions
diff --git a/yt_dlp/utils.py b/yt_dlp/utils.py
index 7d8e97162..cb14908c7 100644
--- a/yt_dlp/utils.py
+++ b/yt_dlp/utils.py
@@ -5305,13 +5305,14 @@ def traverse_obj(
Each of the provided `paths` is tested and the first producing a valid result will be returned.
The next path will also be tested if the path branched but no results could be found.
+ Supported values for traversal are `Mapping`, `Sequence` and `re.Match`.
A value of None is treated as the absence of a value.
The paths will be wrapped in `variadic`, so that `'key'` is conveniently the same as `('key', )`.
The keys in the path can be one of:
- `None`: Return the current object.
- - `str`/`int`: Return `obj[key]`.
+ - `str`/`int`: Return `obj[key]`. For `re.Match, return `obj.group(key)`.
- `slice`: Branch out and return all values in `obj[key]`.
- `Ellipsis`: Branch out and return a list of all values.
- `tuple`/`list`: Branch out and return a list of all matching values.
@@ -5322,7 +5323,7 @@ def traverse_obj(
- `dict` Transform the current object and return a matching dict.
Read as: `{key: traverse_obj(obj, path) for key, path in dct.items()}`.
- `tuple`, `list`, and `dict` all support nested paths and branches
+ `tuple`, `list`, and `dict` all support nested paths and branches.
@params paths Paths which to traverse by.
@param default Value to return if the paths do not match.
@@ -5370,6 +5371,8 @@ def traverse_obj(
yield from obj.values()
elif is_sequence(obj):
yield from obj
+ elif isinstance(obj, re.Match):
+ yield from obj.groups()
elif traverse_string:
yield from str(obj)
@@ -5378,6 +5381,8 @@ def traverse_obj(
iter_obj = enumerate(obj)
elif isinstance(obj, collections.abc.Mapping):
iter_obj = obj.items()
+ elif isinstance(obj, re.Match):
+ iter_obj = enumerate((obj.group(), *obj.groups()))
elif traverse_string:
iter_obj = enumerate(str(obj))
else:
@@ -5389,10 +5394,21 @@ def traverse_obj(
yield {k: v if v is not None else default for k, v in iter_obj
if v is not None or default is not NO_DEFAULT}
- elif isinstance(obj, dict):
+ elif isinstance(obj, collections.abc.Mapping):
yield (obj.get(key) if casesense or (key in obj)
else next((v for k, v in obj.items() if casefold(k) == key), None))
+ elif isinstance(obj, re.Match):
+ if isinstance(key, int) or casesense:
+ with contextlib.suppress(IndexError):
+ yield obj.group(key)
+ return
+
+ if not isinstance(key, str):
+ return
+
+ yield next((v for k, v in obj.groupdict().items() if casefold(k) == key), None)
+
else:
if is_user_input:
key = (int_or_none(key) if ':' not in key