summaryrefslogtreecommitdiff
path: root/numpy/f2py/tests/test_crackfortran.py
blob: d26917f0c23f5b061ecf22a6a92d9d00c8e715f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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)