U
    luf`                     @  s  d Z ddlm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 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Z-dZ.dZ/d Z0d!Z1d"Z2d#Z3G d$d% d%Z4G d&d' d'Z5G d(d) d)Z6G d*d+ d+e5Z7G d,d- d-ej8Z9e:e9 dS ).zCSS matcher.    )annotations)datetime   )utilN)	css_types)IteratorIterableAnyCallableSequencecastz[^ 	
]z	[^ 	
]+ >~+z: z:>z:~z:+zhttp://www.w3.org/1999/xhtmlz$http://www.w3.org/XML/1998/namespace)Zltr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ddZd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.
    bs4.TagNone)elementreturnc                 C  s   |g| _ dS )Initialize.N)contents)selfr     r%   7/tmp/pip-unpacked-wheel-pmua0y5d/soupsieve/css_match.py__init__D   s    z_FakeParent.__init__bs4.PageElementr!   c                 C  s
   t | jS )zLength.)lenr#   r$   r%   r%   r&   __len__I   s    z_FakeParent.__len__N)__name__
__module____qualname____doc__r'   r,   r%   r%   r%   r&   r   ;   s   r   c                   @  sx  e Zd ZdZedddddZeddd	d
dZeddd	ddZeddd	ddZ	eddd	ddZ
eddd	ddZeddd	ddZeddd	ddZeddd	ddZedddddZeddddd Zdddd!d"Zdddd#d$Zd[ddd&d'd(d)Zd\dd,dddd&d-d.d/Zd]dddd&d0d1d2Zd^dddd'd3d4Zedd5dd6d7Zedd5dd8d9Zedd5dd:d;Zed_dddd<d=d>Zed`dddd<d?d@ZeddddAdBZeddCdDdEdFdGZeddHdIdJdKZedaddCdLdLdMdNdOZeddPddQdRZ eddSddTdUZ!dbdddCd'dVdWZ"dcdddXd'dYdZZ#d*S )d_DocumentNavz#Navigate a Beautiful Soup document.r	   r   tagr!   c                 C  s    |  |stdt| dS )z%Check if valid input tag or document.z:Expected a BeautifulSoup 'Tag', but instead received type N)is_tag	TypeErrortype)clsr3   r%   r%   r&   assert_valid_inputR   s    
z_DocumentNav.assert_valid_inputr   bool)objr!   c                 C  s   t | tjS )zIs `BeautifulSoup` object.)
isinstancebs4ZBeautifulSoupr:   r%   r%   r&   is_docZ   s    z_DocumentNav.is_docr(   c                 C  s   t | tjS )zIs tag.)r;   r<   Tagr=   r%   r%   r&   r4   _   s    z_DocumentNav.is_tagc                 C  s   t | tjS )zIs declaration.)r;   r<   Declarationr=   r%   r%   r&   is_declarationd   s    z_DocumentNav.is_declarationc                 C  s   t | tjS )z	Is CDATA.)r;   r<   CDatar=   r%   r%   r&   is_cdatai   s    z_DocumentNav.is_cdatac                 C  s   t | tjS )zIs processing instruction.)r;   r<   ProcessingInstructionr=   r%   r%   r&   is_processing_instructionn   s    z&_DocumentNav.is_processing_instructionc                 C  s   t | tjS )zIs navigable string.)r;   r<   ZNavigableStringr=   r%   r%   r&   is_navigable_strings   s    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<   Commentr@   rB   rD   Doctyper=   r%   r%   r&   is_special_stringx   s    z_DocumentNav.is_special_stringc                 C  s   |  |o| | S )z Check if node is content string.)rF   rI   )r7   r:   r%   r%   r&   is_content_string}   s    z_DocumentNav.is_content_stringr   elr!   c                 C  s   t | S )z'Create fake parent for a given element.)r   rL   r%   r%   r&   create_fake_parent   s    z_DocumentNav.create_fake_parentc                 C  s
   t | jS )z2Check if element (or document) is from a XML tree.)r9   _is_xmlrM   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)r9   rP   namer   loweris_html_tagr$   rL   r%   r%   r&   	is_iframe   s     z_DocumentNav.is_iframec                 C  s:   | j o| j |k}|s6| |}|dk	o4| jo4| |}|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_htmlrV   )r$   rL   rW   parentr%   r%   r&   is_root   s
    
