Created starter files for the project.

This commit is contained in:
Batuhan Berk Başoğlu 2020-10-02 21:26:03 -04:00
commit 73f0c0db42
1992 changed files with 769897 additions and 0 deletions

View file

@ -0,0 +1,233 @@
/* File: wrapmodule.c
* This file is auto-generated with f2py (version:2_1330).
* Hand edited by Pearu.
* f2py is a Fortran to Python Interface Generator (FPIG), Second Edition,
* written by Pearu Peterson <pearu@cens.ioc.ee>.
* See http://cens.ioc.ee/projects/f2py2e/
* Generation date: Fri Oct 21 22:41:12 2005
* $Revision:$
* $Date:$
* Do not edit this file directly unless you know what you are doing!!!
*/
#ifdef __cplusplus
extern "C" {
#endif
/*********************** See f2py2e/cfuncs.py: includes ***********************/
#include "Python.h"
#include "fortranobject.h"
#include <math.h>
static PyObject *wrap_error;
static PyObject *wrap_module;
/************************************ call ************************************/
static char doc_f2py_rout_wrap_call[] = "\
Function signature:\n\
arr = call(type_num,dims,intent,obj)\n\
Required arguments:\n"
" type_num : input int\n"
" dims : input int-sequence\n"
" intent : input int\n"
" obj : input python object\n"
"Return objects:\n"
" arr : array";
static PyObject *f2py_rout_wrap_call(PyObject *capi_self,
PyObject *capi_args) {
PyObject * volatile capi_buildvalue = NULL;
int type_num = 0;
npy_intp *dims = NULL;
PyObject *dims_capi = Py_None;
int rank = 0;
int intent = 0;
PyArrayObject *capi_arr_tmp = NULL;
PyObject *arr_capi = Py_None;
int i;
if (!PyArg_ParseTuple(capi_args,"iOiO|:wrap.call",\
&type_num,&dims_capi,&intent,&arr_capi))
return NULL;
rank = PySequence_Length(dims_capi);
dims = malloc(rank*sizeof(npy_intp));
for (i=0;i<rank;++i) {
PyObject *tmp;
tmp = PySequence_GetItem(dims_capi, i);
if (tmp == NULL) {
goto fail;
}
dims[i] = (npy_intp)PyInt_AsLong(tmp);
Py_DECREF(tmp);
if (dims[i] == -1 && PyErr_Occurred()) {
goto fail;
}
}
capi_arr_tmp = array_from_pyobj(type_num,dims,rank,intent|F2PY_INTENT_OUT,arr_capi);
if (capi_arr_tmp == NULL) {
free(dims);
return NULL;
}
capi_buildvalue = Py_BuildValue("N",capi_arr_tmp);
free(dims);
return capi_buildvalue;
fail:
free(dims);
return NULL;
}
static char doc_f2py_rout_wrap_attrs[] = "\
Function signature:\n\
arr = array_attrs(arr)\n\
Required arguments:\n"
" arr : input array object\n"
"Return objects:\n"
" data : data address in hex\n"
" nd : int\n"
" dimensions : tuple\n"
" strides : tuple\n"
" base : python object\n"
" (kind,type,type_num,elsize,alignment) : 4-tuple\n"
" flags : int\n"
" itemsize : int\n"
;
static PyObject *f2py_rout_wrap_attrs(PyObject *capi_self,
PyObject *capi_args) {
PyObject *arr_capi = Py_None;
PyArrayObject *arr = NULL;
PyObject *dimensions = NULL;
PyObject *strides = NULL;
char s[100];
int i;
memset(s,0,100*sizeof(char));
if (!PyArg_ParseTuple(capi_args,"O!|:wrap.attrs",
&PyArray_Type,&arr_capi))
return NULL;
arr = (PyArrayObject *)arr_capi;
sprintf(s,"%p",PyArray_DATA(arr));
dimensions = PyTuple_New(PyArray_NDIM(arr));
strides = PyTuple_New(PyArray_NDIM(arr));
for (i=0;i<PyArray_NDIM(arr);++i) {
PyTuple_SetItem(dimensions,i,PyInt_FromLong(PyArray_DIM(arr,i)));
PyTuple_SetItem(strides,i,PyInt_FromLong(PyArray_STRIDE(arr,i)));
}
return Py_BuildValue("siNNO(cciii)ii",s,PyArray_NDIM(arr),
dimensions,strides,
(PyArray_BASE(arr)==NULL?Py_None:PyArray_BASE(arr)),
PyArray_DESCR(arr)->kind,
PyArray_DESCR(arr)->type,
PyArray_TYPE(arr),
PyArray_ITEMSIZE(arr),
PyArray_DESCR(arr)->alignment,
PyArray_FLAGS(arr),
PyArray_ITEMSIZE(arr));
}
static PyMethodDef f2py_module_methods[] = {
{"call",f2py_rout_wrap_call,METH_VARARGS,doc_f2py_rout_wrap_call},
{"array_attrs",f2py_rout_wrap_attrs,METH_VARARGS,doc_f2py_rout_wrap_attrs},
{NULL,NULL}
};
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"test_array_from_pyobj_ext",
NULL,
-1,
f2py_module_methods,
NULL,
NULL,
NULL,
NULL
};
PyMODINIT_FUNC PyInit_test_array_from_pyobj_ext(void) {
PyObject *m,*d, *s;
m = wrap_module = PyModule_Create(&moduledef);
Py_SET_TYPE(&PyFortran_Type, &PyType_Type);
import_array();
if (PyErr_Occurred())
Py_FatalError("can't initialize module wrap (failed to import numpy)");
d = PyModule_GetDict(m);
s = PyString_FromString("This module 'wrap' is auto-generated with f2py (version:2_1330).\nFunctions:\n"
" arr = call(type_num,dims,intent,obj)\n"
".");
PyDict_SetItemString(d, "__doc__", s);
wrap_error = PyErr_NewException ("wrap.error", NULL, NULL);
Py_DECREF(s);
#define ADDCONST(NAME, CONST) \
s = PyInt_FromLong(CONST); \
PyDict_SetItemString(d, NAME, s); \
Py_DECREF(s)
ADDCONST("F2PY_INTENT_IN", F2PY_INTENT_IN);
ADDCONST("F2PY_INTENT_INOUT", F2PY_INTENT_INOUT);
ADDCONST("F2PY_INTENT_OUT", F2PY_INTENT_OUT);
ADDCONST("F2PY_INTENT_HIDE", F2PY_INTENT_HIDE);
ADDCONST("F2PY_INTENT_CACHE", F2PY_INTENT_CACHE);
ADDCONST("F2PY_INTENT_COPY", F2PY_INTENT_COPY);
ADDCONST("F2PY_INTENT_C", F2PY_INTENT_C);
ADDCONST("F2PY_OPTIONAL", F2PY_OPTIONAL);
ADDCONST("F2PY_INTENT_INPLACE", F2PY_INTENT_INPLACE);
ADDCONST("NPY_BOOL", NPY_BOOL);
ADDCONST("NPY_BYTE", NPY_BYTE);
ADDCONST("NPY_UBYTE", NPY_UBYTE);
ADDCONST("NPY_SHORT", NPY_SHORT);
ADDCONST("NPY_USHORT", NPY_USHORT);
ADDCONST("NPY_INT", NPY_INT);
ADDCONST("NPY_UINT", NPY_UINT);
ADDCONST("NPY_INTP", NPY_INTP);
ADDCONST("NPY_UINTP", NPY_UINTP);
ADDCONST("NPY_LONG", NPY_LONG);
ADDCONST("NPY_ULONG", NPY_ULONG);
ADDCONST("NPY_LONGLONG", NPY_LONGLONG);
ADDCONST("NPY_ULONGLONG", NPY_ULONGLONG);
ADDCONST("NPY_FLOAT", NPY_FLOAT);
ADDCONST("NPY_DOUBLE", NPY_DOUBLE);
ADDCONST("NPY_LONGDOUBLE", NPY_LONGDOUBLE);
ADDCONST("NPY_CFLOAT", NPY_CFLOAT);
ADDCONST("NPY_CDOUBLE", NPY_CDOUBLE);
ADDCONST("NPY_CLONGDOUBLE", NPY_CLONGDOUBLE);
ADDCONST("NPY_OBJECT", NPY_OBJECT);
ADDCONST("NPY_STRING", NPY_STRING);
ADDCONST("NPY_UNICODE", NPY_UNICODE);
ADDCONST("NPY_VOID", NPY_VOID);
ADDCONST("NPY_NTYPES", NPY_NTYPES);
ADDCONST("NPY_NOTYPE", NPY_NOTYPE);
ADDCONST("NPY_USERDEF", NPY_USERDEF);
ADDCONST("CONTIGUOUS", NPY_ARRAY_C_CONTIGUOUS);
ADDCONST("FORTRAN", NPY_ARRAY_F_CONTIGUOUS);
ADDCONST("OWNDATA", NPY_ARRAY_OWNDATA);
ADDCONST("FORCECAST", NPY_ARRAY_FORCECAST);
ADDCONST("ENSURECOPY", NPY_ARRAY_ENSURECOPY);
ADDCONST("ENSUREARRAY", NPY_ARRAY_ENSUREARRAY);
ADDCONST("ALIGNED", NPY_ARRAY_ALIGNED);
ADDCONST("WRITEABLE", NPY_ARRAY_WRITEABLE);
ADDCONST("UPDATEIFCOPY", NPY_ARRAY_UPDATEIFCOPY);
ADDCONST("WRITEBACKIFCOPY", NPY_ARRAY_WRITEBACKIFCOPY);
ADDCONST("BEHAVED", NPY_ARRAY_BEHAVED);
ADDCONST("BEHAVED_NS", NPY_ARRAY_BEHAVED_NS);
ADDCONST("CARRAY", NPY_ARRAY_CARRAY);
ADDCONST("FARRAY", NPY_ARRAY_FARRAY);
ADDCONST("CARRAY_RO", NPY_ARRAY_CARRAY_RO);
ADDCONST("FARRAY_RO", NPY_ARRAY_FARRAY_RO);
ADDCONST("DEFAULT", NPY_ARRAY_DEFAULT);
ADDCONST("UPDATE_ALL", NPY_ARRAY_UPDATE_ALL);
#undef ADDCONST(
if (PyErr_Occurred())
Py_FatalError("can't initialize module wrap");
#ifdef F2PY_REPORT_ATEXIT
on_exit(f2py_report_on_exit,(void*)"array_from_pyobj.wrap.call");
#endif
return m;
}
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1 @@
dict(real=dict(rk="double"))

View file

@ -0,0 +1,34 @@
subroutine sum(x, res)
implicit none
real, intent(in) :: x(:)
real, intent(out) :: res
integer :: i
!print *, "sum: size(x) = ", size(x)
res = 0.0
do i = 1, size(x)
res = res + x(i)
enddo
end subroutine sum
function fsum(x) result (res)
implicit none
real, intent(in) :: x(:)
real :: res
integer :: i
!print *, "fsum: size(x) = ", size(x)
res = 0.0
do i = 1, size(x)
res = res + x(i)
enddo
end function fsum

View file

@ -0,0 +1,41 @@
module mod
contains
subroutine sum(x, res)
implicit none
real, intent(in) :: x(:)
real, intent(out) :: res
integer :: i
!print *, "sum: size(x) = ", size(x)
res = 0.0
do i = 1, size(x)
res = res + x(i)
enddo
end subroutine sum
function fsum(x) result (res)
implicit none
real, intent(in) :: x(:)
real :: res
integer :: i
!print *, "fsum: size(x) = ", size(x)
res = 0.0
do i = 1, size(x)
res = res + x(i)
enddo
end function fsum
end module mod

