U
    \ShuX                     @  s  d Z ddlm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 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+m,Z, erddl-m.Z. e$/e0Z1e2dej3Z4e2dej3Z5ddddddZ6G dd de(Z7G dd de7Z8G dd  d e7Z9G d!d" d"e7Z:G d#d$ d$e7Z;G d%d& d&e7Z<e= Z>G d'd( d(Z?G d)d* d*Z@G d+d, d,ejAZBG d-d. d.e ZCd/d0d1d2d3ZDdS )4zfMimic doctest in Sphinx.

The extension automatically execute code snippets and checks their results.
    )annotationsN)StringIO)path)TYPE_CHECKINGAnyCallableIterableSequence)nodes)ElementNodeTextElement)
directives)InvalidSpecifierSpecifierSet)Version)Builder)__)logging)bold)SphinxDirective)relpath)
OptionSpec)Sphinxz^\s*<BLANKLINE>z#\s*doctest:.+$strbool)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   E/root/rtd-docs/venv/lib/python3.8/site-packages/sphinx/ext/doctest.pyis_allowed_version)   s    r!   c                   @  s.   e Zd ZdZdZdZdZdZddddZd	S )
TestDirectivez4
    Base class for doctest-related directives.
    Tr      z
list[Node]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 }|D ]}|d
 |dd   }}	|dkr| jjjjtd| | jd qD|	tjkr| jjjjtd|	 | jd qDtj|dd   }
|d
 dk|d |
< qD| jdkr~d| jkr~zN| jd }d d d	 tjd d! D }t||sFt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> no-trim-doctest-flags)	testsetuptestcleanuphidec                 S  s   g | ]}|  qS r   )strip).0xr   r   r    
<listcomp>Y   s     z%TestDirective.run.<locals>.<listcomp>r   ,default)testnodetypegroupstestpyconlanguagetestcodepython
testoutputnoneoptions)r&   r9    r#   z+-z"missing '+' or '-' in '%s' option.)linez'%s' is not a valid option.+	pyversion.c                 S  s   g | ]}t |qS r   )r   )r-   vr   r   r    r/   }   s        ZSKIPTz$'%s' is not a valid pyversion optionskipiftrim-doctest-flagsZ
trim_flagsF)joincontentnameblankline_resubdoctestopt_researchr;   r
   literal_blockcomment	argumentssplitZset_source_inforeplacestateZdocumentreporterwarningr   linenor&   ZOPTIONFLAGS_BY_NAMEsysversion_infor!   r   )selfcoder4   Znodetyper3   nodeoption_stringsoptionprefixZoption_nameflagr   python_versionr   r   r    runG   s    















zTestDirective.runN)	__name__
__module____qualname____doc__Zhas_contentZrequired_argumentsZoptional_argumentsZfinal_argument_whitespacer_   r   r   r   r    r"   =   s   r"   c                   @  s    e Zd ZU dejiZded< dS )TestsetupDirectiverC   r   option_specNr`   ra   rb   r   unchanged_requiredre   __annotations__r   r   r   r    rd      s   
 rd   c                   @  s    e Zd ZU dejiZded< dS )TestcleanupDirectiverC   r   re   Nrf   r   r   r   r    ri      s   
 ri   c                   @  s4   e Zd ZU ejejejejejejdZded< dS )DoctestDirectiver+   r(   r;   r?   rC   rD   r   re   N	r`   ra   rb   r   r]   Z	unchangedrg   re   rh   r   r   r   r    rj      s   
