o
    B a7                     @   s  d Z ddlmZ ddlmZ ddlZddlm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 edZed	Zd
ZdZdZdZdZdZdZdZdZ dZ!ej"ej#B Z$ej%ej&B Z'ej"ej#ddZ(edZ)edZ*edZ+edZ,edZ-edZ.edZ/dZ0dZ1dZ2dZ3d Z4d!Z5d"Z6G d#d$ d$Z7G d%d& d&Z8G d'd( d(Z9G d)d* d*e8Z:G d+d, d,ej;Z<e=e< dS )-zCSS matcher.    )datetime   )utilN)	css_types)IteratorIterableListAnyOptionalTupleUnionDictCallableSequencecastz[^ 	
]z	[^ 	
]+ >~+z: z:>z:~z:+zhttp://www.w3.org/1999/xhtmlz$http://www.w3.org/XML/1998/namespace)ZltrZrtlautoz0^(?P<value>-?(?:[0-9]{1,}(\.[0-9]+)?|\.[0-9]+))$z*^(?P<hour>[0-9]{2}):(?P<minutes>[0-9]{2})$z)^(?P<year>[0-9]{4,})-(?P<month>[0-9]{2})$z)^(?P<year>[0-9]{4,})-W(?P<week>[0-9]{2})$z;^(?P<year>[0-9]{4,})-(?P<month>[0-9]{2})-(?P<day>[0-9]{2})$zd^(?P<year>[0-9]{4,})-(?P<month>[0-9]{2})-(?P<day>[0-9]{2})T(?P<hour>[0-9]{2}):(?P<minutes>[0-9]{2})$z(?:(?:-\*-)(?:\*(?:-|$))*|-\*$))      	                        c                   @   s$   e Zd ZdZdddZdd	d
ZdS )_FakeParentz
    Fake parent class.

    When we have a fragment with no `BeautifulSoup` document object,
    we can't evaluate `nth` selectors properly.  Create a temporary
    fake parent so we can traverse the root element as a child.
    elementbs4.TagreturnNc                 C   s   |g| _ dS )Initialize.N)contents)selfr!    r'   5/usr/lib/python3/dist-packages/soupsieve/css_match.py__init__C      z_FakeParent.__init__bs4.PageElementc                 C   
   t | jS )zLength.)lenr%   r&   r'   r'   r(   __len__H      
z_FakeParent.__len__)r!   r"   r#   N)r#   r+   )__name__
__module____qualname____doc__r)   r/   r'   r'   r'   r(   r    :   s    
r    c                   @   s\  e Zd ZdZededdfddZedddefd	d
Z	edddefddZ
edddefddZedddefddZedddefddZedddefddZedddefddZedddefddZedddefddZedddefddZdddefdd Zdddefd!d"ZdOddd$eded fd%d&Z		#	'	#dPddd(ee d)ed*ed$eded fd+d,Z	'	#dQddd*ed$eded fd-d.ZdOddd$eddfd/d0Zedddee fd1d2Zedddee fd3d4Zedddee fd5d6Z edRddd*eddfd7d8Z!edRddd*eddfd9d:Z"edddefd;d<Z#eddd=ede$ee ee f fd>d?Z%ed@ede&ee'e f fdAdBZ(e	dSdddCedDee&ee'e f  dee&ee'e f  fdEdFZ)edddee$eee&ee'e f  f  fdGdHZ*eddde'e fdIdJZ+dOddd$edefdKdLZ,dOddd$ede-e fdMdNZ.dS )T_DocumentNavz#Navigate a Beautiful Soup document.tagr#   Nc                 C   s    |  |stdt|dS )z%Check if valid input tag or document.z<Expected a BeautifulSoup 'Tag', but instead recieved type {}N)is_tag	TypeErrorformattype)clsr6   r'   r'   r(   assert_valid_inputQ   s   
z_DocumentNav.assert_valid_inputobjr"   c                 C      t | tjS )zIs `BeautifulSoup` object.)
isinstancebs4ZBeautifulSoupr=   r'   r'   r(   is_docY   r*   z_DocumentNav.is_docr+   c                 C   r>   )zIs tag.)r?   r@   ZTagrA   r'   r'   r(   r7   ^   r*   z_DocumentNav.is_tagc                 C   r>   )zIs declaration.)r?   r@   DeclarationrA   r'   r'   r(   is_declarationc   r*   z_DocumentNav.is_declarationc                 C   r>   )z	Is CDATA.)r?   r@   CDatarA   r'   r'   r(   is_cdatah   r*   z_DocumentNav.is_cdatac                 C   r>   )zIs processing instruction.)r?   r@   ProcessingInstructionrA   r'   r'   r(   is_processing_instructionm   r*   z&_DocumentNav.is_processing_instructionc                 C   r>   )zIs navigable string.)r?   r@   ZNavigableStringrA   r'   r'   r(   is_navigable_stringr   r*   z _DocumentNav.is_navigable_stringc                 C   s   t | tjtjtjtjtjfS )zIs special string.)r?   r@   CommentrC   rE   rG   ZDoctyperA   r'   r'   r(   is_special_stringw   s   z_DocumentNav.is_special_stringc                 C   s   |  |o
| | S )z Check if node is content string.)rI   rK   )r;   r=   r'   r'   r(   is_content_string|   s   z_DocumentNav.is_content_stringelc                 C   s   t | S )z'Create fake parent for a given element.)r    rM   r'   r'   r(   create_fake_parent      z_DocumentNav.create_fake_parentc                 C   r,   )z2Check if element (or document) is from a XML tree.)bool_is_xmlrN   r'   r'   r(   is_xml_tree   s   
z_DocumentNav.is_xml_treec                 C   s.   t | |r	|jnt|jdko| |S )z Check if element is an `iframe`.iframe)rQ   rS   namer   loweris_html_tagr&   rM   r'   r'   r(   	is_iframe   s    z_DocumentNav.is_iframec                 C   s:   | j o| j |u }|s| |}|duo| jo| |}|S )z
        Return whether element is a root element.

        We check that the element is the root of the tree (which we have already pre-calculated),
        and we check if it is the root element under an `iframe`.
        N)root