View file

@ -0,0 +1,19 @@
subroutine sum_with_use(x, res)
use precision
implicit none
real(kind=rk), intent(in) :: x(:)
real(kind=rk), intent(out) :: res
integer :: i
!print *, "size(x) = ", size(x)
res = 0.0
do i = 1, size(x)
res = res + x(i)
enddo
end subroutine

View file

@ -0,0 +1,4 @@
module precision
integer, parameter :: rk = selected_real_kind(8)
integer, parameter :: ik = selected_real_kind(4)
end module

View file

@ -0,0 +1,11 @@
SUBROUTINE INITCB
DOUBLE PRECISION LONG
CHARACTER STRING
INTEGER OK
COMMON /BLOCK/ LONG, STRING, OK
LONG = 1.0
STRING = '2'
OK = 3
RETURN
END

View file

@ -0,0 +1,20 @@
subroutine selectedrealkind(p, r, res)
implicit none
integer, intent(in) :: p, r
!f2py integer :: r=0
integer, intent(out) :: res
res = selected_real_kind(p, r)
end subroutine
subroutine selectedintkind(p, res)
implicit none
integer, intent(in) :: p
integer, intent(out) :: res
res = selected_int_kind(p)
end subroutine

View file

@ -0,0 +1,5 @@
subroutine bar11(a)
cf2py intent(out) a
integer a
a = 11
end

View file

@ -0,0 +1,8 @@
module foo_fixed
contains
subroutine bar12(a)
!f2py intent(out) a
integer a
a = 12
end subroutine bar12
end module foo_fixed

View file

@ -0,0 +1,8 @@
module foo_free
contains
subroutine bar13(a)
!f2py intent(out) a
integer a
a = 13
end subroutine bar13
end module foo_free

View file

@ -0,0 +1,57 @@
! Check that parameters are correct intercepted.
! Constants with comma separations are commonly
! used, for instance Pi = 3._dp
subroutine foo(x)
implicit none
integer, parameter :: sp = selected_real_kind(6)
integer, parameter :: dp = selected_real_kind(15)
integer, parameter :: ii = selected_int_kind(9)
integer, parameter :: il = selected_int_kind(18)
real(dp), intent(inout) :: x
dimension x(3)
real(sp), parameter :: three_s = 3._sp
real(dp), parameter :: three_d = 3._dp
integer(ii), parameter :: three_i = 3_ii
integer(il), parameter :: three_l = 3_il
x(1) = x(1) + x(2) * three_s * three_i + x(3) * three_d * three_l
x(2) = x(2) * three_s
x(3) = x(3) * three_l
return
end subroutine
subroutine foo_no(x)
implicit none
integer, parameter :: sp = selected_real_kind(6)
integer, parameter :: dp = selected_real_kind(15)
integer, parameter :: ii = selected_int_kind(9)
integer, parameter :: il = selected_int_kind(18)
real(dp), intent(inout) :: x
dimension x(3)
real(sp), parameter :: three_s = 3.
real(dp), parameter :: three_d = 3.
integer(ii), parameter :: three_i = 3
integer(il), parameter :: three_l = 3
x(1) = x(1) + x(2) * three_s * three_i + x(3) * three_d * three_l
x(2) = x(2) * three_s
x(3) = x(3) * three_l
return
end subroutine
subroutine foo_sum(x)
implicit none
integer, parameter :: sp = selected_real_kind(6)
integer, parameter :: dp = selected_real_kind(15)
integer, parameter :: ii = selected_int_kind(9)
integer, parameter :: il = selected_int_kind(18)
real(dp), intent(inout) :: x
dimension x(3)
real(sp), parameter :: three_s = 2._sp + 1._sp
real(dp), parameter :: three_d = 1._dp + 2._dp
integer(ii), parameter :: three_i = 2_ii + 1_ii
integer(il), parameter :: three_l = 1_il + 2_il
x(1) = x(1) + x(2) * three_s * three_i + x(3) * three_d * three_l
x(2) = x(2) * three_s
x(3) = x(3) * three_l
return
end subroutine

View file

@ -0,0 +1,15 @@
! Check that parameters are correct intercepted.
! Constants with comma separations are commonly
! used, for instance Pi = 3._dp
subroutine foo_compound_int(x)
implicit none
integer, parameter :: ii = selected_int_kind(9)
integer(ii), intent(inout) :: x
dimension x(3)
integer(ii), parameter :: three = 3_ii
integer(ii), parameter :: two = 2_ii
integer(ii), parameter :: six = three * 1_ii * two
x(1) = x(1) + x(2) + x(3) * six
return
end subroutine

View file

@ -0,0 +1,22 @@
! Check that parameters are correct intercepted.
! Constants with comma separations are commonly
! used, for instance Pi = 3._dp
subroutine foo_int(x)
implicit none
integer, parameter :: ii = selected_int_kind(9)
integer(ii), intent(inout) :: x
dimension x(3)
integer(ii), parameter :: three = 3_ii
x(1) = x(1) + x(2) + x(3) * three
return
end subroutine
subroutine foo_long(x)
implicit none
integer, parameter :: ii = selected_int_kind(18)
integer(ii), intent(inout) :: x
dimension x(3)
integer(ii), parameter :: three = 3_ii
x(1) = x(1) + x(2) + x(3) * three
return
end subroutine

View file

@ -0,0 +1,23 @@
! Check that parameters are correct intercepted.
! Specifically that types of constants without
! compound kind specs are correctly inferred
! adapted Gibbs iteration code from pymc
! for this test case
subroutine foo_non_compound_int(x)
implicit none
integer, parameter :: ii = selected_int_kind(9)
integer(ii) maxiterates
parameter (maxiterates=2)
integer(ii) maxseries
parameter (maxseries=2)
integer(ii) wasize
parameter (wasize=maxiterates*maxseries)
integer(ii), intent(inout) :: x
dimension x(wasize)
x(1) = x(1) + x(2) + x(3) + x(4) * wasize
return
end subroutine

View file

@ -0,0 +1,23 @@
! Check that parameters are correct intercepted.
! Constants with comma separations are commonly
! used, for instance Pi = 3._dp
subroutine foo_single(x)
implicit none
integer, parameter :: rp = selected_real_kind(6)
real(rp), intent(inout) :: x
dimension x(3)
real(rp), parameter :: three = 3._rp
x(1) = x(1) + x(2) + x(3) * three
return
end subroutine
subroutine foo_double(x)
implicit none
integer, parameter :: rp = selected_real_kind(15)
real(rp), intent(inout) :: x
dimension x(3)
real(rp), parameter :: three = 3._rp
x(1) = x(1) + x(2) + x(3) * three
return
end subroutine

View file

@ -0,0 +1,9 @@
! Check that intent(in out) translates as intent(inout).
! The separation seems to be a common usage.
subroutine foo(x)
implicit none
real(4), intent(in out) :: x
dimension x(3)
x(1) = x(1) + x(2) + x(3)
return
end

View file

@ -0,0 +1,44 @@
subroutine foo(a, n, m, b)
implicit none
real, intent(in) :: a(n, m)
integer, intent(in) :: n, m
real, intent(out) :: b(size(a, 1))
integer :: i
do i = 1, size(b)
b(i) = sum(a(i,:))
enddo
end subroutine
subroutine trans(x,y)
implicit none
real, intent(in), dimension(:,:) :: x
real, intent(out), dimension( size(x,2), size(x,1) ) :: y
integer :: N, M, i, j
N = size(x,1)
M = size(x,2)
DO i=1,N
do j=1,M
y(j,i) = x(i,j)
END DO
END DO
end subroutine trans
subroutine flatten(x,y)
implicit none
real, intent(in), dimension(:,:) :: x
real, intent(out), dimension( size(x) ) :: y
integer :: N, M, i, j, k
N = size(x,1)
M = size(x,2)
k = 1
DO i=1,N
do j=1,M
y(k) = x(i,j)
k = k + 1
END DO
END DO
end subroutine flatten

View file

@ -0,0 +1,29 @@
MODULE char_test
CONTAINS
SUBROUTINE change_strings(strings, n_strs, out_strings)
IMPLICIT NONE
! Inputs
INTEGER, INTENT(IN) :: n_strs
CHARACTER, INTENT(IN), DIMENSION(2,n_strs) :: strings
CHARACTER, INTENT(OUT), DIMENSION(2,n_strs) :: out_strings
!f2py INTEGER, INTENT(IN) :: n_strs
!f2py CHARACTER, INTENT(IN), DIMENSION(2,n_strs) :: strings
!f2py CHARACTER, INTENT(OUT), DIMENSION(2,n_strs) :: strings
! Misc.
INTEGER*4 :: j
DO j=1, n_strs
out_strings(1,j) = strings(1,j)
out_strings(2,j) = 'A'
END DO
END SUBROUTINE change_strings
END MODULE char_test

View file

