o
    e                     @   s   d Z ddlZddlZddlZddlm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 ejdddZG dd de
eZG d	d
 d
ZedjZedjZ edjZ!G dd dZ"G dd de"Z#dS )a  
    cssselect.xpath
    ===============

    Translation of parsed CSS selectors to XPath expressions.


    :copyright: (c) 2007-2012 Ian Bicking and contributors.
                See AUTHORS for more details.
    :license: BSD, see LICENSE for more details.

    N)Optional)parseparse_seriesPseudoElementSelectorSelectorErrorTreeElementHashClassFunctionPseudoAttribNegationRelationMatchingSpecificityAdjustmentCombinedSelectorc                 C   s   t jdtdd t| ||S )Nzb_unicode_safe_getattr is deprecated and will be removed in the next release, use getattr() instead   )
stacklevel)warningswarnDeprecationWarninggetattr)objnamedefault r   ?D:\Projects\ConvertPro\env\Lib\site-packages\cssselect/xpath.py_unicode_safe_getattr)   s   r   c                   @   s   e Zd ZdZdS )ExpressionErrorz3Unknown or unsupported selector (eg. pseudo-class).N)__name__
__module____qualname____doc__r   r   r   r   r    4   s    r    c                   @   s   e Zd Z	ddededededd	f
d
dZdefddZdefddZddededd fddZd ddZ	d ddZ
			d!dedd dee dedd f
ddZd	S )"	XPathExpr *Fpathelement	conditionstar_prefixreturnNc                 C   s   || _ || _|| _d S N)r(   r)   r*   )selfr(   r)   r*   r+   r   r   r   __init__<   s   
zXPathExpr.__init__c                 C   s,   t | jt | j }| jr|d| j 7 }|S )Nz[%s]strr(   r)   r*   )r.   r(   r   r   r   __str__C   s   zXPathExpr.__str__c                 C   s   d| j j| f S )Nz%s[%s])	__class__r!   r.   r   r   r   __repr__I      zXPathExpr.__repr__and
conjuctionc                 C   s&   | j rd| j ||f | _ | S || _ | S )Nz(%s) %s (%s))r*   )r.   r*   r8   r   r   r   add_conditionL   s
   zXPathExpr.add_conditionc                 C   s.   | j dkrd S | dt| j   d| _ d S )Nr'   zname() = %s)r)   r9   GenericTranslatorxpath_literalr4   r   r   r   add_name_testS   s   

zXPathExpr.add_name_testc                 C   s   |  j d7  _ dS )ze
        Append '*/' to the path to keep the context constrained
        to a single parent.
        */N)r(   r4   r   r   r   add_star_prefixZ   s   zXPathExpr.add_star_prefixcombinerotherclosing_combinerhas_inner_conditionc                 C   s   t | | }|jdkr||j7 }|| _|s&|r|j| n|j| _|j| _| S |j| _|jr9|  jd|j d 7  _|rB|  j|7  _| S )Nr=   []r0   )r.   r?   r@   rA   rB   r(   r   r   r   joina   s   

zXPathExpr.join)r&   r'   r&   F)r7   )r,   N)NF)r!   r"   r#   r1   boolr/   r2   r5   r9   r<   r>   r   rE   r   r   r   r   r%   ;   s>    