get_parentis_htmlrY   )r&   rM   rZ   parentr'   r'   r(   is_root   s
   
z_DocumentNav.is_rootF	no_iframec                 c   s*    |r|  |s|jD ]}|V  qdS dS )z$Get contents or contents in reverse.N)rY   r%   )r&   rM   r_   contentr'   r'   r(   get_contents   s   
z_DocumentNav.get_contentsTstartreversetagsc                 c   s    |r|  |sTt|jd }|du r|r|nd}n|}|r dn|d }|r(dnd}	d|  kr4|krVn dS ||krX|j| }
||	7 }|rK| |
rN|
V  ||ks;dS dS dS dS )zGet children.r   Nr   )rY   r-   r%   r7   )r&   rM   rb   rc   rd   r_   lastindexendZincrnoder'   r'   r(   get_children   s$   

	z_DocumentNav.get_childrenc                 c   s    |r|  |s^d}|jD ]R}|dur||urqd}| |}|rV|rV|  |rV|jdur1|j}n|}| |rH|jrH|jd }| |rH|js;|j}|V  |du rU dS q|rZ|r]|V  qdS dS )zGet descendants.Nre   )rY   Zdescendantsr7   next_siblingr%   Znext_element)r&   rM   rd   r_   Z	next_goodchildr7   Z