z_DocumentNav.is_rootFzIterator[bs4.PageElement])rL   	no_iframer!   c                 c  s   |r|  |s|jE dH  dS )z$Get contents or contents in reverse.N)rV   r#   r$   rL   r\   r%   r%   r&   get_contents   s    z_DocumentNav.get_contentsNT
int | None)rL   startreversetagsr\   r!   c                 c  s   |r|  |st|jd }|dkr2|r,|nd}n|}|r>dn|d }|rNdnd}	d|  krf|krn n0||kr|j| }
||	7 }|r| |
rj|
V  qjdS )zGet children.r   Nr   )rV   r*   r#   r4   )r$   rL   r`   ra   rb   r\   lastindexendincrnoder%   r%   r&   get_children   s    

z_DocumentNav.get_children)rL   rb   r\   r!   c                 c  s   |r|  |sd}|jD ]}|dk	r2||k	r.qd}| |}|r|r|  |r|jdk	r`|j}n&|}| |r|jr|jd }qd|j}|V  |dkr qq|r|r|V  qdS )zGet descendants.Nrc   )rV   Zdescendantsr4   next_siblingr#   Znext_element)r$   rL   rb   r\   Z	next_goodchildr4   Z
last_childr%   r%   r&   get_descendants   s*    


z_DocumentNav.get_descendantsc                 C  s$   |j }|r |dk	r | |r d}|S )zGet parent.N)rZ   rV   )r$   rL   r\   rZ   r%   r%   r&   rX      s    z_DocumentNav.get_parent
str | Nonec                 C  s   t d| jS )Get tag.rm   )r   rR   rM   r%   r%   r&   get_tag_name   s    z_DocumentNav.get_tag_namec                 C  s   t d| jS )Get prefix.rm   )r   prefixrM   r%   r%   r&   get_prefix_name   s    z_DocumentNav.get_prefix_namec                 C  s   t d| jS )zGet namespace `URI`.rm   )r   	namespacerM   r%   r%   r&   get_uri   s    z_DocumentNav.get_uri)rL   rb   r!   c                 C  s(   |j }|r$| |s$|dk	r$|j }q|S )zGet next sibling tag.N)rj   r4   r7   rL   rb   siblingr%   r%   r&   get_next  s    z_DocumentNav.get_nextc                 C  s(   |j }|r$| |s$|dk	r$|j }q|S )zGet previous sibling tag.N)Zprevious_siblingr4   ru   r%   r%   r&   get_previous  s    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`.
        rs   N)getattrr9   NS_XHTML)rL   nsr%   r%   r&   has_html_ns  s    	z_DocumentNav.has_html_nsstrztuple[str | None, str | None])rL   	attr_namer!   c                 C  s   t |ddt |ddfS )z7Return namespace and attribute name without the prefix.rs   NrR   )ry   )rL   r~   r%   r%   r&   split_namespace   s    z_DocumentNav.split_namespacezstr | Sequence[str])valuer!   c                 C  s   |dkrdS t |tr|S t |tr.|dS t |trg }|D ]B}t |ttfslt |trl|t| q@|tt| | q@|S t|S )z6Normalize the value to be a string or list of strings.N utf8)r;   r}   bytesdecoder   appendr   normalize_value)r7   r   	new_valuevr%   r%   r&   r   &  s    



