Skip to content

f2py fails creating an interface file #479

Closed
krischer opened this Issue Oct 4, 2012 · 12 comments

3 participants

@krischer
krischer commented Oct 4, 2012

Somewhere in the code a wrong variable is passed down to an exec statement. This is not a pull request as I believe someone should look into it and potentially also replace the actual exec() call.

In the meanwhile, this ugly hack fixes it:

--- a/numpy/f2py/crackfortran.py
+++ b/numpy/f2py/crackfortran.py
@@ -2606,7 +2606,10 @@
     ret = []
     for intent in lst:
         try:
-            exec('c = isintent_%s(var)' % intent)
+            # Somewhere in the code the intent item of var['intent'] is set to
+            # "in out" instead of "inout". This ugly fix works but is likely
+            # not an ideal solution.
+            exec('c = isintent_%s(var)' % intent.replace(" ", ""))
         except NameError:
             c = 0
         if c:

Additional information

Numpy Version

>>> np.__version__
1.6.2

Library

Used on mtspec library v3.1 if anyone wants to reproduce.

Call and Traceback

$ f2py -m mtspec -h mtspec.pyf *.f90

...

Traceback (most recent call last):
      File "/home/krischer/local/virtual_envs/py2.7/bin/f2py", line 24, in <module>
          main()
        File "/home/krischer/local/virtual_envs/py2.7/lib/python2.7/site-packages/numpy/f2py/f2py2e.py", line 590, in main
          run_main(sys.argv[1:])
        File "/home/krischer/local/virtual_envs/py2.7/lib/python2.7/site-packages/numpy/f2py/f2py2e.py", line 361, in run_main
          postlist=callcrackfortran(files,options)
        File "/home/krischer/local/virtual_envs/py2.7/lib/python2.7/site-packages/numpy/f2py/f2py2e.py", line 286, in callcrackfortran
          pyf=crackfortran.crack2fortran(postlist)
        File "/home/krischer/local/virtual_envs/py2.7/lib/python2.7/site-packages/numpy/f2py/crackfortran.py", line 2749, in crack2fortran
          pyf=crack2fortrangen(block)+'\n'
        File "/home/krischer/local/virtual_envs/py2.7/lib/python2.7/site-packages/numpy/f2py/crackfortran.py", line 2517, in crack2fortrangen
          ret=ret+crack2fortrangen(g,tab,as_interface=as_interface)
        File "/home/krischer/local/virtual_envs/py2.7/lib/python2.7/site-packages/numpy/f2py/crackfortran.py", line 2560, in crack2fortrangen
          body=crack2fortrangen(block['body'],tab+tabchar)
        File "/home/krischer/local/virtual_envs/py2.7/lib/python2.7/site-packages/numpy/f2py/crackfortran.py", line 2517, in crack2fortrangen
          ret=ret+crack2fortrangen(g,tab,as_interface=as_interface)
        File "/home/krischer/local/virtual_envs/py2.7/lib/python2.7/site-packages/numpy/f2py/crackfortran.py", line 2560, in crack2fortrangen
          body=crack2fortrangen(block['body'],tab+tabchar)
        File "/home/krischer/local/virtual_envs/py2.7/lib/python2.7/site-packages/numpy/f2py/crackfortran.py", line 2517, in crack2fortrangen
          ret=ret+crack2fortrangen(g,tab,as_interface=as_interface)
        File "/home/krischer/local/virtual_envs/py2.7/lib/python2.7/site-packages/numpy/f2py/crackfortran.py", line 2561, in crack2fortrangen
          vars=vars2fortran(block,block['vars'],argsl,tab+tabchar, as_interface=as_interface)
        File "/home/krischer/local/virtual_envs/py2.7/lib/python2.7/site-packages/numpy/f2py/crackfortran.py", line 2711, in vars2fortran
          lst = true_intent_list(vars[a])
        File "/home/krischer/local/virtual_envs/py2.7/lib/python2.7/site-packages/numpy/f2py/crackfortran.py", line 2609, in true_intent_list
          exec('c = isintent_%s(var)' % intent)
        File "<string>", line 1
          c = isintent_in out(var)
                            ^
      SyntaxError: invalid syntax
@charris
NumPy member
charris commented Feb 17, 2014

Could you provide a small program that exhibits the problem? f2py is a tangle and the problem isn't easy to find.

@WarrenWeckesser

Here's a test case. Note the space in in out.

foo.f90

subroutine foo(x)
implicit none
real(4), intent(in out) :: x
return
end

Here's the error:

$ f2py -m foo -h foo.pyf foo.f90 
Reading fortran codes...
    Reading file 'foo.f90' (format:free)
Post-processing...
    Block: foo
            Block: foo