last_childr'   r'   r(   get_descendants   s4   



z_DocumentNav.get_descendantsc                 C   s$   |j }|r|dur| |rd}|S )zGet parent.N)r]   rY   )r&   rM   r_   r]   r'   r'   r(   r[      s   z_DocumentNav.get_parentc                 C      t tt | jS )Get tag.)r   r
   strrU   rN   r'   r'   r(   get_tag_name      z_DocumentNav.get_tag_namec                 C   rn   )Get prefix.)r   r
   rp   prefixrN   r'   r'   r(   get_prefix_name   rr   z_DocumentNav.get_prefix_namec                 C   rn   )zGet namespace `URI`.)r   r
   rp   	namespacerN   r'   r'   r(   get_uri   rr   z_DocumentNav.get_uric                 C   <   |j }|r| |s|dur|j }|r| |s|dus|S )zGet next sibling tag.N)rk   r7   r;   rM   rd   siblingr'   r'   r(   get_next  
   z_DocumentNav.get_nextc                 C   rx   )zGet previous sibling tag.N)Zprevious_siblingr7   ry   r'   r'   r(   get_previous  r|   z_DocumentNav.get_previousc                 C   s"   | rt | dnd}t|o|tkS )z
        Check if element has an HTML namespace.

        This is a bit different than whether a element is treated as having an HTML namespace,
        like we do in the case of `is_html_tag`.
        rv   N)getattrrQ   NS_XHTML)rM   nsr'   r'   r(   has_html_ns  s   	z_DocumentNav.has_html_ns	attr_namec                 C   s   t |ddt |ddfS )z7Return namespace and attribute name without the prefix.rv   NrU   )r~   )rM   r   r'   r'   r(   split_namespace      z_DocumentNav.split_namespacevaluec                 C   s   |du rdS t |tr|S t |tr|dS t |trDg }|D ]!}t |ttfs6t |tr6|t| q |tt| | q |S t|S )z6Normalize the value to be a string or list of strings.N utf8)r?   rp   bytesdecoder   appendr   normalize_value)r;   r   Z	new_valuevr'   r'   r(   r   &  s   



z_DocumentNav.normalize_valuerU   defaultc                 C   sl   |}|j rz| |j| }W |S  ty   Y |S w |j D ]\}}t||kr3| |} |S q |S )zGet attribute by name.)rR   r   attrsKeyErroritemsr   rV   )r;   rM   rU   r   r   kr   r'   r'   r(   get_attribute_by_nameG  s    	
z"_DocumentNav.get_attribute_by_namec                 c   s*    |j  D ]\}}|| |fV  qdS )zIterate attributes.N)r   r   r   )r;   rM   r   r   r'   r'   r(   iter_attributes]  s   z_DocumentNav.iter_attributesc                 C   s0   |  |dg }t|trt|}ttt |S )zGet classes.class)r   r?   rp   	RE_NOT_WSfindallr   r   )r;   rM   classesr'   r'   r(   get_classesd  s   

z_DocumentNav.get_classesc                    s$   d  fdd j|d|dD S )z	Get text.r   c                       g | ]	}  |r|qS r'   rL   .0ri   r.   r'   r(   
<listcomp>q      z)_DocumentNav.get_text.<locals>.<listcomp>F)rd   r_   )joinrm   r&   rM   r_   r'   r.   r(   get_textm  s   z_DocumentNav.get_textc                    s    fdd j ||dD S )zGet Own Text.c                    r   r'   r   r   r.   r'   r(   r   w  r   z-_DocumentNav.get_own_text.<locals>.<listcomp>r_   )ra   r   r'   r.   r(   get_own_textt  s   z_DocumentNav.get_own_textF)NFTF)TF)T)N)/r1   r2   r3   r4   classmethodr	   r<   staticmethodrQ   rB   r7   rD   rF   rH   rI   rK   rL   r    rO   rS   rY   r^   r   ra   r
   intrj   rm   r[   rp   rq   ru   rw   r{   r}   r   r   r   r   r   r   r   r   r   r   r   r   r'   r'   r'   r(   r5   N   s    	

$(  0 r5   c                
   @   s   e Zd ZdZededededefddZedededefd	d
ZededefddZ	ededefddZ
ededefddZededefddZededee deeedf  fddZdS )Inputsz-Class for parsing and validating input items.yearmonthdayr#   c                 C   s^   t }|tkr| d dkr| d dks| d dkrtnt}n|tv r#t}d|  ko,|kS   S )zValidate day.r   r   d   i  r   )
LONG_MONTHFEBFEB_LEAP_MONTH	FEB_MONTH	MONTHS_30SHORT_MONTH)r   r   r   Zmax_daysr'   r'   r(   validate_day}  s   .zInputs.validate_dayweekc                 C   sB   t ddd| d d }|dkrd}d|  ko|kS   S )zValidate week.z{}-{}-{}   r   z%m-%d-%Yr   5   )r   strptimer9   Zisocalendar)r   r   Zmax_weekr'   r'   r(   validate_week  s   zInputs.validate_weekc                 C      d|   ko	dkS   S )zValidate month.r   r   r'   )r   r'   r'   r(   validate_month  r   zInputs.validate_monthc                 C   s   d| kS )zValidate year.r   r'   )r   r'   r'   r(   validate_year  rP   zInputs.validate_yearhourc                 C   r   )zValidate hour.r      r'   )r   r'   r'   r(   validate_hour  r   zInputs.validate_hourminutesc                 C   r   )zValidate minutes.r   ;   r'   )r   r'   r'   r(   validate_minutes  r   zInputs.validate_minutesityper   .c                 C   st  d}|du r|S |dkrCt |}|rAt|dd}t|dd}t|dd}| |rA| |rA| |||rA|||f}|S |dkrnt|}|rlt|dd}t|dd}| |rl| |rl||f}|S |dkrt|}|rt|dd}t|dd}| |r| 	||r||f}|S |dkrt
|}|rt|d	d}	t|d
d}
| |	r| |
r|	|
f}|S |dkr#t|}|r!t|dd}t|dd}t|dd}t|d	d}	t|d
d}
| |r!| |r!| |||r!| |	r!| |
r!||||	|
f}|S |dv r8t|}|r8t|df}|S )zParse the input value.Ndater   
   r   r   r   timer   r   datetime-local)numberranger   )RE_DATEmatchr   groupr   r   r   RE_MONTHRE_WEEKr   RE_TIMEr   r   RE_DATETIMERE_NUMfloat)r;   r   r   Zparsedmr   r   r   r   r   r   r'   r'   r(   parse_value  sz   
"
'
 





zInputs.parse_valueN)r1   r2   r3   r4   r   r   rQ   r   r   r   r   r   r   r   rp   r
   r   r   r   r'   r'   r'   r(   r   z  s     
