
    i<              	          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mZmZ ddlmZmZ ddl	mZ dd	lmZ  G d
 de      Zd Z G d dej0                        Z G d de      Z e ej6                   ej8                  ddd            j8                  d      Z e ej6                   ej8                  ddd            j8                  d      Zd Z G d de      Z d Z!ddZ"ddZ#d Z$y)    N)partial   )Errors)
CodeWriter)TreeFragmentstrip_common_indentStringParseContext)TreeVisitorVisitorTransform)TreePath)	PostParsec                   $     e Zd Z fdZd Z xZS )NodeTypeWriterc                 >    t         |           d| _        g | _        y )Nr   )super__init___indentsresultself	__class__s    ;/usr/local/lib/python3.12/site-packages/Cython/TestUtils.pyr   zNodeTypeWriter.__init__   s        c                 d   | j                   sd}n"| j                   d   }|d   	d|dd z  }n|d   }| j                  j                  d| j                  z  |d|j                  j
                  z          | xj                  dz  c_        | j                  |       | xj                  dz  c_        y )	Nz(root)   z%s[%d]r      z  z: )access_pathr   appendr   r   __name__visitchildren)r   nodenametips       r   
visit_NodezNodeTypeWriter.visit_Node   s    D""2&C1v!#a(*1v4$--/'+T^^-D-DEF 	G4 r   )r    
__module____qualname__r   r%   __classcell__r   s   @r   r   r      s    
r   r   c                 ~    t               }|j                  |        dj                  dg|j                  z   dgz         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ws     r   	treetypesr1   )   s7    
 	AGGDM99bTAHH_t+,,r   c                   T    e Zd Zd Zd Zd Zd Zd Zd Zd Z	dd	Z
d
 ZefdZd Zy)
CythonTestc                 ,    t        j                          y Nr   init_threadr   s    r   setUpzCythonTest.setUp5       r   c                 ,    t        j                          y r5   r6   r8   s    r   tearDownzCythonTest.tearDown8   r:   r   c           
         t        |t              s|j                  d      }t        |t              s|j                  d      }t        t	        ||            D ]!  \  }\  }}| j                  ||d|||fz         # | j                  t        |      t        |      ddj                  |      ddj                  |             y)zHChecks that the given strings or lists of strings are equal line by liner+   zLine %d:
Exp: %s
Got: %sUnmatched lines. Got:

