B
    .KcW                 @   s   d Z ddlZddlZddlZddlZddlmZ ddlmZ ddl	m
Z
mZmZmZmZmZmZmZmZmZmZ ddlmZ ddlmZmZmZ ddlmZ dd	lmZmZ dd
l m!Z! ddl"Z"ddl#m$Z$ ddl%m&Z& ddl'm(Z( ddl)m*Z* ddl+m,Z, ddl-m.Z. ddl/m0Z0 e
r&ddl1m2Z2 e(3e4Z5e6dej7Z8e6dej7Z9e:e:e;dddZ<G dd de,Z=G dd de=Z>G dd de=Z?G dd de=Z@G d d! d!e=ZAG d"d# d#e=ZBeC ZDG d$d% d%ZEG d&d' d'ZFG d(d) d)ejGZHG d*d+ d+e$ZId,ee:ef d-d.d/ZJdS )0zfMimic doctest in Sphinx.

The extension automatically execute code snippets and checks their results.
    N)StringIO)path)TYPE_CHECKINGAnyCallableDictIterableListOptionalSequenceSetTupleType)nodes)ElementNodeTextElement)
directives)InvalidSpecifierSpecifierSet)Version)Builder)__)logging)bold)SphinxDirective)relpath)
OptionSpec)Sphinxz^\s*<BLANKLINE>z#\s*doctest:.+$)specversionreturnc             C   s   t |t| kS )aY  Check `spec` satisfies `version` or not.

    This obeys PEP-440 specifiers:
    https://peps.python.org/pep-0440/#version-specifiers

    Some examples:

        >>> is_allowed_version('<=3.5', '3.3')
        True
        >>> is_allowed_version('<=3.2', '3.3')
        False
        >>> is_allowed_version('>3.2, <4.0', '3.3')
        True
    )r   r   )r   r     r"   1lib/python3.7/site-packages/sphinx/ext/doctest.pyis_allowed_version(   s    r$   c               @   s2   e Zd ZdZdZdZdZdZee	 dddZ
dS )	TestDirectivez4
    Base class for doctest-related directives.
    Tr      )r!   c             C   s  d | j}d }| jdkrZd|kr2|}td|}t|rZd| jkrZ|sN|}td|}tj	}| jdkstd| jkrztj
}| jrdd	 | jd
 dD }ndg}|||| j|d}| | |d k	r||d< | jdkrd|d< n(| jdkrd|d< n| jdkr
d|d< i |d< | jdkrd| jkr| jd dd }x|D ]}|d
 |dd   }}	|dkr| jjjjtd| | jd qF|	tjkr| jjjjtd|	 | jd qFtj|dd   }
|d
 dk|d |
< qFW | jdkrd| jkryN| jd }d d d	 tjd d! D }t||sJtjd" }
d#|d |
< W n4 tk
r   | jjjjtd$| | jd Y nX d%| jkr| jd% |d%< d&| jkrd#|d'< nd| jkrd(|d'< |gS ))N
doctestz<BLANKLINE> zno-trim-doctest-flags)	testsetuptestcleanuphidec             S   s   g | ]}|  qS r"   )strip).0xr"   r"   r#   
<listcomp>X   s    z%TestDirective.run.<locals>.<listcomp>r   ,default)testnodetypegroupstestZpyconlanguagetestcodeZpython
testoutputZnoneoptions)r(   r8    r&   z+-z"missing '+' or '-' in '%s' option.)linez'%s' is not a valid option.+	pyversion.c             S   s   g | ]}t |qS r"   )str)r.   vr"   r"   r#   r0   |   s       ZSKIPTz$'%s' is not a valid pyversion optionskipifztrim-doctest-flagsZ
trim_flagsF)joinZcontentnameblankline_resubdoctestopt_researchr9   r   literal_blockcommentZ	argumentssplitZset_source_inforeplacestateZdocumentZreporterwarningr   linenor(   ZOPTIONFLAGS_BY_NAMEsysversion_infor$   r   )selfcoder5   Znodetyper4   nodeoption_stringsoptionprefixZoption_nameflagr   Zpython_versionr"   r"   r#   runF   sz    


