rj   c                   @  s0   e Zd ZU ejejejejejdZded< dS )TestcodeDirective)r+   r(   r?   rC   rD   r   re   N)r`   ra   rb   r   r]   rg   re   rh   r   r   r   r    rm      s   
rm   c                   @  s4   e Zd ZU ejejejejejejdZded< dS )TestoutputDirectiverk   r   re   Nrl   r   r   r   r    rn      s   
rn   c                   @  s>   e Zd ZdddddZddddd	d
dZddddZdS )	TestGroupr   None)rG   r   c                 C  s   || _ g | _g | _g | _d S N)rG   setuptestscleanup)rW   rG   r   r   r    __init__   s    zTestGroup.__init__FTestCoder   )rX   prependr   c                 C  s   |j dkr,|r| jd| q| j| n|j dkrD| j| n||j dkr^| j|g nb|j dkrz| j|d f nF|j dkr| jr| jd }t|dkr|d |g| jd< nttd	d S )
Nr)   r   r*   r&   r7   r9      zinvalid TestCode type)	typerr   insertappendrt   rs   lenRuntimeErrorr   )rW   rX   rw   Zlatest_testr   r   r    add_code   s     





zTestGroup.add_coder$   c              	   C  s&   d| j d| jd| jd| jd	S )NzTestGroup(name=z, setup=z
, cleanup=z, tests=))rG   rr   rt   rs   rW   r   r   r    __repr__   s    zTestGroup.__repr__N)F)r`   ra   rb   ru   r   r   r   r   r   r    ro      s   ro   c                   @  s4   e Zd ZddddddddddZdd	d
dZdS )rv   Nr   intzdict | Nonerp   )rX   rz   filenamerT   r;   r   c                 C  s&   || _ || _|| _|| _|pi | _d S rq   rX   rz   r   rT   r;   )rW   rX   rz   r   rT   r;   r   r   r    ru      s
    zTestCode.__init__r$   c                 C  s.   d| j d| jd| jd| jd| jdS )Nz	TestCode(z, z, filename=z	, lineno=z
, options=r   r   r   r   r   r    r      s    zTestCode.__repr__)N)r`   ra   rb   ru   r   r   r   r   r    rv      s    rv   c                      s<   e Zd Zddddd fddZddd	d	d
ddZ  ZS )SphinxDocTestRunnerNr   zbool | Noneztuple[int, int])outverboser   c                   s<   t  }tj}|t_zt |}W 5 |t_X ||  |S rq   )r   rU   stdoutsuper	summarizegetvalue)rW   r   r   Z	string_ioZ
old_stdoutres	__class__r   r    r      s    zSphinxDocTestRunner.summarizer   r   )r   module_globalsr   c                 C  sj   | j |}|r^|d| jjkr^z| jjt|d }W n tk
rP   Y nX |j	dS | 
||S )NrG   Z
examplenumT)Z%_DocTestRunner__LINECACHE_FILENAME_REmatchgroupr4   rG   examplesr   
IndexErrorsource
splitlinesZsave_linecache_getlines)rW   r   r   mexampler   r   r    *_DocTestRunner__patched_linecache_getlines   s    z>SphinxDocTestRunner._DocTestRunner__patched_linecache_getlines)N)N)r`   ra   rb   r   r   __classcell__r   r   r   r    r      s    r   c                   @  s   e Zd ZdZdZedZddddZddd	d
dZddd	ddZ	d5ddddddZ
ddddZddddZd6dddddddZddddd d!Zedd"d#d$d%Zd&d'd#d(d)Zdddd*d+d,Zdddd-d'd-d.d/d0Zd1dd2d3d4ZdS )7DocTestBuilderz2
    Runs test snippets in the documentation.
    r&   zZTesting of doctests in the sources finished, look at the results in %(outdir)s/output.txt.rp   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_pathrU   r   rz   total_failurestotal_triessetup_failuressetup_triescleanup_failurescleanup_triestimestrftimeopenrE   Zoutdiroutfilewriter}   )rW   dater   r   r    init  s    

zDocTestBuilder.initr   )textr   c                 C  s   t j|dd | j| d S NT)Znonl)loggerinfor   r   rW   r   r   r   r    _out3  s    zDocTestBuilder._outc                 C  s:   | j js| j jrt| ntj|dd | j| d S r   )appquietZwarningiserrorr   rS   r   r   r   r   r   r   r    	_warn_out7  s    zDocTestBuilder._warn_outNz
str | None)docnametypr   c                 C  s   dS )Nr'   r   )rW   r   r   r   r   r    get_target_uri>  s    zDocTestBuilder.get_target_urizset[str]c                 C  s   | j jS rq   )envZ
found_docsr   r   r   r    get_outdated_docsA  s    z DocTestBuilder.get_outdated_docsc              	   C  sz   ddddd}| j || j | j|| j| j|| j| j|| jf}| d|  | j  | jsn| jsn| jrvd| j_d S )Nr   r   )rA   r   c                 S  s   | dkrdS dS )Nr#   sr'   r   )rA   r   r   r    r   F  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#   )	r   r   r   r   r   r   closer   Z
statuscode)rW   r   replr   r   r    finishD  s       
zDocTestBuilder.finishupdatezIterable[str] | NonezSequence[str])build_docnamesupdated_docnamesmethodr   c                 C  sH   |d krt | jj}ttd |D ]}| j|}| || q&d S )Nzrunning tests...)sortedr   Zall_docsr   r   r   Zget_doctreetest_doc)rW   r   r   r   r   doctreer   r   r    r   Y  s    zDocTestBuilder.writer   )rY   r   r   c                 C  sJ   z"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.:docstring of r#   )maxsplitr   F)r   r   r   srcdirrsplit	ExceptionZdoc2path)rW   rY   r   r   r   r   r    get_filename_for_noded  s     z$DocTestBuilder.get_filename_for_noder   rY   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.r   r'   Nr#   )r   basenamer   r=   rY   r   r   r    get_line_numbern  s
    

