
    fo9              	          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e      Zd Z G d dej2                        Z G d de      Z e ej8                   ej:                  ddd            j:                  d      Z e ej8                   ej:                  ddd            j:                  d      Zd Z  G d de      Z!d Z"ddZ#ddZ$y)    )absolute_importN)open)partial   )Errors)
CodeWriter)TreeFragmentstrip_common_indent)TreeVisitorVisitorTransform)TreePathc                   $     e Zd Z fdZd Z xZS )NodeTypeWriterc                 F    t         t        |           d| _        g | _        y )Nr   )superr   __init___indentsresultself	__class__s    d/mounts/lovelace/software/anaconda3/envs/mapdamage2/lib/python3.12/site-packages/Cython/TestUtils.pyr   zNodeTypeWriter.__init__   s    nd,.    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! 3q8+1v54==0(,dnn.E.EFG 	H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   +   s8    
 	AGGDM::seahh&#.//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.setUp7       r   c                 ,    t        j                          y r5   r6   r8   s    r   tearDownzCythonTest.tearDown:   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)~~e,H&$'\\%(F1:3x;P1Q-C--]K9S-Q\<]]_ 2R 	XFGKyyQYGZ\a\f\fgm\no	qr   c                 d    t               }|j                  |       |j                  j                  S r5   )r   writer   lines)r   treewriters      r   codeToLineszCythonTest.codeToLinesI   s%    T}}"""r   c                 B    dj                  | j                  |            S )Nr+   )r.   rQ   )r   rO   s     r   codeToStringzCythonTest.codeToStringN   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.assertCodeQ   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.assertNodeExists\   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pxdsrb   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.treetypesl   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_failo   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)	Exceptionrk   str)r   rm   excs      r   should_not_failzCythonTest.should_not_failz   s1    	 6M 	 IIc#h	 s   	 	616)NN)r    r&   r'   r9   r<   rK   rQ   rS   rY   r^   rh   r1   rr   rp   ru    r   r   r3   r3   5   sB    
q#
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   )rh   r/   )r   rb   pyxrg   rO   Ts         r   run_pipelinezTransformTest.run_pipeline   s:    <D}}S$',,AT7D r   r5   )r    r&   r'   __doc__r|   rv   r   r   rx   rx      s    .r   rx   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:)rd   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                 T    t         t        |           d | _        g | _        g | _        y r5   )r   r   r   _module_pos_c_patterns_c_antipatternsr   s    r   r   zTreeAssertVisitor.__init__   s)    /1!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   rk   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   rk   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   rk   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                 L   | j                   }ss| S t        |d      5 }|j                         }d d d        t              } ||       t        j
                  j                  |      d   dz   }t        j
                  j                  |      r{t        j
                  j                  |      t        j
                  j                  |      k  r;t        |d      5 }|j                         }d d d        t        |      } ||       y y y # 1 sw Y   xY w# 1 sw Y   ,xY w)Nutf8)encodingr   z.html)
c_filer   read_strip_c_commentsosr]   splitextexistsgetmtime_strip_cython_code_from_html)r   r   fr   	html_filer   r   r   s        r   validate_c_filezBTreeAssertVisitor.create_c_file_validator.<locals>.validate_c_file  s    ]]Ffv.!&&( /'0G!&'2((03g=Iww~~i(RWW-=-=f-EIYIYZcId-d)f5ffhG 66w?%i9	 .e( /. 65s   DDDD#)r   r   )r   r   r   r   rk   r   r   s   ` @@@@@r   create_c_file_validatorz)TreeAssertVisitor.create_c_file_validator   s>    !%!1!143G3G,			Y 	Y	:$ 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          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)	
directivesr   r\   r   r   r   r   extendr   )r   r"   r   r]   
first_nodes        r   _check_directivesz#TreeAssertVisitor._check_directives  s    __
$
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 3r   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_CompilerDirectivesNode0  s#    t$4 r   )r    r&   r'   r   r   r   r   r   r   recurse_to_childrenr%   r(   r)   s   @r   r   r      s+    ":xO(
 "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
executabler   r]   r.   tempfilemkdtempr   r   decodere   sepr   dirnamemakedirscloserM   lstriprd   shlexrB   r   KeyError)	tree_fileworkdircython_rootprogramsheadercur_filer   rX   filenamer]   to_closecommandprogargss                 r   unpack_source_treer   8  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   `  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]   r   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)FN)%
__future__r   r   r   unittestr   r   r   r   ior   	functoolsr   Compilerr   r   Compiler.TreeFragmentr	   r
   Compiler.Visitorr   r   r   r   r1   TestCaser3   rx   compilesubr   r   r   r   r   r   r   rv   r   r   <module>r      s    & 	 	   
      " D ; [ .0L "" L ^J L JBJJ
BFF62  	 #r   'zrzz
BFF8R 
 
	( #r  
e6( e6P%P<Ir   