Post-processing (stage 2)...
Saving signatures to file "./foo.pyf"
Traceback (most recent call last):
  File "/Users/warren/anaconda/bin/f2py", line 24, in <module>
    main()
  File "/Users/warren/local_scipy/lib/python2.7/site-packages/numpy/f2py/f2py2e.py", line 592, in main
    run_main(sys.argv[1:])
  File "/Users/warren/local_scipy/lib/python2.7/site-packages/numpy/f2py/f2py2e.py", line 357, in run_main
    postlist=callcrackfortran(files, options)
  File "/Users/warren/local_scipy/lib/python2.7/site-packages/numpy/f2py/f2py2e.py", line 286, in callcrackfortran
    pyf=crackfortran.crack2fortran(postlist)
  File "/Users/warren/local_scipy/lib/python2.7/site-packages/numpy/f2py/crackfortran.py", line 2789, in crack2fortran
    pyf=crack2fortrangen(block)+'\n'
  File "/Users/warren/local_scipy/lib/python2.7/site-packages/numpy/f2py/crackfortran.py", line 2557, in crack2fortrangen
    ret=ret+crack2fortrangen(g, tab, as_interface=as_interface)
  File "/Users/warren/local_scipy/lib/python2.7/site-packages/numpy/f2py/crackfortran.py", line 2600, in crack2fortrangen
    body=crack2fortrangen(block['body'], tab+tabchar)
  File "/Users/warren/local_scipy/lib/python2.7/site-packages/numpy/f2py/crackfortran.py", line 2557, in crack2fortrangen
    ret=ret+crack2fortrangen(g, tab, as_interface=as_interface)
  File "/Users/warren/local_scipy/lib/python2.7/site-packages/numpy/f2py/crackfortran.py", line 2600, in crack2fortrangen
    body=crack2fortrangen(block['body'], tab+tabchar)
  File "/Users/warren/local_scipy/lib/python2.7/site-packages/numpy/f2py/crackfortran.py", line 2557, in crack2fortrangen
    ret=ret+crack2fortrangen(g, tab, as_interface=as_interface)
  File "/Users/warren/local_scipy/lib/python2.7/site-packages/numpy/f2py/crackfortran.py", line 2601, in crack2fortrangen
    vars=vars2fortran(block, block['vars'], argsl, tab+tabchar, as_interface=as_interface)
  File "/Users/warren/local_scipy/lib/python2.7/site-packages/numpy/f2py/crackfortran.py", line 2751, in vars2fortran
    lst = true_intent_list(vars[a])
  File "/Users/warren/local_scipy/lib/python2.7/site-packages/numpy/f2py/crackfortran.py", line 2649, in true_intent_list
    c = eval('isintent_%s(var)' % intent)
  File "<string>", line 1
    isintent_in out(var)
                  ^
SyntaxError: invalid syntax
@charris
NumPy member
charris commented Oct 9, 2014

Arrggghhhh. Some day crackfortran needs to be rewritten using a standard parser ;)

@charris
NumPy member
charris commented Oct 9, 2014

The proximate cause is in the fortran file intent(in out), the in out is not valid fortran. See http://h21007.www2.hp.com/portal/download/files/unprot/fortran/docs/lrm/lrm0103.htm#intent_attr. I suppose catching this and issuing a better error message would help.

@charris
NumPy member
charris commented Oct 9, 2014

I'm inclined to close this. The error is likely in the fortran source, and without the source it is not possible to make progress.

@charris
NumPy member
charris commented Oct 9, 2014

Although I note the original files use that construction. Hmm..., IIRC, Fortran should ignore spaces. So perhaps the correct fix here is to remove any spaces in that argument, basically the fix proposed but perhaps in a different place.

@WarrenWeckesser

I think intent(in out) is valid Fortran; foo.f90 compiles with gfortran, even with -pedantic (I'm not sure if there are other arguments to make gfortran stricter). Fortran is notorious for ignoring spaces (e.g. GO TO and GOTO are both valid).

@WarrenWeckesser

The proposed change works, but I don't know if that is the best place to handle this.

@charris
NumPy member
charris commented Oct 9, 2014

Little changes can lead to problems. I'm thinking the minimal fix as proposed is the safest thing. It's a hack, but...

@charris
NumPy member
charris commented Oct 9, 2014

With the proposed fix, the signature file is not the same as when inout is used.

Fix only

python module foo ! in 
    interface  ! in :foo
        module foo_fixed ! in :foo:foo.f90
            subroutine foo(x) ! in :foo:foo.f90:foo_fixed
                real(kind=4) :: x
            end subroutine foo
        end module foo_fixed
    end interface 
end python module foo

Using inout

python module foo ! in 
    interface  ! in :foo
        module foo_fixed ! in :foo:foo.f90
            subroutine foo(x) ! in :foo:foo.f90:foo_fixed
                real(kind=4) intent(inout) :: x
            end subroutine foo
        end module foo_fixed
    end interface 
end python module foo

I don't know if that matters in practice, but there is a subtle difference in fortran between the two cases.

@charris charris added a commit to charris/numpy that referenced this issue Oct 9, 2014
@charris charris BUG: Make f2py work with intent(in out).
Note that Fortran ignores spaces in this case, so that 'in out' is
treated as 'inout'.

Closes #479.
98010aa
@WarrenWeckesser

Oops. I should have said "it doesn't crash" instead of "it works."

@WarrenWeckesser

There is a difference--I'll comment on it in the pull request.

@charris charris added a commit to charris/numpy that referenced this issue Oct 9, 2014
@charris charris BUG: Make f2py work with intent(in out).
Note that Fortran ignores spaces in this case, so that 'in out' is
treated as 'inout'.

Closes #479.
aef2f7a
@charris charris added a commit to charris/numpy that referenced this issue Oct 10, 2014
@charris charris BUG: Make f2py work with intent(in out).
Note that Fortran ignores spaces in this case, so that 'in out' is
treated as 'inout'.

Closes #479.
1d6ef52
@charris charris closed this in #5168 Oct 10, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.