z_DocumentNav.normalize_valuestr | Sequence[str] | None)rL   rR   defaultr!   c                 C  sj   |}|j r6z| |j| }W qf tk
r2   Y qfX n0|j D ]$\}}t||kr@| |} qfq@|S )zGet attribute by name.)rO   r   attrsKeyErroritemsr   rS   )r7   rL   rR   r   r   kr   r%   r%   r&   get_attribute_by_nameG  s    	
z"_DocumentNav.get_attribute_by_namez0Iterator[tuple[str, str | Sequence[str] | None]]c                 c  s(   |j  D ]\}}|| |fV  q
dS )zIterate attributes.N)r   r   r   )r7   rL   r   r   r%   r%   r&   iter_attributes]  s    z_DocumentNav.iter_attributeszSequence[str]c                 C  s0   |  |dg }t|tr"t|}ttt |S )zGet classes.class)r   r;   r}   	RE_NOT_WSfindallr   r   )r7   rL   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                   s   g | ]}  |r|qS r%   rJ   .0rh   r+   r%   r&   
<listcomp>q  s     
 z)_DocumentNav.get_text.<locals>.<listcomp>F)rb   r\   )joinrl   r]   r%   r+   r&   get_textm  s    z_DocumentNav.get_textz	list[str]c                   s    fdd j ||dD S )zGet Own Text.c                   s   g | ]}  |r|qS r%   r   r   r+   r%   r&   r   w  s     
 z-_DocumentNav.get_own_text.<locals>.<listcomp>r\   )r^   r]   r%   r+   r&   get_own_textt  s    z_DocumentNav.get_own_text)F)NFTF)TF)F)T)T)N)F)F)$r-   r.   r/   r0   classmethodr8   staticmethodr>   r4   rA   rC   rE   rF   rI   rJ   rN   rP   rV   r[   r^   ri   rl   rX   ro   rr   rt   rw   rx   r|   r   r   r   r   r   r   r   r%   r%   r%   r&   r1   O   sx         $  r1   c                   @  s   e Zd ZdZedddddddZedddddd	Zeddd
ddZedddddZedddddZ	edddddZ
eddddddZdS )Inputsz-Class for parsing and validating input items.intr9   )yearmonthdayr!   c                 C  s^   t }|tkr:| d dkr$| d dks0| d dkr4tnt}n|tkrFt}d|  koX|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)r   weekr!   c                 C  sH   t d dd d|  d d }|dkr0d}d|  koB|kS   S )zValidate week.   -r   z%m-%d-%Yr   5   )r   strptimeisocalendar)r   r   Zmax_weekr%   r%   r&   validate_week  s    $zInputs.validate_week)r   r!   c                 C  s   d|   kodkS   S )zValidate month.r   r   r%   )r   r%   r%   r&   validate_month  s    zInputs.validate_month)r   r!   c                 C  s   d| kS )zValidate year.r   r%   )r   r%   r%   r&   validate_year  s    zInputs.validate_year)hourr!   c                 C  s   d|   kodkS   S )zValidate hour.r      r%   )r   r%   r%   r&   validate_hour  s    zInputs.validate_hour)minutesr!   c                 C  s   d|   kodkS   S )zValidate minutes.r   ;   r%   )r   r%   r%   r&   validate_minutes  s    zInputs.validate_minutesr}   rm   ztuple[float, ...] | None)ityper   r!   c                 C  s  d}|dkr|S |dkrt |}|rt|dd}t|dd}t|dd}| |r| |r| |||r|||f}n|dkrt|}|rt|dd}t|dd}| |r| |r||f}n|dkr<t|}|r|t|dd}t|dd}| |r|| 	||r|||f}n@|dkrt
|}|r|t|d	d}	t|d
d}
| |	r|| |
r||	|
f}n|dkrRt|}|r|t|dd}t|dd}t|dd}t|d	d}	t|d
d}
| |r|| |r|| |||r|| |	r|| |
r|||||	|
f}n*|dkr|t|}|r|t|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)r7   r   r   parsedmr   r   r   r   r   r   r%   r%   r&   parse_value  sp    
"









