summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Eldering <eldering@jive.eu>2023-03-22 16:48:56 +0100
committerCharles Harris <charlesr.harris@gmail.com>2023-04-21 17:01:34 -0600
commita1809fc756b5f648b8e2d7b1bae465902a4b7484 (patch)
tree9aa20acda6697ae078eb227ad55fc5f060d14bfd
parent3c6acb51242a4f1067c6ac5159dece8889d19d10 (diff)
downloadnumpy-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-xnumpy/f2py/crackfortran.py40
-rw-r--r--numpy/f2py/tests/src/string/scalar_string.f902
-rw-r--r--numpy/f2py/tests/test_character.py22
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