test_character.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. import pytest
  2. import textwrap
  3. from numpy.testing import assert_array_equal, assert_equal, assert_raises
  4. import numpy as np
  5. from numpy.f2py.tests import util
  6. @pytest.mark.slow
  7. class TestCharacterString(util.F2PyTest):
  8. # options = ['--debug-capi', '--build-dir', '/tmp/test-build-f2py']
  9. suffix = '.f90'
  10. fprefix = 'test_character_string'
  11. length_list = ['1', '3', 'star']
  12. code = ''
  13. for length in length_list:
  14. fsuffix = length
  15. clength = dict(star='(*)').get(length, length)
  16. code += textwrap.dedent(f"""
  17. subroutine {fprefix}_input_{fsuffix}(c, o, n)
  18. character*{clength}, intent(in) :: c
  19. integer n
  20. !f2py integer, depend(c), intent(hide) :: n = slen(c)
  21. integer*1, dimension(n) :: o
  22. !f2py intent(out) o
  23. o = transfer(c, o)
  24. end subroutine {fprefix}_input_{fsuffix}
  25. subroutine {fprefix}_output_{fsuffix}(c, o, n)
  26. character*{clength}, intent(out) :: c
  27. integer n
  28. integer*1, dimension(n), intent(in) :: o
  29. !f2py integer, depend(o), intent(hide) :: n = len(o)
  30. c = transfer(o, c)
  31. end subroutine {fprefix}_output_{fsuffix}
  32. subroutine {fprefix}_array_input_{fsuffix}(c, o, m, n)
  33. integer m, i, n
  34. character*{clength}, intent(in), dimension(m) :: c
  35. !f2py integer, depend(c), intent(hide) :: m = len(c)
  36. !f2py integer, depend(c), intent(hide) :: n = f2py_itemsize(c)
  37. integer*1, dimension(m, n), intent(out) :: o
  38. do i=1,m
  39. o(i, :) = transfer(c(i), o(i, :))
  40. end do
  41. end subroutine {fprefix}_array_input_{fsuffix}
  42. subroutine {fprefix}_array_output_{fsuffix}(c, o, m, n)
  43. character*{clength}, intent(out), dimension(m) :: c
  44. integer n
  45. integer*1, dimension(m, n), intent(in) :: o
  46. !f2py character(f2py_len=n) :: c
  47. !f2py integer, depend(o), intent(hide) :: m = len(o)
  48. !f2py integer, depend(o), intent(hide) :: n = shape(o, 1)
  49. do i=1,m
  50. c(i) = transfer(o(i, :), c(i))
  51. end do
  52. end subroutine {fprefix}_array_output_{fsuffix}
  53. subroutine {fprefix}_2d_array_input_{fsuffix}(c, o, m1, m2, n)
  54. integer m1, m2, i, j, n
  55. character*{clength}, intent(in), dimension(m1, m2) :: c
  56. !f2py integer, depend(c), intent(hide) :: m1 = len(c)
  57. !f2py integer, depend(c), intent(hide) :: m2 = shape(c, 1)
  58. !f2py integer, depend(c), intent(hide) :: n = f2py_itemsize(c)
  59. integer*1, dimension(m1, m2, n), intent(out) :: o
  60. do i=1,m1
  61. do j=1,m2
  62. o(i, j, :) = transfer(c(i, j), o(i, j, :))
  63. end do
  64. end do
  65. end subroutine {fprefix}_2d_array_input_{fsuffix}
  66. """)
  67. @pytest.mark.parametrize("length", length_list)
  68. def test_input(self, length):
  69. fsuffix = {'(*)': 'star'}.get(length, length)
  70. f = getattr(self.module, self.fprefix + '_input_' + fsuffix)
  71. a = {'1': 'a', '3': 'abc', 'star': 'abcde' * 3}[length]
  72. assert_array_equal(f(a), np.array(list(map(ord, a)), dtype='u1'))
  73. @pytest.mark.parametrize("length", length_list[:-1])
  74. def test_output(self, length):
  75. fsuffix = length
  76. f = getattr(self.module, self.fprefix + '_output_' + fsuffix)
  77. a = {'1': 'a', '3': 'abc'}[length]
  78. assert_array_equal(f(np.array(list(map(ord, a)), dtype='u1')),
  79. a.encode())
  80. @pytest.mark.parametrize("length", length_list)
  81. def test_array_input(self, length):
  82. fsuffix = length
  83. f = getattr(self.module, self.fprefix + '_array_input_' + fsuffix)
  84. a = np.array([{'1': 'a', '3': 'abc', 'star': 'abcde' * 3}[length],
  85. {'1': 'A', '3': 'ABC', 'star': 'ABCDE' * 3}[length],
  86. ], dtype='S')
  87. expected = np.array([list(s) for s in a], dtype='u1')
  88. assert_array_equal(f(a), expected)
  89. @pytest.mark.parametrize("length", length_list)
  90. def test_array_output(self, length):
  91. fsuffix = length
  92. f = getattr(self.module, self.fprefix + '_array_output_' + fsuffix)
  93. expected = np.array(
  94. [{'1': 'a', '3': 'abc', 'star': 'abcde' * 3}[length],
  95. {'1': 'A', '3': 'ABC', 'star': 'ABCDE' * 3}[length]], dtype='S')
  96. a = np.array([list(s) for s in expected], dtype='u1')
  97. assert_array_equal(f(a), expected)
  98. @pytest.mark.parametrize("length", length_list)
  99. def test_2d_array_input(self, length):
  100. fsuffix = length
  101. f = getattr(self.module, self.fprefix + '_2d_array_input_' + fsuffix)
  102. a = np.array([[{'1': 'a', '3': 'abc', 'star': 'abcde' * 3}[length],
  103. {'1': 'A', '3': 'ABC', 'star': 'ABCDE' * 3}[length]],
  104. [{'1': 'f', '3': 'fgh', 'star': 'fghij' * 3}[length],
  105. {'1': 'F', '3': 'FGH', 'star': 'FGHIJ' * 3}[length]]],
  106. dtype='S')
  107. expected = np.array([[list(item) for item in row] for row in a],
  108. dtype='u1', order='F')
  109. assert_array_equal(f(a), expected)
  110. class TestCharacter(util.F2PyTest):
  111. # options = ['--debug-capi', '--build-dir', '/tmp/test-build-f2py']
  112. suffix = '.f90'
  113. fprefix = 'test_character'
  114. code = textwrap.dedent(f"""
  115. subroutine {fprefix}_input(c, o)
  116. character, intent(in) :: c
  117. integer*1 o
  118. !f2py intent(out) o
  119. o = transfer(c, o)
  120. end subroutine {fprefix}_input
  121. subroutine {fprefix}_output(c, o)
  122. character :: c
  123. integer*1, intent(in) :: o
  124. !f2py intent(out) c
  125. c = transfer(o, c)
  126. end subroutine {fprefix}_output
  127. subroutine {fprefix}_input_output(c, o)
  128. character, intent(in) :: c
  129. character o
  130. !f2py intent(out) o
  131. o = c
  132. end subroutine {fprefix}_input_output
  133. subroutine {fprefix}_inout(c, n)
  134. character :: c, n
  135. !f2py intent(in) n
  136. !f2py intent(inout) c
  137. c = n
  138. end subroutine {fprefix}_inout
  139. function {fprefix}_return(o) result (c)
  140. character :: c
  141. character, intent(in) :: o
  142. c = transfer(o, c)
  143. end function {fprefix}_return
  144. subroutine {fprefix}_array_input(c, o)
  145. character, intent(in) :: c(3)
  146. integer*1 o(3)
  147. !f2py intent(out) o
  148. integer i
  149. do i=1,3
  150. o(i) = transfer(c(i), o(i))
  151. end do
  152. end subroutine {fprefix}_array_input
  153. subroutine {fprefix}_2d_array_input(c, o)
  154. character, intent(in) :: c(2, 3)
  155. integer*1 o(2, 3)
  156. !f2py intent(out) o
  157. integer i, j
  158. do i=1,2
  159. do j=1,3
  160. o(i, j) = transfer(c(i, j), o(i, j))
  161. end do
  162. end do
  163. end subroutine {fprefix}_2d_array_input
  164. subroutine {fprefix}_array_output(c, o)
  165. character :: c(3)
  166. integer*1, intent(in) :: o(3)
  167. !f2py intent(out) c
  168. do i=1,3
  169. c(i) = transfer(o(i), c(i))
  170. end do
  171. end subroutine {fprefix}_array_output
  172. subroutine {fprefix}_array_inout(c, n)
  173. character :: c(3), n(3)
  174. !f2py intent(in) n(3)
  175. !f2py intent(inout) c(3)
  176. do i=1,3
  177. c(i) = n(i)
  178. end do
  179. end subroutine {fprefix}_array_inout
  180. subroutine {fprefix}_2d_array_inout(c, n)
  181. character :: c(2, 3), n(2, 3)
  182. !f2py intent(in) n(2, 3)
  183. !f2py intent(inout) c(2. 3)
  184. integer i, j
  185. do i=1,2
  186. do j=1,3
  187. c(i, j) = n(i, j)
  188. end do
  189. end do
  190. end subroutine {fprefix}_2d_array_inout
  191. function {fprefix}_array_return(o) result (c)
  192. character, dimension(3) :: c
  193. character, intent(in) :: o(3)
  194. do i=1,3
  195. c(i) = o(i)
  196. end do
  197. end function {fprefix}_array_return
  198. function {fprefix}_optional(o) result (c)
  199. character, intent(in) :: o
  200. !f2py character o = "a"
  201. character :: c
  202. c = o
  203. end function {fprefix}_optional
  204. """)
  205. @pytest.mark.parametrize("dtype", ['c', 'S1'])
  206. def test_input(self, dtype):
  207. f = getattr(self.module, self.fprefix + '_input')
  208. assert_equal(f(np.array('a', dtype=dtype)), ord('a'))
  209. assert_equal(f(np.array(b'a', dtype=dtype)), ord('a'))
  210. assert_equal(f(np.array(['a'], dtype=dtype)), ord('a'))
  211. assert_equal(f(np.array('abc', dtype=dtype)), ord('a'))
  212. assert_equal(f(np.array([['a']], dtype=dtype)), ord('a'))
  213. def test_input_varia(self):
  214. f = getattr(self.module, self.fprefix + '_input')
  215. assert_equal(f('a'), ord('a'))
  216. assert_equal(f(b'a'), ord(b'a'))
  217. assert_equal(f(''), 0)
  218. assert_equal(f(b''), 0)
  219. assert_equal(f(b'\0'), 0)
  220. assert_equal(f('ab'), ord('a'))
  221. assert_equal(f(b'ab'), ord('a'))
  222. assert_equal(f(['a']), ord('a'))
  223. assert_equal(f(np.array(b'a')), ord('a'))
  224. assert_equal(f(np.array([b'a'])), ord('a'))
  225. a = np.array('a')
  226. assert_equal(f(a), ord('a'))
  227. a = np.array(['a'])
  228. assert_equal(f(a), ord('a'))
  229. try:
  230. f([])
  231. except IndexError as msg:
  232. if not str(msg).endswith(' got 0-list'):
  233. raise
  234. else:
  235. raise SystemError(f'{f.__name__} should have failed on empty list')
  236. try:
  237. f(97)
  238. except TypeError as msg:
  239. if not str(msg).endswith(' got int instance'):
  240. raise
  241. else:
  242. raise SystemError(f'{f.__name__} should have failed on int value')
  243. @pytest.mark.parametrize("dtype", ['c', 'S1', 'U1'])
  244. def test_array_input(self, dtype):
  245. f = getattr(self.module, self.fprefix + '_array_input')
  246. assert_array_equal(f(np.array(['a', 'b', 'c'], dtype=dtype)),
  247. np.array(list(map(ord, 'abc')), dtype='i1'))
  248. assert_array_equal(f(np.array([b'a', b'b', b'c'], dtype=dtype)),
  249. np.array(list(map(ord, 'abc')), dtype='i1'))
  250. def test_array_input_varia(self):
  251. f = getattr(self.module, self.fprefix + '_array_input')
  252. assert_array_equal(f(['a', 'b', 'c']),
  253. np.array(list(map(ord, 'abc')), dtype='i1'))
  254. assert_array_equal(f([b'a', b'b', b'c']),
  255. np.array(list(map(ord, 'abc')), dtype='i1'))
  256. try:
  257. f(['a', 'b', 'c', 'd'])
  258. except ValueError as msg:
  259. if not str(msg).endswith(
  260. 'th dimension must be fixed to 3 but got 4'):
  261. raise
  262. else:
  263. raise SystemError(
  264. f'{f.__name__} should have failed on wrong input')
  265. @pytest.mark.parametrize("dtype", ['c', 'S1', 'U1'])
  266. def test_2d_array_input(self, dtype):
  267. f = getattr(self.module, self.fprefix + '_2d_array_input')
  268. a = np.array([['a', 'b', 'c'],
  269. ['d', 'e', 'f']], dtype=dtype, order='F')
  270. expected = a.view(np.uint32 if dtype == 'U1' else np.uint8)
  271. assert_array_equal(f(a), expected)
  272. def test_output(self):
  273. f = getattr(self.module, self.fprefix + '_output')
  274. assert_equal(f(ord(b'a')), b'a')
  275. assert_equal(f(0), b'\0')
  276. def test_array_output(self):
  277. f = getattr(self.module, self.fprefix + '_array_output')
  278. assert_array_equal(f(list(map(ord, 'abc'))),
  279. np.array(list('abc'), dtype='S1'))
  280. def test_input_output(self):
  281. f = getattr(self.module, self.fprefix + '_input_output')
  282. assert_equal(f(b'a'), b'a')
  283. assert_equal(f('a'), b'a')
  284. assert_equal(f(''), b'\0')
  285. @pytest.mark.parametrize("dtype", ['c', 'S1'])
  286. def test_inout(self, dtype):
  287. f = getattr(self.module, self.fprefix + '_inout')
  288. a = np.array(list('abc'), dtype=dtype)
  289. f(a, 'A')
  290. assert_array_equal(a, np.array(list('Abc'), dtype=a.dtype))
  291. f(a[1:], 'B')
  292. assert_array_equal(a, np.array(list('ABc'), dtype=a.dtype))
  293. a = np.array(['abc'], dtype=dtype)
  294. f(a, 'A')
  295. assert_array_equal(a, np.array(['Abc'], dtype=a.dtype))
  296. def test_inout_varia(self):
  297. f = getattr(self.module, self.fprefix + '_inout')
  298. a = np.array('abc', dtype='S3')
  299. f(a, 'A')
  300. assert_array_equal(a, np.array('Abc', dtype=a.dtype))
  301. a = np.array(['abc'], dtype='S3')
  302. f(a, 'A')
  303. assert_array_equal(a, np.array(['Abc'], dtype=a.dtype))
  304. try:
  305. f('abc', 'A')
  306. except ValueError as msg:
  307. if not str(msg).endswith(' got 3-str'):
  308. raise
  309. else:
  310. raise SystemError(f'{f.__name__} should have failed on str value')
  311. @pytest.mark.parametrize("dtype", ['c', 'S1'])
  312. def test_array_inout(self, dtype):
  313. f = getattr(self.module, self.fprefix + '_array_inout')
  314. n = np.array(['A', 'B', 'C'], dtype=dtype, order='F')
  315. a = np.array(['a', 'b', 'c'], dtype=dtype, order='F')
  316. f(a, n)
  317. assert_array_equal(a, n)
  318. a = np.array(['a', 'b', 'c', 'd'], dtype=dtype)
  319. f(a[1:], n)
  320. assert_array_equal(a, np.array(['a', 'A', 'B', 'C'], dtype=dtype))
  321. a = np.array([['a', 'b', 'c']], dtype=dtype, order='F')
  322. f(a, n)
  323. assert_array_equal(a, np.array([['A', 'B', 'C']], dtype=dtype))
  324. a = np.array(['a', 'b', 'c', 'd'], dtype=dtype, order='F')
  325. try:
  326. f(a, n)
  327. except ValueError as msg:
  328. if not str(msg).endswith(
  329. 'th dimension must be fixed to 3 but got 4'):
  330. raise
  331. else:
  332. raise SystemError(
  333. f'{f.__name__} should have failed on wrong input')
  334. @pytest.mark.parametrize("dtype", ['c', 'S1'])
  335. def test_2d_array_inout(self, dtype):
  336. f = getattr(self.module, self.fprefix + '_2d_array_inout')
  337. n = np.array([['A', 'B', 'C'],
  338. ['D', 'E', 'F']],
  339. dtype=dtype, order='F')
  340. a = np.array([['a', 'b', 'c'],
  341. ['d', 'e', 'f']],
  342. dtype=dtype, order='F')
  343. f(a, n)
  344. assert_array_equal(a, n)
  345. def test_return(self):
  346. f = getattr(self.module, self.fprefix + '_return')
  347. assert_equal(f('a'), b'a')
  348. @pytest.mark.skip('fortran function returning array segfaults')
  349. def test_array_return(self):
  350. f = getattr(self.module, self.fprefix + '_array_return')
  351. a = np.array(list('abc'), dtype='S1')
  352. assert_array_equal(f(a), a)
  353. def test_optional(self):
  354. f = getattr(self.module, self.fprefix + '_optional')
  355. assert_equal(f(), b"a")
  356. assert_equal(f(b'B'), b"B")
  357. class TestMiscCharacter(util.F2PyTest):
  358. # options = ['--debug-capi', '--build-dir', '/tmp/test-build-f2py']
  359. suffix = '.f90'
  360. fprefix = 'test_misc_character'
  361. code = textwrap.dedent(f"""
  362. subroutine {fprefix}_gh18684(x, y, m)
  363. character(len=5), dimension(m), intent(in) :: x
  364. character*5, dimension(m), intent(out) :: y
  365. integer i, m
  366. !f2py integer, intent(hide), depend(x) :: m = f2py_len(x)
  367. do i=1,m
  368. y(i) = x(i)
  369. end do
  370. end subroutine {fprefix}_gh18684
  371. subroutine {fprefix}_gh6308(x, i)
  372. integer i
  373. !f2py check(i>=0 && i<12) i
  374. character*5 name, x
  375. common name(12)
  376. name(i + 1) = x
  377. end subroutine {fprefix}_gh6308
  378. subroutine {fprefix}_gh4519(x)
  379. character(len=*), intent(in) :: x(:)
  380. !f2py intent(out) x
  381. integer :: i
  382. ! Uncomment for debug printing:
  383. !do i=1, size(x)
  384. ! print*, "x(",i,")=", x(i)
  385. !end do
  386. end subroutine {fprefix}_gh4519
  387. pure function {fprefix}_gh3425(x) result (y)
  388. character(len=*), intent(in) :: x
  389. character(len=len(x)) :: y
  390. integer :: i
  391. do i = 1, len(x)
  392. j = iachar(x(i:i))
  393. if (j>=iachar("a") .and. j<=iachar("z") ) then
  394. y(i:i) = achar(j-32)
  395. else
  396. y(i:i) = x(i:i)
  397. endif
  398. end do
  399. end function {fprefix}_gh3425
  400. subroutine {fprefix}_character_bc_new(x, y, z)
  401. character, intent(in) :: x
  402. character, intent(out) :: y
  403. !f2py character, depend(x) :: y = x
  404. !f2py character, dimension((x=='a'?1:2)), depend(x), intent(out) :: z
  405. character, dimension(*) :: z
  406. !f2py character, optional, check(x == 'a' || x == 'b') :: x = 'a'
  407. !f2py callstatement (*f2py_func)(&x, &y, z)
  408. !f2py callprotoargument character*, character*, character*
  409. if (y.eq.x) then
  410. y = x
  411. else
  412. y = 'e'
  413. endif
  414. z(1) = 'c'
  415. end subroutine {fprefix}_character_bc_new
  416. subroutine {fprefix}_character_bc_old(x, y, z)
  417. character, intent(in) :: x
  418. character, intent(out) :: y
  419. !f2py character, depend(x) :: y = x[0]
  420. !f2py character, dimension((*x=='a'?1:2)), depend(x), intent(out) :: z
  421. character, dimension(*) :: z
  422. !f2py character, optional, check(*x == 'a' || x[0] == 'b') :: x = 'a'
  423. !f2py callstatement (*f2py_func)(x, y, z)
  424. !f2py callprotoargument char*, char*, char*
  425. if (y.eq.x) then
  426. y = x
  427. else
  428. y = 'e'
  429. endif
  430. z(1) = 'c'
  431. end subroutine {fprefix}_character_bc_old
  432. """)
  433. @pytest.mark.slow
  434. def test_gh18684(self):
  435. # Test character(len=5) and character*5 usages
  436. f = getattr(self.module, self.fprefix + '_gh18684')
  437. x = np.array(["abcde", "fghij"], dtype='S5')
  438. y = f(x)
  439. assert_array_equal(x, y)
  440. def test_gh6308(self):
  441. # Test character string array in a common block
  442. f = getattr(self.module, self.fprefix + '_gh6308')
  443. assert_equal(self.module._BLNK_.name.dtype, np.dtype('S5'))
  444. assert_equal(len(self.module._BLNK_.name), 12)
  445. f("abcde", 0)
  446. assert_equal(self.module._BLNK_.name[0], b"abcde")
  447. f("12345", 5)
  448. assert_equal(self.module._BLNK_.name[5], b"12345")
  449. def test_gh4519(self):
  450. # Test array of assumed length strings
  451. f = getattr(self.module, self.fprefix + '_gh4519')
  452. for x, expected in [
  453. ('a', dict(shape=(), dtype=np.dtype('S1'))),
  454. ('text', dict(shape=(), dtype=np.dtype('S4'))),
  455. (np.array(['1', '2', '3'], dtype='S1'),
  456. dict(shape=(3,), dtype=np.dtype('S1'))),
  457. (['1', '2', '34'],
  458. dict(shape=(3,), dtype=np.dtype('S2'))),
  459. (['', ''], dict(shape=(2,), dtype=np.dtype('S1')))]:
  460. r = f(x)
  461. for k, v in expected.items():
  462. assert_equal(getattr(r, k), v)
  463. def test_gh3425(self):
  464. # Test returning a copy of assumed length string
  465. f = getattr(self.module, self.fprefix + '_gh3425')
  466. # f is equivalent to bytes.upper
  467. assert_equal(f('abC'), b'ABC')
  468. assert_equal(f(''), b'')
  469. assert_equal(f('abC12d'), b'ABC12D')
  470. @pytest.mark.parametrize("state", ['new', 'old'])
  471. def test_character_bc(self, state):
  472. f = getattr(self.module, self.fprefix + '_character_bc_' + state)
  473. c, a = f()
  474. assert_equal(c, b'a')
  475. assert_equal(len(a), 1)
  476. c, a = f(b'b')
  477. assert_equal(c, b'b')
  478. assert_equal(len(a), 2)
  479. assert_raises(Exception, lambda: f(b'c'))
  480. class TestStringScalarArr(util.F2PyTest):
  481. sources = [util.getpath("tests", "src", "string", "scalar_string.f90")]
  482. def test_char(self):
  483. for out in (self.module.string_test.string,
  484. self.module.string_test.string77):
  485. expected = ()
  486. assert out.shape == expected
  487. expected = '|S8'
  488. assert out.dtype == expected
  489. def test_char_arr(self):
  490. for out in (self.module.string_test.strarr,
  491. self.module.string_test.strarr77):
  492. expected = (5,7)
  493. assert out.shape == expected
  494. expected = '|S12'
  495. assert out.dtype == expected
  496. class TestStringAssumedLength(util.F2PyTest):
  497. sources = [util.getpath("tests", "src", "string", "gh24008.f")]
  498. def test_gh24008(self):
  499. self.module.greet("joe", "bob")
  500. @pytest.mark.slow
  501. class TestStringOptionalInOut(util.F2PyTest):
  502. sources = [util.getpath("tests", "src", "string", "gh24662.f90")]
  503. def test_gh24662(self):
  504. self.module.string_inout_optional()
  505. a = np.array('hi', dtype='S32')
  506. self.module.string_inout_optional(a)
  507. assert "output string" in a.tobytes().decode()
  508. with pytest.raises(Exception):
  509. aa = "Hi"
  510. self.module.string_inout_optional(aa)
  511. @pytest.mark.slow
  512. class TestNewCharHandling(util.F2PyTest):
  513. # from v1.24 onwards, gh-19388
  514. sources = [
  515. util.getpath("tests", "src", "string", "gh25286.pyf"),
  516. util.getpath("tests", "src", "string", "gh25286.f90")
  517. ]
  518. module_name = "_char_handling_test"
  519. def test_gh25286(self):
  520. info = self.module.charint('T')
  521. assert info == 2
  522. @pytest.mark.slow
  523. class TestBCCharHandling(util.F2PyTest):
  524. # SciPy style, "incorrect" bindings with a hook
  525. sources = [
  526. util.getpath("tests", "src", "string", "gh25286_bc.pyf"),
  527. util.getpath("tests", "src", "string", "gh25286.f90")
  528. ]
  529. module_name = "_char_handling_test"
  530. def test_gh25286(self):
  531. info = self.module.charint('T')
  532. assert info == 2