o
    iYG                     @  s(  d dl mZ d dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
Z
d dlZd dlZddlmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z" edddedddd	Z#d
d Z$ddddZ%G dd deZ&ej'dddd<ddZ(ej'dddd=ddZ(d>dddd?ddZ(ej'ddddd@d#d$Z)ej'dd%dAd'd$Z)ej'dddddBd)d$Z)ej'ddd*dCd+d$Z)dddddddd,d-d$Z)ej'dd%dAd.d/Z*ej'ddddd@d0d/Z*ddddddd1d2d/Z*ddd3d4d5Z+d6d7 Z,d8d9 Z-dDd:d;Z.dS )E    )annotationsN   )IDENTITY
NO_DEFAULTExtractorErrorLazyListdeprecation_warningget_elements_html_by_classget_elements_html_by_attributeget_elements_by_attributeget_element_by_classget_element_html_by_attributeget_element_by_attributeget_element_html_by_idget_element_by_idget_element_html_by_classget_elements_by_class get_element_text_and_html_by_tagis_iterable_liketry_callurl_or_nonevariadicTF)defaultexpected_typeget_all	casesenseis_user_inputtraverse_stringc                  s
  |t urtd dd ttrfdd
nfdd
 	fdddd	 
fd
dfdd t|dD ]9\}}	|t|k}
z | |	|
d}|dur^|W   S W qC ty| } z|
rrt|j|j	ddW Y d}~qCd}~ww t u rdS S )a  
    Safely traverse nested `dict`s and `Iterable`s

    >>> obj = [{}, {"key": "value"}]
    >>> traverse_obj(obj, (1, "key"))
    'value'

    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`, `Iterable`, `re.Match`,
    `xml.etree.ElementTree` (xpath) and `http.cookies.Morsel`.
    Unhelpful values (`{}`, `None`) are treated as the absence of a value and discarded.

    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.
        - `set`:            Requires the only item in the set to be a type or function,
                            like `{type}`/`{type, type, ...}`/`{func}`. If a `type`, return only
                            values of this type. If a function, returns `func(obj)`.
        - `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.
                            Read as: `[traverse_obj(obj, branch) for branch in branches]`.
        - `function`:       Branch out and return values filtered by the function.
                            Read as: `[value for key, value in obj if function(key, value)]`.
                            For `Iterable`s, `key` is the index of the value.
                            For `re.Match`es, `key` is the group number (0 = full match)
                            as well as additionally any group names, if given.
        - `dict`:           Transform the current object and return a matching dict.
                            Read as: `{key: traverse_obj(obj, path) for key, path in dct.items()}`.
        - `any`-builtin:    Take the first matching object and return it, resetting branching.
        - `all`-builtin:    Take all matching objects and return them as a list, resetting branching.
        - `filter`-builtin: Return the value if it is truthy, `None` otherwise.

        `tuple`, `list`, and `dict` all support nested paths and branches.

    @params paths           Paths by which to traverse.
    @param default          Value to return if the paths do not match.
                            If the last key in the path is a `dict`, it will apply to each value inside
                            the dict instead, depth first. Try to avoid if using nested `dict` keys.
    @param expected_type    If a `type`, only accept final values of this type.
                            If any other callable, try to call the function on each result.
                            If the last key in the path is a `dict`, it will apply to each value inside
                            the dict instead, recursively. This does respect branching paths.
    @param get_all          If `False`, return the first matching result, otherwise all matching ones.
    @param casesense        If `False`, consider string dictionary keys as case insensitive.

    `traverse_string` is only meant to be used by YoutubeDL.prepare_outtmpl and is not part of the API

    @param traverse_string  Whether to traverse into objects as strings.
                            If `True`, any non-compatible object will first be
                            converted into a string and then traversed into.
                            The return value of that path will be a string instead,
                            not respecting any further branching.


    @returns                The result of the object traversal.
                            If successful, `get_all=True`, and the path branches at least once,
                            then a list of results is returned instead.
                            If no `default` is given and the last path branches, a `list` of results
                            is always returned. If a path ends on a `dict` that result will always be a `dict`.
    z=The is_user_input parameter is deprecated and no longer worksc                 S  s   t | tr	|  S | S N)
isinstancestrcasefold)k r#   J/home/ubuntu/.local/lib/python3.10/site-packages/yt_dlp/utils/traversal.py<lambda>l   s    ztraverse_obj.<locals>.<lambda>c                   s   t |  r| S d S r   )r   valr   r#   r$   r%   o       c                   s   t  pt| fdS )Nargs)r   r   r&   r(   r#   r$   r%   q   r)   c           
        s  d}d }d u r	rdu st sttrd}d}ned u r%}n]ttrZtt}tdks;t|trQtdd D sFJ tt	rO}n1t