@ -0,0 +1,579 @@
import os
import sys
import copy
import pytest
from numpy import (
array, alltrue, ndarray, zeros, dtype, intp, clongdouble
)
from numpy.testing import assert_, assert_equal
from numpy.core.multiarray import typeinfo
from . import util
wrap = None
def setup_module():
"""
Build the required testing extension module
"""
global wrap
# Check compiler availability first
if not util.has_c_compiler():
pytest.skip("No C compiler available")
if wrap is None:
config_code = """
config.add_extension('test_array_from_pyobj_ext',
sources=['wrapmodule.c', 'fortranobject.c'],
define_macros=[])
"""
d = os.path.dirname(__file__)
src = [os.path.join(d, 'src', 'array_from_pyobj', 'wrapmodule.c'),
os.path.join(d, '..', 'src', 'fortranobject.c'),
os.path.join(d, '..', 'src', 'fortranobject.h')]
wrap = util.build_module_distutils(src, config_code,
'test_array_from_pyobj_ext')
def flags_info(arr):
flags = wrap.array_attrs(arr)[6]
return flags2names(flags)
def flags2names(flags):
info = []
for flagname in ['CONTIGUOUS', 'FORTRAN', 'OWNDATA', 'ENSURECOPY',
'ENSUREARRAY', 'ALIGNED', 'NOTSWAPPED', 'WRITEABLE',
'WRITEBACKIFCOPY', 'UPDATEIFCOPY', 'BEHAVED', 'BEHAVED_RO',
'CARRAY', 'FARRAY'
]:
if abs(flags) & getattr(wrap, flagname, 0):
info.append(flagname)
return info
class Intent:
def __init__(self, intent_list=[]):
self.intent_list = intent_list[:]
flags = 0
for i in intent_list:
if i == 'optional':
flags |= wrap.F2PY_OPTIONAL
else:
flags |= getattr(wrap, 'F2PY_INTENT_' + i.upper())
self.flags = flags
def __getattr__(self, name):
name = name.lower()
if name == 'in_':
name = 'in'
return self.__class__(self.intent_list + [name])
def __str__(self):
return 'intent(%s)' % (','.join(self.intent_list))
def __repr__(self):
return 'Intent(%r)' % (self.intent_list)
def is_intent(self, *names):
for name in names:
if name not in self.intent_list:
return False
return True
def is_intent_exact(self, *names):
return len(self.intent_list) == len(names) and self.is_intent(*names)
intent = Intent()
_type_names = ['BOOL', 'BYTE', 'UBYTE', 'SHORT', 'USHORT', 'INT', 'UINT',
'LONG', 'ULONG', 'LONGLONG', 'ULONGLONG',
'FLOAT', 'DOUBLE', 'CFLOAT']
_cast_dict = {'BOOL': ['BOOL']}
_cast_dict['BYTE'] = _cast_dict['BOOL'] + ['BYTE']
_cast_dict['UBYTE'] = _cast_dict['BOOL'] + ['UBYTE']
_cast_dict['BYTE'] = ['BYTE']
_cast_dict['UBYTE'] = ['UBYTE']
_cast_dict['SHORT'] = _cast_dict['BYTE'] + ['UBYTE', 'SHORT']
_cast_dict['USHORT'] = _cast_dict['UBYTE'] + ['BYTE', 'USHORT']
_cast_dict['INT'] = _cast_dict['SHORT'] + ['USHORT', 'INT']
_cast_dict['UINT'] = _cast_dict['USHORT'] + ['SHORT', 'UINT']
_cast_dict['LONG'] = _cast_dict['INT'] + ['LONG']
_cast_dict['ULONG'] = _cast_dict['UINT'] + ['ULONG']
_cast_dict['LONGLONG'] = _cast_dict['LONG'] + ['LONGLONG']
_cast_dict['ULONGLONG'] = _cast_dict['ULONG'] + ['ULONGLONG']
_cast_dict['FLOAT'] = _cast_dict['SHORT'] + ['USHORT', 'FLOAT']
_cast_dict['DOUBLE'] = _cast_dict['INT'] + ['UINT', 'FLOAT', 'DOUBLE']
_cast_dict['CFLOAT'] = _cast_dict['FLOAT'] + ['CFLOAT']
# 32 bit system malloc typically does not provide the alignment required by
# 16 byte long double types this means the inout intent cannot be satisfied
# and several tests fail as the alignment flag can be randomly true or fals
# when numpy gains an aligned allocator the tests could be enabled again
if ((intp().dtype.itemsize != 4 or clongdouble().dtype.alignment <= 8) and
sys.platform != 'win32'):
_type_names.extend(['LONGDOUBLE', 'CDOUBLE', 'CLONGDOUBLE'])
_cast_dict['LONGDOUBLE'] = _cast_dict['LONG'] + \
['ULONG', 'FLOAT', 'DOUBLE', 'LONGDOUBLE']
_cast_dict['CLONGDOUBLE'] = _cast_dict['LONGDOUBLE'] + \
['CFLOAT', 'CDOUBLE', 'CLONGDOUBLE']
_cast_dict['CDOUBLE'] = _cast_dict['DOUBLE'] + ['CFLOAT', 'CDOUBLE']
class Type:
_type_cache = {}
def __new__(cls, name):
if isinstance(name, dtype):
dtype0 = name
name = None
for n, i in typeinfo.items():
if not isinstance(i, type) and dtype0.type is i.type:
name = n
break
obj = cls._type_cache.get(name.upper(), None)
if obj is not None:
return obj
obj = object.__new__(cls)
obj._init(name)
cls._type_cache[name.upper()] = obj
return obj
def _init(self, name):
self.NAME = name.upper()
info = typeinfo[self.NAME]
self.type_num = getattr(wrap, 'NPY_' + self.NAME)
assert_equal(self.type_num, info.num)
self.dtype = info.type
self.elsize = info.bits / 8
self.dtypechar = info.char
def cast_types(self):
return [self.__class__(_m) for _m in _cast_dict[self.NAME]]
def all_types(self):
return [self.__class__(_m) for _m in _type_names]
def smaller_types(self):
bits = typeinfo[self.NAME].alignment
types = []
for name in _type_names:
if typeinfo[name].alignment < bits:
types.append(Type(name))
return types
def equal_types(self):
bits = typeinfo[self.NAME].alignment
types = []
for name in _type_names:
if name == self.NAME:
continue
if typeinfo[name].alignment == bits:
types.append(Type(name))
return types
def larger_types(self):
bits = typeinfo[self.NAME].alignment
types = []
for name in _type_names:
if typeinfo[name].alignment > bits:
types.append(Type(name))
return types
class Array:
def __init__(self, typ, dims, intent, obj):
self.type = typ
self.dims = dims
self.intent = intent
self.obj_copy = copy.deepcopy(obj)
self.obj = obj
# arr.dtypechar may be different from typ.dtypechar
self.arr = wrap.call(typ.type_num, dims, intent.flags, obj)
assert_(isinstance(self.arr, ndarray), repr(type(self.arr)))
self.arr_attr = wrap.array_attrs(self.arr)
if len(dims) > 1:
if self.intent.is_intent('c'):
assert_(intent.flags & wrap.F2PY_INTENT_C)
assert_(not self.arr.flags['FORTRAN'],
repr((self.arr.flags, getattr(obj, 'flags', None))))
assert_(self.arr.flags['CONTIGUOUS'])
assert_(not self.arr_attr[6] & wrap.FORTRAN)
else:
assert_(not intent.flags & wrap.F2PY_INTENT_C)
assert_(self.arr.flags['FORTRAN'])
assert_(not self.arr.flags['CONTIGUOUS'])
assert_(self.arr_attr[6] & wrap.FORTRAN)
if obj is None:
self.pyarr = None
self.pyarr_attr = None
return
if intent.is_intent('cache'):
assert_(isinstance(obj, ndarray), repr(type(obj)))
self.pyarr = array(obj).reshape(*dims).copy()
else:
self.pyarr = array(array(obj, dtype=typ.dtypechar).reshape(*dims),
order=self.intent.is_intent('c') and 'C' or 'F')
assert_(self.pyarr.dtype == typ,
repr((self.pyarr.dtype, typ)))
assert_(self.pyarr.flags['OWNDATA'], (obj, intent))
self.pyarr_attr = wrap.array_attrs(self.pyarr)
if len(dims) > 1:
if self.intent.is_intent('c'):
assert_(not self.pyarr.flags['FORTRAN'])
assert_(self.pyarr.flags['CONTIGUOUS'])
assert_(not self.pyarr_attr[6] & wrap.FORTRAN)
else:
assert_(self.pyarr.flags['FORTRAN'])
assert_(not self.pyarr.flags['CONTIGUOUS'])
assert_(self.pyarr_attr[6] & wrap.FORTRAN)
assert_(self.arr_attr[1] == self.pyarr_attr[1]) # nd
assert_(self.arr_attr[2] == self.pyarr_attr[2]) # dimensions
if self.arr_attr[1] <= 1:
assert_(self.arr_attr[3] == self.pyarr_attr[3],
repr((self.arr_attr[3], self.pyarr_attr[3],
self.arr.tobytes(), self.pyarr.tobytes()))) # strides
assert_(self.arr_attr[5][-2:] == self.pyarr_attr[5][-2:],
repr((self.arr_attr[5], self.pyarr_attr[5]))) # descr
assert_(self.arr_attr[6] == self.pyarr_attr[6],
repr((self.arr_attr[6], self.pyarr_attr[6],
flags2names(0 * self.arr_attr[6] - self.pyarr_attr[6]),
flags2names(self.arr_attr[6]), intent))) # flags
if intent.is_intent('cache'):
assert_(self.arr_attr[5][3] >= self.type.elsize,
repr((self.arr_attr[5][3], self.type.elsize)))
else:
assert_(self.arr_attr[5][3] == self.type.elsize,
repr((self.arr_attr[5][3], self.type.elsize)))
assert_(self.arr_equal(self.pyarr, self.arr))
if isinstance(self.obj, ndarray):
if typ.elsize == Type(obj.dtype).elsize:
if not intent.is_intent('copy') and self.arr_attr[1] <= 1:
assert_(self.has_shared_memory())
def arr_equal(self, arr1, arr2):
if arr1.shape != arr2.shape:
return False
s = arr1 == arr2
return alltrue(s.flatten())
def __str__(self):
return str(self.arr)
def has_shared_memory(self):
"""Check that created array shares data with input array.
"""
if self.obj is self.arr:
return True
if not isinstance(self.obj, ndarray):
return False
obj_attr = wrap.array_attrs(self.obj)
return obj_attr[0] == self.arr_attr[0]
class TestIntent:
def test_in_out(self):
assert_equal(str(intent.in_.out), 'intent(in,out)')
assert_(intent.in_.c.is_intent('c'))
assert_(not intent.in_.c.is_intent_exact('c'))
assert_(intent.in_.c.is_intent_exact('c', 'in'))
assert_(intent.in_.c.is_intent_exact('in', 'c'))
assert_(not intent.in_.is_intent('c'))
class TestSharedMemory:
num2seq = [1, 2]
num23seq = [[1, 2, 3], [4, 5, 6]]
@pytest.fixture(autouse=True, scope='class', params=_type_names)
def setup_type(self, request):
request.cls.type = Type(request.param)
request.cls.array = lambda self, dims, intent, obj: \
Array(Type(request.param), dims, intent, obj)
def test_in_from_2seq(self):
a = self.array([2], intent.in_, self.num2seq)
assert_(not a.has_shared_memory())
def test_in_from_2casttype(self):
for t in self.type.cast_types():
obj = array(self.num2seq, dtype=t.dtype)
a = self.array([len(self.num2seq)], intent.in_, obj)
if t.elsize == self.type.elsize:
assert_(
a.has_shared_memory(), repr((self.type.dtype, t.dtype)))
else:
assert_(not a.has_shared_memory(), repr(t.dtype))
def test_inout_2seq(self):
obj = array(self.num2seq, dtype=self.type.dtype)
a = self.array([len(self.num2seq)], intent.inout, obj)
assert_(a.has_shared_memory())
try:
a = self.array([2], intent.in_.inout, self.num2seq)
except TypeError as msg:
if not str(msg).startswith('failed to initialize intent'
'(inout|inplace|cache) array'):
raise
else:
raise SystemError('intent(inout) should have failed on sequence')
def test_f_inout_23seq(self):
obj = array(self.num23seq, dtype=self.type.dtype, order='F')
shape = (len(self.num23seq), len(self.num23seq[0]))
a = self.array(shape, intent.in_.inout, obj)
assert_(a.has_shared_memory())
obj = array(self.num23seq, dtype=self.type.dtype, order='C')
shape = (len(self.num23seq), len(self.num23seq[0]))
try:
a = self.array(shape, intent.in_.inout, obj)
except ValueError as msg:
if not str(msg).startswith('failed to initialize intent'
'(inout) array'):
raise
else:
raise SystemError(
'intent(inout) should have failed on improper array')
def test_c_inout_23seq(self):
obj = array(self.num23seq, dtype=self.type.dtype)
shape = (len(self.num23seq), len(self.num23seq[0]))
a = self.array(shape, intent.in_.c.inout, obj)
assert_(a.has_shared_memory())
def test_in_copy_from_2casttype(self):
for t in self.type.cast_types():
obj = array(self.num2seq, dtype=t.dtype)
a = self.array([len(self.num2seq)], intent.in_.copy, obj)
assert_(not a.has_shared_memory(), repr(t.dtype))
def test_c_in_from_23seq(self):
a = self.array([len(self.num23seq), len(self.num23seq[0])],
intent.in_, self.num23seq)
assert_(not a.has_shared_memory())
def test_in_from_23casttype(self):
for t in self.type.cast_types():
obj = array(self.num23seq, dtype=t.dtype)
a = self.array([len(self.num23seq), len(self.num23seq[0])],
intent.in_, obj)
assert_(not a.has_shared_memory(), repr(t.dtype))
def test_f_in_from_23casttype(self):
for t in self.type.cast_types():
obj = array(self.num23seq, dtype=t.dtype, order='F')
a = self.array([len(self.num23seq), len(self.num23seq[0])],
intent.in_, obj)
if t.elsize == self.type.elsize:
assert_(a.has_shared_memory(), repr(t.dtype))
else:
assert_(not a.has_shared_memory(), repr(t.dtype))
def test_c_in_from_23casttype(self):
for t in self.type.cast_types():
obj = array(self.num23seq, dtype=t.dtype)
a = self.array([len(self.num23seq), len(self.num23seq[0])],
intent.in_.c, obj)
if t.elsize == self.type.elsize:
assert_(a.has_shared_memory(), repr(t.dtype))
else:
assert_(not a.has_shared_memory(), repr(t.dtype))
def test_f_copy_in_from_23casttype(self):
for t in self.type.cast_types():
obj = array(self.num23seq, dtype=t.dtype, order='F')
a = self.array([len(self.num23seq), len(self.num23seq[0])],
intent.in_.copy, obj)
assert_(not a.has_shared_memory(), repr(t.dtype))
def test_c_copy_in_from_23casttype(self):
for t in self.type.cast_types():
obj = array(self.num23seq, dtype=t.dtype)
a = self.array([len(self.num23seq), len(self.num23seq[0])],
intent.in_.c.copy, obj)
assert_(not a.has_shared_memory(), repr(t.dtype))
def test_in_cache_from_2casttype(self):
for t in self.type.all_types():
if t.elsize != self.type.elsize:
continue
obj = array(self.num2seq, dtype=t.dtype)
shape = (len(self.num2seq),)
a = self.array(shape, intent.in_.c.cache, obj)
assert_(a.has_shared_memory(), repr(t.dtype))
a = self.array(shape, intent.in_.cache, obj)
assert_(a.has_shared_memory(), repr(t.dtype))
obj = array(self.num2seq, dtype=t.dtype, order='F')
a = self.array(shape, intent.in_.c.cache, obj)
assert_(a.has_shared_memory(), repr(t.dtype))
a = self.array(shape, intent.in_.cache, obj)
assert_(a.has_shared_memory(), repr(t.dtype))
try:
a = self.array(shape, intent.in_.cache, obj[::-1])
except ValueError as msg:
if not str(msg).startswith('failed to initialize'
' intent(cache) array'):
raise
else:
raise SystemError(
'intent(cache) should have failed on multisegmented array')
def test_in_cache_from_2casttype_failure(self):
for t in self.type.all_types():
if t.elsize >= self.type.elsize:
continue
obj = array(self.num2seq, dtype=t.dtype)
shape = (len(self.num2seq),)
try:
self.array(shape, intent.in_.cache, obj) # Should succeed
except ValueError as msg:
if not str(msg).startswith('failed to initialize'
' intent(cache) array'):
raise
else:
raise SystemError(
'intent(cache) should have failed on smaller array')
def test_cache_hidden(self):
shape = (2,)
a = self.array(shape, intent.cache.hide, None)
assert_(a.arr.shape == shape)
shape = (2, 3)
a = self.array(shape, intent.cache.hide, None)
assert_(a.arr.shape == shape)
shape = (-1, 3)
try:
a = self.array(shape, intent.cache.hide, None)
except ValueError as msg:
if not str(msg).startswith('failed to create intent'
'(cache|hide)|optional array'):
raise
else:
raise SystemError(
'intent(cache) should have failed on undefined dimensions')
def test_hidden(self):
shape = (2,)
a = self.array(shape, intent.hide, None)
assert_(a.arr.shape == shape)
assert_(a.arr_equal(a.arr, zeros(shape, dtype=self.type.dtype)))
shape = (2, 3)
a = self.array(shape, intent.hide, None)
assert_(a.arr.shape == shape)
assert_(a.arr_equal(a.arr, zeros(shape, dtype=self.type.dtype)))
assert_(a.arr.flags['FORTRAN'] and not a.arr.flags['CONTIGUOUS'])
shape = (2, 3)
a = self.array(shape, intent.c.hide, None)
assert_(a.arr.shape == shape)
assert_(a.arr_equal(a.arr, zeros(shape, dtype=self.type.dtype)))
assert_(not a.arr.flags['FORTRAN'] and a.arr.flags['CONTIGUOUS'])
shape = (-1, 3)
try:
a = self.array(shape, intent.hide, None)
except ValueError as msg:
if not str(msg).startswith('failed to create intent'
'(cache|hide)|optional array'):
raise
else:
raise SystemError('intent(hide) should have failed'
' on undefined dimensions')
def test_optional_none(self):
shape = (2,)
a = self.array(shape, intent.optional, None)
assert_(a.arr.shape == shape)
assert_(a.arr_equal(a.arr, zeros(shape, dtype=self.type.dtype)))
shape = (2, 3)
a = self.array(shape, intent.optional, None)
assert_(a.arr.shape == shape)
assert_(a.arr_equal(a.arr, zeros(shape, dtype=self.type.dtype)))
assert_(a.arr.flags['FORTRAN'] and not a.arr.flags['CONTIGUOUS'])
shape = (2, 3)
a = self.array(shape, intent.c.optional, None)
assert_(a.arr.shape == shape)
assert_(a.arr_equal(a.arr, zeros(shape, dtype=self.type.dtype)))
assert_(not a.arr.flags['FORTRAN'] and a.arr.flags['CONTIGUOUS'])
def test_optional_from_2seq(self):
obj = self.num2seq
shape = (len(obj),)
a = self.array(shape, intent.optional, obj)
assert_(a.arr.shape == shape)
assert_(not a.has_shared_memory())
def test_optional_from_23seq(self):
obj = self.num23seq
shape = (len(obj), len(obj[0]))
a = self.array(shape, intent.optional, obj)
assert_(a.arr.shape == shape)
assert_(not a.has_shared_memory())
a = self.array(shape, intent.optional.c, obj)
assert_(a.arr.shape == shape)
assert_(not a.has_shared_memory())
def test_inplace(self):
obj = array(self.num23seq, dtype=self.type.dtype)
assert_(not obj.flags['FORTRAN'] and obj.flags['CONTIGUOUS'])
shape = obj.shape
a = self.array(shape, intent.inplace, obj)
assert_(obj[1][2] == a.arr[1][2], repr((obj, a.arr)))
a.arr[1][2] = 54
assert_(obj[1][2] == a.arr[1][2] ==
array(54, dtype=self.type.dtype), repr((obj, a.arr)))
assert_(a.arr is obj)
assert_(obj.flags['FORTRAN']) # obj attributes are changed inplace!
assert_(not obj.flags['CONTIGUOUS'])
def test_inplace_from_casttype(self):
for t in self.type.cast_types():
if t is self.type:
continue
obj = array(self.num23seq, dtype=t.dtype)
assert_(obj.dtype.type == t.dtype)
assert_(obj.dtype.type is not self.type.dtype)
assert_(not obj.flags['FORTRAN'] and obj.flags['CONTIGUOUS'])
shape = obj.shape
a = self.array(shape, intent.inplace, obj)
assert_(obj[1][2] == a.arr[1][2], repr((obj, a.arr)))
a.arr[1][2] = 54
assert_(obj[1][2] == a.arr[1][2] ==
array(54, dtype=self.type.dtype), repr((obj, a.arr)))
assert_(a.arr is obj)
assert_(obj.flags['FORTRAN']) # obj attributes changed inplace!
assert_(not obj.flags['CONTIGUOUS'])
assert_(obj.dtype.type is self.type.dtype) # obj changed inplace!