r%   z('+)z^[a-zA-Z_][a-zA-Z0-9_.-]*$z^[^ \t\r\n\f]+$c                   @   s  e Zd ZdZdddddZddd	d
dddddZdZdZdZdZ	dZ
eZddededefddZ		ddedededefddZdededefdd Zed!edefd"d#Zd$edefd%d&Zd'edefd(d)Zd*edefd+d,Zd-edefd.d/Zd0edefd1d2Zd0e defd3d4Z!d5e"defd6d7Z#d8e$defd9d:Z%de&defd;d<Z'd=e(defd>d?Z)d@e*defdAdBZ+de,defdCdDZ-dEedFedefdGdHZ.dEedFedefdIdJZ/dEedFedefdKdLZ0dEedFedefdMdNZ1dEedFedefdOdPZ2dEedFedefdQdRZ3dEedFedefdSdTZ4dEedFedefdUdVZ5	Wdded5e"dXedYedef
dZd[Z6ded5e"defd\d]Z7ded5e"defd^d_Z8ded5e"defd`daZ9ded5e"defdbdcZ:ded5e"defdddeZ;dedefdfdgZ<dedefdhdiZ=dedefdjdkZ>dedefdldmZ?dedefdndoZ@dedefdpdqZAdedefdrdsZBdedefdtduZCdedefdvdwZDdedefdxdyZEeEZFeEZGeEZHeEZIeEZJeEZKeEZLeEZMeEZNdedzed{eOe defd|d}ZPdedzed{eOe defd~dZQdedzed{eOe defddZRdedzed{eOe defddZSdedzed{eOe defddZTdedzed{eOe defddZUdedzed{eOe defddZVdedzed{eOe defddZWdS )r:   z
    Translator for "generic" XML documents.

    Everything is case-sensitive, no assumption is made on the meaning
    of element names and attribute names.

    Z
descendantchildZdirect_adjacentZindirect_adjacent) >+~existsequalsZincludesZ	dashmatchZprefixmatchZsuffixmatchZsubstringmatchZ	different)rL   =z~=z|=z^=z$=z*=z!=idzxml:langFdescendant-or-self::cssprefixr,   c                    s   d  fddt|D S )u  Translate a *group of selectors* to XPath.

        Pseudo-elements are not supported here since XPath only knows
        about "real" elements.

        :param css:
            A *group of selectors* as a string.
        :param prefix:
            This string is prepended to the XPath expression for each selector.
            The default makes selectors scoped to the context node’s subtree.
        :raises:
            :class:`~cssselect.SelectorSyntaxError` on invalid selectors,
            :class:`ExpressionError` on unknown/unsupported selectors,
            including pseudo-elements.
        :returns:
            The equivalent XPath 1.0 expression as a string.

        z | c                 3   s     | ]}j | d dV  qdS )T)translate_pseudo_elementsN)selector_to_xpath.0selectorrR   r.   r   r   	<genexpr>   s
    
z1GenericTranslator.css_to_xpath.<locals>.<genexpr>)rE   r   )r.   rQ   rR   r   rX   r   css_to_xpath   s   zGenericTranslator.css_to_xpathrW   rS   c                 C   s`   t |dd}|std|f | |}t|| jsJ |r(|jr(| ||j}|p+dt| S )u+  Translate a parsed selector to XPath.


        :param selector:
            A parsed :class:`Selector` object.
        :param prefix:
            This string is prepended to the resulting XPath expression.
            The default makes selectors scoped to the context node’s subtree.
        :param translate_pseudo_elements:
            Unless this is set to ``True`` (as :meth:`css_to_xpath` does),
            the :attr:`~Selector.pseudo_element` attribute of the selector
            is ignored.
            It is the caller's responsibility to reject selectors
            with pseudo-elements, or to account for them somehow.
        :raises:
            :class:`ExpressionError` on unknown/unsupported selectors.
        :returns:
            The equivalent XPath 1.0 expression as a string.

        parsed_treeNz"Expected a parsed selector, got %rr&   )r   	TypeErrorxpath
isinstancexpathexpr_clspseudo_elementxpath_pseudo_elementr1   )r.   rW   rR   rS   treer]   r   r   r   rT      s   

z#GenericTranslator.selector_to_xpathr]   r`   c                 C   s   t d)zTranslate a pseudo-element.

        Defaults to not supporting pseudo-elements at all,
        but can be overridden by sub-classes.

        z"Pseudo-elements are not supported.)r    )r.   r]   r`   r   r   r   ra     s   z&GenericTranslator.xpath_pseudo_elementsc                 C   sP   t | } d| vrd|  } | S d| vrd|  } | S dddd t| D  } | S )	N''%s'""%s"z
concat(%s),c                 S   s$   g | ]}|rd |v rdpd| qS )rd   rg   re   r   )rV   partr   r   r   
<listcomp>  s    z3GenericTranslator.xpath_literal.<locals>.<listcomp>)r1   rE   split_at_single_quotes)rc   r   r   r   r;     s   	zGenericTranslator.xpath_literalparsed_selectorc                 C   sB   t |j}t| d|  d}|du rtd| tt||S )z%Translate any parsed selector object.zxpath_%sNz%s is not supported.)typer!   r   lowerr    typingcastr%   )r.   rl   	type_namemethodr   r   r   r]      s
   
