
­­­­­­­­­­­­­­­­­­
<!DOCTYPE html>
<html>
3
U*WG                 @   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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e$Z%dd Z&d d!iZ'e(d"krld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_install   c             C   s   | d krd S | j  S d S )N)strip)v r   &/usr/lib64/python3.6/doctestcompare.pyr   ?   s    r   c             C   s   t jd| S )N )_norm_whitespace_resub)r   r   r   r   norm_whitespaceE   s    r   FT)ZrecoverZremove_blank_textc             C   s   t j| tS )N)r   Z
fromstring_html_parser)htmlr   r   r   html_fromstringJ   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_parserW   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(   Z   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)   o   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      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   sn   |dkrdS t |t s$t |t r,||kS |p2d}|p:d}|jdrb|jdd |jdd kS ||kS d S )	Nr9   TrH   z{...}}   rM   )
isinstance_basestringr3   split)r"   r,   r-   r   r   r   r:      s    
zLXMLOutputChecker.tag_comparec             C   sF  |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}g }|jd |j| j||d |jd |j| j|	|d |jd |j| j||	|d 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"   Zexampler-   r.   r,   r/   errorsr0   er1   valuer   Z
diff_partsr   r   r   rV      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   rQ   rH   rR   )rB   rU   
format_tagr_   r   r=   format_textformat_end_tagr>   rW   rX   )r"   docr   indentprefixpartsr^   r   r   r   rX      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   ra   
  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?   itemsrU   ra   r;   rW   )r"   r^   attrsnamer\   r   r   r   r`     s    
zLXMLOutputChecker.format_tagc             C   s   t |tjrdS d|j S )Nz-->z</%s>)rN   r   rh   r;   )r"   r^   r   r   r   rb     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   rQ   rH   r   rR   +-)rB   rU   collect_diff_tagr_   collect_diff_textr=   collect_diff_end_tagr>   rW   r   rC   rX   rD   rY   )r"   r,   r-   r   rd   rf   rF   rG   r   r   r   rY   "  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@   ri   rU   ra   ro   rW   )	r"   r,   r-   r;   rj   r9   rk   r\   r=   r   r   r   rn   H  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   rp   c  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<   ra   )r"   r,   r-   r   r=   r   r   r   ro   j  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:   rV   r_   rX   ra   r`   rb   rY   rn   rp   ro   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#   s  s    z%LHTMLOutputChecker.get_default_parserN)rq   rr   rs   r#   r   r   r   r   r   r  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	   v  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"   ZcheckN)r   r   _find_doctest_framef_localsZ_checker_IS_PYTHON_3__func__r(   Zim_funcr   rt   _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 )ry   c             C   sD   || _ || _| j| j_|| j_|| _|| _|| _| j  | j	  d S )N)
r|   r}   
call_superr&   r$   r   
clone_funcrz   install_cloneinstall_dt_self)r"   r|   r~   Znew_checkerr   r   rz   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)rw   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)rw   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   )rz   rS   modulesrsplitdelattr)r"   rS   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)rq   rr   rs   r   r   r   r   r   r   r   r   r   r   r   r   ry     s   	ry   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))rS   	_getframerv   f_backLookupError)rS   r{   lr   r   r   ru     s    

ru   Z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   rS   rI   rt   r   r   rg   ImportErrorZcgi__all__Z
basestringrO   	NameErrorstrbytesversion_inforw   Zregister_optionflagr   r   r   r'   r   r   Z
HTMLParserr   r   compiler6   r   r   r   r	   r
   objectry   ru   Z__test__rq   Ztestmodr   r   r   r   <module>$   sL   





  #

'6