zInputs.parse_valueN)r-   r.   r/   r0   r   r   r   r   r   r   r   r   r   r%   r%   r%   r&   r   z  s   
r   c                   @  s  e Zd ZdZdddddddd	Zd
dddZdddddZdd
dddZdddddZdddddZ	dddddZ
ddd
dddZddddd d!d"Zdd#d
d$d%d&Zdd'd
d(d)d*Zdd#d
d$d+d,Zdd-d
d$d.d/Zddd
d0d1d2Zdxddd
d
d4d5d6Zddd
d0d7d8Zddd
d0d9d:Zdd;d
d<d=d>Zdd;d
d?d@dAZdd
ddBdCZdd
ddDdEZddd
dFdGdHZddd
dIdJdKZdd
ddLdMZddNd
dOdPdQZddRd
dSdTdUZdd
ddVdWZdd
ddXdYZddZd
d[d\d]Z ddd
d^d_d`Z!ddd
dadbdcZ"dd
ddddeZ#dd
ddfdgZ$ddd
dOdhdiZ%dyddkdldmdnZ&doddpdqZ'drddsdtZ(dd
ddudvZ)dwS )zCSSMatchzPerform CSS matching.ct.SelectorListr   ct.Namespaces | Noner   r   )	selectorsscope
namespacesflagsr!   c           	      C  s   |  | || _g | _g | _g | _|| _|dkr4i n|| _|| _d| _|}| 	|}|rh|}| 	|}qTd}| 
|s||}n| |D ]}|} qq|| _||k	r|n|| _| || _| || _| j p| j| _dS )r"   NF)r8   r3   cached_meta_langcached_default_formscached_indeterminate_formsr   r   r   iframe_restrictrX   r>   ri   rW   r   r|   has_html_namespacerP   is_xmlrY   )	r$   r   r   r   r   docrZ   rW   rk   r%   r%   r&   r'     s2    	


zCSSMatch.__init__r9   r)   c                 C  s   | j p
| jS )z3Check if namespaces are supported in the HTML type.)r   r   r+   r%   r%   r&   supports_namespaces  s    zCSSMatch.supports_namespacesr}   rK   c                 C  s(   |   r d}| |}|r$|}nt}|S )zGet tag namespace.r   )r   rt   rz   )r$   rL   rs   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   rz   rU   r%   r%   r&   rT     s    zCSSMatch.is_html_tagrm   c                 C  s&   |  |}|dk	r"| js"t|S |S )rn   N)ro   r   r   rS   r$   rL   rR   r%   r%   r&   get_tag#  s    
zCSSMatch.get_tagc                 C  s&   |  |}|dk	r"| js"t|S |S )rp   N)rr   r   r   rS   )r$   rL   rq   r%   r%   r&   
get_prefix)  s    
zCSSMatch.get_prefixr_   c              
   C  s   | j |ddD ]}| |rvtt| |ddd}| |dks| |r|dk	rZq| 	|}|dk	r|  S q| 
|rq|D ]2}t|}|dkr|dkrtjntj    S qqdS )	z%Get directionality from element text.Frb   dirr   N)bdiscriptstyletextarearQ   ALRLr   )ri   r4   DIR_MAPgetr   rS   r   r   rT   	find_bidirI   unicodedatabidirectionalctSEL_DIR_LTRSEL_DIR_RTL)r$   rL   rh   	directionr   cbidir%   r%   r&   r   /  s*    



 zCSSMatch.find_bidi)
lang_rangelang_tagr!   c                 C  s0  d}t d| }|d}| d}t|}t|}d}d}	|| }
||	 }|dkrt|dkrt|
st|
|krtdS |
dkr|
|ks|
dkr|dkr|sd}|d7 }|	d7 }	|r,||k r,|| }
z||	 }W n tk
r   d}Y qY nX |
sd}qn(||
kr|d7 }nt|dkr"d}q|	d7 }	q|S )zFilter the language tags.Tr   r   r   *F)RE_WILD_STRIPsubrS   splitr*   
IndexError)r$   r   r   r   rangesZsubtagslengthZslengthrindexZsindexrsr%   r%   r&   extended_language_filterS  sB    
$



z!CSSMatch.extended_language_filterr   )rL   attrrq   r!   c           
      C  s  d}|   rd}|r6| j|}|dkr:|dkr:dS nd}| |D ]\}}| ||\}}	|dkr| jrr||ks| jsDt|t|krD|} qqD|dksD||kr|dkrqD| jst|t|	krqD||	krqD|} qqDn6| |D ]*\}}t|t|krq|} qq|S )z3Match attribute name and return value if it exists.Nr   )r   r   r   r   r   r   r   rS   )
r$   rL   r  rq   r   r{   r   r   rs   rR   r%   r%   r&   match_attribute_name  s6    ($zCSSMatch.match_attribute_namezct.SelectorTag)rL   r3   r!   c                 C  s   d}|  |}| jd}|jdkr(dn| j|j}|jdkrV|dk	rV||krVd}nB|jdk	rt|jdkrt|rtd}n$|jr|jdkr|dks||krd}|S )z#Match the namespace of the element.Tr   NFr   )r   r   r   rq   )r$   rL   r3   r   rs   default_namespaceZtag_nsr%   r%   r&   match_namespace  s$    
zCSSMatch.match_namespacez tuple[ct.SelectorAttribute, ...])rL   
attributesr!   c                 C  s   d}|r|D ]x}|  ||j|j}| jr4|jr4|jn|j}|dkrJd} qt|trX|nd|}|dkrnqq|	|dkrd} qq|S )zMatch attributes.TNFr   )
r  	attributerq   r   Zxml_type_patternpatternr;   r}   r   r   )r$   rL   r  r   atempr
  r   r%   r%   r&   match_attributes  s    zCSSMatch.match_attributesc                 C  s>   | j s|jdk	rt|jn|j}|dk	o:|| |dfk S )zMatch tag name.Nr   )r   rR   r   rS   r   )r$   rL   r3   rR   r%   r%   r&   match_tagname  s    "zCSSMatch.match_tagnamezct.SelectorTag | Nonec                 C  s0   d}|dk	r,|  ||sd}| ||s,d}|S )zMatch the tag.TNF)r  r  )r$   rL   r3   r   r%   r%   r&   	match_tag  s    zCSSMatch.match_tag)rL   relationr!   c                 C  s   d}t |d tjr|S |d jtkr^| j|| jd}|s|r| ||}| j|| jd}q6n|d jtkr| j|| jd}|r| ||}nl|d jt	kr| 
|}|s|r| ||}| 
|}qn2|d jtkr| 
|}|r| |r| ||}|S )zMatch past relationship.Fr   r   )r;   r   SelectorNullrel_type
REL_PARENTrX   r   match_selectorsREL_CLOSE_PARENTREL_SIBLINGrx   REL_CLOSE_SIBLINGr4   )r$   rL   r  foundrZ   rv   r%   r%   r&   match_past_relations  s,    

zCSSMatch.match_past_relationsF)rZ   r  	recursiver!   c                 C  sB   d}|r| j }n| j}||| jdD ]}| ||}|r$ q>q$|S )zMatch future child.Fr   )rl   ri   r   r  )r$   rZ   r  r  r   childrenrk   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r6| ||d}n|d jtkrR| ||}nl|d jtkr| |}|s|r| 	||}| |}qjn2|d jt
kr| |}|r| |r| 	||}|S )zMatch future relationship.Fr   T)r;   r   r  r  REL_HAS_PARENTr  REL_HAS_CLOSE_PARENTREL_HAS_SIBLINGrw   r  REL_HAS_CLOSE_SIBLINGr4   )r$   rL   r  r  rv   r%   r%   r&   match_future_relations'  s"    

zCSSMatch.match_future_relationsc                 C  sT   d}t |d tjs"|d jdkr&|S |d jdrD| ||}n| ||}|S )z%Match relationship to other elements.Fr   N:)r;   r   r  r  
startswithr!  r  )r$   rL   r  r  r%   r%   r&   match_relations>  s    zCSSMatch.match_relationsztuple[str, ...])rL   idsr!   c                 C  s,   d}|D ]}||  |ddkrd} q(q|S )zMatch element's ID.Tidr   F)r   )r$   rL   r%  r  ir%   r%   r&   match_idM  s    zCSSMatch.match_id)rL   r   r!   c                 C  s,   |  |}d}|D ]}||krd} q(q|S )zMatch element's classes.TF)r   )r$   rL   r   Zcurrent_classesr  r   r%   r%   r&   match_classesW  s    
zCSSMatch.match_classesc                 C  s   |  |}|rd| j|dd}|rd|dk	rd| |sN| |rD| sN| |rTd}q| j|dd}q|r| j|dd}|r|dk	r| |s| |r| s| |rd}qv| j|dd}qv|S )zMatch element as root.Fr   N)r[   rx   r4   rJ   striprC   rw   )r$   rL   r[   rv   r%   r%   r&   
match_rootb  s8    
zCSSMatch.match_rootc                 C  s
   | j |kS )zMatch element as scope.)r   rU   r%   r%   r&   match_scope|  s    zCSSMatch.match_scope)rL   rk   r!   c                 C  s(   |  ||  |ko&| || |kS )z!Match tag type for `nth` matches.)r   r   )r$   rL   rk   r%   r%   r&   match_nth_tag_type  s    zCSSMatch.match_nth_tag_type)rL   nthr!   c                 C  s  d}|D ]}d}|j r,| ||j s, q| |}|dkrH| |}|j}t|d }|rb|nd}d}	|j}
|j}|j}d}d}|rdnd}|r|
| | n|
 }}|rd}|dk s||kr|dk r(d| }|dk	r|dkrqd}||7 }|r|
| | n|
 }}d| }||krqq|| }|dk	rH|dkrHqd}||7 }|rf|
| | n|
 }}|| }||krq|}q|}|
dk r|dkr|}||7 }|r|
| | n|
 }}qd}|}|r|
| | n|
 }}d|  kr
|d krn nd}| j	|||dk ddD ]}||7 }| 
|sDq(|j r`| ||j s`q(|jrz| ||szq(|	d7 }	|	|kr||krd}n q||kr( qq(||krĐq|}||7 }|dk rސq|r|
| | n|
}||krqq|s qq|S )zMatch `nth` elements.TFNr   r   rc   )r`   ra   rb   )r   r  rX   rN   rd   r*   r  bnri   r4   Zof_typer-  )r$   rL   r.  matchedr0  rZ   rd   
last_indexre   Zrelative_indexr  r/  varcountZ
count_incrZfactoridxZlast_idxadjustZdiff_lowZdiffZ	diff_highZlowestrk   r%   r%   r&   	match_nth  s    







 