,r   c                   @   s  e Zd ZdZdejdddeej deddf
d	d
Z	de
fddZdddefddZddde
fddZdddee fddZdddee fddZdddee fddZdedede
fddZdddedee deeeee f  fddZddd ejde
fd!d"Zddd#eejd$f de
fd%d&Zddd ejde
fd'd(Zddd eej de
fd)d*Zddd+ejde
fd,d-Zdkd/dd+ejd0e
de
fd1d2Zddd+ejde
fd3d4Zddd+ejde
fd5d6Z ddd7eed$f de
fd8d9Z!ddd:eed$f de
fd;d<Z"ddde
fd=d>Z#ddde
fd?d@Z$dddAdde
fdBdCZ%dddDdde
fdEdFZ&ddde
fdGdHZ'dddeejd$f de
fdIdJZ(dddKeej)d$f de
fdLdMZ*ddde
fdNdOZ+ddde
fdPdQZ,dddReej-d$f de
fdSdTZ.dddUede
fdVdWZ/dddXede
fdYdZZ0ddde
fd[d\Z1ddde
fd]d^Z2dddejde
fd_d`Z3dldbede4d fdcddZ5ded fdedfZ6de7d fdgdhZ8ddde
fdidjZ9dS )mCSSMatchzPerform CSS matching.	selectorsscoper"   
namespacesflagsr#   Nc           	      C   s   |  | || _g | _g | _g | _|| _|du ri n|| _|| _d| _|}| 	|}|r5|}| 	|}|s,d}| 
|s?|}n
| |D ]}|} || _||urR|n|| _| || _| || _| j pg| j| _dS )r$   NF)r<   r6   cached_meta_langcached_default_formscached_indeterminate_formsr   r   r   iframe_restrictr[   rB   rj   rZ   r   r   has_html_namespacerS   is_xmlr\   )	r&   r   r   r   r   docr]   rZ   rl   r'   r'   r(   r)     s4   
	


zCSSMatch.__init__c                 C   s   | j p| jS )z3Check if namespaces are supported in the HTML type.)r   r   r.   r'   r'   r(   supports_namespaces  r*   zCSSMatch.supports_namespacesrM   c                 C   s*   |   rd}| |}|r|}|S t}|S )zGet tag namespace.r   )r   rw   r   )r&   rM   rv   r   r'   r'   r(   
get_tag_ns  s   
zCSSMatch.get_tag_nsc                 C   s   |  |tkS )z"Check if tag is in HTML namespace.)r   r   rX   r'   r'   r(   rW     s   zCSSMatch.is_html_tagc                 C   &   |  |}|dur| jst|S |S )ro   N)rq   r   r   rV   r&   rM   rU   r'   r'   r(   get_tag#     
zCSSMatch.get_tagc                 C   r   )rs   N)ru   r   r   rV   )r&   rM   rt   r'   r'   r(   
get_prefix)  r   zCSSMatch.get_prefixc              
   C   s   | j |ddD ]V}| |r;tt| |ddd}| |dv s,| |r,|dur-q| 	|}|dur:|  S q| 
|rAq|D ]}t|}|dv r\|dkrUtjntj    S qCqdS )	z%Get directionality from element text.Frd   dirr   N)bdiZscriptZstyletextarearT   ZALRLr   )rj   r7   DIR_MAPgetr   rV   r   r   rW   	find_bidirK   unicodedatabidirectionalctSEL_DIR_LTRSEL_DIR_RTL)r&   rM   ri   	directionr   cbidir'   r'   r(   r   /  s.   



zCSSMatch.find_bidi
lang_rangelang_tagc                 C   s   d}t d| }|d}| d}t|}d}d}|| }	|| }
|	dkr0|	|
kr0d}|d7 }|d7 }|ru||k ru|| }	z|| }
W n tyS   d}Y q8w |	sYd}q8|
|	krb|d7 }n	t|
dkrkd}q8|d7 }|ru||k s>|S )zFilter the language tags.T-r   *Fr   )RE_WILD_STRIPsubrV   splitr-   
IndexError)r&   r   r   r   ZrangesZsubtagslengthrindexZsindexrsr'   r'   r(   extended_language_filterS  s@   

z!CSSMatch.extended_language_filterattrrt   c           
      C   s  d}|   rsd}|r| j|}|du r|dkrdS nd}| |D ]N\}}| ||\}}	|du rL| jr9||ksF| jsKt|t|krK|} |S q"|du sX||krY|dkrYq"| jsgt|t|	krln||	krlq"|} |S |S | |D ]\}}t|t|krqx|} |S |S )z3Match attribute name and return value if it exists.Nr   )r   r   r   r   r   r   r   rV   )
r&   rM   r  rt   r   r   r   r   rv   rU   r'   r'   r(   match_attribute_name  s<   ($zCSSMatch.match_attribute_namer6   c                 C   s   d}|  |}| jd}|jdu rdn| j|j}|jdu r,|dur,||kr,d}|S |jdur<|jdkr<|r<d}|S |jrN|jdkrN|du sL||krNd}|S )z#Match the namespace of the element.Tr   NFr   )r   r   r   rt   )r&   rM   r6   r   rv   Zdefault_namespaceZtag_nsr'   r'   r(   match_namespace  s(   

zCSSMatch.match_namespace
attributes.c                 C   s   d}|rD|D ]=}|  ||j|j}| jr|jr|jn|j}|du r&d} |S t|tr-|nd|}|du r7q|	|du rCd} |S q|S )zMatch attributes.TNFr   )
r  Z	attributert   r   Zxml_type_patternpatternr?   rp   r   r   )r&   rM   r	  r   atempr
  r   r'   r'   r(   match_attributes  s$   zCSSMatch.match_attributesc                 C   s>   | j s|jdurt|jn|j}|duo|| |dfv S )zMatch tag name.Nr   )r   rU   r   rV   r   )r&   rM   r6   rU   r'   r'   r(   match_tagname  s   "zCSSMatch.match_tagnamec                 C   s0   d}|dur|  ||sd}| ||sd}|S )zMatch the tag.TNF)r  r  )r&   rM   r6   r   r'   r'   r(   	match_tag  s   zCSSMatch.match_tagrelationc                 C   s  d}t |d tjr|S |d jtkr3| j|| jd}|s1|r1| ||}| j|| jd}|s1|s|S |d jtkrL| j|| jd}|rJ| ||}|S |d jt	krm| 
|}|sk|rk| ||}| 
|}|sk|s\|S |d jtkr| 
|}|r| |r| ||}|S )zMatch past relationship.Fr   r   )r?   r   SelectorNullrel_type
REL_PARENTr[   r   match_selectorsREL_CLOSE_PARENTREL_SIBLINGr}   REL_CLOSE_SIBLINGr7   )r&   rM   r  foundr]   rz   r'   r'   r(   match_past_relations  s6   



zCSSMatch.match_past_relationsFr]   	recursivec                 C   sD   d}|r| j }n| j}||| jdD ]}| ||}|r |S q|S )zMatch future child.Fr   )rm   rj   r   r  )r&   r]   r  r  r   childrenrl   r'   r'   r(   match_future_child  s   zCSSMatch.match_future_childc                 C   s   d}t |d tjr|S |d jtkr| ||d}|S |d jtkr+| ||}|S |d jtkrL| |}|sJ|rJ| 	||}| |}|sJ|s;|S |d jt
kre| |}|re| |re| 	||}|S )zMatch future relationship.Fr   T)r?   r   r  r  REL_HAS_PARENTr  REL_HAS_CLOSE_PARENTREL_HAS_SIBLINGr{   r  REL_HAS_CLOSE_SIBLINGr7   )r&   rM   r  r  rz   r'   r'   r(   match_future_relations"  s*   



zCSSMatch.match_future_relationsc                 C   sV   d}t |d tjs|d jdu r|S |d jdr#| ||}|S | ||}|S )z%Match relationship to other elements.Fr   N:)r?   r   r  r  
startswithr!  r  )r&   rM   r  r  r'   r'   r(   match_relations9  s   zCSSMatch.match_relationsidsc                 C   s.   d}|D ]}||  |ddkrd} |S q|S )zMatch element's ID.Tidr   F)r   )r&   rM   r%  r  ir'   r'   r(   match_idH  s   zCSSMatch.match_idr   c                 C   s.   |  |}d}|D ]}||vrd} |S q	|S )zMatch element's classes.TF)r   )r&   rM   r   Zcurrent_classesr  r   r'   r'   r(   match_classesR  s   
zCSSMatch.match_classesc                 C   s   |  |}|r7| j|dd}|r7|dur7| |s'| |r"| s'| |r*d}n| j|dd}|r7|dus|ri| j|dd}|ri|duri| |sY| |rT| sY| |r\d}n| j|dd}|ri|dusF|S )zMatch element as root.Fr   N)r^   r}   r7   rL   striprF   r{   )r&   rM   r^   rz   r'   r'   r(   
match_root]  s<   
zCSSMatch.match_rootc                 C   s
   | j |u S )zMatch element as scope.)r   rX   r'   r'   r(   match_scopew  r0   zCSSMatch.match_scoperl   c                 C   s(   |  ||  |ko| || |kS )z!Match tag type for `nth` matches.)r   r   )r&   rM   rl   r'   r'   r(   match_nth_tag_type|  s   zCSSMatch.match_nth_tag_typenthc                 C   s  d}|D ]}d}|j r| ||j s |S | |}|du r$| |}|j}t|d }|r1|nd}d}	|j}
|j}|j}d}d}|rFdnd}|rP|
| | n|
 }}|rd}|dk s`||kr|dk rd| }|durq|dkrqnNd}||7 }|r|