|fd}n(ttt	frtd}tj fd	dD }ndu rd}ttjjrtjjd
ttjjr }ntsttjjjr}nttjr  }nψ	rd}t!}nd}nt r2d}ttjjrtjjd
ttjjr" }n;tsttjjjrt#}n*ttjrtt#$ g  R % " }n	rd}t#t!}nd}fdd|D }|s0d&|}nPttrS fdd" D }fdd|D pPd }n/ttjjrttjjrltjjd
sxt
j'fdrt
j(fdntfdd" D d }nttjrtt)srt*+t, $}W d    n	1 sw   Y  ntt!rtfdd% " D d }ntt)tfr)ttjj-tjjjfr	tt}t*+t,  }W d    n	1 sw   Y  ny	r(t*+t, t! }W d    n	1 s#w   Y  nYttjjjrtt!r.d\}}/dsP0dsP}d |/dr\d| }n|rj|/dsjd| }fdd}	|r~tt1|	2|}n|	}||r|fS |ffS )NF.Tr#   r   c                 s  s    | ]}t |tV  qd S r   )r   type.0itemr#   r#   r$   	<genexpr>   s    z2traverse_obj.<locals>.apply_key.<locals>.<genexpr>r*   c                 3  s     | ]} |d  V  qdS )r   Nr#   )r.   branch)
apply_pathis_lastobjr#   r$   r0      s    
)keyvaluec                 3  s(    | ]\}}t  ||fd r|V  qdS )r*   N)r   r.   r"   vr5   r#   r$   r0      s   &  c                 3  s&    | ]\}}| |d fV  qdS )FNr#   r7   )_traverse_objr3   r4   r#   r$   r0      s   $ c                   s2   i | ]\}}|d us t ur||d ur|n qS r   )r   r7   )r   r#   r$   
<dictcomp>   s
    z3traverse_obj.<locals>.apply_key.<locals>.<dictcomp>c                 3  $    | ]\}} |kr|V  qd S r   r#   r7   r!   r5   r#   r$   r0         " c                 3  r=   r   r#   r7   r>   r#   r$   r0      r?   /@z().z./c                   sZ    d u r| S  dkr| j S  drt| j j dd  fdS  dkr&| jS td )NrA   r   r*   ztext()z#apply_specials is missing case for )attrib
startswithr   gettextSyntaxError)element)specialr#   r$   apply_specials   s   
z7traverse_obj.<locals>.apply_key.<locals>.apply_specials)3callabler   slicesetnextiterlenr,   alltupler   list	itertoolschainfrom_iterablehttpcookiesMorseldictr5   r6   collectionsabcMappingvaluesr   xmletreeElementTreeElementreMatchgroupsr    items	enumerategroup	groupdictjoin__contains__rE   int
contextlibsuppress
IndexErrorSequence
rpartitionrD   endswithmapiterfind)
r5   r4   r3   	branchingresultr/   iter_objxpath_rJ   )r;   r2   r!   r   r   r   )r3   r5   r4   rI   r$   	apply_keys   s   






("


ztraverse_obj.<locals>.apply_keyc                 s  sF    t | }t|t}|tu rd S |D ]	}d|fV  |}qd|fV  d S )NFT)rO   rN   r   )iterableiteratorprevr/   r#   r#   r$   	lazy_last   s   

ztraverse_obj.<locals>.lazy_lastc                   s  | f}d}d }t |ttttfD ]d\}}s!t|tr!| }|ttfv rAd}dd |D }|tu r;t	|d f}nt
|f}q|tu rKtd |}qt|rXt|d d  g }|D ]}	 ||	|\}
}||
O }|| q\tj|}q|rt|tt
tfst|}||t|tfS )NFc                 s       | ]}|d i fvr|V  qd S r   r#   )r.   r4   r#   r#   r$   r0         z3traverse_obj.<locals>.apply_path.<locals>.<genexpr>)r   r    bytesrZ   rM   r   r!   anyrQ   rN   rS   filterrK   inspect	signaturebindappendrT   rU   rV   rR   rs   )	start_objpath	test_typeobjshas_branchedr5   lastfiltered_objsnew_objsr4   ru   results)rz   r   r~   	type_testr#   r$   r2      s6   


