U
    :ßôgCE  ã                   @   s:  d Z ddlmZ ddlZddlZddlZzddlmZ W n  e	k
rX   ddl
mZ Y nX ddddd	d
dgZe d¡Ze d¡Ze d¡ZejZdd„ Zdd„ ZejdddZdd„ Ze d¡Ze d¡ZG dd„ deƒZG dd	„ d	eƒZd"dd
„Zd#dd„ZG dd„ dƒZdd„ Zdd iZe d!kr6ddlZe !¡  dS )$aÑ  
lxml-based doctest output comparison.

Note: normally, you should just import the `lxml.usedoctest` and
`lxml.html.usedoctest` modules from within a doctest, instead of this
one::

    >>> import lxml.usedoctest # for XML output

    >>> import lxml.html.usedoctest # for HTML output

To use this module directly, you must call ``lxmldoctest.install()``,
which will cause doctest to use this in all subsequent calls.

This changes the way output is checked and comparisons are made for
XML or HTML-like content.

XML or HTML content is noticed because the example starts with ``<``
(it's HTML if it starts with ``<html``).  You can also use the
``PARSE_HTML`` and ``PARSE_XML`` flags to force parsing.

Some rough wildcard-like things are allowed.  Whitespace is generally
ignored (except in attributes).  In text (attributes and text in the
body) you can use ``...`` as a wildcard.  In an example it also
matches any trailing tags in the element, though it does not match
leading tags.  You may create a tag ``<any>`` or include an ``any``
attribute in the tag.  An ``any`` tag matches any tag, while the
attribute matches any and all attributes.

When a match fails, the reformatted example and gotten text is
displayed (indented), and a rough diff-like output is given.  Anything
marked with ``+`` is in the output but wasn't supposed to be, and
similarly ``-`` means its in the example but wasn't in the output.

You can disable parsing on one line with ``# doctest:+NOPARSE_MARKUP``
é    )ÚetreeN)ÚescapeÚ
PARSE_HTMLÚ	PARSE_XMLÚNOPARSE_MARKUPÚLXMLOutputCheckerÚLHTMLOutputCheckerÚinstallÚtemp_installc                 C   s   | d krd S |   ¡ S d S ©N)Ústrip©Úv© r   ú7/tmp/pip-unpacked-wheel-m1sofc2u/lxml/doctestcompare.pyr   8   s    r   c                 C   s   t  d| ¡S )Nú )Ú_norm_whitespace_reÚsubr   r   r   r   Únorm_whitespace>   s    r   FT)ZrecoverZremove_blank_textc                 C   s   t  | t¡S r   )r   Ú
fromstringÚ_html_parser©Úhtmlr   r   r   Úhtml_fromstringC   s    r   z^<[^>]+ (at|object) z[ \t\n][ \t\n]+c                   @   s    e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zd'dd„Zd(dd„Zd)dd„Zdd„ Zdd„ Zdd„ Zd d!„ Zd"d#„ Zd*d$d%„Zd&S )+r   )
ÚparamÚimgÚareaÚbrÚbasefontÚinputÚbaseÚmetaÚlinkÚcolc                 C   s   t jS r   )r   ÚXML©Úselfr   r   r   Úget_default_parserP   s    z$LXMLOutputChecker.get_default_parserc           	      C   sž   t | dd ƒ}|d k	r | j}|} ntj}|  |||¡}|sF|| |||ƒS z||ƒ}W n tjk
rj   Y dS X z||ƒ}W n tjk
r   Y dS X |  ||¡S )NÚ_temp_override_selfF)ÚgetattrÚ_temp_call_super_check_outputÚOutputCheckerÚcheck_outputÚ
get_parserr   ÚXMLSyntaxErrorÚcompare_docs)	r&   ÚwantÚgotÚoptionflagsZalt_selfZsuper_methodÚparserÚwant_docÚgot_docr   r   r   r,   S   s,       ÿzLXMLOutputChecker.check_outputc                 C   st   d }t |@ rd S t|@ rt}nRt|@ r.tj}nB| ¡  ¡  d¡rT| ¡  d¡rTt}n|  	|¡rp|  	|¡rp|  
¡ }|S )Nz<html)r   r   r   r   r   r$   r   ÚlowerÚ
startswithÚ_looks_like_markupr'   )r&   r0   r1   r2   r3   r   r   r   r-   h   s     ÿ
ÿzLXMLOutputChecker.get_parserc                 C   s   |  ¡ }| d¡ot |¡ S )Nú<)r   r7   Ú_repr_reÚsearch)r&   Úsr   r   r   r8   x   s    

