a ;jgc@sddlZddlZddlZddlZddlZddlmZddlmZddl Z ddl Z ddl m Z ddl mZeddZdd d Ze jd d ddZe jd d ddZe jd d ddZe jd d ddZe jd d ddZe jd d ddZddZddZddZd d!Zd"d#Zd$d%Ze jj e !d&kp@ej"d'kd(d)d*d+Z#e jj e !d&kplej"d'kd(d)d,d-Z$e jj%d.d/Z&d0d1Z'd2d3Z(d4d5Z)d6d7Z*d8d9Z+d:d;Z,dd?Z.d@dAZ/dBdCZ0dDdEZ1dFdGZ2dHdIZ3dJdKZ4e jj5dLd)dMdNZ6dOdPZ7dQdRZ8dSdTZ9dUdVZ:dWdXZ;dYdZZd_d`Z?e jj5dLd)dadbZ@dcddZAdedfZBdgdhZCdidjZDdkdlZEdmdnZFdodpZGdqdrZHdsdtZIdudvZJdwdxZKdydzZLd{d|ZMd}d~ZNddZOddZPddZQddZRdS)N)Path) namedtuple)util)mainPPathsz(finp, f90inp, pyf, wrap77, wrap90, cmodfuntitledc CsRt|}t|d|d|d||d||d||ddS)axTakes in a temporary file for testing and returns the expected output and input paths Here expected output is essentially one of any of the possible generated files. ..note:: Since this does not actually run f2py, none of these are guaranteed to exist, and module names are typically incorrect Parameters ---------- fname_inp : str The input filename mname : str, optional The name of the module, untitled by default Returns ------- genp : NamedTuple PPaths The possible paths which are generated, not all of which exist z.fz.f90.pyfz-f2pywrappers.fz-f2pywrappers2.f90module.c)finpf90inppyfwrap77wrap90cmodf)rr with_suffix with_name)Z fname_inpmnamebpathrF/usr/local/lib/python3.9/site-packages/numpy/f2py/tests/test_f2py2e.py get_io_pathssrsession)scopecCs2tdddd}|d}|j|dd|S)'Generates a single f90 file for testingtestssrccliz hiworld.f90z hello.f90asciiencodingrZgetpath read_textZ getbasetemp write_texttmpdir_factoryfdatfnrrrhello_world_f909s r(cCs2tdddd}|d}|j|dd|S)z(F90 file for testing warnings in gh23598rrZ crackfortranzgh23598Warn.f90rrr!r$rrr gh23598_warnBs r)cCs2tdddd}|d}|j|dd|S)z8F90 file for testing disallowed CLI arguments in ghff819rrrz gh_22819.pyfrrr!r$rrr gh22819_cliKs r*cCs2tdddd}|d}|j|dd|S)'Generates a single f77 file for testingrrrzhi77.fzhello.frrr!r$rrrhello_world_f77Ts r,cCs2tdddd}|d}|j|dd|S)r+rrZ return_realzfoo77.fzfoo.frrr!r$rrr retreal_f77]s r-cCs`tdddd}tdddd}|d}|d}|j|dd |j|dd |S) rrrf2cmapzisoFortranEnvMap.f90z .f2py_f2cmapz f2cmap.f90Zmapfilerrr!)r%r&r.r'Zfmaprrr f2cmap_f90es  r/cCst|}|tdd|t|jdtdd|jdD}d|vsVJd|vsbJd|vsnJd |vszJd sJWd n1s0Yd S) zCheck that module names are handled correctly gh-22819 Essentially, the -m name cannot be used to import the module, so the module named in the .pyf needs to be used instead CLI :: -m and a .pyf file argv f2py -m blah cSsg|]}|r|jqSr)is_filename).0itemrrr }z$test_gh22819_cli..*z blahmodule.czblah-f2pywrappers.fztest_22819-f2pywrappers.fztest_22819module.cz Ignoring blahN) rsetattrsyssplitr switchdirparentf2pyclirglob)capfdr* monkeypatchipathZ gen_pathsrrrtest_gh22819_cliqs    rCc Cst|}|tdd|dt|jDtjt ddt Wdn1sZ0YWdn1sx0YdS)zBOnly one .pyf file allowed gh-22819 CLI :: .pyf files r0r1z hello.pyfzOnly one .pyf file per call)matchN) rr9r:r;rr<r=pytestraises ValueErrorr>)r@r*rArBrrrtest_gh22819_many_pyfs rHcCsxt|dd}|j}|tdd|dt|j,t|j }d|vsVJWdn1sj0YdS)Ntestrr0f2py z -m testzintproductf2pywrap, intpr) rr r9r:r;rr<r=r>rr")r@r)rAfoutlrBwrapperrrrtest_gh23598_warns  rNcCst|}t|jd}|tdd|d|t|j@t| \}}d|vs`Jt| srJWdn1s0YdS)zIEnsures that a signature file is generated via the CLI CLI :: -h r r0zf2py -h  Saving signatures to fileN) rstemr9r:r;rr<r=r> readouterrexists)r@r(rArBZopathout_rrr test_gen_pyfs  rVcCszt|}|tdd|t|j:t|\}}d|vsLJd|vsXJWdn1sl0YdS)zHEnsures that a signature file can be dumped to stdout CLI :: -h r0zf2py -h stdout rPzfunction hi() ! in N rr9r:r;rr<r=r>rRr@r(rArBrTrUrrrtest_gen_pyf_stdouts  rYc Cst|}|tdd|t|jjtdjdddt t .t | \}}d|vsjJWdn1s~0YWdn1s0YdS) zjEnsures that the CLI refuses to overwrite signature files CLI :: -h without --overwrite-signature r0f2py -h faker.pyf faker.pyf Fake newsrrz&Use --overwrite-signature to overwriteN) rr9r:r;rr<r=r#rErF SystemExitr>rR)r@r(rArBrUerrrrrtest_gen_pyf_no_overwrites  r_Linux) zCompiler and 3.12 required)reasoncCsnt|}|tdd|t|j.t|\}}d|vsLJWdn1s`0YdS)z@Check that modules are named correctly CLI :: defaults r0zf2py --backend meson -c zuntitledmodule.cNrWrXrrrtest_untitled_clis  rdc CsPd}t||d}|j}|tdd|d|t|j.t| \}}d|vs`JWdn1st0Y|tddt|j.t| \}}d |vsJWdn1s0Yd }|tdd|d |d t|j0t| \}}d |vs,JWdn1sB0YdS)zqCheck that no distutils imports are performed on 3.12 CLI :: --fcompiler --help-link --backend distutils hirJr0rKz -c --fcompiler=gfortran -m z%--fcompiler cannot be used with mesonNzf2py --help-linkzUse --dep for meson buildsZhi2z -c -m z --backend distutilsz.Cannot use distutils backend with Python>=3.12) rr r9r:r;rr<r=r>rR)r@r(rAMNAMErLrBrTrUrrr!test_no_py312_distutils_fcompilers2  *  * rgc Cst|dd}|j}d}d}|tdd|d|t|jft| \}}|D]} d| d |vs`Jq`|D]} d | d |vsJqWd n1s0Yd S) z9Tests that functions can be skipped CLI :: skip: rIrJt0 t4 t8 sd s8 s4td s0r0rKz -m test skip: z=buildmodule: Could not found the body of interfaced routine " ". Skipping.Constructing wrapper function ""N rr r9r:r;rr<r=r>rR) r@r-rArLrBtoskip remainingrTr^skeyrkeyrrrtest_f2py_skips$     rrc Cst|dd}|j}d}d}|tdd|d|t|jft| \}}|D]} d| d |vs`Jq`|D]} d | d |vsJqWd n1s0Yd S) z>Test that functions can be kept by only: CLI :: only: rIrJrhrir0rKz -m test only: rR)r@r(r-rArLrBrnZipath2rtrrTr^rprqrrrtest_file_processing_switch's*     rxcCsd}t||d}|j}|tdd|d|t|jtWdn1s\0Yt |j svJt |j sJdS)zHChecks the generation of files based on a module name CLI :: -m rerJr0rKrwN) rr r9r:r;rr<r=r>rrSrr)r@r(rArfrLrBrrrtest_mod_gen_f77Es $ryc Csd}t||d}|j}|tdd|d|dt|jVtt d $}| }d|vslJWd n1s0YWd n1s0Yd S) zCheck that pyf files are correctly generated with module structure CLI :: -m -h pyf_file BUG: numpy-gh #20520 rerJr0rKrwz -h hi.pyfzhi.pyfzpython module hiN) rr r9r:r;rr<r=r>ropenread)r@r,rArfrLrBZhipyfZpyfdatrrrtest_mod_gen_gh25263Vs  r|c Cs&t|dd}|j}td}td}|tdd|dt|j Ft | \}}| |dusrJ| |dusJWdn1s0Y|tdd|d t|j Ht | \}}| |dusJ| |dusJWdn1s0YdS) zHLowers cases by flag or when -h is present CLI :: --[no-]lower rIrJzHI\(\)zhi\(\)r0rKz -m test --lowerNz -m test --no-lower) rr recompiler9r:r;rr<r=r>rRsearch r@r,rArLrBZcapshiZcapslorTrUrrrtest_lower_cmodfs$    0 rc Cs6t|dd}|j}td}td}|tdd|d|jdt |j Ft | \}}| |d uszJ| |d usJWd n1s0Y|tdd|d|jd t |j Ht | \}}| |d usJ| |d usJWd n1s(0Yd S) z^Lowers cases in signature files by flag or when -h is present CLI :: --[no-]lower -h rIrJz Block: HIz Block: hir0rKz -h z -m test --overwrite-signatureNz) -m test --overwrite-signature --no-lower)rr r}r~r9r:r r;rr<r=r>rRrrrrrtest_lower_sigs0    0 rc Cst|}d}d}|tdd|d|d|t|j6t|\}}d|d|vshJWd n1s|0Yd S) zNEnsures that the build directory can be specified CLI :: --build-dir rvZtttmpr0f2py -m rOz --build-dir zWrote C/API module "rlNrW)r@r(rArBrZodirrTrUrrrtest_build_dirs rcCst|}|tdd|dt|j@tdjdddt| \}}d|vs`JWd n1st0Yd S) zXEnsures that the build directory can be specified CLI :: --overwrite-signature r0rZz --overwrite-signaturer[r\rrrPN) rr9r:r;rr<r=r#r>rRrXrrrtest_overwrites rc Cst|}d}|tdd|d|dt|jpt|\}}d|vsXJt|d }d| vs|JWd n1s0YWd n1s0Yd S) zJEnsures that TeX documentation is written out CLI :: --latex-doc rvr0rrOz --latex-docDocumentation is saved to file module.tex\documentclassN rr9r:r;rr<r=r>rRrzr{r@r(rArBrrTrUZotexrrr test_latexdocs  rc Cszt|}d}|tdd|d|dt|j.t|\}}d|vsXJWdn1sl0YdS)zMEnsures that TeX documentation is written out CLI :: --no-latex-doc rvr0rrOz --no-latex-docrNrWr@r(rArBrrTrUrrrtest_nolatexdocs rc Cst|}d}|tdd|d|dt|jrt|\}}d|vsXJtd|d }d | vs~JWd n1s0YWd n1s0Yd S) zEnsures that truncated documentation is written out TODO: Test to ensure this has no effect without --latex-doc CLI :: --latex-doc --short-latex rvr0rrOz --latex-doc --short-latexr./rrNrrrrrtest_shortlatexs  rc Cst|}d}|tdd|d|dt|jrt|\}}d|vsXJtd|d }d | vs~JWd n1s0YWd n1s0Yd S) zIEnsures that RsT documentation is written out CLI :: --rest-doc rvr0rrOz --rest-doc#ReST Documentation is saved to filerz module.restz.. -*- rest -*-Nr)r@r(rArBrrTrUZorstrrr test_restdocs  rc Cszt|}d}|tdd|d|dt|j.t|\}}d|vsXJWdn1sl0YdS)zLEnsures that TeX documentation is written out CLI :: --no-rest-doc rvr0rrOz --no-rest-docrNrWrrrrtest_norestexdocs rc Cst|}d}|tdd|d|dt|jZttd|d }d| vsfJWd n1sz0YWd n1s0Yd S) zIEnsures that debugging wrappers are written CLI :: --debug-capi rvr0rrOz --debug-capirr z#define DEBUGCFUNCSN rr9r:r;rr<r=r>rzr{)r@r(rArBrocmodrrrtest_debugcapi#srz2Consistently fails on CI; noisy so skip not xfail.c Cst|}d}|tdd|d|dt|jZttd}t j |ddd }d }t d }|j |ksvJ|j|ksJWd n1s0Yd S) zEEnsures that debugging wrappers work CLI :: --debug-capi -c rvr0rrOz -c --debug-capiz#python3 -c "import blah; blah.hi()"TUTF-8capture_outputr Hello World a debug-capi:Python C/API function blah.hi() debug-capi:float hi=:output,hidden,scalar debug-capi:hi=0 debug-capi:Fortran subroutine `f2pywraphi(&hi)' debug-capi:hi=0 debug-capi:Building return value. debug-capi:Python C/API function blah.hi: successful. debug-capi:Freeing memory. N)rr9r:r;rr<r=r>shlex subprocessruntextwrapdedentstdoutstderr)r(rArBrcmd_runrouteoutZeerrrrrtest_debugcapi_bld3s  rc Cst|}d}|tdd|d|t|jtWdn1sR0Y|\}}d|vstJ|tdd|d|dt|j.t|\}}d|vsJWdn1s0YdS)zoEnsures that fortran subroutine wrappers for F77 are included by default CLI :: --[no]-wrap-functions rvr0rrON Fortran 77 wrappers are saved toz --wrap-functionsrWrrrrtest_wrapfunc_defQs$   rc Cszt|}d}|tdd|d|dt|j.t|\}}d|vsXJWdn1sl0YdS)zeEnsures that fortran subroutine wrappers for F77 can be disabled CLI :: --no-wrap-functions rvr0rrOz --no-wrap-functionsrNrWrrrrtest_nowrapfuncjs rc Cst|}d}|tdd|d|dt|jjttd|d0}| }d|vsjJd |vsvJWd n1s0YWd n1s0Yd S) zcAdd to the include directories CLI :: -include TODO: Document this in the help string rvr0rrOz' -include -include rr z#include z#include Nr)r@r(rArBrrZocmrrrrtest_inclheaderzs rcCsdS)z?Add to the include directories CLI :: --include-paths Nrrrrr test_inclpathsrcCsdS)z;Add to the include directories CLI :: --help-link Nrrrrr test_hlinksrcCst|}|tdd|dt|j^t|\}}d|vsNJd|vsZJd|vsfJd|vsrJd|vs~JWd n1s0Yd S) zOCheck that Fortran-to-Python KIND specs can be passed CLI :: --f2cmap r0r1z --f2cmap mapfilez!Reading f2cmap from 'mapfile' ...z&Mapping "real(kind=real32)" to "float"z'Mapping "real(kind=real64)" to "double"z,Mapping "integer(kind=int64)" to "long_long"z0Successfully applied user defined f2cmap changesNrW)r@r/rArBrTrUrrr test_f2cmaps     rcCstt|}|tdd|dt|j2t|\}}t |dksRJWdn1sf0YdS)z)Reduce verbosity CLI :: --quiet r0r1z --quietrN) rr9r:r;rr<r=r>rRlenrXrrr test_quiets  rcCspt|}|tdd|dt|j.t|\}}d|vsNJWdn1sb0YdS)z-Increase verbosity CLI :: --verbose r0r1z --verboseZ analyzelineNrWrXrrr test_verboses  rcCsl|tddtt<t|\}}ddl}|j | ksJJWdn1s^0YdS)z"Ensure version CLI :: -v r0zf2py -vrN) r9r:r;rErFr]r>rRnumpy __version__strip)r@rArTrUnprrr test_versions   rcCst|}|tdd|dt|jBttd}t j |ddd}d}|j |ksbJWd n1sv0Yd S) z CLI :: -c r0r1z -cz"python -c "import blah; blah.hi()"TrrrN) rr9r:r;rr<r=r>rrrr)r(rArBrrrrrr test_npdistops rcCsdS)z CLI :: -c --fcompiler Nrrrrrtest_npd_fcompilersrcCsdS)z CLI :: -c --compiler Nrrrrrtest_npd_compilersrcCsdS)z$ CLI :: -c --help-fcompiler Nrrrrrtest_npd_help_fcompilersrcCsdS)z CLI :: -c --f77exec Nrrrrrtest_npd_f77exec srcCsdS)z CLI :: -c --f90exec Nrrrrrtest_npd_f90execsrcCsdS)z CLI :: -c --f77flags Nrrrrrtest_npd_f77flagssrcCsdS)z CLI :: -c --f90flags Nrrrrrtest_npd_f90flags#srcCsdS)z CLI :: -c --opt Nrrrrr test_npd_opt+srcCsdS)z CLI :: -c --arch Nrrrrr test_npd_arch3srcCsdS)z CLI :: -c --noopt Nrrrrrtest_npd_noopt;srcCsdS)z CLI :: -c --noarch Nrrrrrtest_npd_noarchCsrcCsdS)z CLI :: -c --debug Nrrrrrtest_npd_debugKsrcCsdS)z% CLI :: -c --link- Nrrrrrtest_npd_link_autoSsrcCsdS)z/ CLI :: -c -L/path/to/lib/ -l Nrrrrr test_npd_lib[srcCsdS)z CLI :: -D Nrrrrrtest_npd_definecsrcCsdS)z CLI :: -U Nrrrrrtest_npd_undefineksrcCsdS)z$ CLI :: -I/path/to/include/ Nrrrrr test_npd_inclssrcCsdS)z8 CLI :: .o .so .a Nrrrrrtest_npd_linker{sr)r)Srr}r:rrpathlibr collectionsrplatformrErZnumpy.f2py.f2py2err>rrZfixturer(r)r*r,r-r/rCrHrNrVrYr_markZskipifsystem version_infordrgZxfailrrrurxryr|rrrrrrrrrrskiprrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrs(      '                "  '