import numpy as np from numpy.testing import assert_array_equal from . import util from numpy.f2py import crackfortran import tempfile import textwrap class TestNoSpace(util.F2PyTest): # issue gh-15035: add handling for endsubroutine, endfunction with no space # between "end" and the block name code = """ subroutine subb(k) real(8), intent(inout) :: k(:) k=k+1 endsubroutine subroutine subc(w,k) real(8), intent(in) :: w(:) real(8), intent(out) :: k(size(w)) k=w+1 endsubroutine function t0(value) character value character t0 t0 = value endfunction """ def test_module(self): k = np.array([1, 2, 3], dtype=np.float64) w = np.array([1, 2, 3], dtype=np.float64) self.module.subb(k) assert_array_equal(k, w + 1) self.module.subc([w, k]) assert_array_equal(k, w + 1) assert self.module.t0(23) == b'2' class TestPublicPrivate(): def test_defaultPrivate(self, tmp_path): f_path = tmp_path / "mod.f90" with f_path.open('w') as ff: ff.write(textwrap.dedent("""\ module foo private integer :: a public :: setA integer :: b contains subroutine setA(v) integer, intent(in) :: v a = v end subroutine setA end module foo """)) mod = crackfortran.crackfortran([str(f_path)]) assert len(mod) == 1 mod = mod[0] assert 'private' in mod['vars']['a']['attrspec'] assert 'public' not in mod['vars']['a']['attrspec'] assert 'private' in mod['vars']['b']['attrspec'] assert 'public' not in mod['vars']['b']['attrspec'] assert 'private' not in mod['vars']['seta']['attrspec'] assert 'public' in mod['vars']['seta']['attrspec'] def test_defaultPublic(self, tmp_path): f_path = tmp_path / "mod.f90" with f_path.open('w') as ff: ff.write(textwrap.dedent("""\ module foo public integer, private :: a public :: setA contains subroutine setA(v) integer, intent(in) :: v a = v end subroutine setA end module foo """)) mod = crackfortran.crackfortran([str(f_path)]) assert len(mod) == 1 mod = mod[0] assert 'private' in mod['vars']['a']['attrspec'] assert 'public' not in mod['vars']['a']['attrspec'] assert 'private' not in mod['vars']['seta']['attrspec'] assert 'public' in mod['vars']['seta']['attrspec'] class TestExternal(util.F2PyTest): # issue gh-17859: add external attribute support code = """ integer(8) function external_as_statement(fcn) implicit none external fcn integer(8) :: fcn external_as_statement = fcn(0) end integer(8) function external_as_attribute(fcn) implicit none integer(8), external :: fcn external_as_attribute = fcn(0) end """ def test_external_as_statement(self): def incr(x): return x + 123 r = self.module.external_as_statement(incr) assert r == 123 def test_external_as_attribute(self): def incr(x): return x + 123 r = self.module.external_as_attribute(incr) assert r == 123 class TestCrackFortran(util.F2PyTest): suffix = '.f90' code = textwrap.dedent(""" subroutine gh2848( & ! first 2 parameters par1, par2,& ! last 2 parameters par3, par4) integer, intent(in) :: par1, par2 integer, intent(out) :: par3, par4 par3 = par1 par4 = par2 end subroutine gh2848 """) def test_gh2848(self): r = self.module.gh2848(1, 2) assert r == (1, 2)