diff options
author | Bob Eldering <eldering@jive.eu> | 2023-03-22 16:48:56 +0100 |
---|---|---|
committer | Charles Harris <charlesr.harris@gmail.com> | 2023-04-21 17:01:34 -0600 |
commit | a1809fc756b5f648b8e2d7b1bae465902a4b7484 (patch) | |
tree | 9aa20acda6697ae078eb227ad55fc5f060d14bfd | |
parent | 3c6acb51242a4f1067c6ac5159dece8889d19d10 (diff) | |
download | numpy-a1809fc756b5f648b8e2d7b1bae465902a4b7484.tar.gz |
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.
-rwxr-xr-x | numpy/f2py/crackfortran.py | 40 | ||||
-rw-r--r-- | numpy/f2py/tests/src/string/scalar_string.f90 | 2 | ||||
-rw-r--r-- | numpy/f2py/tests/test_character.py | 22 |
3 files changed, 37 insertions, 27 deletions
diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py index 84579fdcc..63597cef1 100755 --- a/numpy/f2py/crackfortran.py +++ b/numpy/f2py/crackfortran.py @@ -1744,6 +1744,28 @@ def updatevars(typespec, selector, attrspec, entitydecl): d1[k] = unmarkouterparen(d1[k]) else: del d1[k] + + if 'len' in d1: + if typespec in ['complex', 'integer', 'logical', 'real']: + if ('kindselector' not in edecl) or (not edecl['kindselector']): + edecl['kindselector'] = {} + edecl['kindselector']['*'] = d1['len'] + del d1['len'] + elif typespec == 'character': + if ('charselector' not in edecl) or (not edecl['charselector']): + edecl['charselector'] = {} + if 'len' in edecl['charselector']: + del edecl['charselector']['len'] + edecl['charselector']['*'] = d1['len'] + del d1['len'] + + if 'init' in d1: + if '=' in edecl and (not edecl['='] == d1['init']): + outmess('updatevars: attempt to change the init expression of "%s" ("%s") to "%s". Ignoring.\n' % ( + ename, edecl['='], d1['init'])) + else: + edecl['='] = d1['init'] + if 'len' in d1 and 'array' in d1: if d1['len'] == '': d1['len'] = d1['array'] @@ -1753,6 +1775,7 @@ def updatevars(typespec, selector, attrspec, entitydecl): del d1['len'] errmess('updatevars: "%s %s" is mapped to "%s %s(%s)"\n' % ( typespec, e, typespec, ename, d1['array'])) + if 'array' in d1: dm = 'dimension(%s)' % d1['array'] if 'attrspec' not in edecl or (not edecl['attrspec']): @@ -1766,23 +1789,6 @@ def updatevars(typespec, selector, attrspec, entitydecl): % (ename, dm1, dm)) break - if 'len' in d1: - if typespec in ['complex', 'integer', 'logical', 'real']: - if ('kindselector' not in edecl) or (not edecl['kindselector']): - edecl['kindselector'] = {} - edecl['kindselector']['*'] = d1['len'] - elif typespec == 'character': - if ('charselector' not in edecl) or (not edecl['charselector']): - edecl['charselector'] = {} - if 'len' in edecl['charselector']: - del edecl['charselector']['len'] - edecl['charselector']['*'] = d1['len'] - if 'init' in d1: - if '=' in edecl and (not edecl['='] == d1['init']): - outmess('updatevars: attempt to change the init expression of "%s" ("%s") to "%s". Ignoring.\n' % ( - ename, edecl['='], d1['init'])) - else: - edecl['='] = d1['init'] else: outmess('updatevars: could not crack entity declaration "%s". Ignoring.\n' % ( ename + m.group('after'))) diff --git a/numpy/f2py/tests/src/string/scalar_string.f90 b/numpy/f2py/tests/src/string/scalar_string.f90 index d847668bb..f8f076172 100644 --- a/numpy/f2py/tests/src/string/scalar_string.f90 +++ b/numpy/f2py/tests/src/string/scalar_string.f90 @@ -1,7 +1,9 @@ MODULE string_test character(len=8) :: string + character string77 * 8 character(len=12), dimension(5,7) :: strarr + character strarr77(5,7) * 12 END MODULE string_test diff --git a/numpy/f2py/tests/test_character.py b/numpy/f2py/tests/test_character.py index a5cfffe0d..79998b460 100644 --- a/numpy/f2py/tests/test_character.py +++ b/numpy/f2py/tests/test_character.py @@ -575,16 +575,18 @@ class TestStringScalarArr(util.F2PyTest): @pytest.mark.slow def test_char(self): - out = self.module.string_test.string - expected = () - assert out.shape == expected - expected = '|S8' - assert out.dtype == expected + for out in (self.module.string_test.string, + self.module.string_test.string77): + expected = () + assert out.shape == expected + expected = '|S8' + assert out.dtype == expected @pytest.mark.slow def test_char_arr(self): - out = self.module.string_test.strarr - expected = (5,7) - assert out.shape == expected - expected = '|S12' - assert out.dtype == expected + for out in (self.module.string_test.strarr, + self.module.string_test.strarr77): + expected = (5,7) + assert out.shape == expected + expected = '|S12' + assert out.dtype == expected |