U
    :g8                     @   sr   d dl Z d dlmZ d dlmZ ddlmZmZ ee drBe j	Z	nG dd dZ	G dd	 d	Z
d
d Zdd ZdS )    N)warn)ascii_lower   )compile_selector_listsplit_whitespacecached_propertyc                   @   s&   e Zd ZdddZde fddZdS )r   Nc                 C   s*   |p|j | _ |j| _|p|j| _|| _d S N)__name__
__module____doc__func)selfr   namedoc r   3/tmp/pip-unpacked-wheel-xeg67qda/cssselect2/tree.py__init__   s    zcached_property.__init__c                 C   s>   |d kr| S |j | j|}||kr:| |}||j | j< |S r   )__dict__getr	   r   )r   objtypeZ_cached_property__missingvaluer   r   r   __get__   s    
zcached_property.__get__)NN)r	   r
   __qualname__r   objectr   r   r   r   r   r      s   
c                   @   s$  e Zd ZdZed:ddZed;ddZed<dd	Zd=d
dZdd Z	dd Z
dd Zdd Zedd Zedd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zed$d% Zd&d' Zd(d) Zd*d+ Zed,d- Zed.d/ Zed0d1 Zed2d3 Zed4d5 Z ed6d7 Z!ed8d9 Z"dS )>ElementWrappera  Wrapper of :class:`xml.etree.ElementTree.Element` for Selector matching.

    This class should not be instanciated directly. :meth:`from_xml_root` or
    :meth:`from_html_root` should be used for the root element of a document,
    and other elements should be accessed (and wrappers generated) using
    methods such as :meth:`iter_children` and :meth:`iter_subtree`.

    :class:`ElementWrapper` objects compare equal if their underlying
    :class:`xml.etree.ElementTree.Element` do.

    Nc                 C   s   | j ||ddS )a.  Wrap for selector matching the root of an XML or XHTML document.

        :param root:
            An ElementTree :class:`xml.etree.ElementTree.Element`
            for the root element of a document.
            If the given element is not the root,
            selector matching will behave is if it were.
            In other words, selectors will be not be `scoped`_
            to the subtree rooted at that element.
        :returns:
            A new :class:`ElementWrapper`

        .. _scoped: https://drafts.csswg.org/selectors-4/#scoping

        Fin_html_document
_from_rootclsrootcontent_languager   r   r   from_xml_root-   s    zElementWrapper.from_xml_rootc                 C   s   | j ||ddS )zSame as :meth:`from_xml_root` with case-insensitive attribute names.

        Useful for documents parsed with an HTML parser like html5lib, which
        should be the case of documents with the ``text/html`` MIME type.

        Tr   r   r    r   r   r   from_html_root@   s    zElementWrapper.from_html_rootTc                 C   s&   t |dr| }| |d dd ||dS )Ngetrootr   )parentindexpreviousr   r#   )hasattrr&   )r!   r"   r#   r   r   r   r   r   J   s    
   zElementWrapper._from_rootc                 C   sN   || _ || _|| _|d k	r$|j| _n|g| _|| _|| _|| _d | _d | _	d S r   )
etree_elementr'   r)   etree_childrenZetree_siblingsr(   r   transport_content_language
_ancestors_previous_siblings)r   r+   r'   r(   r)   r   r#   r   r   r   r   S   s    
zElementWrapper.__init__c                 C   s   t | t |ko| j|jkS r   )r   r+   r   otherr   r   r   __eq__o   s    
zElementWrapper.__eq__c                 C   s
   | |k S r   r   r0   r   r   r   __ne__t   s    zElementWrapper.__ne__c                 C   s   t t| | jfS r   )hashr   r+   r   r   r   r   __hash__w   s    zElementWrapper.__hash__c                 c   s   |   E d H  d S r   )iter_childrenr5   r   r   r   __iter__z   s    zElementWrapper.__iter__c                 C   s0   | j dkr*| jdkrdn| jj| jf | _ | j S )u   Tuple of existing ancestors.

        Tuple of existing :class:`ElementWrapper` objects for this element’s
        ancestors, in reversed tree order, from :attr:`parent` to the root.

        Nr   )r.   r'   	ancestorsr5   r   r   r   r9   }   s
    
zElementWrapper.ancestorsc                 C   s0   | j dkr*| jdkrdn| jj| jf | _ | j S )u   Tuple of previous siblings.

        Tuple of existing :class:`ElementWrapper` objects for this element’s
        previous siblings, in reversed tree order.

        Nr   )r/   r)   previous_siblingsr5   r   r   r   r:      s
    