View file

@ -0,0 +1,53 @@
import os
import pytest
import tempfile
from numpy.testing import assert_
from . import util
def _path(*a):
return os.path.join(*((os.path.dirname(__file__),) + a))
class TestAssumedShapeSumExample(util.F2PyTest):
sources = [_path('src', 'assumed_shape', 'foo_free.f90'),
_path('src', 'assumed_shape', 'foo_use.f90'),
_path('src', 'assumed_shape', 'precision.f90'),
_path('src', 'assumed_shape', 'foo_mod.f90'),
_path('src', 'assumed_shape', '.f2py_f2cmap'),
]
@pytest.mark.slow
def test_all(self):
r = self.module.fsum([1, 2])
assert_(r == 3, repr(r))
r = self.module.sum([1, 2])
assert_(r == 3, repr(r))
r = self.module.sum_with_use([1, 2])
assert_(r == 3, repr(r))
r = self.module.mod.sum([1, 2])
assert_(r == 3, repr(r))
r = self.module.mod.fsum([1, 2])
assert_(r == 3, repr(r))
class TestF2cmapOption(TestAssumedShapeSumExample):
def setup(self):
# Use a custom file name for .f2py_f2cmap
self.sources = list(self.sources)
f2cmap_src = self.sources.pop(-1)
self.f2cmap_file = tempfile.NamedTemporaryFile(delete=False)
with open(f2cmap_src, 'rb') as f:
self.f2cmap_file.write(f.read())
self.f2cmap_file.close()
self.sources.append(self.f2cmap_file.name)
self.options = ["--f2cmap", self.f2cmap_file.name]
super(TestF2cmapOption, self).setup()
def teardown(self):
os.unlink(self.f2cmap_file.name)

View file

@ -0,0 +1,23 @@
import sys
import pytest
from . import util
from numpy.testing import assert_equal, IS_PYPY
class TestBlockDocString(util.F2PyTest):
code = """
SUBROUTINE FOO()
INTEGER BAR(2, 3)
COMMON /BLOCK/ BAR
RETURN
END
"""
@pytest.mark.skipif(sys.platform=='win32',
reason='Fails with MinGW64 Gfortran (Issue #9673)')
@pytest.mark.xfail(IS_PYPY,
reason="PyPy cannot modify tp_doc after PyType_Ready")
def test_block_docstring(self):
expected = "'i'-array(2,3)\n"
assert_equal(self.module.block.__doc__, expected)

View file

