a
    hYG                     @  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dddZ(ej'ddddddddddZ(d;dddddddZ(ej'dddddddd d!d"Z)ej'dd#dd$d%d"Z)ej'ddddddd&d'd"Z)ej'ddd(dd)d*d"Z)dddddddd+d,d"Z)ej'dd#dd$d-d.Z*ej'dddddddd d/d.Z*ddddddd0d1d.Z*ddd2d3d4Z+d5d6 Z,d7d8 Z-d<d9d:Z.dS )=    )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r0fdd
nfdd
 	fdddd	 
fd
dfdd t|dD ]t\}}	|t|k}
z$ | |	|
d}|dur|W   S W q ty } z"|
rt|j|j	ddW Y d}~qd}~0 0 qt u r
d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#   K/mnt/pikpak/tmp/myenv/lib/python3.9/site-packages/yt_dlp/utils/traversal.py<lambda>l       ztraverse_obj.<locals>.<lambda>c                   s   t |  r| S d S r   )r   valr   r#   r$   r%   o   r&   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r6d}d}nڈd u rJ}nttrtt}tdksvt|trtdd D sJ tt	r}nt
|fd}nbttt	frd}tj fd	dD }n.du rd}ttjjrtjjd
ttjjr0 }nRtsLttjjjrR}n0ttjrj  }n	r~d}t!}nd}nt rpd}ttjjrtjjd
ttjjrЈ" }nztsttjjjrt#}nTttjr.tt#$ g  R % " }n	rFd}t#t!}nd}fdd|D }|sd&|}nttr fdd" D }fdd|D pd }nbttjjr.ttjjrtjjd
st
j'fdrt
j(fdntfdd" D d }nttjrtt)sNrt*+t, $}W d    n1 sz0    Y  n.tt!rtfdd% " D d }n\tt)tfrbttjj-tjjjfr"tt}t*+t,  }W d    n1 s0    Y  n>	rt*+t, t! }W d    n1 sV0    Y  nttjjjrtt!r.d\}}/ds0ds}d |/drd| }n|r|/dsd| }fdd}	|rtt1|	2|}n|	}||r |n|ffS )NF.Tr#   r   c                 s  s   | ]}t |tV  qd S r   )r   type.0itemr#   r#   r$   	<genexpr>   r&   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      r&    c                 3  s$   | ]\}}| |d fV  qdS )FNr#   r7   )_traverse_objr3   r4   r#   r$   r0      r&   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  s"   | ]\}} |kr|V  qd S r   r#   r7   r!   r5   r#   r$   r0      r&   c                 3  s"   | ]\}} |kr|V  qd S r   r#   r7   r=   r#   r$   r0      r&   /@z().z./c                   s^    d u r| S  dkr| j S  dr>t| j j dd  fdS  dkrL| jS td d S )Nr?   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__rC   int
contextlibsuppress
IndexErrorSequence
rpartitionrB   endswithmapiterfind)
r5   r4   r3   	branchingresultr/   Ziter_objZxpath_rH   )r;   r2   r!   r   r   r   )r3   r5   r4   rG   r$   	apply_keys   s    









(,&
*.
ztraverse_obj.<locals>.apply_keyc                 s  sD   t | }t|t}|tu rd S |D ]}d|fV  |}q"d|fV  d S )NFT)rM   rL   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 ]\}}sBt|trB| }|ttfv rd}dd |D }|tu rvt	|d f}q$t
|f}q$|tu rtd |}q$t|rt|d d  g }|D ]&}	 ||	|\}
}||
O }|| qtj|}q$|rt|tt
tfst|}||t|tfS )NFc                 s  s   | ]}|d i fvr|V  qd S r   r#   )r.   r4   r#   r#   r$   r0     r&   z3traverse_obj.<locals>.apply_path.<locals>.<genexpr>T)r   r    bytesrX   rK   r   r!   anyrO   rL   rQ   filterrI   inspect	signaturebindappendrR   rS   rT   rP   rq   )Z	start_objpath	test_typeobjshas_branchedr5   lastZfiltered_objsZnew_objsr4   rs   results)rv   r   rz   	type_testr#   r$   r2      s6    