ÿz$LXMLOutputChecker._looks_like_markupc           
      C   s  |   |j|j¡sdS |  |j|jd¡s*dS |  |j|jd¡s@dS d|jkrœt|j ¡ ƒ}t|j ¡ ƒ}||krrdS |D ]$}|  |j| |j| d¡sv dS qv|jdks°t|ƒrt	|ƒ}t	|ƒ}|sÊ|r|rÒ|sÖdS | 
d¡}| 
d¡}	|  ||	¡súdS |sÀ|jdkrÀqqÀdS )NFTÚanyz...r   )Útag_compareÚtagÚtext_compareÚtextÚtailÚattribÚsortedÚkeysÚlenÚlistÚpopr/   )
r&   r0   r1   Z	want_keysZgot_keysÚkeyÚwant_childrenÚgot_childrenZ
want_firstZ	got_firstr   r   r   r/   }   s6    



zLXMLOutputChecker.compare_docsc                 C   s^   |pd}|pd}|r,t |ƒ ¡ }t |ƒ ¡ }dt |¡ }| dd¡}t ||¡rVdS dS d S )NÚ z^%s$z\.\.\.z.*TF)r   r   Úrer   Úreplacer;   )r&   r0   r1   r   r   r   r   r@   š   s    zLXMLOutputChecker.text_comparec                 C   sr   |dkrdS t |ttfƒr(t |ttfƒs0||kS |p6d}|p>d}| d¡rf| d¡d | d¡d kS ||kS d S )Nr=   TrL   z{...}Ú}éÿÿÿÿ)Ú
isinstanceÚstrÚbytesr7   Úsplit)r&   r0   r1   r   r   r   r>   §   s    ÿ
zLXMLOutputChecker.tag_comparec                 C   s  |j }|  |||¡}g }|d k	rœz||ƒ}W n0 tjk
r\   t ¡ d }| d| ¡ Y nX z||ƒ}	W n0 tjk
rš   t ¡ d }| d| ¡ Y nX |d ks¨|rÔt | |||¡}
|rÐ| |
¡ d 	|¡S |
S |t
k}d|  ||d¡d|  |	|d¡d|  ||	|d¡g}d 	|¡S )	Né   zIn example: %szIn actual output: %sÚ
z	Expected:é   zGot:zDiff:)r0   r-   r   r.   ÚsysÚexc_infoÚappendr+   Úoutput_differenceÚjoinr   Ú
format_docÚcollect_diff)r&   Zexampler1   r2   r0   r3   Úerrorsr4   Úer5   Úvaluer   Z
diff_partsr   r   r   r[   µ   sD       ÿ

ûz#LXMLOutputChecker.output_differenceTc                 C   s.   |sdS |j | jkrdS |js&t|ƒr*dS dS )NFT)r?   Ú
empty_tagsrA   rF   )r&   Úelr   r   r   r   Úhtml_empty_tagÕ   s    z LXMLOutputChecker.html_empty_tagrL   c              	   C   sž  g }t |ƒsœ| d| ¡ | |¡ | |  |¡¡ |  ||¡slt|jƒr\| |  |j¡¡ | |  |¡¡ t|jƒrˆ| |  |j¡¡ | d¡ d 	|¡S | d| ¡ | |¡ | |  |¡¡ |  ||¡s^| d¡ t|jƒr| d| ¡ | |  |j¡¡ | d¡ |D ]}| |  
|||d ¡¡ q| d| ¡ | |  |¡¡ | d¡ t|jƒr”| d| ¡ | |  |j¡¡ | d¡ d 	|¡S )Nr   rV   rL   rW   )rF   rZ   Ú
format_tagrd   r   rA   Úformat_textÚformat_end_tagrB   r\   r]   )r&   Údocr   ÚindentÚprefixÚpartsrc   r   r   r   r]   ß   s@    