zGenericTranslator.xpathcombinedc                 C   s<   | j |j }t| d| }tt|| |j| |jS )zTranslate a combined selector.zxpath_%s_combinator)	combinator_mapping
combinatorr   ro   rp   r%   r]   rW   subselector)r.   rs   ru   rr   r   r   r   xpath_combinedselector*  s
   z(GenericTranslator.xpath_combinedselectornegationc                 C   s@   |  |j}|  |j}|  |jr|d|j S |dS )Nznot(%s)0)r]   rW   rv   r<   r*   r9   )r.   rx   r]   Z	sub_xpathr   r   r   xpath_negation2  s   
z GenericTranslator.xpath_negationrelationc                 C   sT   |  |j}|j}|j}|  |j}t| d| jtt	|j
  }tt|||S )Nzxpath_relation_%s_combinator)r]   rW   ru   rv   r[   r   rt   ro   rp   r1   valuer%   )r.   r{   r]   ru   rv   rightrr   r   r   r   xpath_relation;  s   z GenericTranslator.xpath_relationmatchingc                    J     |j} fdd|jD }|D ]}|  |jr"||jd q|S )Nc                       g | ]}  |qS r   r]   rU   r4   r   r   rj   I      z4GenericTranslator.xpath_matching.<locals>.<listcomp>orr]   rW   Zselector_listr<   r*   r9   r.   r   r]   exprser   r4   r   xpath_matchingG     z GenericTranslator.xpath_matchingc                    r   )Nc                    r   r   r   rU   r4   r   r   rj   R  r   zAGenericTranslator.xpath_specificityadjustment.<locals>.<listcomp>r   r   r   r   r4   r   xpath_specificityadjustmentP  r   z-GenericTranslator.xpath_specificityadjustmentfunctionc                 C   sJ   d|j dd }t| |d}|std|j  tt|| |j|S )z$Translate a functional pseudo-class.zxpath_%s_function-_Nz!The pseudo-class :%s() is unknown)	r   replacer   r    ro   rp   r%   r]   rW   )r.   r   method_namerr   r   r   r   xpath_functionY  s
   z GenericTranslator.xpath_functionpseudoc                 C   sH   d|j dd }t| |d}|std|j  tt|| |jS )zTranslate a pseudo-class.zxpath_%s_pseudor   r   NzThe pseudo-class :%s is unknown)	identr   r   r    ro   rp   r%   r]   rW   )r.   r   r   rr   r   r   r   xpath_pseudoa  s
   zGenericTranslator.xpath_pseudoc                 C   s   | j |j }t| d| }| jr|j }n|j}t|}|jr.d|j|f }|o-t|j}|r5d| }nd| | }|j	du rDd}n| j
rRtt|j	j	 }n|j	j	}tt|| |j||S )z Translate an attribute selector.zxpath_attrib_%s%s:%s@zattribute::*[name() = %s]N)attribute_operator_mappingoperatorr   lower_case_attribute_namesattribrn   is_safe_name	namespacer;   r|   lower_case_attribute_valuesro   rp   r1   r%   r]   rW   )r.   rW   r   rr   r   safer   r|   r   r   r   xpath_attribj  s$   