z traverse_obj.<locals>.apply_pathc                   sl    | ||\}}}t dd |D }rP|rP|r8| S |rLtu rHg S S d S |r\|d S |rh|rhi S d S )Nc                 s  s   | ]}|d i fvr|V  qd S r   r#   r-   r#   r#   r$   r0   $  r&   z6traverse_obj.<locals>._traverse_obj.<locals>.<genexpr>r   )r   Zexhaustr   )r4   r   Zallow_emptyr   r   r   Zis_dict)r2   r   r   r#   r$   r;   "  s    z#traverse_obj.<locals>._traverse_objr   TNexpected)
r   r   r   r,   re   rN   _RequiredErrorr   Zorig_msgr   )r4   r   r   r   r   r   r   pathsindexr   r3   rt   er#   )r;   rv   r2   r!   r   r   r   r   rz   r   r   r$   traverse_obj&   s(    C
|'*r   c                  s    fddS )Nc                   s    S r   r#   )ru   r6   r#   r$   r%   =  r&   zvalue.<locals>.<lambda>r#   r   r#   r   r$   r6   <  s    r6   r   c                 s    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   Zundlangextz
str | Nonez=collections.abc.Callable[[list[dict]], dict[str, list[dict]]])r   r   returnc                 C  s   d S r   r#   r   r#   r#   r$   subs_list_to_dictN  s    r   zlist[dict] | Nonezdict[str, list[dict]])subsr   r   r   c               C  s   d S r   r#   )r   r   r   r#   r#   r$   r   R  s    )r   c               C  s   | du rt jt||dS tt}| D ]z}t|dsD|dsDq&|dd}t	|t
sd|s`q&|}|d}t	|t
s|s|dd n||d< || | q&t|}| D ]} | jdd d	 q|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 )NZqualityr   )pop)xr#   r#   r$   r%   y  r&   z#subs_list_to_dict.<locals>.<lambda>r9   )	functoolspartialr   rY   defaultdictrQ   r   rC   r   r   r    r   rX   r\   sort)r   r   r   rt   subZsub_idZsub_extr#   r#   r$   r   V  s*    



taghtmlregexr    )attrr6   r   c                 C  s   d S r   r#   r   r6   r   r   r   r#   r#   r$   find_element~  s    r   r   )clsc                 C  s   d S r   r#   r   r   r#   r#   r$   r     s    )r   r   c                 C  s   d S r   r#   )r   r   r   r   r#   r#   r$   r     s    )r   r   )r   c                 C  s   d S r   r#   r   r#   r#   r$   r     s    )r   r   r   r   r6   r   r   c           	        s   s|s|s|r|sJ dd}|rf|rf|r4J d|r@J d|rHt nt}tj|||p\|| dS |r|rvJ dd u sJ d|rJ d|rtnt}t||S |r|rtnt}tj||p|| 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   Z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%     r&   zfind_element.<locals>.<lambda>)
r   r   r   r   r   r   r   r   rj   bool)	r   r   r   r   r6   r   r   ZANY_TAGr   r#   r   r$   r     s$    c                 C  s   d S r   r#   r   r#   r#   r$   find_elements  s    r   c                 C  s   d S r   r#   r   r#   r#   r$   r     s    )r   r   r   r6   r   r   c                 C  s~   |s|r|sJ d|rN|rN|r(J d|r0t nt}tj|||| pDd| dS | rZJ d|rfJ d|rnt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                   s    fdd}|S )Nc                   sR   | d u rd S d}r&|  r&t} rF|  rF| |t   S | |d  S )Nr   )rB   rN   rp   )sZ	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#   )rd   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   )rq   rC   r   )dZkey_or_keysr   Zskip_false_valuesr(   r#   r#   r$   dict_get  s    
r   )N)NT)/
__future__r   rY   collections.abcrk   r   http.cookiesrU   r~   rR   ra   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>   sT   X  
(