summaryrefslogtreecommitdiff
path: root/numpy/f2py/tests/test_string.py
diff options
context:
space:
mode:
authorPearu Peterson <pearu.peterson@gmail.com>2021-04-12 23:23:48 +0300
committerPearu Peterson <pearu.peterson@gmail.com>2021-05-10 17:47:46 +0300
commit8992459df6f8558c85d5036951799b757d74b3d5 (patch)
tree61faaf7398432c894328047a7570218a2cf1a866 /numpy/f2py/tests/test_string.py
parentf9c3ed5bc5c7bad4649bbfc4056c5d6ea39e1abb (diff)
downloadnumpy-8992459df6f8558c85d5036951799b757d74b3d5.tar.gz
BUG: revise string_from_pyobj/try_pyarr_from_string usages, fixes #18431.
Diffstat (limited to 'numpy/f2py/tests/test_string.py')
-rw-r--r--numpy/f2py/tests/test_string.py146
1 files changed, 144 insertions, 2 deletions
diff --git a/numpy/f2py/tests/test_string.py b/numpy/f2py/tests/test_string.py
index e3ec96af9..2a0945934 100644
--- a/numpy/f2py/tests/test_string.py
+++ b/numpy/f2py/tests/test_string.py
@@ -1,6 +1,6 @@
import os
import pytest
-
+import textwrap
from numpy.testing import assert_array_equal
import numpy as np
from . import util
@@ -9,14 +9,156 @@ 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])
+ 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 = textwrap.dedent("""
+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=1, len(s)
+ i = i + ichar(s(j:j)) * 10 ** (j - 1)
+ 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 (ichar(a(1:1)).ne.0) 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)