zLXMLOutputChecker.format_docc                 C   s"   |d krdS |r|  ¡ }t|dƒS )NrL   rU   )r   Úhtml_escape)r&   rA   r   r   r   r   rf     s
    zLXMLOutputChecker.format_textc              	   C   sh   g }t |tjƒrdS t|j ¡ ƒD ]"\}}| d||  |d¡f ¡ q"|sTd|j S d|jd 	|¡f S )Nz<!--ú%s="%s"Fú<%s>ú<%s %s>r   )
rQ   r   ÚCommentBaserD   rC   ÚitemsrZ   rf   r?   r\   )r&   rc   ÚattrsÚnamera   r   r   r   re   	  s    
zLXMLOutputChecker.format_tagc                 C   s   t |tjƒrdS d|j S )Nz-->ú</%s>)rQ   r   rp   r?   )r&   rc   r   r   r   rg     s    z LXMLOutputChecker.format_end_tagc              	   C   s  g }t |ƒs’t |ƒs’| d| ¡ | |  ||¡¡ |  ||¡sh| |  |j|j¡¡ | |  ||¡¡ | |  |j|j¡¡ | d¡ d |¡S | d| ¡ | |  ||¡¡ | d¡ t	|jƒsÐt	|jƒrþ| d| ¡ | |  |j|j¡¡ | d¡ t
|ƒ}t
|ƒ}|s|r˜|sD| |  | d¡||d d¡¡ q|sn| |  | d¡||d d¡¡ q| |  | d¡| d¡||d ¡¡ q| d| ¡ | |  ||¡¡ | d¡ t	|jƒsÚt	|jƒr| d| ¡ | |  |j|j¡¡ | d¡ d |¡S )Nr   rV   rL   r   rW   ú+ú-)rF   rZ   Úcollect_diff_tagrd   Úcollect_diff_textrA   Úcollect_diff_end_tagrB   r\   r   rG   r]   rH   r^   )r&   r0   r1   r   ri   rk   rJ   rK   r   r   r   r^     sP    



     ÿ


zLXMLOutputChecker.collect_diffc           	   	   C   s*  |   |j|j¡s"d|j|jf }n|j}g }|jdkp>d|jk}t|j ¡ ƒD ]p\}}||jkr€|s€| d||  |d¡f ¡ qN||jkr |  |j| |d¡}n|  |d¡}| d||f ¡ qN|st|j ¡ ƒD ].\}}||jkrèqÔ| d||  |d¡f ¡ qÔ|rd|d |¡f }nd	| }|S )
Nú%s (got: %s)r=   z+%s="%s"Frm   z-%s="%s"ro   r   rn   )	r>   r?   rC   rD   rq   rZ   rf   rx   r\   )	r&   r0   r1   r?   rr   r=   rs   ra   rA   r   r   r   rw   @  s*    

z"LXMLOutputChecker.collect_diff_tagc                 C   s,   |j |j krd|j |j f }n|j }d| S )Nrz   rt   )r?   )r&   r0   r1   r?   r   r   r   ry   [  s    z&LXMLOutputChecker.collect_diff_end_tagc                 C   s:   |   |||¡r"|sdS |  ||¡S d||f }|  ||¡S )NrL   rz   )r@   rf   )r&   r0   r1   r   rA   r   r   r   rx   b  s    z#LXMLOutputChecker.collect_diff_textN)T)rL   )T)T)Ú__name__Ú
__module__Ú__qualname__rb   r'   r,   r-   r8   r/   r@   r>   r[   rd   r]   rf   re   rg   r^   rw   ry   rx   r   r   r   r   r   J   s$    