zCSSMatch.match_nthc                 C  sL   d}| j |ddD ]4}| |r*d} qHq| |rt|rd} qHq|S )z)Check if element is empty (if requested).TFr   )ri   r4   rJ   RE_NOT_EMPTYsearch)r$   rL   Zis_emptyrk   r%   r%   r&   match_empty  s    
zCSSMatch.match_emptyztuple[ct.SelectorList, ...])rL   r   r!   c                 C  s"   d}|D ]}|  ||sd}q|S )zMatch selectors.TF)r  )r$   rL   r   r   selr%   r%   r&   match_subselectors  s
    zCSSMatch.match_subselectorsztuple[ct.SelectorContains, ...])rL   containsr!   c           	      C  s   d}d}|D ]}|dkr@|j r0| j|| jd}n| j|| jd}d}|jD ]>}|j rx|D ]}||krXd} qnqX|r qqJ||krJd} qqJ|sd}q|S )z"Match element if it contains text.TNr   F)Zownr   rY   r   text)	r$   rL   r=  r   contentZcontain_listr  r>  r   r%   r%   r&   match_contains  s,    
zCSSMatch.match_containsc                 C  s   d}d}| j |dd}|rP|dkrP| |dkr@| |r@|}q| j |dd}qd}| jD ]$\}}||krZd}||krzd} qqZ|s| j|ddD ]b}| |}	|	dkr q|	dkr| |dd}
|
rt|
d	kr| j||f ||krd} qq|S )
Match default.FNTr   form)inputbuttonr6   r   Zsubmit)	rX   r   rT   r   rl   r   r   rS   r   )r$   rL   r   rB  rZ   
found_formftrk   rR   r   r%   r%   r&   match_default   s6    
zCSSMatch.match_defaultc                   sj  d}t t |d}ddd fdd}||}d} jD ].\}}}	||kr<||kr<d}|	dkrfd} qlq<|sfd}
 j|dd	D ]}||krq |}|d