zTestDirective.runN)__name__
__module____qualname____doc__Zhas_contentZrequired_argumentsZoptional_argumentsZfinal_argument_whitespacer	   r   rY   r"   r"   r"   r#   r%   <   s   r%   c               @   s    e Zd ZU dejiZeed< dS )TestsetupDirectiverB   option_specN)rZ   r[   r\   r   unchanged_requiredr_   r   __annotations__r"   r"   r"   r#   r^      s   
r^   c               @   s    e Zd ZU dejiZeed< dS )TestcleanupDirectiverB   r_   N)rZ   r[   r\   r   r`   r_   r   ra   r"   r"   r"   r#   rb      s   
rb   c               @   s4   e Zd ZU ejejejejejejdZee	d< dS )DoctestDirective)r,   zno-trim-doctest-flagsr9   r=   rB   ztrim-doctest-flagsr_   N)
rZ   r[   r\   r   rX   	unchangedr`   r_   r   ra   r"   r"   r"   r#   rc      s   
rc   c               @   s0   e Zd ZU ejejejejejdZeed< dS )TestcodeDirective)r,   zno-trim-doctest-flagsr=   rB   ztrim-doctest-flagsr_   N)	rZ   r[   r\   r   rX   r`   r_   r   ra   r"   r"   r"   r#   re      s
   
re   c               @   s4   e Zd ZU ejejejejejejdZee	d< dS )TestoutputDirective)r,   zno-trim-doctest-flagsr9   r=   rB   ztrim-doctest-flagsr_   N)
rZ   r[   r\   r   rX   rd   r`   r_   r   ra   r"   r"   r"   r#   rf      s   
rf   c               @   s>   e Zd ZeddddZddedddd	Zed
ddZdS )	TestGroupN)rD   r!   c             C   s   || _ g | _g | _g | _d S )N)rD   setuptestscleanup)rR   rD   r"   r"   r#   __init__   s    zTestGroup.__init__FTestCode)rS   prependr!   c             C   s   |j dkr,|r| jd| q| j| n|j dkrD| j| nt|j dkr^| j|g nZ|j dkrz| j|d g n>|j dkr| jrt| jd dkr|| jd d	< nttd
d S )Nr*   r   r+   r(   r7   r8      r&   zinvalid TestCode type)	typerh   insertappendrj   ri   lenRuntimeErrorr   )rR   rS   rm   r"   r"   r#   add_code   s    




zTestGroup.add_code)r!   c             C   s   d| j | j| j| jf S )Nz2TestGroup(name=%r, setup=%r, cleanup=%r, tests=%r))rD   rh   rj   ri   )rR   r"   r"   r#   __repr__   s    zTestGroup.__repr__)F)rZ   r[   r\   r?   rk   boolru   rv   r"   r"   r"   r#   rg      s   rg   c               @   s8   e Zd Zdeeeeee ddddZedddZdS )	rl   N)rS   rp   filenamerO   r9   r!   c             C   s&   || _ || _|| _|| _|pi | _d S )N)rS   rp   rx   rO   r9   )rR   rS   rp   rx   rO   r9   r"   r"   r#   rk      s
    zTestCode.__init__)r!   c             C   s   d| j | j| j| j| jf S )Nz4TestCode(%r, %r, filename=%r, lineno=%r, options=%r))rS   rp   rx   rO   r9   )rR   r"   r"   r#   rv      s    zTestCode.__repr__)N)	rZ   r[   r\   r?   intr
   r   rk   rv   r"   r"   r"   r#   rl      s   rl   c                   sD   e Zd Zdeeeeef d fddZd	ee	e	dddZ
  ZS )
SphinxDocTestRunnerN)outverboser!   c                s<   t  }tj}|t_zt |}W d |t_X ||  |S )N)r   rP   stdoutsuper	summarizegetvalue)rR   r{   r|   Z	string_ioZ
old_stdoutZres)	__class__r"   r#   r      s    zSphinxDocTestRunner.summarize)rx   module_globalsr!   c             C   sj   | j |}|r^|d| jjkr^y| jjt|d }W n tk
rP   Y nX |j	dS | 
||S )NrD   Z
examplenumT)Z%_DocTestRunner__LINECACHE_FILENAME_REmatchgroupr5   rD   examplesry   
IndexErrorsource
splitlinesZsave_linecache_getlines)rR   rx   r   mexampler"   r"   r#   *_DocTestRunner__patched_linecache_getlines   s    z>SphinxDocTestRunner._DocTestRunner__patched_linecache_getlines)N)N)rZ   r[   r\   r   rw   r   ry   r   r?   r   r   __classcell__r"   r"   )r   r#   rz      s   rz   c               @   s  e Zd ZdZdZedZddddZeddd	d
Z	eddddZ
d)eee edddZee dddZddddZd*ee ee eddddZeeedddZeeee dddZeedddZeedd d!d"Zeeeeeed#d$d%Zedd&d'd(ZdS )+DocTestBuilderz2
    Runs test snippets in the documentation.
    r(   zZTesting of doctests in the sources finished, look at the results in %(outdir)s/output.txt.N)r!   c             C   s   | j j| _| jt_| j jtjdd< d| _d| _	d| _