z ElementWrapper.previous_siblingsc                 c   s   t dt | jE dH  dS )u  Iterate over ancestors.

        Return an iterator of existing :class:`ElementWrapper` objects for this
        element’s ancestors, in reversed tree order (from :attr:`parent` to the
        root).

        The element itself is not included, this is an empty sequence for the
        root element.

        This method is deprecated and will be removed in version 0.7.0. Use
        :attr:`ancestors` instead.

        zfThis method is deprecated and will be removed in version 0.7.0. Use the "ancestors" attribute instead.N)r   DeprecationWarningr9   r5   r   r   r   iter_ancestors   s
    zElementWrapper.iter_ancestorsc                 c   s   t dt | jE dH  dS )u  Iterate over previous siblings.

        Return an iterator of existing :class:`ElementWrapper` objects for this
        element’s previous siblings, in reversed tree order.

        The element itself is not included, this is an empty sequence for a
        first child or the root element.

        This method is deprecated and will be removed in version 0.7.0. Use
        :attr:`previous_siblings` instead.

        znThis method is deprecated and will be removed in version 0.7.0. Use the "previous_siblings" attribute instead.N)r   r;   r:   r5   r   r   r   iter_previous_siblings   s
    z%ElementWrapper.iter_previous_siblingsc                 c   s&   | j dkr| V  n| j  E dH  dS )u   Iterate over siblings.

        Return an iterator of newly-created :class:`ElementWrapper` objects for
        this element’s siblings, in tree order.

        N)r'   r7   r5   r   r   r   iter_siblings   s    
zElementWrapper.iter_siblingsc                 c   s,   d}|   D ]}|r|V  || krd}qdS )u   Iterate over next siblings.

        Return an iterator of newly-created :class:`ElementWrapper` objects for
        this element’s next siblings, in tree order.

        FTN)r>   )r   foundsiblingr   r   r   iter_next_siblings   s    z!ElementWrapper.iter_next_siblingsc                 c   s:   d}t | jD ]&\}}t| || ||| jd}|V  qdS )u   Iterate over children.

        Return an iterator of newly-created :class:`ElementWrapper` objects for
        this element’s child elements, in tree order.

        N)r'   r(   r)   r   )	enumerater,   r   r   )r   childiZetree_childr   r   r   r7      s       zElementWrapper.iter_childrenc                 c   sJ   t | gg}|rFt|d d}|dkr0|  q|V  ||  qdS )a  Iterate over subtree.

        Return an iterator of newly-created :class:`ElementWrapper` objects for
        the entire subtree rooted at this element, in tree order.

        Unlike in other methods, the element itself *is* included.

        This loops over an entire document:

        .. code-block:: python

            for element in ElementWrapper.from_root(root_etree).iter_subtree():
                ...

        N)iternextpopappendr7   )r   stackelementr   r   r   iter_subtree   s    
zElementWrapper.iter_subtreec                 C   s   dd | D S )Nc                 S   s@   g | ]8}t |d r|gnt|D ]}|jdkr |js |jq qS )testN)r*   r   Zpseudo_elementZnever_matchesrM   ).0selectorZcompiled_selectorr   r   r   
<listcomp>  s   

z+ElementWrapper._compile.<locals>.<listcomp>r   )	selectorsr   r   r   _compile  s    zElementWrapper._compilec                    s   t  fdd |D S )zReturn wether this elememt matches any of the given selectors.

        :param selectors:
            Each given selector is either a :class:`compiler.CompiledSelector`,
            or an argument to :func:`compile_selector_list`.

        c                 3   s   | ]}| V  qd S r   r   rN   rM   r5   r   r   	<genexpr>  s     z)ElementWrapper.matches.<locals>.<genexpr>)anyrR   r   rQ   r   r5   r   matches  s    zElementWrapper.matchesc                    sN   |  | t dkr(t d |  S |rB fdd|  D S tdS dS )a  Return elements, in tree order, that match any of given selectors.

        Selectors are `scoped`_ to the subtree rooted at this element.

        .. _scoped: https://drafts.csswg.org/selectors-4/#scoping

        :param selectors:
            Each given selector is either a :class:`compiler.CompiledSelector`,
            or an argument to :func:`compile_selector_list`.
        :returns:
            An iterator of newly-created :class:`ElementWrapper` objects.

        r   r   c                 3   s(   | ]  t  fd dD r V  qdS )c                 3   s   | ]}| V  qd S r   r   rS   rK   r   r   rT   *  s     z5ElementWrapper.query_all.<locals>.<genexpr>.<genexpr>N)rU   )rN   testsrX   r   rT   (  s   z+ElementWrapper.query_all.<locals>.<genexpr>r   N)rR   lenfilterrL   rF   rV   r   rY   r   	query_all  s    