kr>d}d}d} |D ]\}}t|dkrt|dkrd}n4t|dkr||krd}nt|dkrd}|r|r|r|||krd}
 q>q|
r qJq|
sTd} j	|||f |S )rA  FrR   r   bs4.Tag | NonerK   c                   s^   d} j | dd}|dkrZ |dkr8 |r8|}qZ|} j |dd}|dkr|}qZq|S )zFind this input's form.NTr   rB  )rX   r   rT   )rL   rB  rZ   Zlast_parentr+   r%   r&   get_parent_formM  s    z5CSSMatch.match_indeterminate.<locals>.get_parent_formTr   rC  r6   Zradiochecked)
r   r}   r   r   rl   r   r   r   rS   r   )r$   rL   r   rR   rJ  rB  rE  rF  r0  r'  rK  rk   Ztag_nameZis_radiocheckZhas_namer   r   r%   r+   r&   match_indeterminateG  sJ    

zCSSMatch.match_indeterminateztuple[ct.SelectorLang, ...])rL   langsr!   c                 C  s  d}|   }| j}| j}|}d}d}	|s| |}
| |D ]p\}}| ||\}}|r\|
rt| jslt|n|dks|r<|
s<|t	kr<| js|dk	rt|n|dkr<|} qq<|}	| j
|| jd}|dkr$|	}| |}|	}qq$|dkr| jr| jD ]}||d kr|d }q|dkr| jr6|r|jdkrd}dD ]X}d}| j|| jdD ]0}| ||krV| |rVd	}|} qqV|s> qq>|r|D ]}| |rV| |d
krV| |rVd}d}| |D ]t\}}t|dkrt|dkrd	}t|dkr |}|r|r|}| jtt|tt|f  qVq|dk	r qjq|dkr| jtt|df |dk	r|D ]:}d}|D ]}| |tt|rd	}q|s qԐq|S )zMatch languages.FNlangr   r   r   html)rP  headTmetaz
http-equivzcontent-languager?  r   )r   rW   r   r|   r   r   r   r   rS   NS_XMLrX   rY   r   rR   ri   r   rT   r4   r   r   r}   r  )r$   rL   rN  r   Zhas_nsrW   r   rZ   Z
found_langrd   r|   r   r   Zattr_nsr  cacher  r3   rk   Zc_langr?  patternsr
  r%   r%   r&   
