From 16ad79a4c8b59e91f3bb326f8cbeb099a36684e5 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Mon, 31 Jul 2023 06:12:00 +0000 Subject: [PATCH 1/5] BUG: Fix f2py F77 assumed length issues Closes gh-24008. Essentially, array and length setup needs to be done before the length defaults kick in. --- numpy/f2py/crackfortran.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py index 002a2edb1275..b67918802c18 100755 --- a/numpy/f2py/crackfortran.py +++ b/numpy/f2py/crackfortran.py @@ -1742,6 +1742,16 @@ def updatevars(typespec, selector, attrspec, entitydecl): else: del d1[k] + if 'len' in d1 and 'array' in d1: + if d1['len'] == '': + d1['len'] = d1['array'] + del d1['array'] + else: + d1['array'] = d1['array'] + ',' + d1['len'] + del d1['len'] + errmess('updatevars: "%s %s" is mapped to "%s %s(%s)"\n' % ( + typespec, e, typespec, ename, d1['array'])) + if 'len' in d1: if typespec in ['complex', 'integer', 'logical', 'real']: if ('kindselector' not in edecl) or (not edecl['kindselector']): @@ -1763,16 +1773,6 @@ def updatevars(typespec, selector, attrspec, entitydecl): else: edecl['='] = d1['init'] - if 'len' in d1 and 'array' in d1: - if d1['len'] == '': - d1['len'] = d1['array'] - del d1['array'] - else: - d1['array'] = d1['array'] + ',' + d1['len'] - 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']): From 2903e1ce43ce074d1209a562fc05cc4e9bbea1b1 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Mon, 31 Jul 2023 06:31:55 +0000 Subject: [PATCH 2/5] TST: Add a test for assumed length F77 --- numpy/f2py/tests/src/string/gh24008.f | 8 ++++++++ numpy/f2py/tests/test_string.py | 6 ++++++ 2 files changed, 14 insertions(+) create mode 100644 numpy/f2py/tests/src/string/gh24008.f diff --git a/numpy/f2py/tests/src/string/gh24008.f b/numpy/f2py/tests/src/string/gh24008.f new file mode 100644 index 000000000000..ab64cf771f68 --- /dev/null +++ b/numpy/f2py/tests/src/string/gh24008.f @@ -0,0 +1,8 @@ + SUBROUTINE GREET(NAME, GREETING) + CHARACTER NAME*(*), GREETING*(*) + CHARACTER*(50) MESSAGE + + MESSAGE = 'Hello, ' // NAME // ', ' // GREETING +c$$$ PRINT *, MESSAGE + + END SUBROUTINE GREET diff --git a/numpy/f2py/tests/test_string.py b/numpy/f2py/tests/test_string.py index 9e937188c930..c097d1ae6112 100644 --- a/numpy/f2py/tests/test_string.py +++ b/numpy/f2py/tests/test_string.py @@ -19,6 +19,12 @@ def test_char(self): assert out == pytest.approx(expected) +class TestStringAssumedLength(util.F2PyTest): + sources = [util.getpath("tests", "src", "string", "gh24008.f")] + + def test_gh24008(self): + self.module.greet("joe", "bob") + class TestDocStringArguments(util.F2PyTest): sources = [util.getpath("tests", "src", "string", "string.f")] From 8726cd753c84e477b9701e5a8ffb570a6f668798 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sat, 5 Aug 2023 20:35:59 +0000 Subject: [PATCH 3/5] MAINT: move gh24008 to test_character Since it belongs logically to the tests where character array shapes and types are determined --- numpy/f2py/tests/test_character.py | 7 +++++++ numpy/f2py/tests/test_string.py | 6 ------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/numpy/f2py/tests/test_character.py b/numpy/f2py/tests/test_character.py index 0bb0f4290272..1c5f8c2a905f 100644 --- a/numpy/f2py/tests/test_character.py +++ b/numpy/f2py/tests/test_character.py @@ -591,3 +591,10 @@ def test_char_arr(self): assert out.shape == expected expected = '|S12' assert out.dtype == expected + +class TestStringAssumedLength(util.F2PyTest): + sources = [util.getpath("tests", "src", "string", "gh24008.f")] + + @pytest.mark.slow + def test_gh24008(self): + self.module.greet("joe", "bob") diff --git a/numpy/f2py/tests/test_string.py b/numpy/f2py/tests/test_string.py index c097d1ae6112..9e937188c930 100644 --- a/numpy/f2py/tests/test_string.py +++ b/numpy/f2py/tests/test_string.py @@ -19,12 +19,6 @@ def test_char(self): assert out == pytest.approx(expected) -class TestStringAssumedLength(util.F2PyTest): - sources = [util.getpath("tests", "src", "string", "gh24008.f")] - - def test_gh24008(self): - self.module.greet("joe", "bob") - class TestDocStringArguments(util.F2PyTest): sources = [util.getpath("tests", "src", "string", "string.f")] From d29991da8a040d4f52adcd99ebfce750fd9961eb Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sat, 5 Aug 2023 20:36:35 +0000 Subject: [PATCH 4/5] BUG: Rework character array assignments (gh-24008) --- numpy/f2py/crackfortran.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py index b67918802c18..1b8672410e4d 100755 --- a/numpy/f2py/crackfortran.py +++ b/numpy/f2py/crackfortran.py @@ -1746,6 +1746,13 @@ def updatevars(typespec, selector, attrspec, entitydecl): if d1['len'] == '': d1['len'] = d1['array'] del d1['array'] + 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'] else: d1['array'] = d1['array'] + ',' + d1['len'] del d1['len'] From 5b63b895b901b0f3e4a031376fee4df7dbda1500 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Thu, 24 Aug 2023 09:37:22 +0000 Subject: [PATCH 5/5] TST: Stop marking small f2py tests as slow --- numpy/f2py/tests/test_character.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/numpy/f2py/tests/test_character.py b/numpy/f2py/tests/test_character.py index 1c5f8c2a905f..373262bf96a6 100644 --- a/numpy/f2py/tests/test_character.py +++ b/numpy/f2py/tests/test_character.py @@ -574,7 +574,6 @@ def test_character_bc(self, state): class TestStringScalarArr(util.F2PyTest): sources = [util.getpath("tests", "src", "string", "scalar_string.f90")] - @pytest.mark.slow def test_char(self): for out in (self.module.string_test.string, self.module.string_test.string77): @@ -583,7 +582,6 @@ def test_char(self): expected = '|S8' assert out.dtype == expected - @pytest.mark.slow def test_char_arr(self): for out in (self.module.string_test.strarr, self.module.string_test.strarr77): @@ -595,6 +593,5 @@ def test_char_arr(self): class TestStringAssumedLength(util.F2PyTest): sources = [util.getpath("tests", "src", "string", "gh24008.f")] - @pytest.mark.slow def test_gh24008(self): self.module.greet("joe", "bob")