diff --git a/numpy/f2py/__init__.py b/numpy/f2py/__init__.py index 07ab6cd7da96..4f6938ed2b4e 100644 --- a/numpy/f2py/__init__.py +++ b/numpy/f2py/__init__.py @@ -2,7 +2,7 @@ """Fortran to Python Interface Generator. """ -__all__ = ['run_main', 'compile', 'f2py_testing'] +__all__ = ['run_main', 'compile', 'get_include', 'f2py_testing'] import sys import subprocess @@ -122,6 +122,53 @@ def compile(source, return cp.returncode +def get_include(): + """ + Return the directory that contains the fortranobject.c and .h files. + + .. note:: + + This function is not needed when building an extension with + `numpy.distutils` directly from ``.f`` and/or ``.pyf`` files + in one go. + + Python extension modules built with f2py-generated code need to use + ``fortranobject.c`` as a source file, and include the ``fortranobject.h`` + header. This function can be used to obtain the directory containing + both of these files. + + Returns + ------- + include_path : str + Absolute path to the directory containing ``fortranobject.c`` and + ``fortranobject.h``. + + Notes + ----- + .. versionadded:: 1.22.0 + + Unless the build system you are using has specific support for f2py, + building a Python extension using a ``.pyf`` signature file is a two-step + process. For a module ``mymod``: + + - Step 1: run ``python -m numpy.f2py mymod.pyf --quiet``. This + generates ``_mymodmodule.c`` and (if needed) + ``_fblas-f2pywrappers.f`` files next to ``mymod.pyf``. + - Step 2: build your Python extension module. This requires the + following source files: + + - ``_mymodmodule.c`` + - ``_mymod-f2pywrappers.f`` (if it was generated in step 1) + - ``fortranobject.c`` + + See Also + -------- + numpy.get_include : function that returns the numpy include directory + + """ + return os.path.join(os.path.dirname(__file__), 'src') + + if sys.version_info[:2] >= (3, 7): # module level getattr is only supported in 3.7 onwards # https://www.python.org/dev/peps/pep-0562/ diff --git a/numpy/f2py/tests/test_regression.py b/numpy/f2py/tests/test_regression.py index a1b772069a0b..b91499e4adb3 100644 --- a/numpy/f2py/tests/test_regression.py +++ b/numpy/f2py/tests/test_regression.py @@ -25,23 +25,31 @@ def test_inout(self): x = np.arange(3, dtype=np.float32) self.module.foo(x) assert_equal(x, [3, 1, 2]) - + class TestNumpyVersionAttribute(util.F2PyTest): # Check that th attribute __f2py_numpy_version__ is present # in the compiled module and that has the value np.__version__. sources = [_path('src', 'regression', 'inout.f90')] - + @pytest.mark.slow def test_numpy_version_attribute(self): - + # Check that self.module has an attribute named "__f2py_numpy_version__" - assert_(hasattr(self.module, "__f2py_numpy_version__"), + assert_(hasattr(self.module, "__f2py_numpy_version__"), msg="Fortran module does not have __f2py_numpy_version__") - + # Check that the attribute __f2py_numpy_version__ is a string assert_(isinstance(self.module.__f2py_numpy_version__, str), msg="__f2py_numpy_version__ is not a string") - + # Check that __f2py_numpy_version__ has the value numpy.__version__ assert_string_equal(np.__version__, self.module.__f2py_numpy_version__) + + +def test_include_path(): + incdir = np.f2py.get_include() + fnames_in_dir = os.listdir(incdir) + for fname in ('fortranobject.c', 'fortranobject.h'): + assert fname in fnames_in_dir +