match_lang  s    



$

( 





zCSSMatch.match_lang)rL   directionalityr!   c              	     s  |t j@ r|t j@ rdS |dks* |s.dS tt |ddd}|dkrZ||kS  	|}|rz|dkrzt j|kS  
|}|dk}|dk}|dk}|rt |d	dnd}	|r|	d
kr|dkrt j|kS |r|	dks|r|dkr|rd fdd j|ddD }
ntt |dd}
|
r|
D ]<}t|}|dkr:|dkrbt jnt j}||k  S q:t j|kS |rt j|kS   j|dd|S |r|dks|dkr |}|dk	r||kS |rt j|kS   j|dd|S   j|dd|S )zCheck directionality.FNr   r   )Nr   rC  r   r   r6   tel)r>  r9  rX  urlemailr   c                 3  s   | ]}  |r|V  qd S )Nr   r   r+   r%   r&   	<genexpr>  s     
 z%CSSMatch.match_dir.<locals>.<genexpr>Tr   r   r   r   )r   r   r   rT   r   r   r   rS   r   r[   r   r   r^   r   r}   r   r   	match_dirrX   r   )r$   rL   rW  r   r[   rR   Zis_inputZis_textareaZis_bdir   r   r   r   r%   r+   r&   r\    sN    



$






zCSSMatch.match_dir)rL   	conditionr!   c              
   C  sB  d}t | |d}t|tt| |dd}t|tt| |dd}|dkrb|dkrbdS t|tt| |dd}|dk	r,|dkr|dk	r||k rd}|s|dk	r||krd}nn|d	kr,|dk	r|dk	r||kr||k r||krd}n6|dk	r||k rd}|s,|dk	r,||kr,d}|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.
        Fr6   minNmaxr   )r   r   r   r   r   r   Tr   )	r   rS   r   r   r   r   r}   r   SEL_IN_RANGE)r$   rL   r]  Zout_of_ranger   mnZmxr   r%   r%   r&   match_range  s,    


zCSSMatch.match_rangec                 C  s<   |  |}|dk	o:|ddkp:|ddkp:| |dk	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   rc   r"  )r   findr   r   r%   r%   r&   match_defined=  s    
zCSSMatch.match_definedc                 C  s   d}|  |}|dk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$   rL   r   r?  r%   r%   r&   match_placeholder_shownT  s
    
z CSSMatch.match_placeholder_shownc           	      C  s>  d}|j }|j}|r0| j}| j}dti| _d| _|r<| jr(|D ]}|}t|tjrXq@| ||j	shq@|j
tj@ r| |sq@|j
tj@ r| |sq@|j
tj@ r| |sq@|j
tj@ r| |sq@| ||jsq@|j
tj@ r| |sq@|jr
| ||js
q@|jr$| ||js$q@| ||js6q@|j
t@ rX| ||j
t@ sXq@|jrr|  ||jsrq@|j!r| "||j!sq@|j#r| $||j#sq@|j
tj%@ r| &|sq@|j
tj'@ r| (|sq@|j
t)@ r | *||j
t)@ s q@|j+r| ,||j+sq@| } q(q@|r:|| _|| _|S )z.Check if element matches one of the selectors.FrP  T)-is_notrY   r   r   rz   r;   r   r  r  r3   r   ZSEL_DEFINEDrd  ZSEL_ROOTr+  Z	SEL_SCOPEr,  ZSEL_PLACEHOLDER_SHOWNrf  r7  r.  Z	SEL_EMPTYr:  r%  r(  r   r)  r  r  RANGESrb  rO  rV  r   r<  r  r$  ZSEL_DEFAULTrH  ZSEL_INDETERMINATErM  	DIR_FLAGSr\  r=  r@  )	r$   rL   r   r   rg  rY   r   r   selectorr%   r%   r&   r  c  sn    

  zCSSMatch.match_selectorsr   Iterator[bs4.Tag])limitr!   c                 c  sR   |dk rdn|}|  | jD ]0}| |r|V  |dk	r|d8 }|dk r qNqdS )z&Match all tags under the targeted tag.r   N)rl   r3   r   )r$   rl  Zlimrk   r%   r%   r&   select  s    
