U
    c±³eo9  ã                   @   sJ  d dl mZ d dlZd dlZd dl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 ddlmZ ddlmZmZ dd	lmZmZ dd
lmZ G dd„ deƒZdd„ ZG dd„ dejƒZG dd„ deƒZee e ddd¡¡jdƒZee e ddd¡¡jdƒZdd„ Z G dd„ deƒZ!dd„ Z"d#dd „Z#d$d!d"„Z$dS )%é    )Úabsolute_importN)Úopen)Úpartialé   )ÚErrors)Ú
CodeWriter)ÚTreeFragmentÚstrip_common_indent)ÚTreeVisitorÚVisitorTransform)ÚTreePathc                       s$   e Zd Z‡ fdd„Zdd„ Z‡  ZS )ÚNodeTypeWriterc                    s   t t| ƒ ¡  d| _g | _d S )Nr   )Úsuperr   Ú__init__Ú_indentsÚresult©Úself©Ú	__class__© ú/lib/python3.8/site-packages/Cython/TestUtils.pyr      s    zNodeTypeWriter.__init__c                 C   sˆ   | j sd}n0| j d }|d d k	r4d|dd…  }n|d }| j d| j d||jjf  ¡ |  jd7  _|  |¡ |  jd8  _d S )	Nz(root)éÿÿÿÿé   z%s[%d]r   é   z  z%s: %s)Zaccess_pathr   Úappendr   r   Ú__name__Úvisitchildren)r   ÚnodeÚnameZtipr   r   r   Ú
visit_Node   s    
ÿ
zNodeTypeWriter.visit_Node)r   Ú
__module__Ú__qualname__r   r    Ú__classcell__r   r   r   r   r      s   r   c                 C   s(   t ƒ }| | ¡ d dg|j dg ¡S )zÊReturns a string representing the tree by class names.
    There's a leading and trailing whitespace so that it can be
    compared by simple string comparison while still making test
    cases look ok.Ú
Ú )r   ZvisitÚjoinr   )ÚrootÚwr   r   r   Ú	treetypes+   s    
r)   c                   @   sj   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d„Z
dd„ Zefdd„Zdd„ ZdS )Ú
CythonTestc                 C   s   t  ¡  d S ©N©r   Zinit_threadr   r   r   r   ÚsetUp7   s    zCythonTest.setUpc                 C   s   t  ¡  d S r+   r,   r   r   r   r   ÚtearDown:   s    zCythonTest.tearDownc              	   C   sŠ   t |tƒs| d¡}t |tƒs(| d¡}tt||ƒƒD ]$\}\}}|  ||d|||f ¡ q6|  t|ƒt|ƒdd |¡d |¡f ¡ dS )zHChecks that the given strings or lists of strings are equal line by liner$   zLine %d:
Exp: %s
Got: %sú%Unmatched lines. Got:
%s
Expected:
%sN)Ú
isinstanceÚlistÚsplitÚ	enumerateÚzipÚassertEqualÚlenr&   )r   Úexpectedr   ÚidxÚexpected_lineZresult_liner   r   r   ÚassertLines=   s    



