Delete .venv directory
This commit is contained in:
committed by
GitHub
parent
7795984d81
commit
5a2693bd9f
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,228 +0,0 @@
|
||||
/*
|
||||
* This file was auto-generated with f2py (version:2_1330) and hand edited by
|
||||
* Pearu for testing purposes. Do not edit this file 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)PyLong_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,PyLong_FromLong(PyArray_DIM(arr,i)));
|
||||
PyTuple_SetItem(strides,i,PyLong_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 = PyUnicode_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 = PyLong_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
|
@@ -1 +0,0 @@
|
||||
dict(real=dict(rk="double"))
|
@@ -1,34 +0,0 @@
|
||||
|
||||
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
|
@@ -1,41 +0,0 @@
|
||||
|
||||
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
|
@@ -1,19 +0,0 @@
|
||||
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
|
@@ -1,4 +0,0 @@
|
||||
module precision
|
||||
integer, parameter :: rk = selected_real_kind(8)
|
||||
integer, parameter :: ik = selected_real_kind(4)
|
||||
end module
|
@@ -1,11 +0,0 @@
|
||||
SUBROUTINE INITCB
|
||||
DOUBLE PRECISION LONG
|
||||
CHARACTER STRING
|
||||
INTEGER OK
|
||||
|
||||
COMMON /BLOCK/ LONG, STRING, OK
|
||||
LONG = 1.0
|
||||
STRING = '2'
|
||||
OK = 3
|
||||
RETURN
|
||||
END
|
@@ -1,20 +0,0 @@
|
||||
|
||||
|
||||
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
|
@@ -1,5 +0,0 @@
|
||||
subroutine bar11(a)
|
||||
cf2py intent(out) a
|
||||
integer a
|
||||
a = 11
|
||||
end
|
@@ -1,8 +0,0 @@
|
||||
module foo_fixed
|
||||
contains
|
||||
subroutine bar12(a)
|
||||
!f2py intent(out) a
|
||||
integer a
|
||||
a = 12
|
||||
end subroutine bar12
|
||||
end module foo_fixed
|
@@ -1,8 +0,0 @@
|
||||
module foo_free
|
||||
contains
|
||||
subroutine bar13(a)
|
||||
!f2py intent(out) a
|
||||
integer a
|
||||
a = 13
|
||||
end subroutine bar13
|
||||
end module foo_free
|
Binary file not shown.
@@ -1,12 +0,0 @@
|
||||
module mod
|
||||
integer :: i
|
||||
integer :: x(4)
|
||||
real, dimension(2,3) :: a
|
||||
real, allocatable, dimension(:,:) :: b
|
||||
contains
|
||||
subroutine foo
|
||||
integer :: k
|
||||
k = 1
|
||||
a(1,2) = a(1,2)+3
|
||||
end subroutine foo
|
||||
end module mod
|
@@ -1,57 +0,0 @@
|
||||
! 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
|
@@ -1,15 +0,0 @@
|
||||
! 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
|
@@ -1,22 +0,0 @@
|
||||
! 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
|
@@ -1,23 +0,0 @@
|
||||
! 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
|
@@ -1,23 +0,0 @@
|
||||
! 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
|
||||
|
@@ -1,9 +0,0 @@
|
||||
! 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
|
@@ -1,44 +0,0 @@
|
||||
|
||||
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
|
@@ -1,29 +0,0 @@
|
||||
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
|
||||
|
@@ -1,66 +0,0 @@
|
||||
import textwrap
|
||||
from . import util
|
||||
from numpy.f2py import crackfortran
|
||||
|
||||
|
||||
class TestAbstractInterface(util.F2PyTest):
|
||||
suffix = '.f90'
|
||||
|
||||
skip = ['add1', 'add2']
|
||||
|
||||
code = textwrap.dedent("""
|
||||
module ops_module
|
||||
|
||||
abstract interface
|
||||
subroutine op(x, y, z)
|
||||
integer, intent(in) :: x, y
|
||||
integer, intent(out) :: z
|
||||
end subroutine
|
||||
end interface
|
||||
|
||||
contains
|
||||
|
||||
subroutine foo(x, y, r1, r2)
|
||||
integer, intent(in) :: x, y
|
||||
integer, intent(out) :: r1, r2
|
||||
procedure (op) add1, add2
|
||||
procedure (op), pointer::p
|
||||
p=>add1
|
||||
call p(x, y, r1)
|
||||
p=>add2
|
||||
call p(x, y, r2)
|
||||
end subroutine
|
||||
end module
|
||||
|
||||
subroutine add1(x, y, z)
|
||||
integer, intent(in) :: x, y
|
||||
integer, intent(out) :: z
|
||||
z = x + y
|
||||
end subroutine
|
||||
|
||||
subroutine add2(x, y, z)
|
||||
integer, intent(in) :: x, y
|
||||
integer, intent(out) :: z
|
||||
z = x + 2 * y
|
||||
end subroutine
|
||||
""")
|
||||
|
||||
def test_abstract_interface(self):
|
||||
assert self.module.ops_module.foo(3, 5) == (8, 13)
|
||||
|
||||
def test_parse_abstract_interface(self, tmp_path):
|
||||
# Test gh18403
|
||||
f_path = tmp_path / "gh18403_mod.f90"
|
||||
with f_path.open('w') as ff:
|
||||
ff.write(textwrap.dedent("""\
|
||||
module test
|
||||
abstract interface
|
||||
subroutine foo()
|
||||
end subroutine
|
||||
end interface
|
||||
end module test
|
||||
"""))
|
||||
mod = crackfortran.crackfortran([str(f_path)])
|
||||
assert len(mod) == 1
|
||||
assert len(mod[0]['body']) == 1
|
||||
assert mod[0]['body'][0]['block'] == 'abstract interface'
|
@@ -1,596 +0,0 @@
|
||||
import os
|
||||
import sys
|
||||
import copy
|
||||
import platform
|
||||
import pytest
|
||||
|
||||
import numpy as np
|
||||
|
||||
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
|
||||
#
|
||||
# Furthermore, on macOS ARM64, LONGDOUBLE is an alias for DOUBLE.
|
||||
if ((np.intp().dtype.itemsize != 4 or np.clongdouble().dtype.alignment <= 8) and
|
||||
sys.platform != 'win32' and
|
||||
(platform.system(), platform.processor()) != ('Darwin', 'arm')):
|
||||
_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, np.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 = np.dtype(info.type)
|
||||
self.type = 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, np.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, np.ndarray), repr(type(obj)))
|
||||
self.pyarr = np.array(obj).reshape(*dims).copy()
|
||||
else:
|
||||
self.pyarr = np.array(
|
||||
np.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)))
|
||||
self.pyarr.setflags(write=self.arr.flags['WRITEABLE'])
|
||||
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, np.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
|
||||
return (arr1 == arr2).all()
|
||||
|
||||
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, np.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 = np.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))
|
||||
|
||||
@pytest.mark.parametrize('write', ['w', 'ro'])
|
||||
@pytest.mark.parametrize('order', ['C', 'F'])
|
||||
@pytest.mark.parametrize('inp', ['2seq', '23seq'])
|
||||
def test_in_nocopy(self, write, order, inp):
|
||||
"""Test if intent(in) array can be passed without copies
|
||||
"""
|
||||
seq = getattr(self, 'num' + inp)
|
||||
obj = np.array(seq, dtype=self.type.dtype, order=order)
|
||||
obj.setflags(write=(write == 'w'))
|
||||
a = self.array(obj.shape, ((order=='C' and intent.in_.c) or intent.in_), obj)
|
||||
assert a.has_shared_memory()
|
||||
|
||||
def test_inout_2seq(self):
|
||||
obj = np.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 = np.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 = np.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 = np.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 = np.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 = np.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 = np.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 = np.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 = np.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 = np.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 = np.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 = np.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 = np.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, np.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, np.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, np.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, np.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, np.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, np.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 = np.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] ==
|
||||
np.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 = np.array(self.num23seq, dtype=t.dtype)
|
||||
assert_(obj.dtype.type == t.type)
|
||||
assert_(obj.dtype.type is not self.type.type)
|
||||
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] ==
|
||||
np.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.type) # obj changed inplace!
|
@@ -1,53 +0,0 @@
|
||||
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().setup()
|
||||
|
||||
def teardown(self):
|
||||
os.unlink(self.f2cmap_file.name)
|
@@ -1,23 +0,0 @@
|
||||
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 = "bar : 'i'-array(2,3)\n"
|
||||
assert_equal(self.module.block.__doc__, expected)
|
@@ -1,326 +0,0 @@
|
||||
import math
|
||||
import textwrap
|
||||
import sys
|
||||
import pytest
|
||||
import threading
|
||||
import traceback
|
||||
import time
|
||||
import random
|
||||
|
||||
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
|
||||
|
||||
subroutine hidden_callback(a, r)
|
||||
external global_f
|
||||
cf2py intent(callback, hide) global_f
|
||||
integer a, r, global_f
|
||||
cf2py intent(out) r
|
||||
r = global_f(a)
|
||||
end
|
||||
|
||||
subroutine hidden_callback2(a, r)
|
||||
external global_f
|
||||
integer a, r, global_f
|
||||
cf2py intent(out) r
|
||||
r = global_f(a)
|
||||
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))
|
||||
|
||||
def test_threadsafety(self):
|
||||
# Segfaults if the callback handling is not threadsafe
|
||||
|
||||
errors = []
|
||||
|
||||
def cb():
|
||||
# Sleep here to make it more likely for another thread
|
||||
# to call their callback at the same time.
|
||||
time.sleep(1e-3)
|
||||
|
||||
# Check reentrancy
|
||||
r = self.module.t(lambda: 123)
|
||||
assert_(r == 123)
|
||||
|
||||
return 42
|
||||
|
||||
def runner(name):
|
||||
try:
|
||||
for j in range(50):
|
||||
r = self.module.t(cb)
|
||||
assert_(r == 42)
|
||||
self.check_function(name)
|
||||
except Exception:
|
||||
errors.append(traceback.format_exc())
|
||||
|
||||
threads = [threading.Thread(target=runner, args=(arg,))
|
||||
for arg in ("t", "t2") for n in range(20)]
|
||||
|
||||
for t in threads:
|
||||
t.start()
|
||||
|
||||
for t in threads:
|
||||
t.join()
|
||||
|
||||
errors = "\n\n".join(errors)
|
||||
if errors:
|
||||
raise AssertionError(errors)
|
||||
|
||||
def test_hidden_callback(self):
|
||||
try:
|
||||
self.module.hidden_callback(2)
|
||||
except Exception as msg:
|
||||
assert_(str(msg).startswith('Callback global_f not defined'))
|
||||
|
||||
try:
|
||||
self.module.hidden_callback2(2)
|
||||
except Exception as msg:
|
||||
assert_(str(msg).startswith('cb: Callback global_f not defined'))
|
||||
|
||||
self.module.global_f = lambda x: x + 1
|
||||
r = self.module.hidden_callback(2)
|
||||
assert_(r == 3)
|
||||
|
||||
self.module.global_f = lambda x: x + 2
|
||||
r = self.module.hidden_callback(2)
|
||||
assert_(r == 4)
|
||||
|
||||
del self.module.global_f
|
||||
try:
|
||||
self.module.hidden_callback(2)
|
||||
except Exception as msg:
|
||||
assert_(str(msg).startswith('Callback global_f not defined'))
|
||||
|
||||
self.module.global_f = lambda x=0: x + 3
|
||||
r = self.module.hidden_callback(2)
|
||||
assert_(r == 5)
|
||||
|
||||
# reproducer of gh18341
|
||||
r = self.module.hidden_callback2(2)
|
||||
assert_(r == 3)
|
||||
|
||||
|
||||
class TestF77CallbackPythonTLS(TestF77Callback):
|
||||
"""
|
||||
Callback tests using Python thread-local storage instead of
|
||||
compiler-provided
|
||||
"""
|
||||
options = ["-DF2PY_USE_PYTHON_TLS"]
|
||||
|
||||
|
||||
class TestF90Callback(util.F2PyTest):
|
||||
|
||||
suffix = '.f90'
|
||||
|
||||
code = textwrap.dedent(
|
||||
"""
|
||||
function gh17797(f, y) result(r)
|
||||
external f
|
||||
integer(8) :: r, f
|
||||
integer(8), dimension(:) :: y
|
||||
r = f(0)
|
||||
r = r + sum(y)
|
||||
end function gh17797
|
||||
""")
|
||||
|
||||
def test_gh17797(self):
|
||||
|
||||
def incr(x):
|
||||
return x + 123
|
||||
|
||||
y = np.array([1, 2, 3], dtype=np.int64)
|
||||
r = self.module.gh17797(incr, y)
|
||||
assert r == 123 + 1 + 2 + 3
|
||||
|
||||
|
||||
class TestGH18335(util.F2PyTest):
|
||||
"""The reproduction of the reported issue requires specific input that
|
||||
extensions may break the issue conditions, so the reproducer is
|
||||
implemented as a separate test class. Do not extend this test with
|
||||
other tests!
|
||||
"""
|
||||
|
||||
suffix = '.f90'
|
||||
|
||||
code = textwrap.dedent(
|
||||
"""
|
||||
! When gh18335_workaround is defined as an extension,
|
||||
! the issue cannot be reproduced.
|
||||
!subroutine gh18335_workaround(f, y)
|
||||
! implicit none
|
||||
! external f
|
||||
! integer(kind=1) :: y(1)
|
||||
! call f(y)
|
||||
!end subroutine gh18335_workaround
|
||||
|
||||
function gh18335(f) result (r)
|
||||
implicit none
|
||||
external f
|
||||
integer(kind=1) :: y(1), r
|
||||
y(1) = 123
|
||||
call f(y)
|
||||
r = y(1)
|
||||
end function gh18335
|
||||
""")
|
||||
|
||||
def test_gh18335(self):
|
||||
|
||||
def foo(x):
|
||||
x[0] += 1
|
||||
|
||||
y = np.array([1, 2, 3], dtype=np.int8)
|
||||
r = self.module.gh18335(foo)
|
||||
assert r == 123 + 1
|
@@ -1,25 +0,0 @@
|
||||
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))
|
@@ -1,125 +0,0 @@
|
||||
"""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)
|
@@ -1,141 +0,0 @@
|
||||
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']
|
||||
|
||||
class TestExternal(util.F2PyTest):
|
||||
# issue gh-17859: add external attribute support
|
||||
code = """
|
||||
integer(8) function external_as_statement(fcn)
|
||||
implicit none
|
||||
external fcn
|
||||
integer(8) :: fcn
|
||||
external_as_statement = fcn(0)
|
||||
end
|
||||
|
||||
integer(8) function external_as_attribute(fcn)
|
||||
implicit none
|
||||
integer(8), external :: fcn
|
||||
external_as_attribute = fcn(0)
|
||||
end
|
||||
"""
|
||||
|
||||
def test_external_as_statement(self):
|
||||
def incr(x):
|
||||
return x + 123
|
||||
r = self.module.external_as_statement(incr)
|
||||
assert r == 123
|
||||
|
||||
def test_external_as_attribute(self):
|
||||
def incr(x):
|
||||
return x + 123
|
||||
r = self.module.external_as_attribute(incr)
|
||||
assert r == 123
|
||||
|
||||
class TestCrackFortran(util.F2PyTest):
|
||||
|
||||
suffix = '.f90'
|
||||
|
||||
code = textwrap.dedent("""
|
||||
subroutine gh2848( &
|
||||
! first 2 parameters
|
||||
par1, par2,&
|
||||
! last 2 parameters
|
||||
par3, par4)
|
||||
|
||||
integer, intent(in) :: par1, par2
|
||||
integer, intent(out) :: par3, par4
|
||||
|
||||
par3 = par1
|
||||
par4 = par2
|
||||
|
||||
end subroutine gh2848
|
||||
""")
|
||||
|
||||
def test_gh2848(self):
|
||||
r = self.module.gh2848(1, 2)
|
||||
assert r == (1, 2)
|
@@ -1,32 +0,0 @@
|
||||
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)))
|
@@ -1,35 +0,0 @@
|
||||
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)
|
@@ -1,30 +0,0 @@
|
||||
import os
|
||||
import sys
|
||||
import pytest
|
||||
import textwrap
|
||||
|
||||
from . import util
|
||||
from numpy.testing import assert_equal, IS_PYPY
|
||||
|
||||
|
||||
def _path(*a):
|
||||
return os.path.join(*((os.path.dirname(__file__),) + a))
|
||||
|
||||
|
||||
class TestModuleDocString(util.F2PyTest):
|
||||
sources = [_path('src', 'module_data', 'module_data_docstring.f90')]
|
||||
|
||||
@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_module_docstring(self):
|
||||
assert_equal(self.module.mod.__doc__,
|
||||
textwrap.dedent('''\
|
||||
i : 'i'-scalar
|
||||
x : 'i'-array(4)
|
||||
a : 'f'-array(2,3)
|
||||
b : 'f'-array(-1,-1), not allocated\x00
|
||||
foo()\n
|
||||
Wrapper for ``foo``.\n\n''')
|
||||
)
|
@@ -1,116 +0,0 @@
|
||||
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])
|
@@ -1,32 +0,0 @@
|
||||
"""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')'))
|
@@ -1,55 +0,0 @@
|
||||
import os
|
||||
import pytest
|
||||
|
||||
import numpy as np
|
||||
from numpy.testing import assert_, assert_raises, assert_equal, assert_string_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])
|
||||
|
||||
|
||||
class TestNumpyVersionAttribute(util.F2PyTest):
|
||||
# Check that th attribute __f2py_numpy_version__ is present
|
||||
# in the compiled module and that has the value np.__version__.
|
||||
sources = [_path('src', 'regression', 'inout.f90')]
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_numpy_version_attribute(self):
|
||||
|
||||
# Check that self.module has an attribute named "__f2py_numpy_version__"
|
||||
assert_(hasattr(self.module, "__f2py_numpy_version__"),
|
||||
msg="Fortran module does not have __f2py_numpy_version__")
|
||||
|
||||
# Check that the attribute __f2py_numpy_version__ is a string
|
||||
assert_(isinstance(self.module.__f2py_numpy_version__, str),
|
||||
msg="__f2py_numpy_version__ is not a string")
|
||||
|
||||
# Check that __f2py_numpy_version__ has the value numpy.__version__
|
||||
assert_string_equal(np.__version__, self.module.__f2py_numpy_version__)
|
||||
|
||||
|
||||
def test_include_path():
|
||||
incdir = np.f2py.get_include()
|
||||
fnames_in_dir = os.listdir(incdir)
|
||||
for fname in ('fortranobject.c', 'fortranobject.h'):
|
||||
assert fname in fnames_in_dir
|
||||
|
@@ -1,145 +0,0 @@
|
||||
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)
|
@@ -1,163 +0,0 @@
|
||||
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)
|
@@ -1,175 +0,0 @@
|
||||
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)
|
@@ -1,185 +0,0 @@
|
||||
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))
|
@@ -1,203 +0,0 @@
|
||||
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)
|
@@ -1,63 +0,0 @@
|
||||
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)
|
@@ -1,49 +0,0 @@
|
||||
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))
|
@@ -1,22 +0,0 @@
|
||||
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)
|
@@ -1,359 +0,0 @@
|
||||
"""
|
||||
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
|
||||
|
||||
#
|
||||
# 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)
|
Reference in New Issue
Block a user