From f96b8daea959db191ff84b80dbc1ea948722fbaa Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sun, 16 Apr 2023 18:18:02 +0000 Subject: [PATCH 1/6] TST: Add a test for gh-23598 --- numpy/f2py/tests/src/crackfortran/gh23598.f90 | 4 ++++ numpy/f2py/tests/test_crackfortran.py | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 numpy/f2py/tests/src/crackfortran/gh23598.f90 diff --git a/numpy/f2py/tests/src/crackfortran/gh23598.f90 b/numpy/f2py/tests/src/crackfortran/gh23598.f90 new file mode 100644 index 000000000000..e0dffb5ef29e --- /dev/null +++ b/numpy/f2py/tests/src/crackfortran/gh23598.f90 @@ -0,0 +1,4 @@ +integer function intproduct(a, b) result(res) + integer, intent(in) :: a, b + res = a*b +end function diff --git a/numpy/f2py/tests/test_crackfortran.py b/numpy/f2py/tests/test_crackfortran.py index 23965087d41f..886fc596e02e 100644 --- a/numpy/f2py/tests/test_crackfortran.py +++ b/numpy/f2py/tests/test_crackfortran.py @@ -322,4 +322,12 @@ def test_nameargspattern_backtracking(self, adversary): # we accept that maybe the median might double once, due to # the CPU scheduler acting weird or whatever. More than that # seems suspicious. - assert times_median_doubled < 2 \ No newline at end of file + assert times_median_doubled < 2 + + +class TestFunctionReturn(util.F2PyTest): + sources = [util.getpath("tests", "src", "crackfortran", "gh23598.f90")] + + def test_function_rettype(self): + # gh-23598 + assert self.module.intproduct(3, 4) == 12 From f331fe66df280437ca1d4353e89e72dc7b1a3dd6 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sun, 16 Apr 2023 18:18:16 +0000 Subject: [PATCH 2/6] BUG: Fix return types for functions in f2py --- numpy/f2py/crackfortran.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py index 4be41a61b6d0..f87de4943be6 100755 --- a/numpy/f2py/crackfortran.py +++ b/numpy/f2py/crackfortran.py @@ -2850,6 +2850,8 @@ def compute_deps(v, deps): kindselect, charselect, typename = cracktypespec( typespec, selector) vars[n]['typespec'] = typespec + if block['result']: + vars[block['result']]['typespec'] = typespec if kindselect: if 'kind' in kindselect: try: From d64838e04c201e00af66f89ff5c6c7c964bb6b10 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sun, 16 Apr 2023 18:39:52 +0000 Subject: [PATCH 3/6] MAINT: Fix tests for f2py inferred return types --- numpy/f2py/crackfortran.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py index f87de4943be6..c085baf128ac 100755 --- a/numpy/f2py/crackfortran.py +++ b/numpy/f2py/crackfortran.py @@ -2850,8 +2850,11 @@ def compute_deps(v, deps): kindselect, charselect, typename = cracktypespec( typespec, selector) vars[n]['typespec'] = typespec - if block['result']: - vars[block['result']]['typespec'] = typespec + try: + if block['result']: + vars[block['result']]['typespec'] = typespec + except Exception: + pass if kindselect: if 'kind' in kindselect: try: From 6fe296cff6b31747232326511a42599e0a354ee3 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sun, 16 Apr 2023 18:57:07 +0000 Subject: [PATCH 4/6] MAINT,TST: No printing in f2py tests --- doc/source/f2py/code/ftype.f | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/f2py/code/ftype.f b/doc/source/f2py/code/ftype.f index cabbb9e2d5da..67d5a224b949 100644 --- a/doc/source/f2py/code/ftype.f +++ b/doc/source/f2py/code/ftype.f @@ -4,6 +4,6 @@ SUBROUTINE FOO(N) Cf2py integer optional,intent(in) :: n = 13 REAL A,X COMMON /DATA/ A,X(3) - PRINT*, "IN FOO: N=",N," A=",A," X=[",X(1),X(2),X(3),"]" +C PRINT*, "IN FOO: N=",N," A=",A," X=[",X(1),X(2),X(3),"]" END C END OF FTYPE.F From 2ac450e5c0c0ca47040c2fd4147f45f42010510c Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Mon, 17 Apr 2023 00:41:10 +0000 Subject: [PATCH 5/6] BUG: Ensure function wrappers have consistent args --- numpy/f2py/func2subr.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/numpy/f2py/func2subr.py b/numpy/f2py/func2subr.py index 2a05f065b625..cc3cdc5b4f90 100644 --- a/numpy/f2py/func2subr.py +++ b/numpy/f2py/func2subr.py @@ -119,6 +119,12 @@ def add(line, ret=ret): sargs = ', '.join(args) if f90mode: + # gh-23598 fix warning + # Essentially, this gets called again with modules where the name of the + # function is added to the arguments, which is not required, and removed + sargs = sargs.replace(f"{name}, ", '') + args = [arg for arg in args if arg != name] + rout['args'] = args add('subroutine f2pywrap_%s_%s (%s)' % (rout['modulename'], name, sargs)) if not signature: From c7ff4118a345c966e2a0fc688e054e3fd9191e99 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Mon, 17 Apr 2023 00:59:45 +0000 Subject: [PATCH 6/6] TST: Add a test for the f2py function wrapper file --- .../tests/src/crackfortran/gh23598Warn.f90 | 11 ++++++++++ numpy/f2py/tests/test_f2py2e.py | 22 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 numpy/f2py/tests/src/crackfortran/gh23598Warn.f90 diff --git a/numpy/f2py/tests/src/crackfortran/gh23598Warn.f90 b/numpy/f2py/tests/src/crackfortran/gh23598Warn.f90 new file mode 100644 index 000000000000..3b44efc5ef16 --- /dev/null +++ b/numpy/f2py/tests/src/crackfortran/gh23598Warn.f90 @@ -0,0 +1,11 @@ +module test_bug + implicit none + private + public :: intproduct + +contains + integer function intproduct(a, b) result(res) + integer, intent(in) :: a, b + res = a*b + end function +end module diff --git a/numpy/f2py/tests/test_f2py2e.py b/numpy/f2py/tests/test_f2py2e.py index 2c10f046f1d9..5f7b56a68a9d 100644 --- a/numpy/f2py/tests/test_f2py2e.py +++ b/numpy/f2py/tests/test_f2py2e.py @@ -62,6 +62,15 @@ def hello_world_f90(tmpdir_factory): return fn +@pytest.fixture(scope="session") +def gh23598_warn(tmpdir_factory): + """F90 file for testing warnings in gh23598""" + fdat = util.getpath("tests", "src", "crackfortran", "gh23598Warn.f90").read_text() + fn = tmpdir_factory.getbasetemp() / "gh23598Warn.f90" + fn.write_text(fdat, encoding="ascii") + return fn + + @pytest.fixture(scope="session") def hello_world_f77(tmpdir_factory): """Generates a single f77 file for testing""" @@ -91,6 +100,19 @@ def f2cmap_f90(tmpdir_factory): return fn +def test_gh23598_warn(capfd, gh23598_warn, monkeypatch): + foutl = get_io_paths(gh23598_warn, mname="test") + ipath = foutl.f90inp + monkeypatch.setattr( + sys, "argv", + f'f2py {ipath} -m test'.split()) + + with util.switchdir(ipath.parent): + f2pycli() # Generate files + wrapper = foutl.wrap90.read_text() + assert "intproductf2pywrap, intpr" not in wrapper + + def test_gen_pyf(capfd, hello_world_f90, monkeypatch): """Ensures that a signature file is generated via the CLI CLI :: -h