-
-
Notifications
You must be signed in to change notification settings - Fork 11.7k
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).