| | n|
 }}d| }||krn3n*|| }|dur|dkrn%d}||7 }|r|
| | n|
 }}|| }||krn
|}|dk s`||ks`|}|
dk r|dkr|}||7 }|r|
| | n|
 }}|dksd}|}|r|
| | n|
 }}d|  kr|d krn nd}| j	|||dk ddD ]D}||7 }| 
|sq|j r'| ||j s'q|jr4| ||s4q|	d7 }	|	|krG||u rEd}n n	||u rN nq||u rVn+|}||7 }|dk rbn|rk|
| | n|
}||krsnd|  kr|d ksn |s |S q|S )zMatch `nth` elements.TFNr   r   re   )rb   rc   rd   )r   r  r[   rO   rf   r-   r  bnrj   r7   Zof_typer-  )r&   rM   r.  Zmatchedr0  r]   rf   Z
last_indexrg   Zrelative_indexr  r/  varcountZ
count_incrZfactoridxZlast_idxZadjustZdiff_lowZdiffZ	diff_highZlowestrl   r'   r'   r(   	match_nth  s   
[







zCSSMatch.match_nthc                 C   sN   d}| j |ddD ]}| |rd} |S | |r$t|r$d} |S q	|S )z)Check if element is empty (if requested).TFr   )rj   r7   rL   RE_NOT_EMPTYsearch)r&   rM   Zis_emptyrl   r'   r'   r(   match_empty  s   
 zCSSMatch.match_emptyc                 C   s"   d}|D ]
}|  ||sd}q|S )zMatch selectors.TF)r  )r&   rM   r   r   Zselr'   r'   r(   match_subselectors  s   zCSSMatch.match_subselectorscontainsc           	      C   s   d}d}|D ]C}|du r |j r| j|| jd}n| j|| jd}d}|jD ]}|j r<|D ]
}||v r6d} nq,|r; n
q%||v rDd} nq%|sId}q|S )z"Match element if it contains text.TNr   F)Zownr   r\   r   text)	r&   rM   r9  r   r`   Zcontain_listr  r:  r   r'   r'   r(   match_contains  s4   
zCSSMatch.match_containsc                 C   s  d}d}| j |dd}|r-|du r-| |dkr | |r |}n| j |dd}|r-|du sd}| jD ]\}}||u rDd}||u rBd} nq2|s| j|ddD ]3}| |}	|	dkr\ |S |	dv r| |dd}
|
rt|
d	kr| j||f ||u r~d} |S qN|S )
Match default.FNTr   form)inputZbuttonr:   r   Zsubmit)	r[   r   rW   r   rm   r   r   rV   r   )r&   rM   r   r=  r]   
found_formftrl   rU   r   r'   r'   r(   match_default  s@   
 zCSSMatch.match_defaultc                    s`  d}t t |d}dddtd f fdd}||}d} jD ]\}}}	||u r8||kr8d}|	du r6d} nq!|sd}
 j|dd	D ]\}||u rKqD |}|d
krd}d}d} |D ]<\}}t	|dkrtt	|dkrtd}nt	|dkr||krd}n	t	|dkrd}|r|r|r|||u rd}
 nq_|
r nqD|
sd} j
|||f |S )r<  FrU   rM   r"   r#   c                    sl   d} j | dd}|du r4 |dkr |r|}	 |S |} j |dd}|du r0|}	 |S |du s|S )zFind this input's form.NTr   r=  )r[   r   rW   )rM   r=  r]   Zlast_parentr.   r'   r(   get_parent_formH  s   	z5CSSMatch.match_indeterminate.<locals>.get_parent_formTr   r>  r:   Zradiochecked)r   rp   r   r
   r   rm   r   r   r   rV   r   )r&   rM   r   rU   rC  r=  r?  r@  r0  r'  rD  rl   Ztag_nameZis_radiocheckZhas_namer   r   r'   r.   r(   match_indeterminateB  sP   
zCSSMatch.match_indeterminatelangsc                 C   s  d}|   }| j}| j}|}d}d}	|sq| |}
| |D ]8\}}| ||\}}|r.|
r:| js6t|n|dksR|rV|
sV|t	krV| jsN|durNt|n|dkrV|} nq|}	| j
|| jd}|du ro|	}| |}|	}n|r|s| jr| jD ]}||d u r|d }qy|du r0| jr|r0|jdkr0d}dD ]%}d}| j|| jdD ]}| ||kr| |rd	}|} nq|s nq|r0|D ][}| |r| |d
kr| |rd}d}| |D ]6\}}t|dkrt|dkrd	}t|dkr|}|r|r|}| jtt|tt|f  nq|r! nq|s0| jtt|df |rS|D ]}d}|D ]}| |tt|rId	}q;|sQ |S q5|S )zMatch languages.FNlangr   r   r   html)rI  headTmetaz
http-equivzcontent-languager`   r   )r   rZ   r   r   r   r   r   r   rV   NS_XMLr[   r\   r   rU   rj   r   rW   r7   r   r   rp   r  )r&   rM   rG  r   Zhas_nsrZ   r   r]   Z
found_langrf   r   r   r   Zattr_nsr  cacher  r6   rl   Zc_langr`   patternsr
  r'   r'   r(   
match_lang  s   



"(zCSSMatch.match_langdirectionalityc              	   C   s  |t j@ r|t j@ rdS |du s| |sdS tt| |ddd}|dvr-||kS | 	|}|r=|du r=t j|kS | 
|}|dk}|dk}|dk}|rZt| |d	dnd}	|rk|	d
krk|du rkt j|kS |rq|	dv ss|r|dkr|rg }
| j|ddD ]}| |r|
| qd|
}n
tt| |dd}|r|D ]}t|}|dv r|dkrt jnt j}||k  S qt j|kS |rt j|kS | | j|dd|S |r|du s|dkr| |}|dur||kS |rt j|kS | | j|dd|S | | j|dd|S )zCheck directionality.FNr   r   )Nr   r>  r   r   r:   tel)r:  r6  rQ  ZurlZemailr   Tr   r   r   r   )r   r   r   rW   r   r   r   rV   r   r^   r   ra   rL   r   r   r   rp   r   r   	match_dirr[   r   )r&   rM   rP  r   r^   rU   Zis_inputZis_textareaZis_bdir   r  ri   r   r   r   r'   r'   r(   rR    sZ   










zCSSMatch.match_dir	conditionc              
   C   s2  d}t | |d}t|tt| |dd}t|tt| |dd}|du r1|du r1dS t|tt| |dd}|dur|dv r^|durQ||k rQd}|s]|dur]||kr]d}n1|d	kr|dury|dury||kry||k rx||krxd}n|dur||k rd}|s|dur||krd}|tj@ r| S |S )
ac  
        Match range.

        Behavior is modeled after what we see in browsers. Browsers seem to evaluate
        if the value is out of range, and if not, it is in range. So a missing value
        will not evaluate out of range; therefore, value is in range. Personally, I
        feel like this should evaluate as neither in or out of range.
        Fr:   minNmaxr   )r   r   r   r   r   r   Tr   )	r   rV   r   r   r   r   rp   r   SEL_IN_RANGE)r&   rM   rS  Zout_of_ranger   ZmnZmxr   r'   r'   r(   match_range  s0   
zCSSMatch.match_rangec                 C   s<   |  |}|duo|ddkp|ddkp| |duS )a  
        Match defined.

        `:defined` is related to custom elements in a browser.

        - If the document is XML (not XHTML), all tags will match.
        - Tags that are not custom (don't have a hyphen) are marked defined.
        - If the tag has a prefix (without or without a namespace), it will not match.

        This is of course requires the parser to provide us with the proper prefix and namespace info,
        if it doesn't, there is nothing we can do.
        Nr   re   r"  )r   findr   r   r'   r'   r(   match_defined<  s   
zCSSMatch.match_definedc                 C   s   d}|  |}|dv rd}|S )z
        Match placeholder shown according to HTML spec.

        - text area should be checked if they have content. A single newline does not count as content.

        F)r   
T)r   )r&   rM   r   r`   r'   r'   r(   match_placeholder_shownS  s
   
z CSSMatch.match_placeholder_shownc           	      C   s
  d}|j }|j}|r| j}| j}dti| _d| _|r| jr|D ]}|}t|tjr*q| ||j	s2q|j