#
&c                   @   s   e Zd Zdd„ ZdS )r   c                 C   s   t S r   )r   r%   r   r   r   r'   k  s    z%LHTMLOutputChecker.get_default_parserN)r{   r|   r}   r'   r   r   r   r   r   j  s   c                 C   s   | rt t_ntt_dS )z£
    Install doctestcompare for all future doctests.

    If html is true, then by default the HTML parser will be used;
    otherwise the XML parser is used.
    N)r   Údoctestr+   r   r   r   r   r   r	   n  s    c           	      C   s`   | r
t }nt}tƒ }|jd }|ƒ }|j}||_|jd j}|jj}tt_t	||||||ƒ dS )zÁ
    Use this *inside* a doctest to enable this checker for this
    doctest only.

    If html is true, then by default the HTML parser will be used;
    otherwise the XML parser is used.
    r&   ÚcheckN)
r   r   Ú_find_doctest_frameÚf_localsZ_checkerÚ__func__r,   r   r~   Ú_RestoreChecker)	r   Ú
del_moduleZCheckerÚframeÚdt_selfÚcheckerÚold_checkerÚ
check_funcZchecker_check_funcr   r   r   r
   z  s     

 þc                   @   sL   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ Zdd„ Z	dd„ Z
dS )rƒ   c                 C   sD   || _ || _| j| j_|| j_|| _|| _|| _|  ¡  |  	¡  d S r   )
r†   r‡   Ú
call_superr*   r(   r‰   Ú
clone_funcr„   Úinstall_cloneÚinstall_dt_self)r&   r†   rˆ   Znew_checkerr‰   r‹   r„   r   r   r   Ú__init__ž  s    
z_RestoreChecker.__init__c                 C   s$   | j j| _| j j| _| jj| j _d S r   )r‰   Ú__code__Ú	func_codeÚ__globals__Zfunc_globalsr‹   r%   r   r   r   rŒ   ©  s    

z_RestoreChecker.install_clonec                 C   s   | j | j_d S r   )r   r‰   r   r%   r   r   r   Úuninstall_clone­  s    z_RestoreChecker.uninstall_clonec                 C   s   | j j| _| | j _d S r   )r†   Ú_DocTestRunner__record_outcomeÚ	prev_funcr%   r   r   r   r   ¯  s    
z_RestoreChecker.install_dt_selfc                 C   s   | j | j_d S r   )r”   r†   r“   r%   r   r   r   Úuninstall_dt_self²  s    z!_RestoreChecker.uninstall_dt_selfc                 C   sL   | j rHdd l}|j| j = d| j krH| j  dd¡\}}|j| }t||ƒ d S )Nr   Ú.rU   )r„   rX   ÚmodulesÚrsplitÚdelattr)r&   rX   ÚpackageÚmoduleZpackage_modr   r   r   Úuninstall_module´  s    


z _RestoreChecker.uninstall_modulec                 O   s4   |   ¡  |  ¡  | j`| j`| j||Ž}|  ¡  |S r   )r’   r•   r‡   r(   r*   r”   rœ   )r&   ÚargsÚkwÚresultr   r   r   Ú__call__¼  s    z_RestoreChecker.__call__c                 O   s(   |   ¡  z| j||ŽW ¢S |  ¡  X d S r   )r’   rŒ   r‰   )r&   r   rž   r   r   r   rŠ   Ä  s    z_RestoreChecker.call_superN)r{   r|   r}   rŽ   rŒ   r’   r   r•   rœ   r    rŠ   r   r   r   r   rƒ     s   rƒ   c                  C   s<   dd l } |  d¡}|r0|j}d|kr(|S |j}qtdƒ‚d S )Nr   rU   ZBOOMzBCould not find doctest (only use this function *inside* a doctest))rX   Ú	_getframer   Úf_backÚLookupError)rX   r…   Úlr   r   r   r€   Ë  s    
ÿr€   Úbasicai  
    >>> temp_install()
    >>> print """<xml a="1" b="2">stuff</xml>"""
    <xml b="2" a="1">...</xml>
    >>> print """<xml xmlns="http://example.com"><tag   attr="bar"   /></xml>"""
    <xml xmlns="...">
      <tag attr="..." />
    </xml>
    >>> print """<xml>blahblahblah<foo /></xml>""" # doctest: +NOPARSE_MARKUP, +ELLIPSIS
    <xml>...foo /></xml>
    Ú__main__)F)FN)"Ú__doc__Úlxmlr   rX   rM   r~   r   r   rl   ÚImportErrorÚcgiÚ__all__Zregister_optionflagr   r   r   r+   r   r   Ú
HTMLParserr   r   Úcompiler:   r   r   r   r	   r
   rƒ   r€   Z__test__r{   Útestmodr   r   r   r   Ú<module>   sJ   %  ÿ




  "

#. ÿ