zGenericTranslator.xpath_attribclass_selectorc                 C      |  |j}| |d|jS )zTranslate a class selector.z@class)r]   rW   xpath_attrib_includes
class_name)r.   r   r]   r   r   r   xpath_class  s   zGenericTranslator.xpath_classid_selectorc                 C   r   )zTranslate an ID selector.z@id)r]   rW   xpath_attrib_equalsrO   )r.   r   r]   r   r   r   
xpath_hash  s   zGenericTranslator.xpath_hashc                 C   sp   |j }|s
d}d}ntt|}| jr| }|jr*d|j|f }|o)tt|j}| j|d}|s6|  |S )z'Translate a type or universal selector.r'   Tr   )r)   )r)   rF   r   lower_case_element_namesrn   r   r_   r<   )r.   rW   r)   r   r]   r   r   r   xpath_element  s   zGenericTranslator.xpath_elementleftr}   c                 C      | d|S )z;right is a child, grand-child or further descendant of leftz/descendant-or-self::*/rE   r.   r   r}   r   r   r   xpath_descendant_combinator     z-GenericTranslator.xpath_descendant_combinatorc                 C   r   )z#right is an immediate child of left/r   r   r   r   r   xpath_child_combinator  r   z(GenericTranslator.xpath_child_combinatorc                 C   s   | d|}|  |dS )z)right is a sibling immediately after left/following-sibling::zposition() = 1)rE   r<   r9   r.   r   r}   r]   r   r   r    xpath_direct_adjacent_combinator  s   
z2GenericTranslator.xpath_direct_adjacent_combinatorc                 C   r   )z1right is a sibling after left, immediately or notr   r   r   r   r   r   "xpath_indirect_adjacent_combinator  r   z4GenericTranslator.xpath_indirect_adjacent_combinatorc                 C   s   |j d|dddS )zHright is a child, grand-child or further descendant of left; select leftz[descendant::rD   T)rA   rB   r   r   r   r   r   $xpath_relation_descendant_combinator  s   z6GenericTranslator.xpath_relation_descendant_combinatorc                 C      |j d|ddS )z0right is an immediate child of left; select leftz[./rD   rA   r   r   r   r   r   xpath_relation_child_combinator  s   z1GenericTranslator.xpath_relation_child_combinatorc                 C   s   | d|j}|S )z6right is a sibling immediately after left; select leftz:following-sibling::*[(name() = '{}') and (position() = 1)])r9   formatr)   r   r   r   r   )xpath_relation_direct_adjacent_combinator  s   
z;GenericTranslator.xpath_relation_direct_adjacent_combinatorc                 C   r   )z>right is a sibling after left, immediately or not; select leftz[following-sibling::rD   r   r   r   r   r   r   +xpath_relation_indirect_adjacent_combinator  s   z=GenericTranslator.xpath_relation_indirect_adjacent_combinatorTlastr<   c                    sh  z	t |j\}}W n ty   td|j w |d }|dkr&|dkr&|S |dk r3|dk r3|dS |r8d}nd|j }|sDd| }	nd| }	|dkrU|d	|	|f S g }
|dkri|dkrh|
d
|	|f  n	|
d|	|f  t|dkr|	}| t| }|dkrd| }d||f }|
d||f  t|
dkrd nd |d	 fdd|
D  |S )NzInvalid series: '%r'   r   ry   r'   z%szcount(preceding-sibling::%s)zcount(following-sibling::%s)%s = %sz%s >= %sz%s <= %sz+%sz(%s %s)z%s mod %s = 0z(%s)z and c                 3   s    | ]} | V  qd S r-   r   )rV   Z
expressiontemplater   r   rY   P  s    z=GenericTranslator.xpath_nth_child_function.<locals>.<genexpr>)
r   	arguments
ValueErrorr    r9   r)   appendabslenrE   )r.   r]   r   r   r<   abZb_min_1ZnodetestZsiblings_countZexpressionsr   Zb_negZb_neg_as_strr   r   r   xpath_nth_child_function  sH   ,