z traverse_obj.<locals>.apply_pathc                   sl    | ||\}}}t dd |D }r(|r(|r| S |r&tu r$g S S d S |r.|d S |r4|r4i S d S )Nc                 s  r   r   r#   r-   r#   r#   r$   r0   $  r   z6traverse_obj.<locals>._traverse_obj.<locals>.<genexpr>r   )r   exhaustr   )r4   r   allow_emptyr   r   r   is_dict)r2   r   r   r#   r$   r;   "  s   z#traverse_obj.<locals>._traverse_objr   TNexpected)
r   r   r   r,   rg   rP   _RequiredErrorr   orig_msgr   )r4   r   r   r   r   r   r   pathsindexr   r3   rv   er#   )r;   rz   r2   r!   r   r   r   r   r~   r   r   r$   traverse_obj&   s0   C
|'
r   c                  s    fddS )Nc                   s    S r   r#   )ry   r6   r#   r$   r%   =  s    zvalue.<locals>.<lambda>r#   r   r#   r   r$   r6   <  s   r6   r   c                     fdd}|S )Nc                   s   | d u rt d  d| S )NzUnable to extract r   )r   r   r   namer#   r$   funcA  s   zrequire.<locals>.funcr#   )r   r   r   r#   r   r$   require@  s   r   c                   @  s   e Zd ZdS )r   N)__name__
__module____qualname__r#   r#   r#   r$   r   J  s    r   undlangextr   
str | Noner   return=collections.abc.Callable[[list[dict]], dict[str, list[dict]]]c                 C     d S r   r#   r   r#   r#   r$   subs_list_to_dictN     r   subslist[dict] | Nonedict[str, list[dict]]c               C  r   r   r#   )r   r   r   r#   r#   r$   r   R  r   c               C  s   | du rt jt||dS tt}| D ]=}t|ds"|ds"q|dd}t	|t
s2|s0q|}|d}t	|t
sI|sE|dd n||d< || | qt|}| D ]
} | jdd d	 qY|S )
ax  
    Convert subtitles from a traversal into a subtitle dict.
    The path should have an `all` immediately before this function.

    Arguments:
    `ext`      The default value for `ext` in the subtitle dict

    In the dict you can set the following additional items:
    `id`       The subtitle id to sort the dict into
    `quality`  The sort order for each subtitle
    Nr   urldataidr   c                 S  s   |  ddpdS )Nqualityr   )pop)xr#   r#   r$   r%   y  s    z#subs_list_to_dict.<locals>.<lambda>r9   )	functoolspartialr   r[   defaultdictrS   r   rE   r   r   r    r   rZ   r^   sort)r   r   r   rv   subsub_idsub_extr#   r#   r$   r   V  s*   



taghtmlregexattrr    r   c                 C  r   r   r#   r   r6   r   r   r   r#   r#   r$   find_element~  r   r   r   clsc                 C  r   r   r#   r   r   r#   r#   r$   r     r   r   c                 C  r   r   r#   )r   r   r   r   r#   r#   r$   r     r   )r   r   c                 C  r   r   r#   r   r#   r#   r$   r     r   )r   r   r   r   r6   r   r   c           	        s   s|s|s|r
|sJ dd}|r3|r3|rJ d|r J d|r$t nt}tj|||p.|| dS |rU|r;J dd u sCJ d|rIJ d|rMtnt}t||S |ri|r[tnt}tj||pd|| dS tt	|  fd	d
S )Nz3One of tag, id, cls or (attr AND value) is required[\w:.-]+Cannot match both attr and clszCannot match both attr and idr   escape_valuezCannot match both cls and idCannot match both cls and tagCannot use regex with clsc                   s   t |   S r   )r   r   r   r   r#   r$   r%     s    zfind_element.<locals>.<lambda>)
r   r   r   r   r   r   r   r   rl   bool)	r   r   r   r   r6   r   r   ANY_TAGr   r#   r   r$   r     s$   c                 C  r   r   r#   r   r#   r#   r$   find_elements  r   r   c                 C  r   r   r#   r   r#   r#   r$   r     r   )r   r   r   r6   r   r   c                 C  s~   |s
|r|s
J d|r'|r'|rJ d|rt nt}tj|||| p"d| dS | r-J d|r3J d|r7tnt}t||S )Nz*One of cls or (attr AND value) is requiredr   r   r   r   r   )r
   r   r   r   r	   r   )r   r   r   r6   r   r   r   r#   r#   r$   r     s   )startendc                   r   )Nc                   sR   | d u rd S d}r|  rt} r#|  r#| |t   S | |d  S )Nr   )rD   rP   rr   )s	start_idxr   r   r#   r$   trim  s   ztrim_str.<locals>.trimr#   )r   r   r   r#   r   r$   trim_str  s   
r   c                   s   t   fdd}|S )Nc                   s    | i S r   r#   )rf   r   kwargsr#   r$   inner  s   zunpack.<locals>.inner)r   wraps)r   r   r   r#   r   r$   unpack  s   r   c                 O  s(   t | gdd |D R i |ddiS )Nc                 s  s     | ]}d gt |R V  qdS ).N)r   )r.   keysr#   r#   r$   r0     r   zget_first.<locals>.<genexpr>r   F)r   )r4   r   r   r#   r#   r$   	get_first  s   (r   c                 C  s2   t | jt|D ]}|d ur|s|s|  S q|S r   )rs   rE   r   )dkey_or_keysr   skip_false_valuesr'   r#   r#   r$   dict_get  s
   r   )r   r   r   r   r   r   )r   r   r   r   r   r   r   r   r   )r   r   )r   r    r6   r    r   r   )r   r    )r   r    r   r   )r   r    )NT)/
__future__r   r[   collections.abcrm   r   http.cookiesrW   r   rT   rc   typingxml.etree.ElementTreer_   _utilsr   r   r   r   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r6   r   r   overloadr   r   r   r   r   r   r   r#   r#   r#   r$   <module>   sV    X  
(