Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: add numpy.f2py.get_include function #19348

Merged
merged 1 commit into from Jun 25, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
49 changes: 48 additions & 1 deletion numpy/f2py/__init__.py
Expand Up @@ -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
Expand Down Expand Up @@ -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/
Expand Down
20 changes: 14 additions & 6 deletions numpy/f2py/tests/test_regression.py
Expand Up @@ -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