B
    eAd£G  ã               @   sp  d Z ddlmZ ddlZddlZddlZy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yeZW n ek
r   eefZY nX ejd dk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e$ƒZ%dd„ Z&d d!iZ'e(d"krld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_installé   c             C   s   | d krd S |   ¡ S d S )N)Ústrip)Úv© r   úE/var/www/html/venv/lib/python3.7/site-packages/lxml/doctestcompare.pyr   ?   s    r   c             C   s   t  d| ¡S )Nú )Ú_norm_whitespace_reÚsub)r   r   r   r   Únorm_whitespaceE   s    r   FT)ZrecoverZremove_blank_textc             C   s   t  | t¡S )N)r   Ú
fromstringÚ_html_parser)Úhtmlr   r   r   Úhtml_fromstringJ   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   )
ÚparamZimgZareaÚbrZbasefontÚinputÚbaseÚmetaÚlinkÚcolc             C   s   t jS )N)r   ÚXML)Úselfr   r   r   Úget_default_parserW   s    z$LXMLOutputChecker.get_default_parserc       	      C   sš   t | dd ƒ}|d k	r | j}|} ntj}|  |||¡}|sF|| |||ƒS y||ƒ}W n tjk
rh   dS X y||ƒ}W n tjk
rŒ   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&   Z   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    r*   r+   r,   r-   r   r   r   r'   o   s    

zLXMLOutputChecker.get_parserc             C   s   |  ¡ }| d¡ot |¡ S )Nú<)r   r1   Ú_repr_reÚsearch)r    Úsr   r   r   r2      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 x*|D ]"}|  |j| |j| d¡sxdS qxW |jdks²t|ƒrt	|ƒ}t	|ƒ}xN|sÎ|r|rÖ|sÚdS | 
d¡}| 
d¡}	|  ||	¡sþdS |sÄ|jdkrÄP qÄW dS )NFTÚanyz...r   )Útag_compareÚtagÚtext_compareÚtextÚtailÚattribÚsortedÚkeysÚlenÚlistÚpopr)   )
r    r*   r+   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   Úreplacer5   )r    r*   r+   r   r   r   r   r:   ¡   s    zLXMLOutputChecker.text_comparec             C   sj   |dkrdS t |tƒr t |tƒs(||kS |p.d}|p6d}| d¡r^| d¡d | d¡d kS ||kS d S )Nr7   TrF   z{...}Ú}éÿÿÿÿ)Ú
isinstanceÚ_basestringr1   Úsplit)r    r*   r+   r   r   r   r8   ®   s    


zLXMLOutputChecker.tag_comparec             C   s  |j }|  |||¡}g }|d k	rœy||ƒ}W n0 tjk
r\   t ¡ d }| d| ¡ Y nX y||ƒ}	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:)r*   r'   r   r(   ÚsysÚexc_infoÚappendr%   Úoutput_differenceÚjoinr   Ú
format_docÚcollect_diff)r    Zexampler+   r,   r*   r-   Úerrorsr.   Úer/   Úvaluer   Z
diff_partsr   r   r   rT   ¼   s:    

z#LXMLOutputChecker.output_differenceTc             C   s.   |sdS |j | jkrdS |js&t|ƒr*dS dS )NFT)r9   Ú
empty_tagsr;   r@   )r    Úelr   r   r   r   Úhtml_empty_tagÜ   s    z LXMLOutputChecker.html_empty_tagrF   c          	   C   s¢  g }t |ƒsœ| d| ¡ | |¡ | |  |¡¡ |  ||¡slt|jƒr\| |  |j¡¡ | |  |¡¡ t|jƒrˆ| |  |j¡¡ | d¡ d 	|¡S | d| ¡ | |¡ | |  |¡¡ |  ||¡sb| d¡ t|jƒr| d| ¡ | |  |j¡¡ | d¡ x&|D ]}| |  
|||d ¡¡ qW | d| ¡ | |  |¡¡ | d¡ t|jƒr˜| d| ¡ | |  |j¡¡ | d¡ d 	|¡S )Nr   rO   rF   rP   )r@   rS   Ú
format_tagr]   r   r;   Úformat_textÚformat_end_tagr<   rU   rV   )r    Údocr   ÚindentÚprefixÚpartsr\   r   r   r   rV   æ   s@    










zLXMLOutputChecker.format_docc             C   s"   |d krdS |r|  ¡ }t|dƒS )NrF   rN   )r   Úhtml_escape)r    r;   r   r   r   r   r_   	  s
    zLXMLOutputChecker.format_textc          	   C   sl   g }t |tjƒrdS x4t|j ¡ ƒD ]"\}}| d||  |d¡f ¡ q$W |sXd|j S d|jd 	|¡f S )Nz<!--z%s="%s"Fz<%s>z<%s %s>r   )
