3
(hCE                 @   s:  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ejdZejdZejdZejZdd Zdd ZejdddZdd ZejdZej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j!  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 | j  S d S )N)strip)v r   5/tmp/pip-install-q3hcpn_q/lxml/lxml/doctestcompare.pyr   8   s    r   c             C   s   t jd| S )N )_norm_whitespace_resub)r   r   r   r   norm_whitespace>   s    r   FT)ZrecoverZremove_blank_textc             C   s   t j| tS )N)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d0Zdd Zdd Zdd Zdd Zdd Zdd Z	dd Z
dd Zd1ddZd2dd Zd3d!d"Zd#d$ Zd%d& Zd'd( Zd)d* Zd+d, Zd4d-d.Zd/S )5r   paramimgareabrbasefontinputbasemetalinkcolc             C   s   t jS )N)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}| j|||}|sF|| |||S y||}W n tjk
rh   dS X y||}W n tjk
r   dS X | j||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|j j jdrT|j jdrTt}n| j	|rp| j	|rp| j
 }|S )Nz<html)r   r   r   r   r   r!   r   lower
startswith_looks_like_markupr#   )r"   r,   r-   r.   r/   r   r   r   r)   h   s    

zLXMLOutputChecker.get_parserc             C   s   |j  }|jdotj| S )N<)r   r3   _repr_research)r"   sr   r   r   r4   x   s    
z$LXMLOutputChecker._looks_like_markupc       
      C   s  | j |j|jsdS | j|j|jds*dS | j|j|jds@dS d|jkrt|jj }t|jj }||krrdS x*|D ]"}| j|j| |j| dsxdS qxW |jdkst|rt	|}t	|}xV|s|r| s| rdS |j
d}|j
d}	| j||	sdS | r|jdkrP qW 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 |j }t |j }dtj| }|jdd}tj||rVdS dS d S )N z^%s$z\.\.\.z.*TF)r   r   rer   replacer7   )r"   r,   r-   r   r   r   r   r<      s    zLXMLOutputChecker.text_comparec             C   sv   |dkrdS t |ttf s,t |ttf r4||kS |p:d}|pBd}|jdrj|jdd |jdd kS ||kS d S )	Nr9   TrH   z{...}}   rM   )
isinstancestrbytesr3   split)r"   r,   r-   r   r   r   r:      s    
zLXMLOutputChecker.tag_comparec             C   s  |j }| j|||}g }|d k	ry||}W n0 tjk
r\   tj d }|jd|  Y nX y||}	W n0 tjk
r   tj d }|jd|  Y nX |d ks|rtj| |||}
|r|j|
 dj	|S |
S |t
k}d| j||dd| j|	|dd| j||	|dg}dj	|S )	NrL   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"   exampler-   r.   r,   r/   errorsr0   er1   valuer   Z
diff_partsr   r   r   rW      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)r;   
empty_tagsr=   rB   )r"   elr   r   r   r   html_empty_tag   s    z LXMLOutputChecker.html_empty_tagrH   c             C   s  g }t |s|jd|  |j| |j| j| | j||slt|jr\|j| j|j |j| j| t|jr|j| j|j |jd dj	|S |jd|  |j| |j| j| | j||sb|jd t|jr|jd|  |j| j|j |jd x&|D ]}|j| j
|||d  qW |jd|  |j| j| |jd t|jr|jd|  |j| j|j |jd dj	|S )Nr   rR   rH   rS   )rB   rV   
format_tagra   r   r=   format_textformat_end_tagr>   rX   rY   )r"   docr   indentprefixpartsr`   r   r   r   rY      s@    










zLXMLOutputChecker.format_docc             C   s"   |d krdS |r|j  }t|dS )NrH   rL   )r   html_escape)r"   r=   r   r   r   r   rc     s
    zLXMLOutputChecker.format_textc             C   sl   g }t |tjrdS x4t|jj D ]"\}}|jd|| j|df  q$W |sXd|j S d|jdj	|f S )Nz<!--z%s="%s"Fz<%s>z<%s %s>r   )
