o
    &[ho9                     @   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__ E/var/www/vscode/pina/lib/python3.10/site-packages/Cython/TestUtils.pyr      s   
zNodeTypeWriter.__init__c                 C   s   | j sd}n| j d }|d d urd|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)access_pathr   appendr   r   __name__visitchildren)r   nodename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 )zReturns 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   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      t   d S Nr   init_threadr   r   r   r   setUp7      zCythonTest.setUpc                 C   r.   r/   r0   r   r   r   r   tearDown:   r3   zCythonTest.tearDownc              	   C   s   t |ts
|d}t |ts|d}tt||D ]\}\}}| ||d|||f  q| 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_line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)   rF   )r   rD   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: %sr5   )rF   r	   r8   r9   r:   r;   r<   r)   )r   r=   result_treeresult_linesexpected_linesr>   liner?   r   r   r   
assertCodeQ   s   
zCythonTest.assertCodec                 C   s   |  t||d d|  d S )Nz"Path '%s' not found in result tree)assertNotEqualr   
find_first)r   pathrH   r   r   r   assertNodeExists\   s   zCythonTest.assertNodeExistsNc                 C   sV   |du ri }|du 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
startswithr<   replacer   )r   codepxdsrS   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   sT   z|  |  d|  W dS  |y) } z| t|| |W  Y d}~S d}~ww )zCalls "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)fail
assertTruer6   )r   funcexc_typeer   r   r   should_failo   s   zCythonTest.should_failc              
   C   s>   z| W S  t y } z| t| W Y d}~dS d}~ww )zCalls 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)	ExceptionrZ   str)r   r\   excr   r   r   should_not_failz   s   zCythonTest.should_not_fail)NN)r   r#   r$   r2   r4   rA   rF   rG   rL   rP   rY   r,   r`   r_   rc   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 u ri }|  ||j}|D ]}||}q|S r/   )rY   r*   )r   rS   pyxrX   rD   Tr   r   r   run_pipeline   s   
zTransformTest.run_pipeliner/   )r   r#   r$   __doc__rg   r   r   r   r   rd      s    rd   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rt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:)rU   rer8   strip)patternstartendr   r   r   _parse_pattern   s   



rq   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   rr   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 %swaszwas not)r   error)posrn   found	file_pathr   r   r   rZ      s
   
z7TreeAssertVisitor.create_c_file_validator.<locals>.failc                    sv   |rt ||}|r|| d  }n	 j|d| d |r9t ||}|r0|d |  }|S  j|d| d |S )NFry   rz   )rl   searchrp   rs   ro   )rz   contentro   rp   r8   )rZ   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||rCj|d| d q$d S )NFr{   T)rq   rl   r|   rs   )rz   r}   rn   ro   rp   sectionantipattern)antipatternsr~   rZ   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 d    n1 sw   Y  t|}|| tj|d d }tj|rmtj|tj|krot|dd}| }W d    n1 s]w   Y  t	|}|| d S d S d S )Nutf8)encodingr   z.html)
c_filer   read_strip_c_commentsosrO   splitextexistsgetmtime_strip_cython_code_from_html)r   r   fr}   	html_file)r   r   r   r   r   validate_c_file  s    

$
zBTreeAssertVisitor.create_c_file_validator.<locals>.validate_c_file)rt   ru   )r   r   r   )r   r~   rZ   r   r   r   r   create_c_file_validator   s   z)TreeAssertVisitor.create_c_file_validatorc                 C   s   |j }d|v r|d D ]}t||d u rt|jd|  qd|v r=|d D ]}t||}|d ur<t|jd|  q'd|v rI| j|d  d|v rW| j|d  d S d S )Ntest_assert_path_existsz+Expected path '%s' not found in result treetest_fail_if_path_existsz)Unexpected path '%s' found in result treetest_assert_c_code_hastest_fail_if_c_code_has)	
directivesr   rN   r   rw   rx   rt   extendru   )r   r   r   rO   
first_noder   r   r   _check_directives  s.   z#TreeAssertVisitor._check_directivesc                 C   s    |j | _| | | | |S r/   )rx   rs   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   recurse_to_childrenr"   r%   r   r   r   r   rr      s    <rr   c              
   C   s  t jgt jtj|dgt jtj|dgd}|d u r t }g d }}t| d}z|D ]}|d d dkrw| d 	d
d	tjj}tj||}	tjtj|	sdttj|	 |d urq|d }
}|
  t|	d
}q.|d ur|| q.| r| ds| dvrt|	d}|sq.|d |dd  }}z||| |  W q. ty   || Y q.w q.W |d ur|  n
|d ur|  w w W d    ||fS 1 sw   Y  ||fS )Nz	cython.pyzcythonize.py)PYTHONCYTHON	CYTHONIZErb   s   #####   #r   ri   wb)s   """s   '''r   r   )sys
executabler   rO   r)   tempfilemkdtempr   rm   decoderV   sepr   dirnamemakedirscloserB   lstriprU   shlexr8   r   KeyError)	tree_fileworkdircython_rootprogramsheadercur_filer   rK   filenamerO   to_closecommandprogargsr   r   r   unpack_source_tree8  sX   
$


r   Fc                 C   s~   t |trd}d}d}nd}d}d}|du r|}|rt|}t| |||d}|| W d   dS 1 s8w   Y  dS )zWrite 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)moder   newline)r6   bytestextwrapdedentr   rB   )rz   r}   r   r   r   r   default_encodingr   r   r   r   
write_file`  s   

"r   c                 C   s   t | |||d ztj|}W n ty   d}Y nw |du s(|tj| kr>t | |||d |du s(|tj| ks(dS 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   r   N)r   r   rO   r   OSError)rz   
newer_thanr}   r   r   
other_timer   r   r   write_newer_file~  s    r   )FN)%
__future__r   r   rl   unittestr   r   r   r   ior   	functoolsr   Compilerr   r   Compiler.TreeFragmentr   r	   Compiler.Visitorr
   r   r   r   r,   TestCaser-   rd   compilesubr   r   rq   rr   r   r   r   r   r   r   r   <module>   sD    
O&
h
(