@ -0,0 +1,163 @@
import math
import textwrap
import sys
import pytest
import numpy as np
from numpy.testing import assert_, assert_equal, IS_PYPY
from . import util
class TestF77Callback(util.F2PyTest):
code = """
subroutine t(fun,a)
integer a
cf2py intent(out) a
external fun
call fun(a)
end
subroutine func(a)
cf2py intent(in,out) a
integer a
a = a + 11
end
subroutine func0(a)
cf2py intent(out) a
integer a
a = 11
end
subroutine t2(a)
cf2py intent(callback) fun
integer a
cf2py intent(out) a
external fun
call fun(a)
end
subroutine string_callback(callback, a)
external callback
double precision callback
double precision a
character*1 r
cf2py intent(out) a
r = 'r'
a = callback(r)
end
subroutine string_callback_array(callback, cu, lencu, a)
external callback
integer callback
integer lencu
character*8 cu(lencu)
integer a
cf2py intent(out) a
a = callback(cu, lencu)
end
"""
@pytest.mark.parametrize('name', 't,t2'.split(','))
def test_all(self, name):
self.check_function(name)
@pytest.mark.xfail(IS_PYPY,
reason="PyPy cannot modify tp_doc after PyType_Ready")
def test_docstring(self):
expected = textwrap.dedent("""\
a = t(fun,[fun_extra_args])
Wrapper for ``t``.
Parameters
----------
fun : call-back function
Other Parameters
----------------
fun_extra_args : input tuple, optional
Default: ()
Returns
-------
a : int
Notes
-----
Call-back functions::
def fun(): return a
Return objects:
a : int
""")
assert_equal(self.module.t.__doc__, expected)
def check_function(self, name):
t = getattr(self.module, name)
r = t(lambda: 4)
assert_(r == 4, repr(r))
r = t(lambda a: 5, fun_extra_args=(6,))
assert_(r == 5, repr(r))
r = t(lambda a: a, fun_extra_args=(6,))
assert_(r == 6, repr(r))
r = t(lambda a: 5 + a, fun_extra_args=(7,))
assert_(r == 12, repr(r))
r = t(lambda a: math.degrees(a), fun_extra_args=(math.pi,))
assert_(r == 180, repr(r))
r = t(math.degrees, fun_extra_args=(math.pi,))
assert_(r == 180, repr(r))
r = t(self.module.func, fun_extra_args=(6,))
assert_(r == 17, repr(r))
r = t(self.module.func0)
assert_(r == 11, repr(r))
r = t(self.module.func0._cpointer)
assert_(r == 11, repr(r))
class A:
def __call__(self):
return 7
def mth(self):
return 9
a = A()
r = t(a)
assert_(r == 7, repr(r))
r = t(a.mth)
assert_(r == 9, repr(r))
@pytest.mark.skipif(sys.platform=='win32',
reason='Fails with MinGW64 Gfortran (Issue #9673)')
def test_string_callback(self):
def callback(code):
if code == 'r':
return 0
else:
return 1
f = getattr(self.module, 'string_callback')
r = f(callback)
assert_(r == 0, repr(r))
@pytest.mark.skipif(sys.platform=='win32',
reason='Fails with MinGW64 Gfortran (Issue #9673)')
def test_string_callback_array(self):
# See gh-10027
cu = np.zeros((1, 8), 'S1')
def callback(cu, lencu):
if cu.shape != (lencu, 8):
return 1
if cu.dtype != 'S1':
return 2
if not np.all(cu == b''):
return 3
return 0
f = getattr(self.module, 'string_callback_array')
res = f(callback, cu, len(cu))
assert_(res == 0, repr(res))

View file

@ -0,0 +1,25 @@
import os
import sys
import pytest
import numpy as np
from . import util
from numpy.testing import assert_array_equal
def _path(*a):
return os.path.join(*((os.path.dirname(__file__),) + a))
class TestCommonBlock(util.F2PyTest):
sources = [_path('src', 'common', 'block.f')]
@pytest.mark.skipif(sys.platform=='win32',
reason='Fails with MinGW64 Gfortran (Issue #9673)')
def test_common_block(self):
self.module.initcb()
assert_array_equal(self.module.block.long_bn,
np.array(1.0, dtype=np.float64))
assert_array_equal(self.module.block.string_bn,
np.array('2', dtype='|S1'))
assert_array_equal(self.module.block.ok,
np.array(3, dtype=np.int32))

View file