tj@ r>| |s>q|j
tj@ rJ| |sJq|j
tj@ rV| |sVq|j
tj@ rb| |sbq| ||jsjq|j
tj@ rv| |svq|jr| ||jsq|jr| ||jsq| ||jsq|j
t@ r| ||j
t@ sq|jr|  ||jsq|j!r| "||j!sq|j#r| $||j#sq|j
tj%@ r| &|sq|j
tj'@ r| (|sq|j
t)@ r| *||j
t)@ sq|j+r| ,||j+sq| } |r|| _|| _|S )z.Check if element matches one of the selectors.FrI  T)-is_notr\   r   r   r   r?   r   r  r  r6   r   ZSEL_DEFINEDrY  ZSEL_ROOTr+  Z	SEL_SCOPEr,  ZSEL_PLACEHOLDER_SHOWNr[  r4  r.  Z	SEL_EMPTYr7  r%  r(  r   r)  r  r	  RANGESrW  rH  rO  r   r8  r  r$  ZSEL_DEFAULTrB  ZSEL_INDETERMINATErF  	DIR_FLAGSrR  r9  r;  )	r&   rM   r   r   r\  r\   r   r   Zselectorr'   r'   r(   r  b  sn   

zCSSMatch.match_selectorsr   limitc                 c   sV    |dk rdn|}|  | jD ]}| |r(|V  |dur(|d8 }|dk r( dS qdS )z&Match all tags under the targeted tag.r   N)rm   r6   r   )r&   r_  Zlimrl   r'   r'   r(   select  s   
zCSSMatch.selectc                 C   sH   | j }d}|du r"|dur"| |r|}n| |}|du r"|dus|S )Match closest ancestor.N)r6   r   r[   )r&   Zcurrentclosestr'   r'   r(   rb    s   