z*GenericTranslator.xpath_nth_child_functionc                 C   s   | j ||ddS )NT)r   )r   r.   r]   r   r   r   r   xpath_nth_last_child_functionS  r6   z/GenericTranslator.xpath_nth_last_child_functionc                 C   s"   |j dkr	td| j||ddS )Nr'   "*:nth-of-type() is not implementedF)r<   r)   r    r   r   r   r   r   xpath_nth_of_type_functionV     
z,GenericTranslator.xpath_nth_of_type_functionc                 C   s$   |j dkr	td| j||dddS )Nr'   r   TF)r   r<   r   r   r   r   r   xpath_nth_last_of_type_function[  s   
z1GenericTranslator.xpath_nth_last_of_type_functionc                 C   J   |  dgdgfvrtd|j tt|jd j}|d| | S )NSTRINGIDENTz9Expected a single string or ident for :contains(), got %rr   zcontains(., %s)	argument_typesr    r   ro   rp   r1   r|   r9   r;   r.   r]   r   r|   r   r   r   xpath_contains_function`  s   z)GenericTranslator.xpath_contains_functionc                 C   r   )Nr   r   5Expected a single string or ident for :lang(), got %rr   zlang(%s)r   r   r   r   r   xpath_lang_functionj  s   z%GenericTranslator.xpath_lang_functionc                 C   
   | dS )Nznot(parent::*)r9   r.   r]   r   r   r   xpath_root_pseudot     
z#GenericTranslator.xpath_root_pseudoc                 C   r   )N1r   r   r   r   r   xpath_scope_pseudo|  r   z$GenericTranslator.xpath_scope_pseudoc                 C   r   )Nzcount(preceding-sibling::*) = 0r   r   r   r   r   xpath_first_child_pseudo  r   z*GenericTranslator.xpath_first_child_pseudoc                 C   r   )Nzcount(following-sibling::*) = 0r   r   r   r   r   xpath_last_child_pseudo  r   z)GenericTranslator.xpath_last_child_pseudoc                 C   "   |j dkr	td|d|j  S )Nr'   z"*:first-of-type is not implementedz count(preceding-sibling::%s) = 0r)   r    r9   r   r   r   r   xpath_first_of_type_pseudo  r   z,GenericTranslator.xpath_first_of_type_pseudoc                 C   r   )Nr'   z!*:last-of-type is not implementedz count(following-sibling::%s) = 0r   r   r   r   r   xpath_last_of_type_pseudo  r   z+GenericTranslator.xpath_last_of_type_pseudoc                 C   r   )Nzcount(parent::*/child::*) = 1r   r   r   r   r   xpath_only_child_pseudo  r   z)GenericTranslator.xpath_only_child_pseudoc                 C   r   )Nr'   z!*:only-of-type is not implementedzcount(parent::*/child::%s) = 1r   r   r   r   r   xpath_only_of_type_pseudo  r   z+GenericTranslator.xpath_only_of_type_pseudoc                 C   r   )Nznot(*) and not(string-length())r   r   r   r   r   xpath_empty_pseudo  r   z$GenericTranslator.xpath_empty_pseudoc                 C   r   )z:Common implementation for pseudo-classes that never match.ry   r   r   r   r   r   pseudo_never_matches  s   
z&GenericTranslator.pseudo_never_matchesr   r|   c                 C   s   |rJ | | |S r-   r   r.   r]   r   r|   r   r   r   xpath_attrib_exists  s   
z%GenericTranslator.xpath_attrib_existsc                 C   s(   |d usJ | d|| |f  |S )Nr   r9   r;   r   r   r   r   r     s   z%GenericTranslator.xpath_attrib_equalsc                 C   sJ   |d usJ |r| d||| |f  |S | d|| |f  |S )Nznot(%s) or %s != %sz%s != %sr   r   r   r   r   xpath_attrib_different  s   z(GenericTranslator.xpath_attrib_differentc              	   C   s@   |rt |r|d||| d| d f  |S |d |S )Nz:%s and contains(concat(' ', normalize-space(%s), ' '), %s)rH   ry   )is_non_whitespacer9   r;   r   r   r   r   r     s   
z'GenericTranslator.xpath_attrib_includesc                 C   s8   |d usJ | d||| ||| |d f  |S )Nz'%s and (%s = %s or starts-with(%s, %s))r   r   r   r   r   r   xpath_attrib_dashmatch  s   z(GenericTranslator.xpath_attrib_dashmatchc                 C   0   |r| d||| |f  |S | d |S )Nz%s and starts-with(%s, %s)ry   r   r   r   r   r   xpath_attrib_prefixmatch  s   
z*GenericTranslator.xpath_attrib_prefixmatchc              
   C   s<   |r| d|||t|d | |f  |S | d |S )Nz/%s and substring(%s, string-length(%s)-%s) = %sr   ry   )r9   r   r;   r   r   r   r   xpath_attrib_suffixmatch  s   
z*GenericTranslator.xpath_attrib_suffixmatchc                 C   r   )Nz%s and contains(%s, %s)ry   r   r   r   r   r   xpath_attrib_substringmatch  s   
z-GenericTranslator.xpath_attrib_substringmatchN)rP   )rP   F)FT)Xr!   r"   r#   r$   rt   r   Zid_attributelang_attributer   r   r   r%   r_   r1   rZ   r   rF   rT   r   ra   staticmethodr;   r   r]   r   rw   r   rz   r   r~   r   r   r   r   r   r   r   r   r   r   r   r   r
   r   r	   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   xpath_link_pseudoZxpath_visited_pseudoZxpath_hover_pseudoZxpath_active_pseudoZxpath_focus_pseudoZxpath_target_pseudoxpath_enabled_pseudoxpath_disabled_pseudoxpath_checked_pseudor   r   r   r   r   r   r   r   r   r   r   r   r   r:      sD   
#	
				
	
	
 






r:   c                   @   s   e Zd ZdZdZddeddfddZd	edefd
dZd	ede	defddZ
d	edefddZd	edefddZd	edefddZdS )HTMLTranslatora  
    Translator for (X)HTML documents.

    Has a more useful implementation of some pseudo-classes based on
    HTML-specific element names and attribute names, as described in
    the `HTML5 specification`_. It assumes no-quirks mode.
    The API is the same as :class:`GenericTranslator`.

    .. _HTML5 specification: http://www.w3.org/TR/html5/links.html#selectors

    :param xhtml:
        If false (the default), element names and attribute names
        are case-insensitive.

    langFxhtmlr,   Nc                 C   s   || _ |sd| _d| _d S d S )NT)r   r   r   )r.   r   r   r   r   r/     s
   
zHTMLTranslator.__init__r]   c                 C   r   )Nz(@selected and name(.) = 'option') or (@checked and (name(.) = 'input' or name(.) = 'command')and (@type = 'checkbox' or @type = 'radio'))r   r   r   r   r   r        z#HTMLTranslator.xpath_checked_pseudor   c                 C   sX   |  dgdgfvrtd|j |jd j}|sJ |d| j| | d f S )Nr   r   r   r   zancestor-or-self::*[@lang][1][starts-with(concat(translate(@%s, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '-'), %s)]r   )r   r    r   r|   r9   r   r;   rn   r   r   r   r   r     s   z"HTMLTranslator.xpath_lang_functionc                 C   r   )NzA@href and (name(.) = 'a' or name(.) = 'link' or name(.) = 'area')r   r   r   r   r   r   -  s   z HTMLTranslator.xpath_link_pseudoc                 C   r   )Na  
        (
            @disabled and
            (
                (name(.) = 'input' and @type != 'hidden') or
                name(.) = 'button' or
                name(.) = 'select' or
                name(.) = 'textarea' or
                name(.) = 'command' or
                name(.) = 'fieldset' or
                name(.) = 'optgroup' or
                name(.) = 'option'
            )
        ) or (
            (
                (name(.) = 'input' and @type != 'hidden') or
                name(.) = 'button' or
                name(.) = 'select' or
                name(.) = 'textarea'
            )
            and ancestor::fieldset[@disabled]
        )
        r   r   r   r   r   r   5  r   z$HTMLTranslator.xpath_disabled_pseudoc                 C   r   )Na'  
        (
            @href and (
                name(.) = 'a' or
                name(.) = 'link' or
                name(.) = 'area'
            )
        ) or (
            (
                name(.) = 'command' or
                name(.) = 'fieldset' or
                name(.) = 'optgroup'
            )
            and not(@disabled)
        ) or (
            (
                (name(.) = 'input' and @type != 'hidden') or
                name(.) = 'button' or
                name(.) = 'select' or
                name(.) = 'textarea' or
                name(.) = 'keygen'
            )
            and not (@disabled or ancestor::fieldset[@disabled])
        ) or (
            name(.) = 'option' and not(
                @disabled or ancestor::optgroup[@disabled]
            )
        )
        r   r   r   r   r   r   S  r   z#HTMLTranslator.xpath_enabled_pseudo)F)r!   r"   r#   r$   r   rF   r/   r%   r   r   r   r   r   r   r   r   r   r   r     s    	r   r-   )$r$   rero   r   r   Zcssselect.parserr   r   r   r   r   r   r	   r
   r   r   r   r   r   r   r   r   r   no_type_checkr   RuntimeErrorr    r%   compilesplitrk   matchr   r   r:   r   r   r   r   r   <module>   s&   L
>    x