zElementWrapper.query_allc                 G   s   t | j| dS )aj  Return first element that matches any of given selectors.

        :param selectors:
            Each given selector is either a :class:`compiler.CompiledSelector`,
            or an argument to :func:`compile_selector_list`.
        :returns:
            A newly-created :class:`ElementWrapper` object,
            or :obj:`None` if there is no match.

        N)rG   r]   rV   r   r   r   query.  s    zElementWrapper.queryc                 C   s   dd | j D S )a%  Children as a list of :class:`xml.etree.ElementTree.Element`.

        Other ElementTree nodes such as
        :func:`comments <xml.etree.ElementTree.Comment>` and
        :func:`processing instructions
        <xml.etree.ElementTree.ProcessingInstruction>`
        are not included.

        c                 S   s   g | ]}t |jtr|qS r   )
isinstancetagstr)rN   rK   r   r   r   rP   F  s   z1ElementWrapper.etree_children.<locals>.<listcomp>)r+   r5   r   r   r   r,   ;  s    zElementWrapper.etree_childrenc                 C   s"   t | jj\}}|| jtd< |S )z,The local name of this element, as a string.namespace_url_split_etree_tagr+   r`   r   ra   r   rb   
local_namer   r   r   rf   J  s    zElementWrapper.local_namec                 C   s"   t | jj\}}|| jtd< |S )z/The namespace URL of this element, as a string.rf   rc   re   r   r   r   rb   Q  s    zElementWrapper.namespace_urlc                 C   s   | j dS )z$The ID of this element, as a string.id)r+   r   r5   r   r   r   rg   X  s    zElementWrapper.idc                 C   s   t t| jddS )z:The classes of this element, as a :class:`set` of strings.class )setr   r+   r   r5   r   r   r   classes]  s    zElementWrapper.classesc                 C   s   | j d}|dk	rt|S | jp*| jdk}|rL| j d}|dk	rLt|S | jdk	r^| jjS |rd}| j d}|D ]*}|dd}t|dkrvt|d	}qv|dk	rt|S t| j	pdS )
z*The language of this element, as a string.z*{http://www.w3.org/XML/1998/namespace}langNzhttp://www.w3.org/1999/xhtmllangz"{http://www.w3.org/1999/xhtml}metaz
http-equivri   zcontent-languagecontent)
r+   r   r   r   rb   r'   rl   rF   _parse_content_languager-   )r   Zxml_langZis_htmlrl   r#   iteratormetaZ
http_equivr   r   r   rl   b  s8    
zElementWrapper.langc                    sh   | j d krdS d}d | j jj|koZ| j jdd k	oZ| jj kpZt fdd|  D }|pf| j jS )NFz&{http://www.w3.org/1999/xhtml}fieldsetz${http://www.w3.org/1999/xhtml}legenddisabledc                 3   s   | ]}|j j kV  qd S r   )r+   r`   )rN   r@   Zlegendr   r   rT     s   z6ElementWrapper.in_disabled_fieldset.<locals>.<genexpr>)r'   r+   r`   r   rU   r=   in_disabled_fieldset)r   fieldsetZdisabled_fieldsetr   rr   r   rs     s    
z#ElementWrapper.in_disabled_fieldset)N)N)T)N)#r	   r
   r   r   classmethodr$   r%   r   r   r2   r3   r6   r8   propertyr9   r:   r<   r=   r>   rA   r7   rL   staticmethodrR   rW   r]   r^   r   r,   rf   rb   rg   rk   rl   rs   r   r   r   r   r   !   sT   		 











r   c                 C   sJ   |  d}|dkrd| fS | d dks*t| d| | |d d  fS d S )N}rE   ri   r   {r   )rfindAssertionError)r`   positionr   r   r   rd     s
    
rd   c                 C   s0   | d k	r,d| kr,t | }t|dkr,|d S d S )N,r   r   )r   r[   )r   partsr   r   r   rn     s    rn   )	functoolswarningsr   webencodingsr   compilerr   r   r*   r   r   rd   rn   r   r   r   r   <module>   s   
  r	