zDocTestBuilder.get_line_numberr   r   c                 C  sV   d|krdS |d }i }| j jr.t| j j| t||}| j jrNt| j j| |S d S )NrC   F)r   doctest_global_setupexecevaldoctest_global_cleanup)rW   rY   	conditioncontextshould_skipr   r   r    skipped~  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rjddddd}nddddd}||D ]}| 	|rqd	|kr|d	 n|
 }| ||}| |}	|sttd
|dd||	 t||dd||	|dd}
|ddg}d|kr&||
 q|D ]*}||krDt|||< || |
 q*q|D ] }
| D ]}||
 qhq\| jjrt| jjdddd}
| D ]}|j|
dd q| jjrt| jjdddd}
| D ]}||
 q|sd S | d|dt| f  | D ]}| | q| 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optionflagsr   r   r   c                 S  s&   t | tjtjfrd| kp$t | tjS Nr2   )
isinstancer
   rL   rM   Zdoctest_blockr   r   r   r    r     s
    
z*DocTestBuilder.test_doc.<locals>.conditionc                 S  s   t | tjtjfod| kS r   )r   r
   rL   rM   r   r   r   r    r     s    r4   z#no code/output in %s block at %s:%sr2   r&   r;   )rz   r   rT   r;   r3   r1   *r)   z<global_setup>r   )r   rT   T)rw   r*   z<global_cleanup>z
Document: %s
----------%s
-)r   )#r   r   setup_runnertest_runnercleanup_runnerZ_fakeoutr   doctest_test_doctest_blocksfindallr   Zastextr   r   r   rS   r   getrv   r|   ro   r   valuesr   r   r   r}   
test_groupr   r   r   triesr   r   r   r   )rW   r   r   r3   Zadd_to_all_groupsr   rY   r   r   line_numberrX   Znode_groupsZ	groupnamer   Zres_fZres_tr   r   r    r     s    



  



  
  



zDocTestBuilder.test_docr   )rX   rG   rz   flagsdont_inheritr   c                 C  s   t ||| j||S rq   )r   rz   )rW   rX   rG   rz   r   r   r   r   r    r     s    zDocTestBuilder.compilero   )r   r   c              
     s  i ddddd fdd}|j  jds4d S  jD ]z}t|dkrz*t|d	 ji  j|d	 j|d	 j	}W nB t
k
r   tjtd
|d	 j|d	 j|d	 j	fd Y q:Y nX |jsq:|jD ]$}|d	 j }||j ||_qd_n|d r
|d jnd}|d r"|d jni }d|tj< tj|}	|	rN|	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 q:|j jd d S )Nr   zlist[TestCode]r   )runner	testcodeswhatr   c                   s   g }|D ]"}t j|jd|jd}|| q|s4dS t |i  j d| d|d jdd }|_| j	}d_
| j|jdd	 | j	|krdS dS )
Nr'   )rT   Tz (z code)r   r   Fr   Zclear_globs)r&   ExamplerX   rT   r|   DocTestrG   r   globsZfailuresrz   r_   r   )r   r   r   r   r7   r   Zsim_doctestZold_fr   nsrW   r   r    run_setup_cleanup  s&      
z4DocTestBuilder.test_group.<locals>.run_setup_cleanuprr   r#   r   z!ignoring invalid doctest code: %r)locationr   r'   Tmsg)exc_msgrT   r;   r   Fr   rt   ) r   rr   rs   r}   parserZget_doctestrX   rG   r   rT   r   r   rS   r   r   r;   copyr   rz   r&   ZDONT_ACCEPT_BLANKLINEZ_EXCEPTION_REr   r   r   r   r   r   r_   r   r   rt   )rW   r   r   rX   r4   r   Znew_optoutputr;   r   r   r   r   r    r     sV     


   zDocTestBuilder.test_group)N)r   )r`   ra   rb   rc   rG   r   epilogr   r   r   r   r   r   r   r   staticmethodr   r   r   r   r   r   r   r   r    r     s$    
Nr   r   zdict[str, Any])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   r9   r   Fr   r1   r   r'   r   r   T)r   Zparallel_read_safe)Zadd_directiverd   ri   rj   rm   rn   Zadd_builderr   Zadd_config_valuer&   ZDONT_ACCEPT_TRUE_FOR_1ELLIPSISZIGNORE_EXCEPTION_DETAILsphinxZ__display_version__)r   r   r   r    rr   $  s     
rr   )Erc   
__future__r   r&   rerU   r   ior   osr   typingr   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   	getLoggerr`   r   r   	MULTILINErH   rJ   r!   r"   rd   ri   rj   rm   rn   ZDocTestParserr   ro   rv   ZDocTestRunnerr   r   rr   r   r   r   r    <module>   sR   
Q
!   