Expected:
N)
isinstancelistsplit	enumeratezipassertEquallenr.   )r   expectedr   idxexpected_lineresult_lines         r   assertLineszCythonTest.assertLines;   s    (D)~~d+H&$'\\$'F1:3x;P1Q-C--]K9S-Q\<]]_ 2R 	XFGKyyQYGZ\`\e\efl\mn	pr   c                 d    t               }|j                  |       |j                  j                  S r5   )r   writer   lines)r   treewriters      r   codeToLineszCythonTest.codeToLinesG   s%    T}}"""r   c                 B    dj                  | j                  |            S )Nr+   )r.   rQ   )r   rO   s     r   codeToStringzCythonTest.codeToStringL   s    yy))$/00r   c           	      @   | j                  |      }t        |j                  d            }t        t	        ||            D ]!  \  }\  }}| j                  ||d|||fz         # | j                  t        |      t        |      ddj                  |      d|       y )Nr+   zLine %d:
Got: %s
Exp: %sr>   r?   )rQ   r   rB   rC   rD   rE   rF   r.   )r   rG   result_treeresult_linesexpected_linesrH   linerI   s           r   
assertCodezCythonTest.assertCodeO   s    ''4,X^^D-AB*3Cn4U*V&C&$]D9S$<VVX +W 	\*C,?GKyyQ]G^`hi	kr   c                 X    | j                  t        j                  ||      d d|z         y )Nz"Path '%s' not found in result tree)assertNotEqualr   
find_first)r   pathrU   s      r   assertNodeExistszCythonTest.assertNodeExistsZ   s*    H//TBD@4G	Ir   Nc                     |i }|g }| j                         }|j                  d      r|t        d      d }|j                  dd      }t	        ||||      S )zNSimply create a tree fragment using the name of the test-case in parse errors.Nz	__main__.._pipeline)id
startswithrF   replacer   )r   codepxdsrc   r#   s        r   fragmentzCythonTest.fragment^   sa    <DHwwy??;'K()*D||C%D$x@@r   c                     t        |      S r5   )r1   )r   r/   s     r   r1   zCythonTest.treetypesj   s    r   c                     	  |        | j                  d|z         y# |$ r'}| j                  t        ||             |cY d}~S d}~ww xY 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
assertTruer@   )r   funcexc_typees       r   should_failzCythonTest.should_failm   sF    	FII88CD 	OOJq(34H	s    A
AA
A
c                 r    	  |       S # t         $ r$}| j                  t        |             Y d}~yd}~ww xY 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)	Exceptionrl   str)r   rn   excs      r   should_not_failzCythonTest.should_not_failx   s1    	 6M 	 IIc#h	 s   	 	616)NN)r    r&   r'   r9   r<   rK   rQ   rS   rY   r^   ri   r1   rs   rq   rv    r   r   r3   r3   3   sB    
p#
1	kI
A *3 	 r   r3   c                       e Zd ZdZddZy)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                 d    |i }| j                  ||      j                  }|D ]
  } ||      } |S r5   )ri   r/   )r   rc   pyxrh   rO   Ts         r   run_pipelinezTransformTest.run_pipeline   s:    <D}}S$',,AT7D r   r5   )r    r&   r'   __doc__r}   rw   r   r   ry   ry      s    .r   ry   z\s+r,   zz
        /[*] (
            (?: [^*\n] | [*][^/] )*
            [\n]
            (?: [^*] | [*][^/] )*
        ) [*]/
    z\s\s+z
    (?:
        <pre class=["'][^"']*cython\s+line[^"']*["']\s*>
        (?:[^<]|<(?!/pre))+
        </pre>
    )|(?:
        <style[^>]*>
        (?:[^<]|<(?!/style))+
        </style>
    )
    c                 X   d x}}| j                  d      r.t        j                  d| dd  d      \  }} | j                         } | j                  d      rR| dd  j                         } | j                  d      r.t        j                  d| dd  d      \  }} | j                         } ||| fS )N/z(?<!\\)/r   )maxsplit:)re   rerB   strip)patternstartends      r   _parse_patternr      s    EC#+wqr{QGw--/#!"+##%c"88KqILCmmoG#wr   c                   N     e Zd Z fdZd Zd Zd Zd Zej                  Z
 xZS )TreeAssertVisitorc                 L    t         |           d | _        g | _        g | _        y r5   )r   r   _module_pos_c_patterns_c_antipatternsr   s    r   r   zTreeAssertVisitor.__init__   s&    !r   c                 v      j                    j                  cd  fd fdfd}|S )Nc           	      J    t        j                  | d|d|rdndd|       y )Nz	Pattern 'z' waszwas notz
 found in )r   error)posr   found	file_paths       r   rl   z7TreeAssertVisitor.create_c_file_validator.<locals>.fail   s%    LLI- r   c                    |rBt        j                  ||      }|r||j                         d  }n j                  |d|        |rCt        j                  ||      }|r|d |j	                          }|S  j                  |d|        |S )NFr   r   )r   searchr   r   r   )r   contentr   r   rB   rl   r   s        r   extract_sectionzBTreeAssertVisitor.create_c_file_validator.<locals>.extract_section   s    		%1%eiikl3G))5S		#w/%nu{{}5G N ))3eyQNr   c                 >   
D ]I  }t        |      \  }}} | |||      }t        j                  ||      r4 	j                  |d|        K D ]I  }t        |      \  }}} | |||      }t        j                  ||      s4 	j                  |d|        K y )NFr   T)r   r   r   r   )r   r   r   r   r   sectionantipatternantipatternsr   rl   patternsr   s          r   validate_file_contentzHTreeAssertVisitor.create_c_file_validator.<locals>.validate_file_content   s    #&4W&=#sG))WeSIyy'2))7%9U $  ,*8*E'sK))WeSI99['2));diX  ,r   c                     | j                   }ss| S t        |d      5 }|j                         }d d d        t              } ||       y # 1 sw Y   xY w)Nutf8)encoding)c_fileopenread_strip_c_comments)r   r   fr   r   r   r   s       r   validate_c_filezBTreeAssertVisitor.create_c_file_validator.<locals>.validate_c_file   sO    ]]Ffv.!&&( /'0G!&'2 /.s   AA)r   r   )r   r   r   r   rl   r   r   s   ` @@@@@r   create_c_file_validatorz)TreeAssertVisitor.create_c_file_validator   s>    !%!1!143G3G,			Y 	Y		3 r   c                    |j                   }d|v rD|d   D ]<  }t        j                  ||      t        j                  |j
                  d|z         > d|v rF|d   D ]>  }t        j                  ||      }|t        j                  |j
                  d|z         @ d|v r| j                  j                  |d          d|v r| j                  j                  |d          d|v ra|d   }|Ydd	l	m
}  |       } ||j                         }||k7  r3 ||j                         t        j                  |j
                  d
       y y y y )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"test_body_needs_exception_handlingr   )HasNoExceptionHandlingVisitorz,Node had unexpected exception handling value)
