Skip to content

Commit a1809fc

Browse files
bobelderingcharris
authored andcommitted
BUG: Fix bug in parsing F77 style string arrays.
Example problematic variable: CHARACTER WORDARR(3)*8 This would be wrapped by an array with shape (3, 8) and dtype |S1, instead of the desired shape (3,) and dtype |S8. See #23356.
1 parent 3c6acb5 commit a1809fc

3 files changed

Lines changed: 37 additions & 27 deletions

File tree

numpy/f2py/crackfortran.py

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,6 +1744,28 @@ def updatevars(typespec, selector, attrspec, entitydecl):
17441744
d1[k] = unmarkouterparen(d1[k])
17451745
else:
17461746
del d1[k]
1747+
1748+
if 'len' in d1:
1749+
if typespec in ['complex', 'integer', 'logical', 'real']:
1750+
if ('kindselector' not in edecl) or (not edecl['kindselector']):
1751+
edecl['kindselector'] = {}
1752+
edecl['kindselector']['*'] = d1['len']
1753+
del d1['len']
1754+
elif typespec == 'character':
1755+
if ('charselector' not in edecl) or (not edecl['charselector']):
1756+
edecl['charselector'] = {}
1757+
if 'len' in edecl['charselector']:
1758+
del edecl['charselector']['len']
1759+
edecl['charselector']['*'] = d1['len']
1760+
del d1['len']
1761+
1762+
if 'init' in d1:
1763+
if '=' in edecl and (not edecl['='] == d1['init']):
1764+
outmess('updatevars: attempt to change the init expression of "%s" ("%s") to "%s". Ignoring.\n' % (
1765+
ename, edecl['='], d1['init']))
1766+
else:
1767+
edecl['='] = d1['init']
1768+
17471769
if 'len' in d1 and 'array' in d1:
17481770
if d1['len'] == '':
17491771
d1['len'] = d1['array']
@@ -1753,6 +1775,7 @@ def updatevars(typespec, selector, attrspec, entitydecl):
17531775
del d1['len']
17541776
errmess('updatevars: "%s %s" is mapped to "%s %s(%s)"\n' % (
17551777
typespec, e, typespec, ename, d1['array']))
1778+
17561779
if 'array' in d1:
17571780
dm = 'dimension(%s)' % d1['array']
17581781
if 'attrspec' not in edecl or (not edecl['attrspec']):
@@ -1766,23 +1789,6 @@ def updatevars(typespec, selector, attrspec, entitydecl):
17661789
% (ename, dm1, dm))
17671790
break
17681791

1769-
if 'len' in d1:
1770-
if typespec in ['complex', 'integer', 'logical', 'real']:
1771-
if ('kindselector' not in edecl) or (not edecl['kindselector']):
1772-
edecl['kindselector'] = {}
1773-
edecl['kindselector']['*'] = d1['len']
1774-
elif typespec == 'character':
1775-
if ('charselector' not in edecl) or (not edecl['charselector']):
1776-
edecl['charselector'] = {}
1777-
if 'len' in edecl['charselector']:
1778-
del edecl['charselector']['len']
1779-
edecl['charselector']['*'] = d1['len']
1780-
if 'init' in d1:
1781-
if '=' in edecl and (not edecl['='] == d1['init']):
1782-
outmess('updatevars: attempt to change the init expression of "%s" ("%s") to "%s". Ignoring.\n' % (
1783-
ename, edecl['='], d1['init']))
1784-
else:
1785-
edecl['='] = d1['init']
17861792
else:
17871793
outmess('updatevars: could not crack entity declaration "%s". Ignoring.\n' % (
17881794
ename + m.group('after')))
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
MODULE string_test
22

33
character(len=8) :: string
4+
character string77 * 8
45

56
character(len=12), dimension(5,7) :: strarr
7+
character strarr77(5,7) * 12
68

79
END MODULE string_test

numpy/f2py/tests/test_character.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -575,16 +575,18 @@ class TestStringScalarArr(util.F2PyTest):
575575

576576
@pytest.mark.slow
577577
def test_char(self):
578-
out = self.module.string_test.string
579-
expected = ()
580-
assert out.shape == expected
581-
expected = '|S8'
582-
assert out.dtype == expected
578+
for out in (self.module.string_test.string,
579+
self.module.string_test.string77):
580+
expected = ()
581+
assert out.shape == expected
582+
expected = '|S8'
583+
assert out.dtype == expected
583584

584585
@pytest.mark.slow
585586
def test_char_arr(self):
586-
out = self.module.string_test.strarr
587-
expected = (5,7)
588-
assert out.shape == expected
589-
expected = '|S12'
590-
assert out.dtype == expected
587+
for out in (self.module.string_test.strarr,
588+
self.module.string_test.strarr77):
589+
expected = (5,7)
590+
assert out.shape == expected
591+
expected = '|S12'
592+
assert out.dtype == expected

0 commit comments

Comments
 (0)