d| _d| _d| _d| _td}tt| jdddd| _| jd|d	t| f  d S )
Nr   singlez%Y-%m-%d %H:%M:%Sz
output.txtwzutf-8)encodingzJResults of doctest builder run on %s
==================================%s
=)configdoctest_default_flagsoptcompiler(   doctest_pathrP   r   rp   total_failurestotal_triessetup_failuressetup_triescleanup_failurescleanup_triestimeZstrftimeopenrC   Zoutdiroutfilewriters   )rR   Zdater"   r"   r#   init  s    

zDocTestBuilder.init)textr!   c             C   s   t j|dd | j| d S )NT)nonl)loggerinfor   r   )rR   r   r"   r"   r#   _out/  s    zDocTestBuilder._outc             C   s:   | j js| j jrt| ntj|dd | j| d S )NT)r   )appquietZwarningiserrorr   rN   r   r   r   )rR   r   r"   r"   r#   	_warn_out3  s    zDocTestBuilder._warn_out)docnametypr!   c             C   s   dS )Nr)   r"   )rR   r   r   r"   r"   r#   get_target_uri:  s    zDocTestBuilder.get_target_uric             C   s   | j jS )N)envZ
found_docs)rR   r"   r"   r#   get_outdated_docs=  s    z DocTestBuilder.get_outdated_docsc          	   C   sz   t tddd}| j|| j| j|| j| j|| j| j|| jf}| d|  | j  | jsn| jsn| jrvd| j	_
d S )N)r@   r!   c             S   s   | dkrdS dS )Nr&   sr)   r"   )r@   r"   r"   r#   r   B  s    z DocTestBuilder.finish.<locals>.sz}
Doctest summary
===============
%5d test%s
%5d failure%s in tests
%5d failure%s in setup code
%5d failure%s in cleanup code
r&   )ry   r?   r   r   r   r   r   r   closer   Z
statuscode)rR   r   replr"   r"   r#   finish@  s    

zDocTestBuilder.finishupdate)build_docnamesupdated_docnamesmethodr!   c             C   sL   |d krt | jj}ttd x$|D ]}| j|}| || q(W d S )Nzrunning tests...)sortedr   Zall_docsr   r   r   Zget_doctreetest_doc)rR   r   r   r   r   doctreer"   r"   r#   r   U  s    
zDocTestBuilder.write)rT   r   r!   c             C   sJ   y"t |j| jjjdddd }W n" tk
rD   | j|d}Y nX |S )zsTry to get the file which actually contains the doctest, not the
        filename of the document it's included in.z:docstring of r&   )maxsplitr   F)r   r   r   Zsrcdirrsplit	ExceptionZdoc2path)rR   rT   r   rx   r"   r"   r#   get_filename_for_node`  s    z$DocTestBuilder.get_filename_for_node)rT   r!   c             C   s0   dt | jpdkrdS | jdk	r,| jd S dS )z0Get the real line number or admit we don't know.z:docstring of r)   Nr&   )r   basenamer   r;   )rT   r"   r"   r#   get_line_numberj  s
    

zDocTestBuilder.get_line_numberc             C   sV   d|krdS |d }i }| j jr.t| j j| t||}| j jrNt| j j| |S d S )NrB   F)r   doctest_global_setupexecevaldoctest_global_cleanup)rR   rT   	conditioncontextZshould_skipr"   r"   r#   skippedz  s    
zDocTestBuilder.skipped)r   r   r!   c          	   C   s  i }g }t d| jd| _t d| jd| _t d| jd| _| jj| j_| jj| j_| jjrjtt	ddd}ntt	ddd}x|
|D ]}| |rqd|kr|d n| }| ||}| |}	|sttd|d	d
||	 t||d	d
||	|dd}
|ddg}d|kr(||
 qx2|D ]*}||krHt|||< || |
 q.W qW x,|D ]$}
x| D ]}||
 qtW qfW | jjrt| jjdd dd}
x | D ]}|j|
dd qW | jjr
t| jjdd dd}
x| D ]}||
 qW |sd S | d|dt| f  x| D ]}| | q8W | jj| jdd\}}|  j|7  _|  j|7  _| jj r| jj| jdd\}}|  j!|7  _!|  j"|7  _"| jj r| jj| jdd\}}|  j#|7  _#|  j$|7  _$d S )NF)r|   Zoptionflags)rT   r!   c             S   s&   t | tjtjfrd| kp$t | tjS )Nr3   )