rN   r   CommentBaser@   r?   itemsrV   rc   r;   rX   )r"   r`   attrsnamer^   r   r   r   rb   	  s    
zLXMLOutputChecker.format_tagc             C   s   t |tjrdS d|j S )Nz-->z</%s>)rN   r   rj   r;   )r"   r`   r   r   r   rd     s    z LXMLOutputChecker.format_end_tagc             C   s  g }t | rt | r|jd|  |j| j|| | j||sl|j| j|j|j |j| j|| |j| j|j|j |jd dj|S |jd|  |j| j|| |jd t	|jst	|jr|jd|  |j| j|j|j |jd t
|}t
|}x|s"|r|sL|j| j|jd||d d q|sv|j| j|jd||d d q|j| j|jd|jd||d  qW |jd|  |j| j|| |jd t	|jst	|jr|jd|  |j| j|j|j |jd dj|S )Nr   rR   rH   r   rS   +-)rB   rV   collect_diff_tagra   collect_diff_textr=   collect_diff_end_tagr>   rX   r   rC   rY   rD   rZ   )r"   r,   r-   r   rf   rh   rF   rG   r   r   r   rZ     sH    



  $

zLXMLOutputChecker.collect_diffc       	      C   s4  | j |j|js"d|j|jf }n|j}g }|jdkp>d|jk}xt|jj D ]r\}}||jkr| r|jd|| j|df  qP||jkr| j|j| |d}n| j|d}|jd||f  qPW |sx@t|jj D ].\}}||jkrq|jd|| j|df  qW |r(d|dj|f }nd	| }|S )
Nz%s (got: %s)r9   z+%s="%s"Fz%s="%s"z-%s="%s"z<%s %s>r   z<%s>)	r:   r;   r?   r@   rk   rV   rc   rq   rX   )	r"   r,   r-   r;   rl   r9   rm   r^   r=   r   r   r   rp   @  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>)r;   )r"   r,   r-   r;   r   r   r   rr   [  s    z&LXMLOutputChecker.collect_diff_end_tagc             C   s:   | j |||r"|sdS | j||S d||f }| j||S )NrH   z%s (got: %s))r<   rc   )r"   r,   r-   r   r=   r   r   r   rq   b  s    z#LXMLOutputChecker.collect_diff_textN)
r   r   r   r   r   r   r   r   r   r    )T)rH   )T)T)__name__
__module____qualname__r_   r#   r(   r)   r4   r+   r<   r:   rW   ra   rY   rc   rb   rd   rZ   rp   rr   rq   r   r   r   r   r   J   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#   k  s    z%LHTMLOutputChecker.get_default_parserN)rs   rt   ru   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   rv   _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_|| _|| _|| _| j  | j	  d S )N)
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 )N)r   __code__	func_code__globals__Zfunc_globalsr   )r"   r   r   r   r     s    

z_RestoreChecker.install_clonec             C   s   | j | j_d S )N)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 jdd\}}|j| }t|| d S )Nr   .rL   )r|   rT   modulesrsplitdelattr)r"   rT   packagemoduleZpackage_modr   r   r   uninstall_module  s    


z _RestoreChecker.uninstall_modulec             O   s4   | j   | j  | j`| 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$   | j   z| j||S | j  X d S )N)r   r   r   )r"   r   r   r   r   r   r     s    z_RestoreChecker.call_superN)rs   rt   ru   r   r   r   r   r   r   r   r   r   r   r   r   r{     s   r{   c              C   s@   dd l } | jd}x |r2|j}d|kr*|S |j}qW tdd S )Nr   rL   ZBOOMzBCould not find doctest (only use this function *inside* a doctest))rT   	_getframery   f_backLookupError)rT   r}   lr   r   r   rx     s    

rx   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   rT   rI   rv   r   r   ri   ImportErrorcgi__all__Zregister_optionflagr   r   r   r'   r   r   
HTMLParserr   r   compiler6   r   r   r   r	   r
   r{   rx   Z__test__rs   testmodr   r   r   r   <module>$   sB   





  "

#.

