bilderbuchi · GitHub

Describe the issue:

When using callstatement to overrride a subroutine with different code as per the docs , this works when said subroutine is directly invoked by Python. However, when invoking another subroutine that calls the first subroutine, this override is not in effect.

MWE:
test.f90

module utils
    implicit none
  contains
    subroutine my_abort(message)
      implicit none
      character(len=*), intent(in) :: message
      !f2py callstatement PyErr_SetString(PyExc_ValueError, message);f2py_success = 0;
      !f2py callprotoargument char*
      write(0,*) "THIS SHOULD NOT APPEAR"
      stop 1
    end subroutine my_abort
    subroutine do_something()
        call my_abort("aborting inside")
    end subroutine do_something
end module utils

To avoid #2547, you have to do the compilation in 2 steps:

python3 -m numpy.f2py -h test.pyf --no-lower -m test test.f90
python3 -m numpy.f2py -c --f90exec=gfortran --fcompiler=gnu95 test.pyf test.f90

Invoking my_abort directly works as expected, raising the ValueError I have defined:

$ python3 -c "import test; test.utils.my_abort('aborting directly')"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ValueError: aborting directly

However, when calling do_something, which in turn calls my_abort, the override seems to do nothing, and we run into the stop:

$ python3 -c "import test; test.utils.do_something()"
 THIS SHOULD NOT APPEAR
STOP 1

Expected result: Python raises ValueError: aborting inside

Reproduce the code example:

python3 -c "import test; test.utils.do_something()"
 THIS SHOULD NOT APPEAR
STOP 1
# Expected result: Python raises `ValueError: aborting inside`

Error message:

No response

Python and NumPy Versions:

Numpy: 2.0.0rc2 via conda-forge
python: 3.11.9 | packaged by conda-forge | (main, Apr 19 2024, 18:36:13) [GCC 12.3.0]
gfortran: GNU Fortran (conda-forge gcc 11.2.0-16) 11.2.0

Using 2.0.0rc2 to avoid issue #26156

Runtime Environment:

[{'numpy_version': '2.0.0rc2',
'python': '3.11.9 | packaged by conda-forge | (main, Apr 19 2024, 18:36:13) '
'[GCC 12.3.0]',
'uname': uname_result(system='Linux', node='b5dc6932b437', release='5.15.146.1-microsoft-standard-WSL2', version='#1 SMP Thu Jan 11 04:09:03 UTC 2024', machine='x86_64')},
{'simd_extensions': {'baseline': ['SSE', 'SSE2', 'SSE3'],
'found': ['SSSE3',
'SSE41',
'POPCNT',
'SSE42',
'AVX',
'F16C',
'FMA3',
'AVX2',
'AVX512F',
'AVX512CD',
'AVX512_SKX',
'AVX512_CLX',
'AVX512_CNL',
'AVX512_ICL'],
'not_found': ['AVX512_KNL', 'AVX512_KNM', 'AVX512_SPR']}},
{'architecture': 'SkylakeX',
'filepath': '/opt/conda/envs/xplengine/lib/libopenblasp-r0.3.27.so',
'internal_api': 'openblas',
'num_threads': 4,
'prefix': 'libopenblas',
'threading_layer': 'pthreads',
'user_api': 'blas',
'version': '0.3.27'}]

Context for the issue:

What I'm intending here is to avoid executing the Fortran stop statement when running wrapped code in Python, because that also kills the Python interpreter and thus, in my case, the pytest run of a whole test suite that this code is part of.

This my_abort cleanup subroutine is potentially called from many places throughout the actual codebase.

A similar-feeling issue involving callbacks: #7855
Feels related: #26156
ping @HaoZeke

Read the original on github.com ↗