directivesr   r\   r   r   r   r   extendr   Compiler.ParseTreeTransformsr   body)	r   r"   r   r]   
first_nodevaluer   visitorr   s	            r   _check_directivesz#TreeAssertVisitor._check_directives  sS   __
$
2"#<=&&tT2:LLELN >
 &3"#=>%00t<
)LL"CdJL ? $z1##J/G$HI$
2  ''
3L(MN/:=CDE W79$TYY//F?DII&LLF #	 ! >r   c                 l    |j                   | _        | j                  |       | j                  |       |S r5   )r   r   r   r!   r   r"   s     r   visit_ModuleNodez"TreeAssertVisitor.visit_ModuleNode-  s/    88t$4 r   c                 J    | j                  |       | j                  |       |S r5   )r   r!   r   s     r   visit_CompilerDirectivesNodez.TreeAssertVisitor.visit_CompilerDirectivesNode3  s#    t$4 r   )r    r&   r'   r   r   r   r   r   r   recurse_to_childrenr%   r(   r)   s   @r   r   r      s+    "3j@
 "55Jr   r   c                    t         j                  gt         j                  t        j                  j	                  |d      gt         j                  t        j                  j	                  |d      gd}|t        j                         }g d }}t        | d      5 }	 |D ]  }|d d dk(  r|j                         j                  d      j                         j                  d      j                  d	t        j                  j                        }t        j                  j	                  ||      }	t        j                  j                  t        j                  j                  |	            s2t        j                  t        j                  j                  |	             ||d }}
|
j                          t        |	d
      }#||j!                  |       8|j                         sJ|j#                         j%                  d      rk|j                         dvst'        j(                  |j                  d            }|s|d   |dd  }}	 |j+                  ||   |z           	 ||j                          	 d d d        ||fS # t,        $ r |j+                  |       Y 	w xY w# ||j                          w w xY w# 1 sw Y   ||fS xY w)Nz	cython.pyzcythonize.py)PYTHONCYTHON	CYTHONIZErb   s   #####   #r   r   wb)s   """s   '''r   r   )sys
executableosr]   r.   tempfilemkdtempr   r   decoderf   sepexistsdirnamemakedirscloserM   lstripre   shlexrB   r   KeyError)	tree_fileworkdircython_rootprogramsheadercur_filer   rX   filenamer]   to_closecommandprogargss                 r   unpack_source_treer   ;  s4   >>">>277<<[#IJnnbggll;&OPH ""$4HF	i	!	!8x'#zz|11$7==?FFvNVVWZ\^\c\c\g\ghH77<<:D77>>"''//$*?@BGGOOD$9:+-5t( (#D$/H)NN4(ZZ\$++-*B*B4*Hzz|+;;"'++dkk&.A"B&%,QZd3"MM(4.*=>' . # 5 
6 F?  ( 3"MM'23 #  $3 
6 F?s[   KE
J)&J)J)2J)J%J))KJ&"J)%J&&J))J>>KKc                     t        |t              rd}d}d}nd}d}d}||}|rt        j                  |      }t	        | |||      5 }|j                  |       ddd       y# 1 sw Y   yxY w)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   Nr0   r+   zutf-8)moder   newline)r@   bytestextwrapdedentr   rM   )r   r   r   r   r   r   default_encodingr   s           r   
write_filer   c  sw     '5!  "#//'*	idXw	G1	 
H	G	Gs   A##A,c                 8   t        | |||       	 t        j                  j                  |      }|"|t        j                  j                  |       k\  r6t        | |||       ||t        j                  j                  |       k\  r5yy# t        $ r d}Y hw xY w)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   r]   getmtimeOSError)r   
newer_thanr   r   r   
other_times         r   write_newer_filer     s     y'&8DWW%%j1

 

bgg.>.>y.I I9gfxH 

bgg.>.>y.I I	  
s   B BBc                 ,   t        d      }	 t        j                         5 }t        | t	        |      g      }|j                         }ddd       r|d   S # 1 sw Y   xY w# t        j                  $ r}t        |j                        d}~ww xY w)z
    Compiles code far enough to get errors from the parser and post-parse stage.

    Is useful for checking for syntax errors, however it doesn't generate runable
    code.
    testrb   Nr   )	r	   r   local_errorsr   r   
substituteCompileErrorSyntaxErrormessage_only)rg   contexterrorsr   rp   s        r   py_parse_coder     s     !(G	*  "f!$)G2D1EFF&&(F # )OM #"  *!..))*s.   A& (A	A& A#A& &B9BB)FN)%r   r   unittestr   r   r   r   	functoolsr   Compilerr   r   Compiler.TreeFragmentr   r   r	   Compiler.Visitorr
   r   r   r   r   r   r1   TestCaser3   ry   compilesubr   _strip_cython_code_from_htmlr   r   r   r   r   r   rw   r   r   <module>r     s   	 	   
     " X X ;  3[ .-L "" L ^J L JBJJ
BFF62  	 #r   'zrzz
BFF8R 
 
	( #r  
j6( j6Z%P<I&*r   