Spaces:
Running
Running
"""See https://github.com/numpy/numpy/pull/11937. | |
""" | |
import sys | |
import os | |
import uuid | |
from importlib import import_module | |
import pytest | |
import numpy.f2py | |
from numpy.testing import assert_equal | |
from . import util | |
def setup_module(): | |
if not util.has_c_compiler(): | |
pytest.skip("Needs C compiler") | |
if not util.has_f77_compiler(): | |
pytest.skip('Needs FORTRAN 77 compiler') | |
# extra_args can be a list (since gh-11937) or string. | |
# also test absence of extra_args | |
def test_f2py_init_compile(extra_args): | |
# flush through the f2py __init__ compile() function code path as a | |
# crude test for input handling following migration from | |
# exec_command() to subprocess.check_output() in gh-11937 | |
# the Fortran 77 syntax requires 6 spaces before any commands, but | |
# more space may be added/ | |
fsource = """ | |
integer function foo() | |
foo = 10 + 5 | |
return | |
end | |
""" | |
# use various helper functions in util.py to enable robust build / | |
# compile and reimport cycle in test suite | |
moddir = util.get_module_dir() | |
modname = util.get_temp_module_name() | |
cwd = os.getcwd() | |
target = os.path.join(moddir, str(uuid.uuid4()) + '.f') | |
# try running compile() with and without a source_fn provided so | |
# that the code path where a temporary file for writing Fortran | |
# source is created is also explored | |
for source_fn in [target, None]: | |
# mimic the path changing behavior used by build_module() in | |
# util.py, but don't actually use build_module() because it has | |
# its own invocation of subprocess that circumvents the | |
# f2py.compile code block under test | |
try: | |
os.chdir(moddir) | |
ret_val = numpy.f2py.compile( | |
fsource, | |
modulename=modname, | |
extra_args=extra_args, | |
source_fn=source_fn | |
) | |
finally: | |
os.chdir(cwd) | |
# check for compile success return value | |
assert_equal(ret_val, 0) | |
# we are not currently able to import the Python-Fortran | |
# interface module on Windows / Appveyor, even though we do get | |
# successful compilation on that platform with Python 3.x | |
if sys.platform != 'win32': | |
# check for sensible result of Fortran function; that means | |
# we can import the module name in Python and retrieve the | |
# result of the sum operation | |
return_check = import_module(modname) | |
calc_result = return_check.foo() | |
assert_equal(calc_result, 15) | |
# Removal from sys.modules, is not as such necessary. Even with | |
# removal, the module (dict) stays alive. | |
del sys.modules[modname] | |
def test_f2py_init_compile_failure(): | |
# verify an appropriate integer status value returned by | |
# f2py.compile() when invalid Fortran is provided | |
ret_val = numpy.f2py.compile(b"invalid") | |
assert_equal(ret_val, 1) | |
def test_f2py_init_compile_bad_cmd(): | |
# verify that usage of invalid command in f2py.compile() returns | |
# status value of 127 for historic consistency with exec_command() | |
# error handling | |
# patch the sys Python exe path temporarily to induce an OSError | |
# downstream NOTE: how bad of an idea is this patching? | |
try: | |
temp = sys.executable | |
sys.executable = 'does not exist' | |
# the OSError should take precedence over invalid Fortran | |
ret_val = numpy.f2py.compile(b"invalid") | |
assert_equal(ret_val, 127) | |
finally: | |
sys.executable = temp | |
def test_compile_from_strings(tmpdir, fsource): | |
# Make sure we can compile str and bytes gh-12796 | |
cwd = os.getcwd() | |
try: | |
os.chdir(str(tmpdir)) | |
ret_val = numpy.f2py.compile( | |
fsource, | |
modulename='test_compile_from_strings', | |
extension='.f90') | |
assert_equal(ret_val, 0) | |
finally: | |
os.chdir(cwd) | |