mirror of
				https://github.com/yt-dlp/yt-dlp.git
				synced 2025-10-30 14:15:13 +00:00 
			
		
		
		
	[utils] traverse_obj: Allow re.Match objects (#5174)
				
					
				
			Authored by: Grub4K
This commit is contained in:
		| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Simon Sawicki
					Simon Sawicki