Spaces:
Running
Running
File size: 4,434 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 |
"""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
@pytest.mark.parametrize(
"extra_args", [['--noopt', '--debug'], '--noopt --debug', '']
)
@pytest.mark.leaks_references(reason="Imported module seems never deleted.")
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
@pytest.mark.parametrize('fsource',
['program test_f2py\nend program test_f2py',
b'program test_f2py\nend program test_f2py',])
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)
|