ÿÿzCythonTest.assertLinesc                 C   s   t ƒ }| |¡ |jjS r+   )r   Úwriter   Úlines)r   ÚtreeÚwriterr   r   r   ÚcodeToLinesI   s    
zCythonTest.codeToLinesc                 C   s   d  |  |¡¡S )Nr$   )r&   r?   )r   r=   r   r   r   ÚcodeToStringN   s    zCythonTest.codeToStringc              	   C   st   |   |¡}t| d¡ƒ}tt||ƒƒD ]$\}\}}|  ||d|||f ¡ q&|  t|ƒt|ƒdd |¡|f ¡ d S )Nr$   zLine %d:
Got: %s
Exp: %sr/   )r?   r	   r2   r3   r4   r5   r6   r&   )r   r7   Úresult_treeZresult_linesZexpected_linesr8   Úliner9   r   r   r   Ú
assertCodeQ   s    
ÿÿzCythonTest.assertCodec                 C   s   |   t ||¡d d| ¡ d S )Nz"Path '%s' not found in result tree)ZassertNotEqualr   Ú
find_first)r   ÚpathrA   r   r   r   ÚassertNodeExists\   s    ÿzCythonTest.assertNodeExistsNc                 C   sV   |dkri }|dkrg }|   ¡ }| d¡r:|tdƒd… }| dd¡}t||||dS )zNSimply create a tree fragment using the name of the test-case in parse errors.Nz	__main__.Ú.Ú_)Úpipeline)ÚidÚ
startswithr6   Úreplacer   )r   ÚcodeÚpxdsrI   r   r   r   r   Úfragment`   s    
zCythonTest.fragmentc                 C   s   t |ƒS r+   )r)   )r   r'   r   r   r   r)   l   s    zCythonTest.treetypesc              
   C   sX   z|ƒ  |   d| ¡ W n: |k
rR } z|  t||ƒ¡ | W Y ¢S d}~X Y nX dS )z“Calls "func" and fails if it doesn't raise the right exception
        (any exception by default). Also returns the exception in question.
        z Expected an exception of type %rN)ÚfailZ
assertTruer0   )r   ÚfuncÚexc_typeÚer   r   r   Úshould_failo   s    zCythonTest.should_failc              
   C   s>   z|ƒ W S  t k
r8 } z|  t|ƒ¡ W 5 d}~X Y nX dS )z©Calls func and succeeds if and only if no exception is raised
        (i.e. converts exception raising into a failed testcase). Returns
        the return value of func.N)Ú	ExceptionrP   Ústr)r   rQ   Úexcr   r   r   Úshould_not_failz   s    zCythonTest.should_not_fail)NN)r   r!   r"   r-   r.   r:   r?   r@   rC   rF   rO   r)   rU   rT   rX   r   r   r   r   r*   5   s   
r*   c                   @   s   e Zd ZdZddd„ZdS )ÚTransformTesta.  
    Utility base class for transform unit tests. It is based around constructing
    test trees (either explicitly or by parsing a Cython code string); running
    the transform, serialize it using a customized Cython serializer (with
    special markup for nodes that cannot be represented in Cython),
    and do a string-comparison line-by-line of the result.

    To create a test case:
     - Call run_pipeline. The pipeline should at least contain the transform you
       are testing; pyx should be either a string (passed to the parser to
       create a post-parse tree) or a node representing input to pipeline.
       The result will be a transformed result.

     - Check that the tree is correct. If wanted, assertCode can be used, which
       takes a code string as expected, and a ModuleNode in result_tree
       (it serializes the ModuleNode to a string and compares line-by-line).

    All code strings are first stripped for whitespace lines and then common
    indentation.

    Plans: One could have a pxd dictionary parameter to run_pipeline.
    Nc                 C   s0   |d kri }|   ||¡j}|D ]}||ƒ}q|S r+   )rO   r'   )r   rI   ZpyxrN   r=   ÚTr   r   r   Úrun_pipelineœ   s    
zTransformTest.run_pipeline)N)r   r!   r"   Ú__doc__r[   r   r   r   r   rY   „   s   rY   z\s+r%   zz
        /[*] (
            (?: [^*\n] | [*][^/] )*
            [\n]
            (?: [^*] | [*][^/] )*
        ) [*]/
    z\s\s+zÅ
    (?:
        <pre class=["'][^"']*cython\s+line[^"']*["']\s*>
        (?:[^<]|<(?!/pre))+
        </pre>
    )|(?:
        <style[^>]*>
        (?:[^<]|<(?!/style))+
        </style>
    )
    c                 C   sˆ   d  }}|   d¡r6tjd| dd … dd\}} |  ¡ } |   d¡r~| dd …  ¡ } |   d¡r~tjd| dd … dd\}} |  ¡ } ||| fS )Nú/z(?<!\\)/r   )Úmaxsplitú:)rK   Úrer2   Ústrip)ÚpatternÚstartÚendr   r   r   Ú_parse_patternÃ   s    


re   c                       sB   e Zd Z‡ fdd„Zdd„ Zdd„ Zdd„ Zd	d
„ Zej	Z
‡  ZS )ÚTreeAssertVisitorc                    s$   t t| ƒ ¡  d | _g | _g | _d S r+   )r   rf   r   Ú_module_posÚ_c_patternsÚ_c_antipatternsr   r   r   r   r   Ô   s    zTreeAssertVisitor.__init__c                    sL   ˆj ˆj ‰‰ dd„ ‰‡‡fdd„‰‡ ‡‡‡‡fdd„‰‡ ‡‡fdd„}|S )	Nc                 S   s"   t  | d||rdnd|f ¡ d S )NzPattern '%s' %s found in %sZwaszwas not)r   Úerror)Úposrb   ÚfoundÚ	file_pathr   r   r   rP   Ý   s
    
ýz7TreeAssertVisitor.create_c_file_validator.<locals>.failc                    st   |r8t  ||¡}|r&|| ¡ d … }nˆ ˆj|d| d |rpt  ||¡}|r^|d | ¡ … }nˆ ˆj|d| d |S )NF©rl   rm   )r`   Úsearchrd   rg   rc   )rm   Úcontentrc   rd   r2   )rP   r   r   r   Úextract_sectionä   s    zBTreeAssertVisitor.create_c_file_validator.<locals>.extract_sectionc                    sŒ   ˆD ]>}t |ƒ\}}}ˆ| |||ƒ}t ||¡sˆˆj|d| d qˆ D ]>}t |ƒ\}}}ˆ| |||ƒ}t ||¡rHˆˆj|d| d qHd S )NFrn   T)re   r`   ro   rg   )rm   rp   rb   rc   rd   ZsectionZantipattern)Úantipatternsrq   rP   Úpatternsr   r   r   Úvalidate_file_contentó   s    zHTreeAssertVisitor.create_c_file_validator.<locals>.validate_file_contentc              	      s²   | j }ˆsˆ s| S t|dd}| ¡ }W 5 Q R X t|ƒ}ˆ||ƒ tj |¡d d }tj |¡r®tj |¡tj |¡kr®t|dd}| ¡ }W 5 Q R X t	|ƒ}ˆ||ƒ d S )NÚutf8)Úencodingr   z.html)
Úc_filer   ÚreadÚ_strip_c_commentsÚosrE   ÚsplitextÚexistsÚgetmtimeÚ_strip_cython_code_from_html)r   rw   Úfrp   Z	html_file)rr   rs   rt   r   r   Úvalidate_c_file  s    
$zBTreeAssertVisitor.create_c_file_validator.<locals>.validate_c_file)rh   ri   )r   r€   r   )rr   rq   rP   rs   r   rt   r   Úcreate_c_file_validatorÚ   s    z)TreeAssertVisitor.create_c_file_validatorc                 C   s®   |j }d|kr>|d D ]&}t ||¡d krt |jd| ¡ qd|krz|d D ]*}t ||¡}|d k	rNt |jd| ¡ qNd|kr’| j |d ¡ d|krª| j |d ¡ d S )NZtest_assert_path_existsz+Expected path '%s' not found in result treeZtest_fail_if_path_existsz)Unexpected path '%s' found in result treeZtest_assert_c_code_hasZtest_fail_if_c_code_has)	Ú
directivesr   rD   r   rj   rk   rh   Úextendri   )r   r   r‚   rE   Z
first_noder   r   r   Ú_check_directives  s(    þþz#TreeAssertVisitor._check_directivesc                 C   s    |j | _|  |¡ |  |¡ |S r+   )rk   rg   r„   r   ©r   r   r   r   r   Úvisit_ModuleNode*  s    

z"TreeAssertVisitor.visit_ModuleNodec                 C   s   |   |¡ |  |¡ |S r+   )r„   r   r…   r   r   r   Úvisit_CompilerDirectivesNode0  s    

z.TreeAssertVisitor.visit_CompilerDirectivesNode)r   r!   r"   r   r   r„   r†   r‡   r   Zrecurse_to_childrenr    r#   r   r   r   r   rf   Ð   s   <rf   c              
   C   s¾  t jgt jtj |d¡gt jtj |d¡gdœ}|d kr@t ¡ }g d  }}t| dƒZ}z<|D ]0}|d d… dkrô| 	¡  	d¡ 	¡  
d¡ d	tjj¡}tj ||¡}	tj tj |	¡¡sÎt tj |	¡¡ |d k	rè|d  }
}|
 ¡  t|	d
ƒ}q`|d k	r
| |¡ q`| 	¡ r`| ¡  d¡s`| 	¡ dkr`t | 
d¡¡}|sDq`|d |dd …  }}z| || | ¡ W q` tk
r   | |¡ Y q`X q`W 5 |d k	rª| ¡  X W 5 Q R X ||fS )Nz	cython.pyzcythonize.py)ZPYTHONZCYTHONZ	CYTHONIZEÚrbé   s   #####ó   #ru   r]   Úwb)s   """s   '''r   r   )ÚsysÚ
executablerz   rE   r&   ÚtempfileZmkdtempr   Úclosera   ÚdecoderL   Úsepr|   ÚdirnameÚmakedirsr;   ÚlstriprK   Úshlexr2   r   ÚKeyError)Z	tree_fileZworkdirZcython_rootZprogramsÚheaderZcur_filer   rB   ÚfilenamerE   Zto_closeZcommandÚprogÚargsr   r   r   Úunpack_source_tree8  sD    ý