rK   r   ÚCommentBaser>   r=   ÚitemsrS   r_   r9   rU   )r    r\   ÚattrsÚnamerZ   r   r   r   r^     s    
zLXMLOutputChecker.format_tagc             C   s   t |tjƒrdS d|j S )Nz-->z</%s>)rK   r   rf   r9   )r    r\   r   r   r   r`     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
|ƒ}xŒ|s|rš|sF| |  | d¡||d d¡¡ q|sp| |  | d¡||d d¡¡ q| |  | d¡| d¡||d ¡¡ qW | d| ¡ | |  ||¡¡ | d¡ t	|jƒsÞt	|jƒr| d| ¡ | |  |j|j¡¡ | d¡ d |¡S )Nr   rO   rF   r   rP   ú+ú-)r@   rS   Úcollect_diff_tagr]   Úcollect_diff_textr;   Úcollect_diff_end_tagr<   rU   r   rA   rV   rB   rW   )r    r*   r+   r   rb   rd   rD   rE   r   r   r   rW   !  sH    



  $

zLXMLOutputChecker.collect_diffc       	   	   C   s2  |   |j|j¡s"d|j|jf }n|j}g }|jdkp>d|jk}x‚t|j ¡ ƒD ]p\}}||jkr‚|s‚| d||  |d¡f ¡ qP||jkr¢|  |j| |d¡}n|  |d¡}| d||f ¡ qPW |sx@t|j ¡ ƒD ].\}}||jkrîqÚ| d||  |d¡f ¡ qÚW |r&d|d |¡f }nd	| }|S )
Nz%s (got: %s)r7   z+%s="%s"Fz%s="%s"z-%s="%s"z<%s %s>r   z<%s>)	r8   r9   r=   r>   rg   rS   r_   rm   rU   )	r    r*   r+   r9   rh   r7   ri   rZ   r;   r   r   r   rl   G  s*    

z"LXMLOutputChecker.collect_diff_tagc             C   s,   |j |j krd|j |j f }n|j }d| S )Nz%s (got: %s)z</%s>)r9   )r    r*   r+   r9   r   r   r   rn   b  s    z&LXMLOutputChecker.collect_diff_end_tagc             C   s:   |   |||¡r"|sdS |  ||¡S d||f }|  ||¡S )NrF   z%s (got: %s))r:   r_   )r    r*   r+   r   r;   r   r   r   rm   i  s    z#LXMLOutputChecker.collect_diff_textN)T)rF   )T)T)Ú__name__Ú
__module__Ú__qualname__r[   r!   r&   r'   r2   r)   r:   r8   rT   r]   rV   r_   r^   r`   rW   rl   rn   rm   r   r   r   r   r   Q   s$    


#
&c               @   s   e Zd Zdd„ ZdS )r   c             C   s   t S )N)r   )r    r   r   r   r!   r  s    z%LHTMLOutputChecker.get_default_parserN)ro   rp   rq   r!   r   r   r   r   r   q  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	   u  s    c       	      C   sz   | r
t }nt}tƒ }|jd }|ƒ }|j}||_trJ|jd j}|jj}n|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Ú_IS_PYTHON_3Ú__func__r&   Zim_funcr   rr   Ú_RestoreChecker)	r   Ú
del_moduleZCheckerÚframeÚdt_selfÚcheckerÚold_checkerÚ
check_funcZchecker_check_funcr   r   r   r
     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 )rx   c             C   sD   || _ || _| j| j_|| j_|| _|| _|| _|  ¡  |  	¡  d S )N)
r{   r|   Ú
call_superr$   r"   r~   Ú
clone_funcry   Úinstall_cloneÚinstall_dt_self)r    r{   r}   Znew_checkerr~   r€   ry   r   r   r   Ú__init__©  s    
z_RestoreChecker.__init__c             C   sJ   t r&| jj| _| jj| _| jj| j_n | jj| _| jj| _| jj| j_d S )N)rv   r~   Ú__code__Ú	func_codeÚ__globals__Zfunc_globalsr€   )r    r   r   r   r   ´  s    



z_RestoreChecker.install_clonec             C   s   t r| j| j_n
| j| j_d S )N)rv   r…   r~   r„   )r    r   r   r   Úuninstall_clone½  s    z_RestoreChecker.uninstall_clonec             C   s   | j j| _| | j _d S )N)r{   Ú_DocTestRunner__record_outcomeÚ	prev_func)r    r   r   r   r‚   Â  s    
z_RestoreChecker.install_dt_selfc             C   s   | j | j_d S )N)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   Ú.rN   )ry   rQ   ÚmodulesÚrsplitÚdelattr)r    rQ   ÚpackageÚmoduleZpackage_modr   r   r   Úuninstall_moduleÇ  s    


z _RestoreChecker.uninstall_modulec             O   s4   |   ¡  |  ¡  | j`| j`| j||Ž}|  ¡  |S )N)r‡   rŠ   r|   r"   r$   r‰   r‘   )r    ÚargsÚkwÚresultr   r   r   Ú__call__Ï  s    z_RestoreChecker.__call__c             O   s$   |   ¡  z| j||ŽS |  ¡  X d S )N)r‡   r~   r   )r    r’   r“   r   r   r   r   ×  s    z_RestoreChecker.call_superN)ro   rp   rq   rƒ   r   r‡   r‚   rŠ   r‘   r•   r   r   r   r   r   rx   ¨  s   	rx   c              C   s@   dd l } |  d¡}x |r2|j}d|kr*|S |j}qW tdƒ‚d S )Nr   rN   ZBOOMzBCould not find doctest (only use this function *inside* a doctest))rQ   Ú	_getframeru   Úf_backÚLookupError)rQ   rz   Úlr   r   r   rt   Þ  s    

rt   Ú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__Zlxmlr   rQ   rG   rr   r   r   re   ÚImportErrorÚcgiÚ__all__Ú
basestringrL   Ú	NameErrorÚstrÚbytesÚversion_inforv   Zregister_optionflagr   r   r   r%   r   r   Ú
HTMLParserr   r   Úcompiler4   r   r   r   r	   r
   Úobjectrx   rt   Z__test__ro   Útestmodr   r   r   r   Ú<module>$   sL   





  "

'6

