Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions doc/release/upcoming_changes/21807.improvement.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
F2PY supports the value attribute
=================================

The Fortran standard requires that variables declared with the ``value``
attribute must be passed by value instead of reference. F2PY now supports this
use pattern correctly. So ``integer, intent(in), value :: x`` in Fortran codes
will have correct wrappers generated.
8 changes: 6 additions & 2 deletions numpy/f2py/auxfuncs.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
'isunsigned_chararray', 'isunsigned_long_long',
'isunsigned_long_longarray', 'isunsigned_short',
'isunsigned_shortarray', 'l_and', 'l_not', 'l_or', 'outmess',
'replace', 'show', 'stripcomma', 'throw_error',
'replace', 'show', 'stripcomma', 'throw_error', 'isattr_value'
]


Expand Down Expand Up @@ -298,6 +298,9 @@ def issubroutine_wrap(rout):
return 0
return issubroutine(rout) and hasassumedshape(rout)

def isattr_value(var):
return 'value' in var.get('attrspec', [])


def hasassumedshape(rout):
if rout.get('hasassumedshape'):
Expand Down Expand Up @@ -692,7 +695,8 @@ def getcallprotoargument(rout, cb_map={}):
elif isstring(var):
pass
else:
ctype = ctype + '*'
if not isattr_value(var):
ctype = ctype + '*'
if ((isstring(var)
or isarrayofstrings(var) # obsolete?
or isstringarray(var))):
Expand Down
4 changes: 2 additions & 2 deletions numpy/f2py/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
islong_double, islong_doublefunction, islong_long,
islong_longfunction, ismoduleroutine, isoptional, isrequired,
isscalar, issigned_long_longarray, isstring, isstringarray,
isstringfunction, issubroutine,
isstringfunction, issubroutine, isattr_value,
issubroutine_wrap, isthreadsafe, isunsigned, isunsigned_char,
isunsigned_chararray, isunsigned_long_long,
isunsigned_long_longarray, isunsigned_short, isunsigned_shortarray,
Expand Down Expand Up @@ -874,7 +874,7 @@
{ # Common
'decl': ' #ctype# #varname# = 0;',
'pyobjfrom': {debugcapi: ' fprintf(stderr,"#vardebugshowvalue#\\n",#varname#);'},
'callfortran': {isintent_c: '#varname#,', l_not(isintent_c): '&#varname#,'},
'callfortran': {l_or(isintent_c, isattr_value): '#varname#,', l_not(l_or(isintent_c, isattr_value)): '&#varname#,'},
'return': {isintent_out: ',#varname#'},
'_check': l_and(isscalar, l_not(iscomplex))
}, {
Expand Down
9 changes: 9 additions & 0 deletions numpy/f2py/tests/src/value_attrspec/gh21665.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module fortfuncs
implicit none
contains
subroutine square(x,y)
integer, intent(in), value :: x
integer, intent(out) :: y
y = x*x
end subroutine square
end module fortfuncs
14 changes: 14 additions & 0 deletions numpy/f2py/tests/test_value_attrspec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import os
import pytest

from . import util

class TestValueAttr(util.F2PyTest):
sources = [util.getpath("tests", "src", "value_attrspec", "gh21665.f90")]

# gh-21665
def test_long_long_map(self):
inp = 2
out = self.module.fortfuncs.square(inp)
exp_out = 4
assert out == exp_out