$

 
r›   Fc              	   C   sh   t |tƒrd}d}d}nd}d}d}|dkr0|}|r>t |¡}t| |||d}| |¡ W 5 Q R X dS )zœWrite some content (text or bytes) to the file
    at `file_path` without translating `'\n'` into `os.linesep`.

    The default encoding is `'utf-8'`.
    r‹   Nr(   r$   zutf-8)Úmoderv   Únewline)r0   ÚbytesÚtextwrapÚdedentr   r;   )rm   rp   r    rv   rœ   r   Zdefault_encodingr   r   r   r   Ú
write_file`  s    

r¡   c                 C   sh   t | |||d ztj |¡}W n tk
r8   d}Y nX |dksR|tj | ¡krdt | |||d q:dS )zÛ
    Write `content` to the file `file_path` without translating `'\n'`
    into `os.linesep` and make sure it is newer than the file `newer_than`.

    The default encoding is `'utf-8'` (same as for `write_file`).
    )r    rv   N)r¡   rz   rE   r}   ÚOSError)rm   Z
newer_thanrp   r    rv   Z
other_timer   r   r   Úwrite_newer_file~  s    
r£   )FN)FN)%Z
__future__r   rz   r`   Zunittestr•   rŒ   rŽ   rŸ   Úior   Ú	functoolsr   ZCompilerr   r   ZCompiler.TreeFragmentr   r	   ZCompiler.Visitorr
   r   r   r   r)   ZTestCaser*   rY   ÚcompileÚsubry   r~   re   rf   r›   r¡   r£   r   r   r   r   Ú<module>   sB   
O&ÿø
ÿôh(
