2022-05-23 00:16:32 +04:00

167 lines
4.4 KiB
Python

import os
import pytest
import textwrap
from numpy.testing import assert_array_equal
import numpy as np
from . import util
def _path(*a):
return os.path.join(*((os.path.dirname(__file__),) + a))
class TestString(util.F2PyTest):
sources = [_path('src', 'string', 'char.f90')]
@pytest.mark.slow
def test_char(self):
strings = np.array(['ab', 'cd', 'ef'], dtype='c').T
inp, out = self.module.char_test.change_strings(strings,
strings.shape[1])
assert_array_equal(inp, strings)
expected = strings.copy()
expected[1, :] = 'AAA'
assert_array_equal(out, expected)
class TestDocStringArguments(util.F2PyTest):
suffix = '.f'
code = """
C FILE: STRING.F
SUBROUTINE FOO(A,B,C,D)
CHARACTER*5 A, B
CHARACTER*(*) C,D
Cf2py intent(in) a,c
Cf2py intent(inout) b,d
PRINT*, "A=",A
PRINT*, "B=",B
PRINT*, "C=",C
PRINT*, "D=",D
PRINT*, "CHANGE A,B,C,D"
A(1:1) = 'A'
B(1:1) = 'B'
C(1:1) = 'C'
D(1:1) = 'D'
PRINT*, "A=",A
PRINT*, "B=",B
PRINT*, "C=",C
PRINT*, "D=",D
END
C END OF FILE STRING.F
"""
def test_example(self):
a = np.array(b'123\0\0')
b = np.array(b'123\0\0')
c = np.array(b'123')
d = np.array(b'123')
self.module.foo(a, b, c, d)
assert a.tobytes() == b'123\0\0'
assert b.tobytes() == b'B23\0\0', (b.tobytes(),)
assert c.tobytes() == b'123'
assert d.tobytes() == b'D23'
class TestFixedString(util.F2PyTest):
suffix = '.f90'
code = textwrap.dedent("""
function sint(s) result(i)
implicit none
character(len=*) :: s
integer :: j, i
i = 0
do j=len(s), 1, -1
if (.not.((i.eq.0).and.(s(j:j).eq.' '))) then
i = i + ichar(s(j:j)) * 10 ** (j - 1)
endif
end do
return
end function sint
function test_in_bytes4(a) result (i)
implicit none
integer :: sint
character(len=4) :: a
integer :: i
i = sint(a)
a(1:1) = 'A'
return
end function test_in_bytes4
function test_inout_bytes4(a) result (i)
implicit none
integer :: sint
character(len=4), intent(inout) :: a
integer :: i
if (a(1:1).ne.' ') then
a(1:1) = 'E'
endif
i = sint(a)
return
end function test_inout_bytes4
""")
@staticmethod
def _sint(s, start=0, end=None):
"""Return the content of a string buffer as integer value.
For example:
_sint('1234') -> 4321
_sint('123A') -> 17321
"""
if isinstance(s, np.ndarray):
s = s.tobytes()
elif isinstance(s, str):
s = s.encode()
assert isinstance(s, bytes)
if end is None:
end = len(s)
i = 0
for j in range(start, min(end, len(s))):
i += s[j] * 10 ** j
return i
def _get_input(self, intent='in'):
if intent in ['in']:
yield ''
yield '1'
yield '1234'
yield '12345'
yield b''
yield b'\0'
yield b'1'
yield b'\01'
yield b'1\0'
yield b'1234'
yield b'12345'
yield np.ndarray((), np.bytes_, buffer=b'') # array(b'', dtype='|S0')
yield np.array(b'') # array(b'', dtype='|S1')
yield np.array(b'\0')
yield np.array(b'1')
yield np.array(b'1\0')
yield np.array(b'\01')
yield np.array(b'1234')
yield np.array(b'123\0')
yield np.array(b'12345')
def test_intent_in(self):
for s in self._get_input():
r = self.module.test_in_bytes4(s)
# also checks that s is not changed inplace
expected = self._sint(s, end=4)
assert r == expected, (s)
def test_intent_inout(self):
for s in self._get_input(intent='inout'):
rest = self._sint(s, start=4)
r = self.module.test_inout_bytes4(s)
expected = self._sint(s, end=4)
assert r == expected
# check that the rest of input string is preserved
assert rest == self._sint(s, start=4)