@ -0,0 +1,125 @@
"""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)

View file

@ -0,0 +1,88 @@
import numpy as np
from numpy.testing import assert_array_equal
from . import util
from numpy.f2py import crackfortran
import tempfile
import textwrap
class TestNoSpace(util.F2PyTest):
# issue gh-15035: add handling for endsubroutine, endfunction with no space
# between "end" and the block name
code = """
subroutine subb(k)
real(8), intent(inout) :: k(:)
k=k+1
endsubroutine
subroutine subc(w,k)
real(8), intent(in) :: w(:)
real(8), intent(out) :: k(size(w))
k=w+1
endsubroutine
function t0(value)
character value
character t0
t0 = value
endfunction
"""
def test_module(self):
k = np.array([1, 2, 3], dtype=np.float64)
w = np.array([1, 2, 3], dtype=np.float64)
self.module.subb(k)
assert_array_equal(k, w + 1)
self.module.subc([w, k])
assert_array_equal(k, w + 1)
assert self.module.t0(23) == b'2'
class TestPublicPrivate():
def test_defaultPrivate(self, tmp_path):
f_path = tmp_path / "mod.f90"
with f_path.open('w') as ff:
ff.write(textwrap.dedent("""\
module foo
private
integer :: a
public :: setA
integer :: b
contains
subroutine setA(v)
integer, intent(in) :: v
a = v
end subroutine setA
end module foo
"""))
mod = crackfortran.crackfortran([str(f_path)])
assert len(mod) == 1
mod = mod[0]
assert 'private' in mod['vars']['a']['attrspec']
assert 'public' not in mod['vars']['a']['attrspec']
assert 'private' in mod['vars']['b']['attrspec']
assert 'public' not in mod['vars']['b']['attrspec']
assert 'private' not in mod['vars']['seta']['attrspec']
assert 'public' in mod['vars']['seta']['attrspec']
def test_defaultPublic(self, tmp_path):
f_path = tmp_path / "mod.f90"
with f_path.open('w') as ff:
ff.write(textwrap.dedent("""\
module foo
public
integer, private :: a
public :: setA
contains
subroutine setA(v)
integer, intent(in) :: v
a = v
end subroutine setA
end module foo
"""))
mod = crackfortran.crackfortran([str(f_path)])
assert len(mod) == 1
mod = mod[0]
assert 'private' in mod['vars']['a']['attrspec']
assert 'public' not in mod['vars']['a']['attrspec']
assert 'private' not in mod['vars']['seta']['attrspec']
assert 'public' in mod['vars']['seta']['attrspec']

View file

@ -0,0 +1,32 @@
import os
import pytest
from numpy.testing import assert_
from numpy.f2py.crackfortran import (
_selected_int_kind_func as selected_int_kind,
_selected_real_kind_func as selected_real_kind
)
from . import util
def _path(*a):
return os.path.join(*((os.path.dirname(__file__),) + a))
class TestKind(util.F2PyTest):
sources = [_path('src', 'kind', 'foo.f90')]
@pytest.mark.slow
def test_all(self):
selectedrealkind = self.module.selectedrealkind
selectedintkind = self.module.selectedintkind
for i in range(40):
assert_(selectedintkind(i) in [selected_int_kind(i), -1],
'selectedintkind(%s): expected %r but got %r' %
(i, selected_int_kind(i), selectedintkind(i)))
for i in range(20):
assert_(selectedrealkind(i) in [selected_real_kind(i), -1],
'selectedrealkind(%s): expected %r but got %r' %
(i, selected_real_kind(i), selectedrealkind(i)))

View file

@ -0,0 +1,35 @@
import os
import textwrap
import pytest
from numpy.testing import assert_, assert_equal, IS_PYPY
from . import util
def _path(*a):
return os.path.join(*((os.path.dirname(__file__),) + a))
class TestMixed(util.F2PyTest):
sources = [_path('src', 'mixed', 'foo.f'),
_path('src', 'mixed', 'foo_fixed.f90'),
_path('src', 'mixed', 'foo_free.f90')]
def test_all(self):
assert_(self.module.bar11() == 11)
assert_(self.module.foo_fixed.bar12() == 12)
assert_(self.module.foo_free.bar13() == 13)
@pytest.mark.xfail(IS_PYPY,
reason="PyPy cannot modify tp_doc after PyType_Ready")
def test_docstring(self):
expected = textwrap.dedent("""\
a = bar11()
Wrapper for ``bar11``.
Returns
-------
a : int
""")
assert_equal(self.module.bar11.__doc__, expected)

View file

@ -0,0 +1,116 @@
import os
import pytest
import numpy as np
from numpy.testing import assert_raises, assert_equal
from . import util
def _path(*a):
return os.path.join(*((os.path.dirname(__file__),) + a))
class TestParameters(util.F2PyTest):
# Check that intent(in out) translates as intent(inout)
sources = [_path('src', 'parameter', 'constant_real.f90'),
_path('src', 'parameter', 'constant_integer.f90'),
_path('src', 'parameter', 'constant_both.f90'),
_path('src', 'parameter', 'constant_compound.f90'),
_path('src', 'parameter', 'constant_non_compound.f90'),
]
@pytest.mark.slow
def test_constant_real_single(self):
# non-contiguous should raise error
x = np.arange(6, dtype=np.float32)[::2]
assert_raises(ValueError, self.module.foo_single, x)
# check values with contiguous array
x = np.arange(3, dtype=np.float32)
self.module.foo_single(x)
assert_equal(x, [0 + 1 + 2*3, 1, 2])
@pytest.mark.slow
def test_constant_real_double(self):
# non-contiguous should raise error
x = np.arange(6, dtype=np.float64)[::2]
assert_raises(ValueError, self.module.foo_double, x)
# check values with contiguous array
x = np.arange(3, dtype=np.float64)
self.module.foo_double(x)
assert_equal(x, [0 + 1 + 2*3, 1, 2])
@pytest.mark.slow
def test_constant_compound_int(self):
# non-contiguous should raise error
x = np.arange(6, dtype=np.int32)[::2]
assert_raises(ValueError, self.module.foo_compound_int, x)
# check values with contiguous array
x = np.arange(3, dtype=np.int32)
self.module.foo_compound_int(x)
assert_equal(x, [0 + 1 + 2*6, 1, 2])
@pytest.mark.slow
def test_constant_non_compound_int(self):
# check values
x = np.arange(4, dtype=np.int32)
self.module.foo_non_compound_int(x)
assert_equal(x, [0 + 1 + 2 + 3*4, 1, 2, 3])
@pytest.mark.slow
def test_constant_integer_int(self):
# non-contiguous should raise error
x = np.arange(6, dtype=np.int32)[::2]
assert_raises(ValueError, self.module.foo_int, x)
# check values with contiguous array
x = np.arange(3, dtype=np.int32)
self.module.foo_int(x)
assert_equal(x, [0 + 1 + 2*3, 1, 2])
@pytest.mark.slow
def test_constant_integer_long(self):
# non-contiguous should raise error
x = np.arange(6, dtype=np.int64)[::2]
assert_raises(ValueError, self.module.foo_long, x)
# check values with contiguous array
x = np.arange(3, dtype=np.int64)
self.module.foo_long(x)
assert_equal(x, [0 + 1 + 2*3, 1, 2])
@pytest.mark.slow
def test_constant_both(self):
# non-contiguous should raise error
x = np.arange(6, dtype=np.float64)[::2]
assert_raises(ValueError, self.module.foo, x)
# check values with contiguous array
x = np.arange(3, dtype=np.float64)
self.module.foo(x)
assert_equal(x, [0 + 1*3*3 + 2*3*3, 1*3, 2*3])
@pytest.mark.slow
def test_constant_no(self):
# non-contiguous should raise error
x = np.arange(6, dtype=np.float64)[::2]
assert_raises(ValueError, self.module.foo_no, x)
# check values with contiguous array
x = np.arange(3, dtype=np.float64)
self.module.foo_no(x)
assert_equal(x, [0 + 1*3*3 + 2*3*3, 1*3, 2*3])
@pytest.mark.slow
def test_constant_sum(self):
# non-contiguous should raise error
x = np.arange(6, dtype=np.float64)[::2]
assert_raises(ValueError, self.module.foo_sum, x)
# check values with contiguous array
x = np.arange(3, dtype=np.float64)
self.module.foo_sum(x)
assert_equal(x, [0 + 1*3*3 + 2*3*3, 1*3, 2*3])

View file

@ -0,0 +1,32 @@
"""See https://github.com/numpy/numpy/pull/10676.
"""
import sys
import pytest
from numpy.testing import assert_equal
from . import util
class TestQuotedCharacter(util.F2PyTest):
code = """
SUBROUTINE FOO(OUT1, OUT2, OUT3, OUT4, OUT5, OUT6)
CHARACTER SINGLE, DOUBLE, SEMICOL, EXCLA, OPENPAR, CLOSEPAR
PARAMETER (SINGLE="'", DOUBLE='"', SEMICOL=';', EXCLA="!",
1 OPENPAR="(", CLOSEPAR=")")
CHARACTER OUT1, OUT2, OUT3, OUT4, OUT5, OUT6
Cf2py intent(out) OUT1, OUT2, OUT3, OUT4, OUT5, OUT6
OUT1 = SINGLE
OUT2 = DOUBLE
OUT3 = SEMICOL
OUT4 = EXCLA
OUT5 = OPENPAR
OUT6 = CLOSEPAR
RETURN
END
"""
@pytest.mark.skipif(sys.platform=='win32',
reason='Fails with MinGW64 Gfortran (Issue #9673)')
def test_quoted_character(self):
assert_equal(self.module.foo(), (b"'", b'"', b';', b'!', b'(', b')'))

View file

@ -0,0 +1,27 @@
import os
import pytest
import numpy as np
from numpy.testing import assert_raises, assert_equal
from . import util
def _path(*a):
return os.path.join(*((os.path.dirname(__file__),) + a))
class TestIntentInOut(util.F2PyTest):
# Check that intent(in out) translates as intent(inout)
sources = [_path('src', 'regression', 'inout.f90')]
@pytest.mark.slow
def test_inout(self):
# non-contiguous should raise error
x = np.arange(6, dtype=np.float32)[::2]
assert_raises(ValueError, self.module.foo, x)
# check values with contiguous array
x = np.arange(3, dtype=np.float32)
self.module.foo(x)
assert_equal(x, [3, 1, 2])

View file

@ -0,0 +1,145 @@
import pytest
from numpy import array
from numpy.testing import assert_
from . import util
import platform
IS_S390X = platform.machine() == 's390x'
class TestReturnCharacter(util.F2PyTest):
def check_function(self, t, tname):
if tname in ['t0', 't1', 's0', 's1']:
assert_(t(23) == b'2')
r = t('ab')
assert_(r == b'a', repr(r))
r = t(array('ab'))
assert_(r == b'a', repr(r))
r = t(array(77, 'u1'))
assert_(r == b'M', repr(r))
#assert_(_raises(ValueError, t, array([77,87])))
#assert_(_raises(ValueError, t, array(77)))
elif tname in ['ts', 'ss']:
assert_(t(23) == b'23 ', repr(t(23)))
assert_(t('123456789abcdef') == b'123456789a')
elif tname in ['t5', 's5']:
assert_(t(23) == b'23 ', repr(t(23)))
assert_(t('ab') == b'ab ', repr(t('ab')))
assert_(t('123456789abcdef') == b'12345')
else:
raise NotImplementedError
class TestF77ReturnCharacter(TestReturnCharacter):
code = """
function t0(value)
character value
character t0
t0 = value
end
function t1(value)
character*1 value
character*1 t1
t1 = value
end
function t5(value)
character*5 value
character*5 t5
t5 = value
end
function ts(value)
character*(*) value
character*(*) ts
ts = value
end
subroutine s0(t0,value)
character value
character t0
cf2py intent(out) t0
t0 = value
end
subroutine s1(t1,value)
character*1 value
character*1 t1
cf2py intent(out) t1
t1 = value
end
subroutine s5(t5,value)
character*5 value
character*5 t5
cf2py intent(out) t5
t5 = value
end
subroutine ss(ts,value)
character*(*) value
character*10 ts
cf2py intent(out) ts
ts = value
end
"""
@pytest.mark.xfail(IS_S390X, reason="calback returns ' '")
@pytest.mark.parametrize('name', 't0,t1,t5,s0,s1,s5,ss'.split(','))
def test_all(self, name):
self.check_function(getattr(self.module, name), name)
class TestF90ReturnCharacter(TestReturnCharacter):
suffix = ".f90"
code = """
module f90_return_char
contains
function t0(value)
character :: value
character :: t0
t0 = value
end function t0
function t1(value)
character(len=1) :: value
character(len=1) :: t1
t1 = value
end function t1
function t5(value)
character(len=5) :: value
character(len=5) :: t5
t5 = value
end function t5
function ts(value)
character(len=*) :: value
character(len=10) :: ts
ts = value
end function ts
subroutine s0(t0,value)
character :: value
character :: t0
!f2py intent(out) t0
t0 = value
end subroutine s0
subroutine s1(t1,value)
character(len=1) :: value
character(len=1) :: t1
!f2py intent(out) t1
t1 = value
end subroutine s1
subroutine s5(t5,value)
character(len=5) :: value
character(len=5) :: t5
!f2py intent(out) t5
t5 = value
end subroutine s5
subroutine ss(ts,value)
character(len=*) :: value
character(len=10) :: ts
!f2py intent(out) ts
ts = value
end subroutine ss
end module f90_return_char
"""
@pytest.mark.xfail(IS_S390X, reason="calback returns ' '")
@pytest.mark.parametrize('name', 't0,t1,t5,ts,s0,s1,s5,ss'.split(','))
def test_all(self, name):
self.check_function(getattr(self.module.f90_return_char, name), name)

View file

@ -0,0 +1,163 @@
import pytest
from numpy import array
from numpy.testing import assert_, assert_raises
from . import util
class TestReturnComplex(util.F2PyTest):
def check_function(self, t, tname):
if tname in ['t0', 't8', 's0', 's8']:
err = 1e-5
else:
err = 0.0
assert_(abs(t(234j) - 234.0j) <= err)
assert_(abs(t(234.6) - 234.6) <= err)
assert_(abs(t(234) - 234.0) <= err)
assert_(abs(t(234.6 + 3j) - (234.6 + 3j)) <= err)
#assert_( abs(t('234')-234.)<=err)
#assert_( abs(t('234.6')-234.6)<=err)
assert_(abs(t(-234) + 234.) <= err)
assert_(abs(t([234]) - 234.) <= err)
assert_(abs(t((234,)) - 234.) <= err)
assert_(abs(t(array(234)) - 234.) <= err)
assert_(abs(t(array(23 + 4j, 'F')) - (23 + 4j)) <= err)
assert_(abs(t(array([234])) - 234.) <= err)
assert_(abs(t(array([[234]])) - 234.) <= err)
assert_(abs(t(array([234], 'b')) + 22.) <= err)
assert_(abs(t(array([234], 'h')) - 234.) <= err)
assert_(abs(t(array([234], 'i')) - 234.) <= err)
assert_(abs(t(array([234], 'l')) - 234.) <= err)
assert_(abs(t(array([234], 'q')) - 234.) <= err)
assert_(abs(t(array([234], 'f')) - 234.) <= err)
assert_(abs(t(array([234], 'd')) - 234.) <= err)
assert_(abs(t(array([234 + 3j], 'F')) - (234 + 3j)) <= err)
assert_(abs(t(array([234], 'D')) - 234.) <= err)
#assert_raises(TypeError, t, array([234], 'a1'))
assert_raises(TypeError, t, 'abc')
assert_raises(IndexError, t, [])
assert_raises(IndexError, t, ())
assert_raises(TypeError, t, t)
assert_raises(TypeError, t, {})
try:
r = t(10 ** 400)
assert_(repr(r) in ['(inf+0j)', '(Infinity+0j)'], repr(r))
except OverflowError:
pass
class TestF77ReturnComplex(TestReturnComplex):
code = """
function t0(value)
complex value
complex t0
t0 = value
end
function t8(value)
complex*8 value
complex*8 t8
t8 = value
end
function t16(value)
complex*16 value
complex*16 t16
t16 = value
end
function td(value)
double complex value
double complex td
td = value
end
subroutine s0(t0,value)
complex value
complex t0
cf2py intent(out) t0
t0 = value
end
subroutine s8(t8,value)
complex*8 value
complex*8 t8
cf2py intent(out) t8
t8 = value
end
subroutine s16(t16,value)
complex*16 value
complex*16 t16
cf2py intent(out) t16
t16 = value
end
subroutine sd(td,value)
double complex value
double complex td
cf2py intent(out) td
td = value
end
"""
@pytest.mark.parametrize('name', 't0,t8,t16,td,s0,s8,s16,sd'.split(','))
def test_all(self, name):
self.check_function(getattr(self.module, name), name)
class TestF90ReturnComplex(TestReturnComplex):
suffix = ".f90"
code = """
module f90_return_complex
contains
function t0(value)
complex :: value
complex :: t0
t0 = value
end function t0
function t8(value)
complex(kind=4) :: value
complex(kind=4) :: t8
t8 = value
end function t8
function t16(value)
complex(kind=8) :: value
complex(kind=8) :: t16
t16 = value
end function t16
function td(value)
double complex :: value
double complex :: td
td = value
end function td
subroutine s0(t0,value)
complex :: value
complex :: t0
!f2py intent(out) t0
t0 = value
end subroutine s0
subroutine s8(t8,value)
complex(kind=4) :: value
complex(kind=4) :: t8
!f2py intent(out) t8
t8 = value
end subroutine s8
subroutine s16(t16,value)
complex(kind=8) :: value
complex(kind=8) :: t16
!f2py intent(out) t16
t16 = value
end subroutine s16
subroutine sd(td,value)
double complex :: value
double complex :: td
!f2py intent(out) td
td = value
end subroutine sd
end module f90_return_complex
"""
@pytest.mark.parametrize('name', 't0,t8,t16,td,s0,s8,s16,sd'.split(','))
def test_all(self, name):
self.check_function(getattr(self.module.f90_return_complex, name), name)

View file

@ -0,0 +1,175 @@
import pytest
from numpy import array
from numpy.testing import assert_, assert_raises
from . import util
class TestReturnInteger(util.F2PyTest):
def check_function(self, t, tname):
assert_(t(123) == 123, repr(t(123)))
assert_(t(123.6) == 123)
assert_(t('123') == 123)
assert_(t(-123) == -123)
assert_(t([123]) == 123)
assert_(t((123,)) == 123)
assert_(t(array(123)) == 123)
assert_(t(array([123])) == 123)
assert_(t(array([[123]])) == 123)
assert_(t(array([123], 'b')) == 123)
assert_(t(array([123], 'h')) == 123)
assert_(t(array([123], 'i')) == 123)
assert_(t(array([123], 'l')) == 123)
assert_(t(array([123], 'B')) == 123)
assert_(t(array([123], 'f')) == 123)
assert_(t(array([123], 'd')) == 123)
#assert_raises(ValueError, t, array([123],'S3'))
assert_raises(ValueError, t, 'abc')
assert_raises(IndexError, t, [])
assert_raises(IndexError, t, ())
assert_raises(Exception, t, t)
assert_raises(Exception, t, {})
if tname in ['t8', 's8']:
assert_raises(OverflowError, t, 100000000000000000000000)
assert_raises(OverflowError, t, 10000000011111111111111.23)
class TestF77ReturnInteger(TestReturnInteger):
code = """
function t0(value)
integer value
integer t0
t0 = value
end
function t1(value)
integer*1 value
integer*1 t1
t1 = value
end
function t2(value)
integer*2 value
integer*2 t2
t2 = value
end
function t4(value)
integer*4 value
integer*4 t4
t4 = value
end
function t8(value)
integer*8 value
integer*8 t8
t8 = value
end
subroutine s0(t0,value)
integer value
integer t0
cf2py intent(out) t0
t0 = value
end
subroutine s1(t1,value)
integer*1 value
integer*1 t1
cf2py intent(out) t1
t1 = value
end
subroutine s2(t2,value)
integer*2 value
integer*2 t2
cf2py intent(out) t2
t2 = value
end
subroutine s4(t4,value)
integer*4 value
integer*4 t4
cf2py intent(out) t4
t4 = value
end
subroutine s8(t8,value)
integer*8 value
integer*8 t8
cf2py intent(out) t8
t8 = value
end
"""
@pytest.mark.parametrize('name',
't0,t1,t2,t4,t8,s0,s1,s2,s4,s8'.split(','))
def test_all(self, name):
self.check_function(getattr(self.module, name), name)
class TestF90ReturnInteger(TestReturnInteger):
suffix = ".f90"
code = """
module f90_return_integer
contains
function t0(value)
integer :: value
integer :: t0
t0 = value
end function t0
function t1(value)
integer(kind=1) :: value
integer(kind=1) :: t1
t1 = value
end function t1
function t2(value)
integer(kind=2) :: value
integer(kind=2) :: t2
t2 = value
end function t2
function t4(value)
integer(kind=4) :: value
integer(kind=4) :: t4
t4 = value
end function t4
function t8(value)
integer(kind=8) :: value
integer(kind=8) :: t8
t8 = value
end function t8
subroutine s0(t0,value)
integer :: value
integer :: t0
!f2py intent(out) t0
t0 = value
end subroutine s0
subroutine s1(t1,value)
integer(kind=1) :: value
integer(kind=1) :: t1
!f2py intent(out) t1
t1 = value
end subroutine s1
subroutine s2(t2,value)
integer(kind=2) :: value
integer(kind=2) :: t2
!f2py intent(out) t2
t2 = value
end subroutine s2
subroutine s4(t4,value)
integer(kind=4) :: value
integer(kind=4) :: t4
!f2py intent(out) t4
t4 = value
end subroutine s4
subroutine s8(t8,value)
integer(kind=8) :: value
integer(kind=8) :: t8
!f2py intent(out) t8
t8 = value
end subroutine s8
end module f90_return_integer
"""
@pytest.mark.parametrize('name',
't0,t1,t2,t4,t8,s0,s1,s2,s4,s8'.split(','))
def test_all(self, name):
self.check_function(getattr(self.module.f90_return_integer, name), name)

View file

@ -0,0 +1,185 @@
import pytest
from numpy import array
from numpy.testing import assert_, assert_raises
from . import util
class TestReturnLogical(util.F2PyTest):
def check_function(self, t):
assert_(t(True) == 1, repr(t(True)))
assert_(t(False) == 0, repr(t(False)))
assert_(t(0) == 0)
assert_(t(None) == 0)
assert_(t(0.0) == 0)
assert_(t(0j) == 0)
assert_(t(1j) == 1)
assert_(t(234) == 1)
assert_(t(234.6) == 1)
assert_(t(234.6 + 3j) == 1)
assert_(t('234') == 1)
assert_(t('aaa') == 1)
assert_(t('') == 0)
assert_(t([]) == 0)
assert_(t(()) == 0)
assert_(t({}) == 0)
assert_(t(t) == 1)
assert_(t(-234) == 1)
assert_(t(10 ** 100) == 1)
assert_(t([234]) == 1)
assert_(t((234,)) == 1)
assert_(t(array(234)) == 1)
assert_(t(array([234])) == 1)
assert_(t(array([[234]])) == 1)
assert_(t(array([234], 'b')) == 1)
assert_(t(array([234], 'h')) == 1)
assert_(t(array([234], 'i')) == 1)
assert_(t(array([234], 'l')) == 1)
assert_(t(array([234], 'f')) == 1)
assert_(t(array([234], 'd')) == 1)
assert_(t(array([234 + 3j], 'F')) == 1)
assert_(t(array([234], 'D')) == 1)
assert_(t(array(0)) == 0)
assert_(t(array([0])) == 0)
assert_(t(array([[0]])) == 0)
assert_(t(array([0j])) == 0)
assert_(t(array([1])) == 1)
assert_raises(ValueError, t, array([0, 0]))
class TestF77ReturnLogical(TestReturnLogical):
code = """
function t0(value)
logical value
logical t0
t0 = value
end
function t1(value)
logical*1 value
logical*1 t1
t1 = value
end
function t2(value)
logical*2 value
logical*2 t2
t2 = value
end
function t4(value)
logical*4 value
logical*4 t4
t4 = value
end
c function t8(value)
c logical*8 value
c logical*8 t8
c t8 = value
c end
subroutine s0(t0,value)
logical value
logical t0
cf2py intent(out) t0
t0 = value
end
subroutine s1(t1,value)
logical*1 value
logical*1 t1
cf2py intent(out) t1
t1 = value
end
subroutine s2(t2,value)
logical*2 value
logical*2 t2
cf2py intent(out) t2
t2 = value
end
subroutine s4(t4,value)
logical*4 value
logical*4 t4
cf2py intent(out) t4
t4 = value
end
c subroutine s8(t8,value)
c logical*8 value
c logical*8 t8
cf2py intent(out) t8
c t8 = value
c end
"""
@pytest.mark.slow
@pytest.mark.parametrize('name', 't0,t1,t2,t4,s0,s1,s2,s4'.split(','))
def test_all(self, name):
self.check_function(getattr(self.module, name))
class TestF90ReturnLogical(TestReturnLogical):
suffix = ".f90"
code = """
module f90_return_logical
contains
function t0(value)
logical :: value
logical :: t0
t0 = value
end function t0
function t1(value)
logical(kind=1) :: value
logical(kind=1) :: t1
t1 = value
end function t1
function t2(value)
logical(kind=2) :: value
logical(kind=2) :: t2
t2 = value
end function t2
function t4(value)
logical(kind=4) :: value
logical(kind=4) :: t4
t4 = value
end function t4
function t8(value)
logical(kind=8) :: value
logical(kind=8) :: t8
t8 = value
end function t8
subroutine s0(t0,value)
logical :: value
logical :: t0
!f2py intent(out) t0
t0 = value
end subroutine s0
subroutine s1(t1,value)
logical(kind=1) :: value
logical(kind=1) :: t1
!f2py intent(out) t1
t1 = value
end subroutine s1
subroutine s2(t2,value)
logical(kind=2) :: value
logical(kind=2) :: t2
!f2py intent(out) t2
t2 = value
end subroutine s2
subroutine s4(t4,value)
logical(kind=4) :: value
logical(kind=4) :: t4
!f2py intent(out) t4
t4 = value
end subroutine s4
subroutine s8(t8,value)
logical(kind=8) :: value
logical(kind=8) :: t8
!f2py intent(out) t8
t8 = value
end subroutine s8
end module f90_return_logical
"""
@pytest.mark.slow
@pytest.mark.parametrize('name',
't0,t1,t2,t4,t8,s0,s1,s2,s4,s8'.split(','))
def test_all(self, name):
self.check_function(getattr(self.module.f90_return_logical, name))

View file

@ -0,0 +1,203 @@
import platform
import pytest
from numpy import array
from numpy.testing import assert_, assert_raises
from . import util
class TestReturnReal(util.F2PyTest):
def check_function(self, t, tname):
if tname in ['t0', 't4', 's0', 's4']:
err = 1e-5
else:
err = 0.0
assert_(abs(t(234) - 234.0) <= err)
assert_(abs(t(234.6) - 234.6) <= err)
assert_(abs(t('234') - 234) <= err)
assert_(abs(t('234.6') - 234.6) <= err)
assert_(abs(t(-234) + 234) <= err)
assert_(abs(t([234]) - 234) <= err)
assert_(abs(t((234,)) - 234.) <= err)
assert_(abs(t(array(234)) - 234.) <= err)
assert_(abs(t(array([234])) - 234.) <= err)
assert_(abs(t(array([[234]])) - 234.) <= err)
assert_(abs(t(array([234], 'b')) + 22) <= err)
assert_(abs(t(array([234], 'h')) - 234.) <= err)
assert_(abs(t(array([234], 'i')) - 234.) <= err)
assert_(abs(t(array([234], 'l')) - 234.) <= err)
assert_(abs(t(array([234], 'B')) - 234.) <= err)
assert_(abs(t(array([234], 'f')) - 234.) <= err)
assert_(abs(t(array([234], 'd')) - 234.) <= err)
if tname in ['t0', 't4', 's0', 's4']:
assert_(t(1e200) == t(1e300)) # inf
#assert_raises(ValueError, t, array([234], 'S1'))
assert_raises(ValueError, t, 'abc')
assert_raises(IndexError, t, [])
assert_raises(IndexError, t, ())
assert_raises(Exception, t, t)
assert_raises(Exception, t, {})
try:
r = t(10 ** 400)
assert_(repr(r) in ['inf', 'Infinity'], repr(r))
except OverflowError:
pass
@pytest.mark.skipif(
platform.system() == 'Darwin',
reason="Prone to error when run with numpy/f2py/tests on mac os, "
"but not when run in isolation")
class TestCReturnReal(TestReturnReal):
suffix = ".pyf"
module_name = "c_ext_return_real"
code = """
python module c_ext_return_real
usercode \'\'\'
float t4(float value) { return value; }
void s4(float *t4, float value) { *t4 = value; }
double t8(double value) { return value; }
void s8(double *t8, double value) { *t8 = value; }
\'\'\'
interface
function t4(value)
real*4 intent(c) :: t4,value
end
function t8(value)
real*8 intent(c) :: t8,value
end
subroutine s4(t4,value)
intent(c) s4
real*4 intent(out) :: t4
real*4 intent(c) :: value
end
subroutine s8(t8,value)
intent(c) s8
real*8 intent(out) :: t8
real*8 intent(c) :: value
end
end interface
end python module c_ext_return_real
"""
@pytest.mark.parametrize('name', 't4,t8,s4,s8'.split(','))
def test_all(self, name):
self.check_function(getattr(self.module, name), name)
class TestF77ReturnReal(TestReturnReal):
code = """
function t0(value)
real value
real t0
t0 = value
end
function t4(value)
real*4 value
real*4 t4
t4 = value
end
function t8(value)
real*8 value
real*8 t8
t8 = value
end
function td(value)
double precision value
double precision td
td = value
end
subroutine s0(t0,value)
real value
real t0
cf2py intent(out) t0
t0 = value
end
subroutine s4(t4,value)
real*4 value
real*4 t4
cf2py intent(out) t4
t4 = value
end
subroutine s8(t8,value)
real*8 value
real*8 t8
cf2py intent(out) t8
t8 = value
end
subroutine sd(td,value)
double precision value
double precision td
cf2py intent(out) td
td = value
end
"""
@pytest.mark.parametrize('name', 't0,t4,t8,td,s0,s4,s8,sd'.split(','))
def test_all(self, name):
self.check_function(getattr(self.module, name), name)
class TestF90ReturnReal(TestReturnReal):
suffix = ".f90"
code = """
module f90_return_real
contains
function t0(value)
real :: value
real :: t0
t0 = value
end function t0
function t4(value)
real(kind=4) :: value
real(kind=4) :: t4
t4 = value
end function t4
function t8(value)
real(kind=8) :: value
real(kind=8) :: t8
t8 = value
end function t8
function td(value)
double precision :: value
double precision :: td
td = value
end function td
subroutine s0(t0,value)
real :: value
real :: t0
!f2py intent(out) t0
t0 = value
end subroutine s0
subroutine s4(t4,value)
real(kind=4) :: value
real(kind=4) :: t4
!f2py intent(out) t4
t4 = value
end subroutine s4
subroutine s8(t8,value)
real(kind=8) :: value
real(kind=8) :: t8
!f2py intent(out) t8
t8 = value
end subroutine s8
subroutine sd(td,value)
double precision :: value
double precision :: td
!f2py intent(out) td
td = value
end subroutine sd
end module f90_return_real
"""
@pytest.mark.parametrize('name', 't0,t4,t8,td,s0,s4,s8,sd'.split(','))
def test_all(self, name):
self.check_function(getattr(self.module.f90_return_real, name), name)

View file

@ -0,0 +1,63 @@
import platform
import pytest
from . import util
from numpy.testing import assert_equal
@pytest.mark.skipif(
platform.system() == 'Darwin',
reason="Prone to error when run with numpy/f2py/tests on mac os, "
"but not when run in isolation")
class TestMultiline(util.F2PyTest):
suffix = ".pyf"
module_name = "multiline"
code = """
python module {module}
usercode '''
void foo(int* x) {{
char dummy = ';';
*x = 42;
}}
'''
interface
subroutine foo(x)
intent(c) foo
integer intent(out) :: x
end subroutine foo
end interface
end python module {module}
""".format(module=module_name)
def test_multiline(self):
assert_equal(self.module.foo(), 42)
@pytest.mark.skipif(
platform.system() == 'Darwin',
reason="Prone to error when run with numpy/f2py/tests on mac os, "
"but not when run in isolation")
class TestCallstatement(util.F2PyTest):
suffix = ".pyf"
module_name = "callstatement"
code = """
python module {module}
usercode '''
void foo(int* x) {{
}}
'''
interface
subroutine foo(x)
intent(c) foo
integer intent(out) :: x
callprotoargument int*
callstatement {{ &
; &
x = 42; &
}}
end subroutine foo
end interface
end python module {module}
""".format(module=module_name)
def test_callstatement(self):
assert_equal(self.module.foo(), 42)

View file

@ -0,0 +1,49 @@
import os
import pytest
from numpy.testing import assert_equal
from . import util
def _path(*a):
return os.path.join(*((os.path.dirname(__file__),) + a))
class TestSizeSumExample(util.F2PyTest):
sources = [_path('src', 'size', 'foo.f90')]
@pytest.mark.slow
def test_all(self):
r = self.module.foo([[]])
assert_equal(r, [0], repr(r))
r = self.module.foo([[1, 2]])
assert_equal(r, [3], repr(r))
r = self.module.foo([[1, 2], [3, 4]])
assert_equal(r, [3, 7], repr(r))
r = self.module.foo([[1, 2], [3, 4], [5, 6]])
assert_equal(r, [3, 7, 11], repr(r))
@pytest.mark.slow
def test_transpose(self):
r = self.module.trans([[]])
assert_equal(r.T, [[]], repr(r))
r = self.module.trans([[1, 2]])
assert_equal(r, [[1], [2]], repr(r))
r = self.module.trans([[1, 2, 3], [4, 5, 6]])
assert_equal(r, [[1, 4], [2, 5], [3, 6]], repr(r))
@pytest.mark.slow
def test_flatten(self):
r = self.module.flatten([[]])
assert_equal(r, [], repr(r))
r = self.module.flatten([[1, 2]])
assert_equal(r, [1, 2], repr(r))
r = self.module.flatten([[1, 2, 3], [4, 5, 6]])
assert_equal(r, [1, 2, 3, 4, 5, 6], repr(r))

View file

@ -0,0 +1,22 @@
import os
import pytest
from numpy.testing import assert_array_equal
import numpy as np
from . import util
def _path(*a):
return os.path.join(*((os.path.dirname(__file__),) + a))
class TestString(util.F2PyTest):
sources = [_path('src', 'string', 'char.f90')]
@pytest.mark.slow
def test_char(self):
strings = np.array(['ab', 'cd', 'ef'], dtype='c').T
inp, out = self.module.char_test.change_strings(strings, strings.shape[1])
assert_array_equal(inp, strings)
expected = strings.copy()
expected[1, :] = 'AAA'
assert_array_equal(out, expected)

View file

@ -0,0 +1,361 @@
"""
Utility functions for
- building and importing modules on test time, using a temporary location
- detecting if compilers are present
"""
import os
import sys
import subprocess
import tempfile
import shutil
import atexit
import textwrap
import re
import pytest
from numpy.compat import asbytes, asstr
from numpy.testing import temppath
from importlib import import_module
from hashlib import md5
#
# Maintaining a temporary module directory
#
_module_dir = None
_module_num = 5403
def _cleanup():
global _module_dir
if _module_dir is not None:
try:
sys.path.remove(_module_dir)
except ValueError:
pass
try:
shutil.rmtree(_module_dir)
except (IOError, OSError):
pass
_module_dir = None
def get_module_dir():
global _module_dir
if _module_dir is None:
_module_dir = tempfile.mkdtemp()
atexit.register(_cleanup)
if _module_dir not in sys.path:
sys.path.insert(0, _module_dir)
return _module_dir
def get_temp_module_name():
# Assume single-threaded, and the module dir usable only by this thread
global _module_num
d = get_module_dir()
name = "_test_ext_module_%d" % _module_num
_module_num += 1
if name in sys.modules:
# this should not be possible, but check anyway
raise RuntimeError("Temporary module name already in use.")
return name
def _memoize(func):
memo = {}
def wrapper(*a, **kw):
key = repr((a, kw))
if key not in memo:
try:
memo[key] = func(*a, **kw)
except Exception as e:
memo[key] = e
raise
ret = memo[key]
if isinstance(ret, Exception):
raise ret
return ret
wrapper.__name__ = func.__name__
return wrapper
#
# Building modules
#
@_memoize
def build_module(source_files, options=[], skip=[], only=[], module_name=None):
"""
Compile and import a f2py module, built from the given files.
"""
code = ("import sys; sys.path = %s; import numpy.f2py as f2py2e; "
"f2py2e.main()" % repr(sys.path))
d = get_module_dir()
# Copy files
dst_sources = []
f2py_sources = []
for fn in source_files:
if not os.path.isfile(fn):
raise RuntimeError("%s is not a file" % fn)
dst = os.path.join(d, os.path.basename(fn))
shutil.copyfile(fn, dst)
dst_sources.append(dst)
base, ext = os.path.splitext(dst)
if ext in ('.f90', '.f', '.c', '.pyf'):
f2py_sources.append(dst)
# Prepare options
if module_name is None:
module_name = get_temp_module_name()
f2py_opts = ['-c', '-m', module_name] + options + f2py_sources
if skip:
f2py_opts += ['skip:'] + skip
if only:
f2py_opts += ['only:'] + only
# Build
cwd = os.getcwd()
try:
os.chdir(d)
cmd = [sys.executable, '-c', code] + f2py_opts
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
out, err = p.communicate()
if p.returncode != 0:
raise RuntimeError("Running f2py failed: %s\n%s"
% (cmd[4:], asstr(out)))
finally:
os.chdir(cwd)
# Partial cleanup
for fn in dst_sources:
os.unlink(fn)
# Import
return import_module(module_name)
@_memoize
def build_code(source_code, options=[], skip=[], only=[], suffix=None,
module_name=None):
"""
Compile and import Fortran code using f2py.
"""
if suffix is None:
suffix = '.f'
with temppath(suffix=suffix) as path:
with open(path, 'w') as f:
f.write(source_code)
return build_module([path], options=options, skip=skip, only=only,
module_name=module_name)
#
# Check if compilers are available at all...
#
_compiler_status = None
def _get_compiler_status():
global _compiler_status
if _compiler_status is not None:
return _compiler_status
_compiler_status = (False, False, False)
# XXX: this is really ugly. But I don't know how to invoke Distutils
# in a safer way...
code = textwrap.dedent("""\
import os
import sys
sys.path = %(syspath)s
def configuration(parent_name='',top_path=None):
global config
from numpy.distutils.misc_util import Configuration
config = Configuration('', parent_name, top_path)
return config
from numpy.distutils.core import setup
setup(configuration=configuration)
config_cmd = config.get_config_cmd()
have_c = config_cmd.try_compile('void foo() {}')
print('COMPILERS:%%d,%%d,%%d' %% (have_c,
config.have_f77c(),
config.have_f90c()))
sys.exit(99)
""")
code = code % dict(syspath=repr(sys.path))
tmpdir = tempfile.mkdtemp()
try:
script = os.path.join(tmpdir, 'setup.py')
with open(script, 'w') as f:
f.write(code)
cmd = [sys.executable, 'setup.py', 'config']
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
cwd=tmpdir)
out, err = p.communicate()
finally:
shutil.rmtree(tmpdir)
m = re.search(br'COMPILERS:(\d+),(\d+),(\d+)', out)
if m:
_compiler_status = (bool(int(m.group(1))), bool(int(m.group(2))),
bool(int(m.group(3))))
# Finished
return _compiler_status
def has_c_compiler():
return _get_compiler_status()[0]
def has_f77_compiler():
return _get_compiler_status()[1]
def has_f90_compiler():
return _get_compiler_status()[2]
#
# Building with distutils
#
@_memoize
def build_module_distutils(source_files, config_code, module_name, **kw):
"""
Build a module via distutils and import it.
"""
from numpy.distutils.misc_util import Configuration
from numpy.distutils.core import setup
d = get_module_dir()
# Copy files
dst_sources = []
for fn in source_files:
if not os.path.isfile(fn):
raise RuntimeError("%s is not a file" % fn)
dst = os.path.join(d, os.path.basename(fn))
shutil.copyfile(fn, dst)
dst_sources.append(dst)
# Build script
config_code = textwrap.dedent(config_code).replace("\n", "\n ")
code = textwrap.dedent("""\
import os
import sys
sys.path = %(syspath)s
def configuration(parent_name='',top_path=None):
from numpy.distutils.misc_util import Configuration
config = Configuration('', parent_name, top_path)
%(config_code)s
return config
if __name__ == "__main__":
from numpy.distutils.core import setup
setup(configuration=configuration)
""") % dict(config_code=config_code, syspath=repr(sys.path))
script = os.path.join(d, get_temp_module_name() + '.py')
dst_sources.append(script)
with open(script, 'wb') as f:
f.write(asbytes(code))
# Build
cwd = os.getcwd()
try:
os.chdir(d)
cmd = [sys.executable, script, 'build_ext', '-i']
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
out, err = p.communicate()
if p.returncode != 0:
raise RuntimeError("Running distutils build failed: %s\n%s"
% (cmd[4:], asstr(out)))
finally:
os.chdir(cwd)
# Partial cleanup
for fn in dst_sources:
os.unlink(fn)
# Import
__import__(module_name)
return sys.modules[module_name]
#
# Unittest convenience
#
class F2PyTest:
code = None
sources = None
options = []
skip = []
only = []
suffix = '.f'
module = None
module_name = None
def setup(self):
if sys.platform == 'win32':
pytest.skip('Fails with MinGW64 Gfortran (Issue #9673)')
if self.module is not None:
return
# Check compiler availability first
if not has_c_compiler():
pytest.skip("No C compiler available")
codes = []
if self.sources:
codes.extend(self.sources)
if self.code is not None:
codes.append(self.suffix)
needs_f77 = False
needs_f90 = False
for fn in codes:
if fn.endswith('.f'):
needs_f77 = True
elif fn.endswith('.f90'):
needs_f90 = True
if needs_f77 and not has_f77_compiler():
pytest.skip("No Fortran 77 compiler available")
if needs_f90 and not has_f90_compiler():
pytest.skip("No Fortran 90 compiler available")
# Build the module
if self.code is not None:
self.module = build_code(self.code, options=self.options,
skip=self.skip, only=self.only,
suffix=self.suffix,
module_name=self.module_name)
if self.sources is not None:
self.module = build_module(self.sources, options=self.options,
skip=self.skip, only=self.only,
module_name=self.module_name)