zCSSMatch.selectrI  c                 C  s:   | j }d}|dkr6|dk	r6| |r*|}q
| |}q
|S )Match closest ancestor.N)r3   r   rX   )r$   currentclosestr%   r%   r&   rp    s    
zCSSMatch.closestlist[bs4.Tag]c                   s    fdd   jD S )zFilter tag's children.c                   s$   g | ]}  |s |r|qS r%   )rF   r   )r   r3   r+   r%   r&   r     s     
 
 z#CSSMatch.filter.<locals>.<listcomp>)r^   r3   r+   r%   r+   r&   filter  s    zCSSMatch.filterc                 C  s$   |  | o"| |o"| || jS zMatch.)r>   r4   r  r   rU   r%   r%   r&   r     s    zCSSMatch.matchN)F)r   )*r-   r.   r/   r0   r'   r   r   rT   r   r   r   r  r  r  r  r  r  r  r  r!  r$  r(  r)  r+  r,  r-  r7  r:  r<  r@  rH  rM  rV  r\  rb  rd  rf  r  rm  rp  rr  r   r%   r%   r%   r&   r     sN   )$85	
e	'=V;(Tr   c                      s   e Zd ZU dZded< ded< ded< ded	< d
ed< dZddddd
d fddZdddddZdddddZdddddZ	dddddZ
d)dd
dd d!d"Zd*dd
d#d d$d%Zdd&d'd(ZeZ  ZS )+	SoupSievez-Compiled Soup Sieve selector matching object.r}   r
  r   r   r   r   zdict[str, str]customr   r   )r
  r   r   ru  r   _hashzct.CustomSelectors | Noner
  r   r   ru  r   c                   s   t  j|||||d dS )r"   rw  N)superr'   )r$   r
  r   r   ru  r   	__class__r%   r&   r'     s    
zSoupSieve.__init__r   r9   r2   c                 C  s   t | j|| j| j|S rs  )r   r   r   r   r   r$   r3   r%   r%   r&   r     s    zSoupSieve.matchc                 C  s   t | j|| j| j S )rn  )r   r   r   r   rp  r{  r%   r%   r&   rp    s    zSoupSieve.closestzIterable[bs4.Tag]rq  )iterabler!   c                   s8   t |r"t  j| j j S  fdd|D S 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   rF   r   r   r+   r%   r&   r     s     
 
 z$SoupSieve.filter.<locals>.<listcomp>N)r   r4   r   r   r   rr  )r$   r|  r%   r+   r&   rr    s    
zSoupSieve.filterc                 C  s   | j |dd}|r|d S dS )zSelect a single tag.r   )rl  r   N)rm  )r$   r3   rb   r%   r%   r&   
select_one  s    zSoupSieve.select_oner   )r3   rl  r!   c                 C  s   t | ||S )zSelect the specified tags.)listiselectr$   r3   rl  r%   r%   r&   rm    s    zSoupSieve.selectrk  c                 c  s$   t | j|| j| j|E dH  dS )zIterate the specified tags.N)r   r   r   r   rm  r  r%   r%   r&   r    s    zSoupSieve.iselectr)   c              	   C  s&   d| j d| jd| jd| jd	S )zRepresentation.zSoupSieve(pattern=z, namespaces=z	, custom=z, flags=))r
  r   ru  r   r+   r%   r%   r&   __repr__#  s    $zSoupSieve.__repr__)r   )r   )r-   r.   r/   r0   __annotations__	__slots__r'   r   rp  rr  r}  rm  r  r  __str____classcell__r%   r%   ry  r&   rt    s    
rt  );r0   
__future__r   r   r   r   rer   r   r   r<   typingr   r   r	   r
   r   r   compiler8  r   r  r  r  r  r  r  r  r   rz   rS  r   r   ri  r`  ZSEL_OUT_OF_RANGErh  r   r   r   r   r   r   r   r   r   r   r   r   r   r   ZDAYS_IN_WEEKr   r1   r   r   Z	Immutablert  Zpickle_registerr%   r%   r%   r&   <module>   st    







  -g        S