zCSSMatch.closestc                    s    fdd   jD S )zFilter tag's children.c                    s$   g | ]}  |s |r|qS r'   )rI   r   )r   r6   r.   r'   r(   r        $ z#CSSMatch.filter.<locals>.<listcomp>)ra   r6   r.   r'   r.   r(   filter     zCSSMatch.filterc                 C   s$   |  | o| |o| || jS zMatch.)rB   r7   r  r   rX   r'   r'   r(   r     s   $zCSSMatch.matchr   r   ):r1   r2   r3   r4   r   SelectorListr
   
Namespacesr   r)   rQ   r   rp   r   rW   r   r   r   r  r   r   r  ZSelectorTagr  r   ZSelectorAttributer  r  r  r  r  r!  r$  r(  r)  r+  r,  r-  r4  r7  r8  ZSelectorContainsr;  rB  rF  ZSelectorLangrO  rR  rW  rY  r[  r  r   r`  rb  r   rd  r   r'   r'   r'   r(   r     st    
)$3
5 	
e  	' =V?(Tr   c                
       s  e Zd ZU dZeed< ejed< eej	 ed< e
eef ed< eed< dZdedejdeej	 deej def
 fdd	Zd
ddefddZdddZded ded fddZdddZdd
ddeded fddZdd
ddeded fddZdefddZeZ  ZS ) 	SoupSievez-Compiled Soup Sieve selector matching object.r
  r   r   customr   )r
  r   r   rk  r   _hashc                    s   t  j|||||d dS )r$   )r
  r   r   rk  r   N)superr)   )r&   r
  r   r   rk  r   	__class__r'   r(   r)     s   

zSoupSieve.__init__r6   r"   r#   c                 C   s   t | j|| j| j|S rf  )r   r   r   r   r   r&   r6   r'   r'   r(   r     re  zSoupSieve.matchc                 C   s   t | j|| j| j S )ra  )r   r   r   r   rb  rp  r'   r'   r(   rb    s   zSoupSieve.closestiterablec                    s4   t |rt  j| j j S  fdd|D S )a  
        Filter.

        `CSSMatch` can cache certain searches for tags of the same document,
        so if we are given a tag, all tags are from the same document,
        and we can take advantage of the optimization.

        Any other kind of iterable could have tags from different documents or detached tags,
        so for those, we use a new `CSSMatch` for each item in the iterable.
        c                    s$   g | ]}t |s |r|qS r'   )r   rI   r   r   r.   r'   r(   r     rc  z$SoupSieve.filter.<locals>.<listcomp>)r   r7   r   r   r   rd  )r&   rq  r'   r.   r(   rd    s   
zSoupSieve.filterc                 C   s   | j |dd}|r|d S dS )zSelect a single tag.r   )r_  r   N)r`  )r&   r6   rd   r'   r'   r(   
select_one  s   zSoupSieve.select_oner   r_  c                 C   s   t | ||S )zSelect the specified tags.)listiselect)r&   r6   r_  r'   r'   r(   r`    s   zSoupSieve.selectc                 c   s,    t | j|| j| j|D ]}|V  qdS )zIterate the specified tags.N)r   r   r   r   r`  )r&   r6   r_  rM   r'   r'   r(   rt    s   zSoupSieve.iselectc                 C   s   d | j| j| j| jS )zRepresentation.zASoupSieve(pattern={!r}, namespaces={!r}, custom={!r}, flags={!r}))r9   r
  r   rk  r   r.   r'   r'   r(   __repr__#  s   zSoupSieve.__repr__)r6   r"   r#   r"   rg  )r1   r2   r3   r4   rp   __annotations__r   rh  r
   ri  r   r   	__slots__ZCustomSelectorsr)   rQ   r   rb  r   r   rd  rr  r`  r   rt  ru  __str____classcell__r'   r'   rn  r(   rj    s6   
 



rj  )>r4   r   r   r   rer   r   r   r@   typingr   r   r   r	   r
   r   r   r   r   r   r   compiler5  r   r  r  r  r  r  r  r  r   r   rL  r   r   r^  rV  ZSEL_OUT_OF_RANGEr]  r   r   r   r   r   r   r   r   r   r   r   r   r   r   ZDAYS_IN_WEEKr    r5   r   r   Z	Immutablerj  Zpickle_registerr'   r'   r'   r(   <module>   st    4







  .g        V