-
-
Notifications
You must be signed in to change notification settings - Fork 11.6k
Description
Here is the implementation:
Lines 18 to 121 in 9340fca
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 | |
-------- | |
.. literalinclude:: ../../source/f2py/code/results/compile_session.dat | |
:language: python | |
""" | |
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, capture_output=True) | |
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 |
It was lightly amended recently for meson
use in #25111, however there is really very little justification for its (continued) existence. Some thoughts:
- Things shouldn't be in
__init__
- It is essentially a wrapper around
subprocess.run
- Has barely been touched since it was brought in 18 years ago or so (from the
git blame
) - It leaks memory
The only slight functionality it provides is that it can work with a block of text (by generating a temporary file). Additionally, tests for compile
are pretty broken on Windows, and given that it still generates a module file, and the fact that since the meson
transition users cannot use most of the old -c
commands, it is really easier to use externally or be explicit about using subprocess
with environment variables set.
It has always been marked as experimental and subject to change, I would like to therefore remove it ASAP :)
Any user who needs such functionality would be better suited by writing their own thin wrapper over subprocess
based functionality (or use something like sh
).