isinstancer   rI   rJ   Zdoctest_block)rT   r"   r"   r#   r     s    z*DocTestBuilder.test_doc.<locals>.conditionc             S   s   t | tjtjfod| kS )Nr3   )r   r   rI   rJ   )rT   r"   r"   r#   r     s    r5   z#no code/output in %s block at %s:%sr3   r(   r9   )rp   rx   rO   r9   r4   r2   *r*   r   )rx   rO   T)rm   r+   z
Document: %s
----------%s
-)r|   )%rz   r   setup_runnertest_runnercleanup_runnerZ_fakeoutr   doctest_test_doctest_blocksr   rw   findallr   Zastextr   r   r   rN   r   getrl   rr   rg   ru   valuesr   r   r   rs   
test_groupr   r   r   Ztriesr   r   r   r   )rR   r   r   r4   Zadd_to_all_groupsr   rT   r   rx   Zline_numberrS   Znode_groupsZ	groupnamer   Zres_fZres_tr"   r"   r#   r     s    













zDocTestBuilder.test_doc)rS   rD   rp   flagsdont_inheritr!   c             C   s   t ||| j||S )N)r   rp   )rR   rS   rD   rp   r   r   r"   r"   r#   r     s    zDocTestBuilder.compile)r   r!   c          
      s  i t tt t td fdd}|j jds8d S x jD ]~}t|dkry*t	|d j
i  j|d j|d j}W n@ tk
r   tjtd|d j
|d j|d jfd wBY nX |jsqBx.|jD ]$}|d j }||j ||_qW d	_n|d r|d j
nd
}|d r.|d jni }d|tj< tj|}	|	rZ|	d}
nd }
tj|d j
||
|d j|d}t|gi  j|d j|d jd }d_|_jj |j!dd qBW |j" j#d d S )N)runner	testcodeswhatr!   c                s   g }x*|D ]"}t j|jd|jd}|| q
W |s8dS t |i d j|f |d jdd }|_| j	}d_
| j|jdd | j	|krdS dS )	Nr)   )rO   Tz%s (%s code)r   r   F)r{   clear_globs)r(   ExamplerS   rO   rr   DocTestrD   rx   globsZfailuresrp   rY   r   )r   r   r   r   r7   r   Zsim_doctestZold_f)r   nsrR   r"   r#   run_setup_cleanup  s     

z4DocTestBuilder.test_group.<locals>.run_setup_cleanuprh   r&   r   z!ignoring invalid doctest code: %r)locationr   r)   Tmsg)exc_msgrO   r9   r   F)r{   r   rj   )$r   r	   rl   rw   r   rh   ri   rs   parserZget_doctestrS   rD   rx   rO   r   r   rN   r   r   r9   copyr   rp   r(   ZDONT_ACCEPT_BLANKLINEZ_EXCEPTION_REr   r   r   r   r   r   rY   r   r   rj   )rR   r   r   rS   r5   r   Znew_optoutputr9   r   r   r"   )r   r   rR   r#   r     sF     

zDocTestBuilder.test_group)N)r   ) rZ   r[   r\   r]   rD   r   epilogr   r?   r   r   r
   r   r   r   r   r   r   r   r   r   staticmethodry   r   r   rw   r   r   r   r   rg   r   r"   r"   r"   r#   r   
  s"   

Nr   r   )r   r!   c             C   s   |  dt |  dt |  dt |  dt |  dt | t | dg d | dd	d | d
dd | ddd | dt	j
t	jB t	jB d tjddS )Nr*   r+   r(   r7   r8   r   Fr   r2   r   r)   r   r   T)r    Zparallel_read_safe)Zadd_directiver^   rb   rc   re   rf   Zadd_builderr   Zadd_config_valuer(   ZDONT_ACCEPT_TRUE_FOR_1ELLIPSISZIGNORE_EXCEPTION_DETAILsphinxZ__display_version__)r   r"   r"   r#   rh      s    
rh   )Kr]   r(   rerP   r   ior   osr   typingr   r   r   r   r   r	   r
   r   r   r   r   Zdocutilsr   Zdocutils.nodesr   r   r   Zdocutils.parsers.rstr   Zpackaging.specifiersr   r   Zpackaging.versionr   r   Zsphinx.buildersr   Zsphinx.localer   Zsphinx.utilr   Zsphinx.util.consoler   Zsphinx.util.docutilsr   Zsphinx.util.osutilr   Zsphinx.util.typingr   Zsphinx.applicationr   Z	getLoggerrZ   r   r   	MULTILINErE   rG   r?   rw   r$   r%   r^   rb   rc   re   rf   ZDocTestParserr   rg   rl   ZDocTestRunnerrz   r   rh   r"   r"   r"   r#   <module>   sP   4
Q
   