File size: 5,964 Bytes
dc2106c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#!/usr/bin/env python3
"""Fortran to Python Interface Generator.



"""
__all__ = ['run_main', 'compile', 'get_include', 'f2py_testing']

import sys
import subprocess
import os

from . import f2py2e
from . import diagnose

run_main = f2py2e.run_main
main = f2py2e.main


def compile(source,

            modulename='untitled',

            extra_args='',

            verbose=True,

            source_fn=None,

            extension='.f',

            full_output=False

           ):
    """

    Build extension module from a Fortran 77 source string with f2py.



    Parameters

    ----------

    source : str or bytes

        Fortran source of module / subroutine to compile



        .. versionchanged:: 1.16.0

           Accept str as well as bytes



    modulename : str, optional

        The name of the compiled python module

    extra_args : str or list, optional

        Additional parameters passed to f2py



        .. versionchanged:: 1.16.0

            A list of args may also be provided.



    verbose : bool, optional

        Print f2py output to screen

    source_fn : str, optional

        Name of the file where the fortran source is written.

        The default is to use a temporary file with the extension

        provided by the `extension` parameter

    extension : {'.f', '.f90'}, optional

        Filename extension if `source_fn` is not provided.

        The extension tells which fortran standard is used.

        The default is `.f`, which implies F77 standard.



        .. versionadded:: 1.11.0



    full_output : bool, optional

        If True, return a `subprocess.CompletedProcess` containing

        the stdout and stderr of the compile process, instead of just

        the status code.



        .. versionadded:: 1.20.0





    Returns

    -------

    result : int or `subprocess.CompletedProcess`

        0 on success, or a `subprocess.CompletedProcess` if

        ``full_output=True``



    Examples

    --------

    .. include:: compile_session.dat

        :literal:



    """
    import tempfile
    import shlex

    if source_fn is None:
        f, fname = tempfile.mkstemp(suffix=extension)
        # f is a file descriptor so need to close it
        # carefully -- not with .close() directly
        os.close(f)
    else:
        fname = source_fn

    if not isinstance(source, str):
        source = str(source, 'utf-8')
    try:
        with open(fname, 'w') as f:
            f.write(source)

        args = ['-c', '-m', modulename, f.name]

        if isinstance(extra_args, str):
            is_posix = (os.name == 'posix')
            extra_args = shlex.split(extra_args, posix=is_posix)

        args.extend(extra_args)

        c = [sys.executable,
             '-c',
             'import numpy.f2py as f2py2e;f2py2e.main()'] + args
        try:
            cp = subprocess.run(c, stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        except OSError:
            # preserve historic status code used by exec_command()
            cp = subprocess.CompletedProcess(c, 127, stdout=b'', stderr=b'')
        else:
            if verbose:
                print(cp.stdout.decode())
    finally:
        if source_fn is None:
            os.remove(fname)

    if full_output:
        return cp
    else:
        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/
    def __getattr__(attr):

        # Avoid importing things that aren't needed for building
        # which might import the main numpy module
        if attr == "f2py_testing":
            import numpy.f2py.f2py_testing as f2py_testing
            return f2py_testing

        elif attr == "test":
            from numpy._pytesttester import PytestTester
            test = PytestTester(__name__)
            return test

        else:
            raise AttributeError("module {!r} has no attribute "
                                 "{!r}".format(__name__, attr))

    def __dir__():
        return list(globals().keys() | {"f2py_testing", "test"})

else:
    from . import f2py_testing

    from numpy._pytesttester import PytestTester
    test = PytestTester(__name__)
    del PytestTester