f2py: Unable to expose parameters from “used” modules #3562

Open
jsolbrig opened this Issue Aug 1, 2013 · 4 comments

Comments

Projects
None yet
4 participants

jsolbrig commented Aug 1, 2013

I have tried to put the problem in the first paragraph. The rest shows a basic example of the problem.

I am attempting to compile a module that contains a USE statement pointing to another, more general, module. I would prefer to keep the used module separate so that it can be used in several places as a set of general settings. When I complie the two modules using f2py, everything works correctly from the fortran side, but fromt he python side USE appears to be ignored. If I allow f2py to generate a signature file, the file contains a USE statement as is appropriate, but if I complete the compilation and import from the resulting library, the parameters from the used module are not available in the module that contains the use statement. Below are two modules illustrating the situation:

MODULE test
    INTEGER, PARAMETER :: a = 1
END MODULE test

MODULE test2
    USE test
    INTEGER, PARAMETER :: b = 2
END MODULE test2

In order to show the intermediate step I ran f2py -h test.pyf test.f90 test2.f90. The following signature file is generated; note that the "test2" module contains use test:

!    -*- f90 -*-
! Note: the context of this file is case sensitive.

python module test ! in
    interface  ! in :test
        module test ! in :test:test.f90
            integer, parameter,optional :: a=1
        end module test
        module test2 ! in :test:test2.f90
            use test
            integer, parameter,optional :: b=2
        end module test2
    end interface
end python module test

! This file was auto-generated with f2py (version:2).
! See http://cens.ioc.ee/projects/f2py2e/

If I now compile with f2py --fcompiler=gfortran -c test.pyf test.f90 test2.f90 I obtain test.so (same as running f2py --fcompiler=gfortran -m test -c test.f90 test2.f90 without creating the signature file first). Importing from this library in python exposes test.test.a and test.test2.b, but does not expose test.test2.a as can be seen here:

In [1]: import test

In [2]: print test.test.a
1

In [3]: print test.test2.b
2

In [4]: print test.test2.a
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/users/solbrig/svn_checkouts/inversion/satmet/branches/solbrig/rootpath/data/users
/GeoIPS/src/test/<ipython-input-4-bffcf464e408> in <module>() 
----> 1 print test.test2.a

AttributeError: a

Just to illustrate that b is defined properly in test2 from the perspective of fortran, the following code uses test2 and prings both a and b:

SUBROUTINE run_test()
    USE test2
    IMPLICIT NONE
    print *, "a = ", a
    print *, "b = ", b
END SUBROUTINE run_test

After compiling with f2py -m run_test -c test.f90 test2.f90 run_test.f90 and obtaining run_test.so, run_test can be imported in python and works as expected:

In [1]: import run_test

In [2]: run_test.run_test()
 a =            1
 b =            2

Please let me know if there is any other information that I can provide or if there is a solution for this issue.

jsolbrig commented Aug 1, 2013

How can I tag this as an f2py issue?

Owner

rgommers commented Aug 1, 2013

You can't; I tagged it.

Contributor

chatcannon commented Sep 15, 2013

Try this

        module test2 ! in :test:test2.f90
            use test : test_a => a
            integer, parameter,optional :: a=test_a
            integer, parameter,optional :: b=2
        end module test2

Thanks chatcannon! That got me on the right track for a temporary solution. It was close to working, but had to be modified to:

    module test2 ! in :test:test2.f90
        use test : test_a => a
        integer, parameter :: a=test_a
        integer, parameter :: b=2
    end module test2

A solution that worked better, since it didn't require modification of the .pyf during the compile, was to add an f2py directive to test2:

    module test
        integer, parameter :: a = 1
    end module test

    module test2
        use test
        !f2py integer, parameter :: a  ! THIS EXPOSES test2.a
        integer, parameter :: b = 2
    end module test2

I don't think this is optimal, though. f2py should be able to figure this one out. It has all of the information that it requires in the .pyf file. It just needs to piece it together. I'm looking into the source to see if I can do something about it.

@charris charris added Defect labels Feb 23, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment