8th day of python challenges 111-117
This commit is contained in:
@@ -0,0 +1,224 @@
|
||||
/* File: wrapmodule.c
|
||||
* This file is auto-generated with f2py (version:2_1330).
|
||||
* Hand edited by Pearu.
|
||||
* f2py is a Fortran to Python Interface Generator (FPIG), Second Edition,
|
||||
* written by Pearu Peterson <pearu@cens.ioc.ee>.
|
||||
* See http://cens.ioc.ee/projects/f2py2e/
|
||||
* Generation date: Fri Oct 21 22:41:12 2005
|
||||
* $Revision:$
|
||||
* $Date:$
|
||||
* Do not edit this file directly unless you know what you are doing!!!
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************** See f2py2e/cfuncs.py: includes ***********************/
|
||||
#include "Python.h"
|
||||
#include "fortranobject.h"
|
||||
#include <math.h>
|
||||
|
||||
static PyObject *wrap_error;
|
||||
static PyObject *wrap_module;
|
||||
|
||||
/************************************ call ************************************/
|
||||
static char doc_f2py_rout_wrap_call[] = "\
|
||||
Function signature:\n\
|
||||
arr = call(type_num,dims,intent,obj)\n\
|
||||
Required arguments:\n"
|
||||
" type_num : input int\n"
|
||||
" dims : input int-sequence\n"
|
||||
" intent : input int\n"
|
||||
" obj : input python object\n"
|
||||
"Return objects:\n"
|
||||
" arr : array";
|
||||
static PyObject *f2py_rout_wrap_call(PyObject *capi_self,
|
||||
PyObject *capi_args) {
|
||||
PyObject * volatile capi_buildvalue = NULL;
|
||||
int type_num = 0;
|
||||
npy_intp *dims = NULL;
|
||||
PyObject *dims_capi = Py_None;
|
||||
int rank = 0;
|
||||
int intent = 0;
|
||||
PyArrayObject *capi_arr_tmp = NULL;
|
||||
PyObject *arr_capi = Py_None;
|
||||
int i;
|
||||
|
||||
if (!PyArg_ParseTuple(capi_args,"iOiO|:wrap.call",\
|
||||
&type_num,&dims_capi,&intent,&arr_capi))
|
||||
return NULL;
|
||||
rank = PySequence_Length(dims_capi);
|
||||
dims = malloc(rank*sizeof(npy_intp));
|
||||
for (i=0;i<rank;++i)
|
||||
dims[i] = (npy_intp)PyInt_AsLong(PySequence_GetItem(dims_capi,i));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static char doc_f2py_rout_wrap_attrs[] = "\
|
||||
Function signature:\n\
|
||||
arr = array_attrs(arr)\n\
|
||||
Required arguments:\n"
|
||||
" arr : input array object\n"
|
||||
"Return objects:\n"
|
||||
" data : data address in hex\n"
|
||||
" nd : int\n"
|
||||
" dimensions : tuple\n"
|
||||
" strides : tuple\n"
|
||||
" base : python object\n"
|
||||
" (kind,type,type_num,elsize,alignment) : 4-tuple\n"
|
||||
" flags : int\n"
|
||||
" itemsize : int\n"
|
||||
;
|
||||
static PyObject *f2py_rout_wrap_attrs(PyObject *capi_self,
|
||||
PyObject *capi_args) {
|
||||
PyObject *arr_capi = Py_None;
|
||||
PyArrayObject *arr = NULL;
|
||||
PyObject *dimensions = NULL;
|
||||
PyObject *strides = NULL;
|
||||
char s[100];
|
||||
int i;
|
||||
memset(s,0,100*sizeof(char));
|
||||
if (!PyArg_ParseTuple(capi_args,"O!|:wrap.attrs",
|
||||
&PyArray_Type,&arr_capi))
|
||||
return NULL;
|
||||
arr = (PyArrayObject *)arr_capi;
|
||||
sprintf(s,"%p",PyArray_DATA(arr));
|
||||
dimensions = PyTuple_New(PyArray_NDIM(arr));
|
||||
strides = PyTuple_New(PyArray_NDIM(arr));
|
||||
for (i=0;i<PyArray_NDIM(arr);++i) {
|
||||
PyTuple_SetItem(dimensions,i,PyInt_FromLong(PyArray_DIM(arr,i)));
|
||||
PyTuple_SetItem(strides,i,PyInt_FromLong(PyArray_STRIDE(arr,i)));
|
||||
}
|
||||
return Py_BuildValue("siOOO(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}
|
||||
};
|
||||
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
static struct PyModuleDef moduledef = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"test_array_from_pyobj_ext",
|
||||
NULL,
|
||||
-1,
|
||||
f2py_module_methods,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
#define RETVAL m
|
||||
PyMODINIT_FUNC PyInit_test_array_from_pyobj_ext(void) {
|
||||
#else
|
||||
#define RETVAL
|
||||
PyMODINIT_FUNC inittest_array_from_pyobj_ext(void) {
|
||||
#endif
|
||||
PyObject *m,*d, *s;
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
m = wrap_module = PyModule_Create(&moduledef);
|
||||
#else
|
||||
m = wrap_module = Py_InitModule("test_array_from_pyobj_ext", f2py_module_methods);
|
||||
#endif
|
||||
Py_TYPE(&PyFortran_Type) = &PyType_Type;
|
||||
import_array();
|
||||
if (PyErr_Occurred())
|
||||
Py_FatalError("can't initialize module wrap (failed to import numpy)");
|
||||
d = PyModule_GetDict(m);
|
||||
s = PyString_FromString("This module 'wrap' is auto-generated with f2py (version:2_1330).\nFunctions:\n"
|
||||
" arr = call(type_num,dims,intent,obj)\n"
|
||||
".");
|
||||
PyDict_SetItemString(d, "__doc__", s);
|
||||
wrap_error = PyErr_NewException ("wrap.error", NULL, NULL);
|
||||
Py_DECREF(s);
|
||||
PyDict_SetItemString(d, "F2PY_INTENT_IN", PyInt_FromLong(F2PY_INTENT_IN));
|
||||
PyDict_SetItemString(d, "F2PY_INTENT_INOUT", PyInt_FromLong(F2PY_INTENT_INOUT));
|
||||
PyDict_SetItemString(d, "F2PY_INTENT_OUT", PyInt_FromLong(F2PY_INTENT_OUT));
|
||||
PyDict_SetItemString(d, "F2PY_INTENT_HIDE", PyInt_FromLong(F2PY_INTENT_HIDE));
|
||||
PyDict_SetItemString(d, "F2PY_INTENT_CACHE", PyInt_FromLong(F2PY_INTENT_CACHE));
|
||||
PyDict_SetItemString(d, "F2PY_INTENT_COPY", PyInt_FromLong(F2PY_INTENT_COPY));
|
||||
PyDict_SetItemString(d, "F2PY_INTENT_C", PyInt_FromLong(F2PY_INTENT_C));
|
||||
PyDict_SetItemString(d, "F2PY_OPTIONAL", PyInt_FromLong(F2PY_OPTIONAL));
|
||||
PyDict_SetItemString(d, "F2PY_INTENT_INPLACE", PyInt_FromLong(F2PY_INTENT_INPLACE));
|
||||
PyDict_SetItemString(d, "NPY_BOOL", PyInt_FromLong(NPY_BOOL));
|
||||
PyDict_SetItemString(d, "NPY_BYTE", PyInt_FromLong(NPY_BYTE));
|
||||
PyDict_SetItemString(d, "NPY_UBYTE", PyInt_FromLong(NPY_UBYTE));
|
||||
PyDict_SetItemString(d, "NPY_SHORT", PyInt_FromLong(NPY_SHORT));
|
||||
PyDict_SetItemString(d, "NPY_USHORT", PyInt_FromLong(NPY_USHORT));
|
||||
PyDict_SetItemString(d, "NPY_INT", PyInt_FromLong(NPY_INT));
|
||||
PyDict_SetItemString(d, "NPY_UINT", PyInt_FromLong(NPY_UINT));
|
||||
PyDict_SetItemString(d, "NPY_INTP", PyInt_FromLong(NPY_INTP));
|
||||
PyDict_SetItemString(d, "NPY_UINTP", PyInt_FromLong(NPY_UINTP));
|
||||
PyDict_SetItemString(d, "NPY_LONG", PyInt_FromLong(NPY_LONG));
|
||||
PyDict_SetItemString(d, "NPY_ULONG", PyInt_FromLong(NPY_ULONG));
|
||||
PyDict_SetItemString(d, "NPY_LONGLONG", PyInt_FromLong(NPY_LONGLONG));
|
||||
PyDict_SetItemString(d, "NPY_ULONGLONG", PyInt_FromLong(NPY_ULONGLONG));
|
||||
PyDict_SetItemString(d, "NPY_FLOAT", PyInt_FromLong(NPY_FLOAT));
|
||||
PyDict_SetItemString(d, "NPY_DOUBLE", PyInt_FromLong(NPY_DOUBLE));
|
||||
PyDict_SetItemString(d, "NPY_LONGDOUBLE", PyInt_FromLong(NPY_LONGDOUBLE));
|
||||
PyDict_SetItemString(d, "NPY_CFLOAT", PyInt_FromLong(NPY_CFLOAT));
|
||||
PyDict_SetItemString(d, "NPY_CDOUBLE", PyInt_FromLong(NPY_CDOUBLE));
|
||||
PyDict_SetItemString(d, "NPY_CLONGDOUBLE", PyInt_FromLong(NPY_CLONGDOUBLE));
|
||||
PyDict_SetItemString(d, "NPY_OBJECT", PyInt_FromLong(NPY_OBJECT));
|
||||
PyDict_SetItemString(d, "NPY_STRING", PyInt_FromLong(NPY_STRING));
|
||||
PyDict_SetItemString(d, "NPY_UNICODE", PyInt_FromLong(NPY_UNICODE));
|
||||
PyDict_SetItemString(d, "NPY_VOID", PyInt_FromLong(NPY_VOID));
|
||||
PyDict_SetItemString(d, "NPY_NTYPES", PyInt_FromLong(NPY_NTYPES));
|
||||
PyDict_SetItemString(d, "NPY_NOTYPE", PyInt_FromLong(NPY_NOTYPE));
|
||||
PyDict_SetItemString(d, "NPY_USERDEF", PyInt_FromLong(NPY_USERDEF));
|
||||
|
||||
PyDict_SetItemString(d, "CONTIGUOUS", PyInt_FromLong(NPY_ARRAY_C_CONTIGUOUS));
|
||||
PyDict_SetItemString(d, "FORTRAN", PyInt_FromLong(NPY_ARRAY_F_CONTIGUOUS));
|
||||
PyDict_SetItemString(d, "OWNDATA", PyInt_FromLong(NPY_ARRAY_OWNDATA));
|
||||
PyDict_SetItemString(d, "FORCECAST", PyInt_FromLong(NPY_ARRAY_FORCECAST));
|
||||
PyDict_SetItemString(d, "ENSURECOPY", PyInt_FromLong(NPY_ARRAY_ENSURECOPY));
|
||||
PyDict_SetItemString(d, "ENSUREARRAY", PyInt_FromLong(NPY_ARRAY_ENSUREARRAY));
|
||||
PyDict_SetItemString(d, "ALIGNED", PyInt_FromLong(NPY_ARRAY_ALIGNED));
|
||||
PyDict_SetItemString(d, "WRITEABLE", PyInt_FromLong(NPY_ARRAY_WRITEABLE));
|
||||
PyDict_SetItemString(d, "UPDATEIFCOPY", PyInt_FromLong(NPY_ARRAY_UPDATEIFCOPY));
|
||||
PyDict_SetItemString(d, "WRITEBACKIFCOPY", PyInt_FromLong(NPY_ARRAY_WRITEBACKIFCOPY));
|
||||
|
||||
PyDict_SetItemString(d, "BEHAVED", PyInt_FromLong(NPY_ARRAY_BEHAVED));
|
||||
PyDict_SetItemString(d, "BEHAVED_NS", PyInt_FromLong(NPY_ARRAY_BEHAVED_NS));
|
||||
PyDict_SetItemString(d, "CARRAY", PyInt_FromLong(NPY_ARRAY_CARRAY));
|
||||
PyDict_SetItemString(d, "FARRAY", PyInt_FromLong(NPY_ARRAY_FARRAY));
|
||||
PyDict_SetItemString(d, "CARRAY_RO", PyInt_FromLong(NPY_ARRAY_CARRAY_RO));
|
||||
PyDict_SetItemString(d, "FARRAY_RO", PyInt_FromLong(NPY_ARRAY_FARRAY_RO));
|
||||
PyDict_SetItemString(d, "DEFAULT", PyInt_FromLong(NPY_ARRAY_DEFAULT));
|
||||
PyDict_SetItemString(d, "UPDATE_ALL", PyInt_FromLong(NPY_ARRAY_UPDATE_ALL));
|
||||
|
||||
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 RETVAL;
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
dict(real=dict(rk="double"))
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
subroutine sum(x, res)
|
||||
implicit none
|
||||
real, intent(in) :: x(:)
|
||||
real, intent(out) :: res
|
||||
|
||||
integer :: i
|
||||
|
||||
!print *, "sum: size(x) = ", size(x)
|
||||
|
||||
res = 0.0
|
||||
|
||||
do i = 1, size(x)
|
||||
res = res + x(i)
|
||||
enddo
|
||||
|
||||
end subroutine sum
|
||||
|
||||
function fsum(x) result (res)
|
||||
implicit none
|
||||
real, intent(in) :: x(:)
|
||||
real :: res
|
||||
|
||||
integer :: i
|
||||
|
||||
!print *, "fsum: size(x) = ", size(x)
|
||||
|
||||
res = 0.0
|
||||
|
||||
do i = 1, size(x)
|
||||
res = res + x(i)
|
||||
enddo
|
||||
|
||||
end function fsum
|
||||
@@ -0,0 +1,41 @@
|
||||
|
||||
module mod
|
||||
|
||||
contains
|
||||
|
||||
subroutine sum(x, res)
|
||||
implicit none
|
||||
real, intent(in) :: x(:)
|
||||
real, intent(out) :: res
|
||||
|
||||
integer :: i
|
||||
|
||||
!print *, "sum: size(x) = ", size(x)
|
||||
|
||||
res = 0.0
|
||||
|
||||
do i = 1, size(x)
|
||||
res = res + x(i)
|
||||
enddo
|
||||
|
||||
end subroutine sum
|
||||
|
||||
function fsum(x) result (res)
|
||||
implicit none
|
||||
real, intent(in) :: x(:)
|
||||
real :: res
|
||||
|
||||
integer :: i
|
||||
|
||||
!print *, "fsum: size(x) = ", size(x)
|
||||
|
||||
res = 0.0
|
||||
|
||||
do i = 1, size(x)
|
||||
res = res + x(i)
|
||||
enddo
|
||||
|
||||
end function fsum
|
||||
|
||||
|
||||
end module mod
|
||||
@@ -0,0 +1,19 @@
|
||||
subroutine sum_with_use(x, res)
|
||||
use precision
|
||||
|
||||
implicit none
|
||||
|
||||
real(kind=rk), intent(in) :: x(:)
|
||||
real(kind=rk), intent(out) :: res
|
||||
|
||||
integer :: i
|
||||
|
||||
!print *, "size(x) = ", size(x)
|
||||
|
||||
res = 0.0
|
||||
|
||||
do i = 1, size(x)
|
||||
res = res + x(i)
|
||||
enddo
|
||||
|
||||
end subroutine
|
||||
@@ -0,0 +1,4 @@
|
||||
module precision
|
||||
integer, parameter :: rk = selected_real_kind(8)
|
||||
integer, parameter :: ik = selected_real_kind(4)
|
||||
end module
|
||||
@@ -0,0 +1,11 @@
|
||||
SUBROUTINE INITCB
|
||||
DOUBLE PRECISION LONG
|
||||
CHARACTER STRING
|
||||
INTEGER OK
|
||||
|
||||
COMMON /BLOCK/ LONG, STRING, OK
|
||||
LONG = 1.0
|
||||
STRING = '2'
|
||||
OK = 3
|
||||
RETURN
|
||||
END
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
|
||||
subroutine selectedrealkind(p, r, res)
|
||||
implicit none
|
||||
|
||||
integer, intent(in) :: p, r
|
||||
!f2py integer :: r=0
|
||||
integer, intent(out) :: res
|
||||
res = selected_real_kind(p, r)
|
||||
|
||||
end subroutine
|
||||
|
||||
subroutine selectedintkind(p, res)
|
||||
implicit none
|
||||
|
||||
integer, intent(in) :: p
|
||||
integer, intent(out) :: res
|
||||
res = selected_int_kind(p)
|
||||
|
||||
end subroutine
|
||||
@@ -0,0 +1,5 @@
|
||||
subroutine bar11(a)
|
||||
cf2py intent(out) a
|
||||
integer a
|
||||
a = 11
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
module foo_fixed
|
||||
contains
|
||||
subroutine bar12(a)
|
||||
!f2py intent(out) a
|
||||
integer a
|
||||
a = 12
|
||||
end subroutine bar12
|
||||
end module foo_fixed
|
||||
@@ -0,0 +1,8 @@
|
||||
module foo_free
|
||||
contains
|
||||
subroutine bar13(a)
|
||||
!f2py intent(out) a
|
||||
integer a
|
||||
a = 13
|
||||
end subroutine bar13
|
||||
end module foo_free
|
||||
@@ -0,0 +1,57 @@
|
||||
! Check that parameters are correct intercepted.
|
||||
! Constants with comma separations are commonly
|
||||
! used, for instance Pi = 3._dp
|
||||
subroutine foo(x)
|
||||
implicit none
|
||||
integer, parameter :: sp = selected_real_kind(6)
|
||||
integer, parameter :: dp = selected_real_kind(15)
|
||||
integer, parameter :: ii = selected_int_kind(9)
|
||||
integer, parameter :: il = selected_int_kind(18)
|
||||
real(dp), intent(inout) :: x
|
||||
dimension x(3)
|
||||
real(sp), parameter :: three_s = 3._sp
|
||||
real(dp), parameter :: three_d = 3._dp
|
||||
integer(ii), parameter :: three_i = 3_ii
|
||||
integer(il), parameter :: three_l = 3_il
|
||||
x(1) = x(1) + x(2) * three_s * three_i + x(3) * three_d * three_l
|
||||
x(2) = x(2) * three_s
|
||||
x(3) = x(3) * three_l
|
||||
return
|
||||
end subroutine
|
||||
|
||||
|
||||
subroutine foo_no(x)
|
||||
implicit none
|
||||
integer, parameter :: sp = selected_real_kind(6)
|
||||
integer, parameter :: dp = selected_real_kind(15)
|
||||
integer, parameter :: ii = selected_int_kind(9)
|
||||
integer, parameter :: il = selected_int_kind(18)
|
||||
real(dp), intent(inout) :: x
|
||||
dimension x(3)
|
||||
real(sp), parameter :: three_s = 3.
|
||||
real(dp), parameter :: three_d = 3.
|
||||
integer(ii), parameter :: three_i = 3
|
||||
integer(il), parameter :: three_l = 3
|
||||
x(1) = x(1) + x(2) * three_s * three_i + x(3) * three_d * three_l
|
||||
x(2) = x(2) * three_s
|
||||
x(3) = x(3) * three_l
|
||||
return
|
||||
end subroutine
|
||||
|
||||
subroutine foo_sum(x)
|
||||
implicit none
|
||||
integer, parameter :: sp = selected_real_kind(6)
|
||||
integer, parameter :: dp = selected_real_kind(15)
|
||||
integer, parameter :: ii = selected_int_kind(9)
|
||||
integer, parameter :: il = selected_int_kind(18)
|
||||
real(dp), intent(inout) :: x
|
||||
dimension x(3)
|
||||
real(sp), parameter :: three_s = 2._sp + 1._sp
|
||||
real(dp), parameter :: three_d = 1._dp + 2._dp
|
||||
integer(ii), parameter :: three_i = 2_ii + 1_ii
|
||||
integer(il), parameter :: three_l = 1_il + 2_il
|
||||
x(1) = x(1) + x(2) * three_s * three_i + x(3) * three_d * three_l
|
||||
x(2) = x(2) * three_s
|
||||
x(3) = x(3) * three_l
|
||||
return
|
||||
end subroutine
|
||||
@@ -0,0 +1,15 @@
|
||||
! Check that parameters are correct intercepted.
|
||||
! Constants with comma separations are commonly
|
||||
! used, for instance Pi = 3._dp
|
||||
subroutine foo_compound_int(x)
|
||||
implicit none
|
||||
integer, parameter :: ii = selected_int_kind(9)
|
||||
integer(ii), intent(inout) :: x
|
||||
dimension x(3)
|
||||
integer(ii), parameter :: three = 3_ii
|
||||
integer(ii), parameter :: two = 2_ii
|
||||
integer(ii), parameter :: six = three * 1_ii * two
|
||||
|
||||
x(1) = x(1) + x(2) + x(3) * six
|
||||
return
|
||||
end subroutine
|
||||
@@ -0,0 +1,22 @@
|
||||
! Check that parameters are correct intercepted.
|
||||
! Constants with comma separations are commonly
|
||||
! used, for instance Pi = 3._dp
|
||||
subroutine foo_int(x)
|
||||
implicit none
|
||||
integer, parameter :: ii = selected_int_kind(9)
|
||||
integer(ii), intent(inout) :: x
|
||||
dimension x(3)
|
||||
integer(ii), parameter :: three = 3_ii
|
||||
x(1) = x(1) + x(2) + x(3) * three
|
||||
return
|
||||
end subroutine
|
||||
|
||||
subroutine foo_long(x)
|
||||
implicit none
|
||||
integer, parameter :: ii = selected_int_kind(18)
|
||||
integer(ii), intent(inout) :: x
|
||||
dimension x(3)
|
||||
integer(ii), parameter :: three = 3_ii
|
||||
x(1) = x(1) + x(2) + x(3) * three
|
||||
return
|
||||
end subroutine
|
||||
@@ -0,0 +1,23 @@
|
||||
! Check that parameters are correct intercepted.
|
||||
! Specifically that types of constants without
|
||||
! compound kind specs are correctly inferred
|
||||
! adapted Gibbs iteration code from pymc
|
||||
! for this test case
|
||||
subroutine foo_non_compound_int(x)
|
||||
implicit none
|
||||
integer, parameter :: ii = selected_int_kind(9)
|
||||
|
||||
integer(ii) maxiterates
|
||||
parameter (maxiterates=2)
|
||||
|
||||
integer(ii) maxseries
|
||||
parameter (maxseries=2)
|
||||
|
||||
integer(ii) wasize
|
||||
parameter (wasize=maxiterates*maxseries)
|
||||
integer(ii), intent(inout) :: x
|
||||
dimension x(wasize)
|
||||
|
||||
x(1) = x(1) + x(2) + x(3) + x(4) * wasize
|
||||
return
|
||||
end subroutine
|
||||
@@ -0,0 +1,23 @@
|
||||
! Check that parameters are correct intercepted.
|
||||
! Constants with comma separations are commonly
|
||||
! used, for instance Pi = 3._dp
|
||||
subroutine foo_single(x)
|
||||
implicit none
|
||||
integer, parameter :: rp = selected_real_kind(6)
|
||||
real(rp), intent(inout) :: x
|
||||
dimension x(3)
|
||||
real(rp), parameter :: three = 3._rp
|
||||
x(1) = x(1) + x(2) + x(3) * three
|
||||
return
|
||||
end subroutine
|
||||
|
||||
subroutine foo_double(x)
|
||||
implicit none
|
||||
integer, parameter :: rp = selected_real_kind(15)
|
||||
real(rp), intent(inout) :: x
|
||||
dimension x(3)
|
||||
real(rp), parameter :: three = 3._rp
|
||||
x(1) = x(1) + x(2) + x(3) * three
|
||||
return
|
||||
end subroutine
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
! Check that intent(in out) translates as intent(inout).
|
||||
! The separation seems to be a common usage.
|
||||
subroutine foo(x)
|
||||
implicit none
|
||||
real(4), intent(in out) :: x
|
||||
dimension x(3)
|
||||
x(1) = x(1) + x(2) + x(3)
|
||||
return
|
||||
end
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
subroutine foo(a, n, m, b)
|
||||
implicit none
|
||||
|
||||
real, intent(in) :: a(n, m)
|
||||
integer, intent(in) :: n, m
|
||||
real, intent(out) :: b(size(a, 1))
|
||||
|
||||
integer :: i
|
||||
|
||||
do i = 1, size(b)
|
||||
b(i) = sum(a(i,:))
|
||||
enddo
|
||||
end subroutine
|
||||
|
||||
subroutine trans(x,y)
|
||||
implicit none
|
||||
real, intent(in), dimension(:,:) :: x
|
||||
real, intent(out), dimension( size(x,2), size(x,1) ) :: y
|
||||
integer :: N, M, i, j
|
||||
N = size(x,1)
|
||||
M = size(x,2)
|
||||
DO i=1,N
|
||||
do j=1,M
|
||||
y(j,i) = x(i,j)
|
||||
END DO
|
||||
END DO
|
||||
end subroutine trans
|
||||
|
||||
subroutine flatten(x,y)
|
||||
implicit none
|
||||
real, intent(in), dimension(:,:) :: x
|
||||
real, intent(out), dimension( size(x) ) :: y
|
||||
integer :: N, M, i, j, k
|
||||
N = size(x,1)
|
||||
M = size(x,2)
|
||||
k = 1
|
||||
DO i=1,N
|
||||
do j=1,M
|
||||
y(k) = x(i,j)
|
||||
k = k + 1
|
||||
END DO
|
||||
END DO
|
||||
end subroutine flatten
|
||||
@@ -0,0 +1,29 @@
|
||||
MODULE char_test
|
||||
|
||||
CONTAINS
|
||||
|
||||
SUBROUTINE change_strings(strings, n_strs, out_strings)
|
||||
IMPLICIT NONE
|
||||
|
||||
! Inputs
|
||||
INTEGER, INTENT(IN) :: n_strs
|
||||
CHARACTER, INTENT(IN), DIMENSION(2,n_strs) :: strings
|
||||
CHARACTER, INTENT(OUT), DIMENSION(2,n_strs) :: out_strings
|
||||
|
||||
!f2py INTEGER, INTENT(IN) :: n_strs
|
||||
!f2py CHARACTER, INTENT(IN), DIMENSION(2,n_strs) :: strings
|
||||
!f2py CHARACTER, INTENT(OUT), DIMENSION(2,n_strs) :: strings
|
||||
|
||||
! Misc.
|
||||
INTEGER*4 :: j
|
||||
|
||||
|
||||
DO j=1, n_strs
|
||||
out_strings(1,j) = strings(1,j)
|
||||
out_strings(2,j) = 'A'
|
||||
END DO
|
||||
|
||||
END SUBROUTINE change_strings
|
||||
|
||||
END MODULE char_test
|
||||
|
||||
@@ -0,0 +1,581 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
import copy
|
||||
import pytest
|
||||
|
||||
from numpy import (
|
||||
array, alltrue, ndarray, zeros, dtype, intp, clongdouble
|
||||
)
|
||||
from numpy.testing import assert_, assert_equal
|
||||
from numpy.core.multiarray import typeinfo
|
||||
from . import util
|
||||
|
||||
wrap = None
|
||||
|
||||
|
||||
def setup_module():
|
||||
"""
|
||||
Build the required testing extension module
|
||||
|
||||
"""
|
||||
global wrap
|
||||
|
||||
# Check compiler availability first
|
||||
if not util.has_c_compiler():
|
||||
pytest.skip("No C compiler available")
|
||||
|
||||
if wrap is None:
|
||||
config_code = """
|
||||
config.add_extension('test_array_from_pyobj_ext',
|
||||
sources=['wrapmodule.c', 'fortranobject.c'],
|
||||
define_macros=[])
|
||||
"""
|
||||
d = os.path.dirname(__file__)
|
||||
src = [os.path.join(d, 'src', 'array_from_pyobj', 'wrapmodule.c'),
|
||||
os.path.join(d, '..', 'src', 'fortranobject.c'),
|
||||
os.path.join(d, '..', 'src', 'fortranobject.h')]
|
||||
wrap = util.build_module_distutils(src, config_code,
|
||||
'test_array_from_pyobj_ext')
|
||||
|
||||
|
||||
def flags_info(arr):
|
||||
flags = wrap.array_attrs(arr)[6]
|
||||
return flags2names(flags)
|
||||
|
||||
|
||||
def flags2names(flags):
|
||||
info = []
|
||||
for flagname in ['CONTIGUOUS', 'FORTRAN', 'OWNDATA', 'ENSURECOPY',
|
||||
'ENSUREARRAY', 'ALIGNED', 'NOTSWAPPED', 'WRITEABLE',
|
||||
'WRITEBACKIFCOPY', 'UPDATEIFCOPY', 'BEHAVED', 'BEHAVED_RO',
|
||||
'CARRAY', 'FARRAY'
|
||||
]:
|
||||
if abs(flags) & getattr(wrap, flagname, 0):
|
||||
info.append(flagname)
|
||||
return info
|
||||
|
||||
|
||||
class Intent(object):
|
||||
|
||||
def __init__(self, intent_list=[]):
|
||||
self.intent_list = intent_list[:]
|
||||
flags = 0
|
||||
for i in intent_list:
|
||||
if i == 'optional':
|
||||
flags |= wrap.F2PY_OPTIONAL
|
||||
else:
|
||||
flags |= getattr(wrap, 'F2PY_INTENT_' + i.upper())
|
||||
self.flags = flags
|
||||
|
||||
def __getattr__(self, name):
|
||||
name = name.lower()
|
||||
if name == 'in_':
|
||||
name = 'in'
|
||||
return self.__class__(self.intent_list + [name])
|
||||
|
||||
def __str__(self):
|
||||
return 'intent(%s)' % (','.join(self.intent_list))
|
||||
|
||||
def __repr__(self):
|
||||
return 'Intent(%r)' % (self.intent_list)
|
||||
|
||||
def is_intent(self, *names):
|
||||
for name in names:
|
||||
if name not in self.intent_list:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_intent_exact(self, *names):
|
||||
return len(self.intent_list) == len(names) and self.is_intent(*names)
|
||||
|
||||
intent = Intent()
|
||||
|
||||
_type_names = ['BOOL', 'BYTE', 'UBYTE', 'SHORT', 'USHORT', 'INT', 'UINT',
|
||||
'LONG', 'ULONG', 'LONGLONG', 'ULONGLONG',
|
||||
'FLOAT', 'DOUBLE', 'CFLOAT']
|
||||
|
||||
_cast_dict = {'BOOL': ['BOOL']}
|
||||
_cast_dict['BYTE'] = _cast_dict['BOOL'] + ['BYTE']
|
||||
_cast_dict['UBYTE'] = _cast_dict['BOOL'] + ['UBYTE']
|
||||
_cast_dict['BYTE'] = ['BYTE']
|
||||
_cast_dict['UBYTE'] = ['UBYTE']
|
||||
_cast_dict['SHORT'] = _cast_dict['BYTE'] + ['UBYTE', 'SHORT']
|
||||
_cast_dict['USHORT'] = _cast_dict['UBYTE'] + ['BYTE', 'USHORT']
|
||||
_cast_dict['INT'] = _cast_dict['SHORT'] + ['USHORT', 'INT']
|
||||
_cast_dict['UINT'] = _cast_dict['USHORT'] + ['SHORT', 'UINT']
|
||||
|
||||
_cast_dict['LONG'] = _cast_dict['INT'] + ['LONG']
|
||||
_cast_dict['ULONG'] = _cast_dict['UINT'] + ['ULONG']
|
||||
|
||||
_cast_dict['LONGLONG'] = _cast_dict['LONG'] + ['LONGLONG']
|
||||
_cast_dict['ULONGLONG'] = _cast_dict['ULONG'] + ['ULONGLONG']
|
||||
|
||||
_cast_dict['FLOAT'] = _cast_dict['SHORT'] + ['USHORT', 'FLOAT']
|
||||
_cast_dict['DOUBLE'] = _cast_dict['INT'] + ['UINT', 'FLOAT', 'DOUBLE']
|
||||
|
||||
_cast_dict['CFLOAT'] = _cast_dict['FLOAT'] + ['CFLOAT']
|
||||
|
||||
# 32 bit system malloc typically does not provide the alignment required by
|
||||
# 16 byte long double types this means the inout intent cannot be satisfied
|
||||
# and several tests fail as the alignment flag can be randomly true or fals
|
||||
# when numpy gains an aligned allocator the tests could be enabled again
|
||||
if ((intp().dtype.itemsize != 4 or clongdouble().dtype.alignment <= 8) and
|
||||
sys.platform != 'win32'):
|
||||
_type_names.extend(['LONGDOUBLE', 'CDOUBLE', 'CLONGDOUBLE'])
|
||||
_cast_dict['LONGDOUBLE'] = _cast_dict['LONG'] + \
|
||||
['ULONG', 'FLOAT', 'DOUBLE', 'LONGDOUBLE']
|
||||
_cast_dict['CLONGDOUBLE'] = _cast_dict['LONGDOUBLE'] + \
|
||||
['CFLOAT', 'CDOUBLE', 'CLONGDOUBLE']
|
||||
_cast_dict['CDOUBLE'] = _cast_dict['DOUBLE'] + ['CFLOAT', 'CDOUBLE']
|
||||
|
||||
|
||||
class Type(object):
|
||||
_type_cache = {}
|
||||
|
||||
def __new__(cls, name):
|
||||
if isinstance(name, dtype):
|
||||
dtype0 = name
|
||||
name = None
|
||||
for n, i in typeinfo.items():
|
||||
if not isinstance(i, type) and dtype0.type is i.type:
|
||||
name = n
|
||||
break
|
||||
obj = cls._type_cache.get(name.upper(), None)
|
||||
if obj is not None:
|
||||
return obj
|
||||
obj = object.__new__(cls)
|
||||
obj._init(name)
|
||||
cls._type_cache[name.upper()] = obj
|
||||
return obj
|
||||
|
||||
def _init(self, name):
|
||||
self.NAME = name.upper()
|
||||
info = typeinfo[self.NAME]
|
||||
self.type_num = getattr(wrap, 'NPY_' + self.NAME)
|
||||
assert_equal(self.type_num, info.num)
|
||||
self.dtype = info.type
|
||||
self.elsize = info.bits / 8
|
||||
self.dtypechar = info.char
|
||||
|
||||
def cast_types(self):
|
||||
return [self.__class__(_m) for _m in _cast_dict[self.NAME]]
|
||||
|
||||
def all_types(self):
|
||||
return [self.__class__(_m) for _m in _type_names]
|
||||
|
||||
def smaller_types(self):
|
||||
bits = typeinfo[self.NAME].alignment
|
||||
types = []
|
||||
for name in _type_names:
|
||||
if typeinfo[name].alignment < bits:
|
||||
types.append(Type(name))
|
||||
return types
|
||||
|
||||
def equal_types(self):
|
||||
bits = typeinfo[self.NAME].alignment
|
||||
types = []
|
||||
for name in _type_names:
|
||||
if name == self.NAME:
|
||||
continue
|
||||
if typeinfo[name].alignment == bits:
|
||||
types.append(Type(name))
|
||||
return types
|
||||
|
||||
def larger_types(self):
|
||||
bits = typeinfo[self.NAME].alignment
|
||||
types = []
|
||||
for name in _type_names:
|
||||
if typeinfo[name].alignment > bits:
|
||||
types.append(Type(name))
|
||||
return types
|
||||
|
||||
|
||||
class Array(object):
|
||||
|
||||
def __init__(self, typ, dims, intent, obj):
|
||||
self.type = typ
|
||||
self.dims = dims
|
||||
self.intent = intent
|
||||
self.obj_copy = copy.deepcopy(obj)
|
||||
self.obj = obj
|
||||
|
||||
# arr.dtypechar may be different from typ.dtypechar
|
||||
self.arr = wrap.call(typ.type_num, dims, intent.flags, obj)
|
||||
|
||||
assert_(isinstance(self.arr, ndarray), repr(type(self.arr)))
|
||||
|
||||
self.arr_attr = wrap.array_attrs(self.arr)
|
||||
|
||||
if len(dims) > 1:
|
||||
if self.intent.is_intent('c'):
|
||||
assert_(intent.flags & wrap.F2PY_INTENT_C)
|
||||
assert_(not self.arr.flags['FORTRAN'],
|
||||
repr((self.arr.flags, getattr(obj, 'flags', None))))
|
||||
assert_(self.arr.flags['CONTIGUOUS'])
|
||||
assert_(not self.arr_attr[6] & wrap.FORTRAN)
|
||||
else:
|
||||
assert_(not intent.flags & wrap.F2PY_INTENT_C)
|
||||
assert_(self.arr.flags['FORTRAN'])
|
||||
assert_(not self.arr.flags['CONTIGUOUS'])
|
||||
assert_(self.arr_attr[6] & wrap.FORTRAN)
|
||||
|
||||
if obj is None:
|
||||
self.pyarr = None
|
||||
self.pyarr_attr = None
|
||||
return
|
||||
|
||||
if intent.is_intent('cache'):
|
||||
assert_(isinstance(obj, ndarray), repr(type(obj)))
|
||||
self.pyarr = array(obj).reshape(*dims).copy()
|
||||
else:
|
||||
self.pyarr = array(array(obj, dtype=typ.dtypechar).reshape(*dims),
|
||||
order=self.intent.is_intent('c') and 'C' or 'F')
|
||||
assert_(self.pyarr.dtype == typ,
|
||||
repr((self.pyarr.dtype, typ)))
|
||||
assert_(self.pyarr.flags['OWNDATA'], (obj, intent))
|
||||
self.pyarr_attr = wrap.array_attrs(self.pyarr)
|
||||
|
||||
if len(dims) > 1:
|
||||
if self.intent.is_intent('c'):
|
||||
assert_(not self.pyarr.flags['FORTRAN'])
|
||||
assert_(self.pyarr.flags['CONTIGUOUS'])
|
||||
assert_(not self.pyarr_attr[6] & wrap.FORTRAN)
|
||||
else:
|
||||
assert_(self.pyarr.flags['FORTRAN'])
|
||||
assert_(not self.pyarr.flags['CONTIGUOUS'])
|
||||
assert_(self.pyarr_attr[6] & wrap.FORTRAN)
|
||||
|
||||
assert_(self.arr_attr[1] == self.pyarr_attr[1]) # nd
|
||||
assert_(self.arr_attr[2] == self.pyarr_attr[2]) # dimensions
|
||||
if self.arr_attr[1] <= 1:
|
||||
assert_(self.arr_attr[3] == self.pyarr_attr[3],
|
||||
repr((self.arr_attr[3], self.pyarr_attr[3],
|
||||
self.arr.tobytes(), self.pyarr.tobytes()))) # strides
|
||||
assert_(self.arr_attr[5][-2:] == self.pyarr_attr[5][-2:],
|
||||
repr((self.arr_attr[5], self.pyarr_attr[5]))) # descr
|
||||
assert_(self.arr_attr[6] == self.pyarr_attr[6],
|
||||
repr((self.arr_attr[6], self.pyarr_attr[6],
|
||||
flags2names(0 * self.arr_attr[6] - self.pyarr_attr[6]),
|
||||
flags2names(self.arr_attr[6]), intent))) # flags
|
||||
|
||||
if intent.is_intent('cache'):
|
||||
assert_(self.arr_attr[5][3] >= self.type.elsize,
|
||||
repr((self.arr_attr[5][3], self.type.elsize)))
|
||||
else:
|
||||
assert_(self.arr_attr[5][3] == self.type.elsize,
|
||||
repr((self.arr_attr[5][3], self.type.elsize)))
|
||||
assert_(self.arr_equal(self.pyarr, self.arr))
|
||||
|
||||
if isinstance(self.obj, ndarray):
|
||||
if typ.elsize == Type(obj.dtype).elsize:
|
||||
if not intent.is_intent('copy') and self.arr_attr[1] <= 1:
|
||||
assert_(self.has_shared_memory())
|
||||
|
||||
def arr_equal(self, arr1, arr2):
|
||||
if arr1.shape != arr2.shape:
|
||||
return False
|
||||
s = arr1 == arr2
|
||||
return alltrue(s.flatten())
|
||||
|
||||
def __str__(self):
|
||||
return str(self.arr)
|
||||
|
||||
def has_shared_memory(self):
|
||||
"""Check that created array shares data with input array.
|
||||
"""
|
||||
if self.obj is self.arr:
|
||||
return True
|
||||
if not isinstance(self.obj, ndarray):
|
||||
return False
|
||||
obj_attr = wrap.array_attrs(self.obj)
|
||||
return obj_attr[0] == self.arr_attr[0]
|
||||
|
||||
|
||||
class TestIntent(object):
|
||||
|
||||
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(object):
|
||||
num2seq = [1, 2]
|
||||
num23seq = [[1, 2, 3], [4, 5, 6]]
|
||||
|
||||
@pytest.fixture(autouse=True, scope='class', params=_type_names)
|
||||
def setup_type(self, request):
|
||||
request.cls.type = Type(request.param)
|
||||
request.cls.array = lambda self, dims, intent, obj: \
|
||||
Array(Type(request.param), dims, intent, obj)
|
||||
|
||||
def test_in_from_2seq(self):
|
||||
a = self.array([2], intent.in_, self.num2seq)
|
||||
assert_(not a.has_shared_memory())
|
||||
|
||||
def test_in_from_2casttype(self):
|
||||
for t in self.type.cast_types():
|
||||
obj = array(self.num2seq, dtype=t.dtype)
|
||||
a = self.array([len(self.num2seq)], intent.in_, obj)
|
||||
if t.elsize == self.type.elsize:
|
||||
assert_(
|
||||
a.has_shared_memory(), repr((self.type.dtype, t.dtype)))
|
||||
else:
|
||||
assert_(not a.has_shared_memory(), repr(t.dtype))
|
||||
|
||||
def test_inout_2seq(self):
|
||||
obj = array(self.num2seq, dtype=self.type.dtype)
|
||||
a = self.array([len(self.num2seq)], intent.inout, obj)
|
||||
assert_(a.has_shared_memory())
|
||||
|
||||
try:
|
||||
a = self.array([2], intent.in_.inout, self.num2seq)
|
||||
except TypeError as msg:
|
||||
if not str(msg).startswith('failed to initialize intent'
|
||||
'(inout|inplace|cache) array'):
|
||||
raise
|
||||
else:
|
||||
raise SystemError('intent(inout) should have failed on sequence')
|
||||
|
||||
def test_f_inout_23seq(self):
|
||||
obj = array(self.num23seq, dtype=self.type.dtype, order='F')
|
||||
shape = (len(self.num23seq), len(self.num23seq[0]))
|
||||
a = self.array(shape, intent.in_.inout, obj)
|
||||
assert_(a.has_shared_memory())
|
||||
|
||||
obj = array(self.num23seq, dtype=self.type.dtype, order='C')
|
||||
shape = (len(self.num23seq), len(self.num23seq[0]))
|
||||
try:
|
||||
a = self.array(shape, intent.in_.inout, obj)
|
||||
except ValueError as msg:
|
||||
if not str(msg).startswith('failed to initialize intent'
|
||||
'(inout) array'):
|
||||
raise
|
||||
else:
|
||||
raise SystemError(
|
||||
'intent(inout) should have failed on improper array')
|
||||
|
||||
def test_c_inout_23seq(self):
|
||||
obj = array(self.num23seq, dtype=self.type.dtype)
|
||||
shape = (len(self.num23seq), len(self.num23seq[0]))
|
||||
a = self.array(shape, intent.in_.c.inout, obj)
|
||||
assert_(a.has_shared_memory())
|
||||
|
||||
def test_in_copy_from_2casttype(self):
|
||||
for t in self.type.cast_types():
|
||||
obj = array(self.num2seq, dtype=t.dtype)
|
||||
a = self.array([len(self.num2seq)], intent.in_.copy, obj)
|
||||
assert_(not a.has_shared_memory(), repr(t.dtype))
|
||||
|
||||
def test_c_in_from_23seq(self):
|
||||
a = self.array([len(self.num23seq), len(self.num23seq[0])],
|
||||
intent.in_, self.num23seq)
|
||||
assert_(not a.has_shared_memory())
|
||||
|
||||
def test_in_from_23casttype(self):
|
||||
for t in self.type.cast_types():
|
||||
obj = array(self.num23seq, dtype=t.dtype)
|
||||
a = self.array([len(self.num23seq), len(self.num23seq[0])],
|
||||
intent.in_, obj)
|
||||
assert_(not a.has_shared_memory(), repr(t.dtype))
|
||||
|
||||
def test_f_in_from_23casttype(self):
|
||||
for t in self.type.cast_types():
|
||||
obj = array(self.num23seq, dtype=t.dtype, order='F')
|
||||
a = self.array([len(self.num23seq), len(self.num23seq[0])],
|
||||
intent.in_, obj)
|
||||
if t.elsize == self.type.elsize:
|
||||
assert_(a.has_shared_memory(), repr(t.dtype))
|
||||
else:
|
||||
assert_(not a.has_shared_memory(), repr(t.dtype))
|
||||
|
||||
def test_c_in_from_23casttype(self):
|
||||
for t in self.type.cast_types():
|
||||
obj = array(self.num23seq, dtype=t.dtype)
|
||||
a = self.array([len(self.num23seq), len(self.num23seq[0])],
|
||||
intent.in_.c, obj)
|
||||
if t.elsize == self.type.elsize:
|
||||
assert_(a.has_shared_memory(), repr(t.dtype))
|
||||
else:
|
||||
assert_(not a.has_shared_memory(), repr(t.dtype))
|
||||
|
||||
def test_f_copy_in_from_23casttype(self):
|
||||
for t in self.type.cast_types():
|
||||
obj = array(self.num23seq, dtype=t.dtype, order='F')
|
||||
a = self.array([len(self.num23seq), len(self.num23seq[0])],
|
||||
intent.in_.copy, obj)
|
||||
assert_(not a.has_shared_memory(), repr(t.dtype))
|
||||
|
||||
def test_c_copy_in_from_23casttype(self):
|
||||
for t in self.type.cast_types():
|
||||
obj = array(self.num23seq, dtype=t.dtype)
|
||||
a = self.array([len(self.num23seq), len(self.num23seq[0])],
|
||||
intent.in_.c.copy, obj)
|
||||
assert_(not a.has_shared_memory(), repr(t.dtype))
|
||||
|
||||
def test_in_cache_from_2casttype(self):
|
||||
for t in self.type.all_types():
|
||||
if t.elsize != self.type.elsize:
|
||||
continue
|
||||
obj = array(self.num2seq, dtype=t.dtype)
|
||||
shape = (len(self.num2seq),)
|
||||
a = self.array(shape, intent.in_.c.cache, obj)
|
||||
assert_(a.has_shared_memory(), repr(t.dtype))
|
||||
|
||||
a = self.array(shape, intent.in_.cache, obj)
|
||||
assert_(a.has_shared_memory(), repr(t.dtype))
|
||||
|
||||
obj = array(self.num2seq, dtype=t.dtype, order='F')
|
||||
a = self.array(shape, intent.in_.c.cache, obj)
|
||||
assert_(a.has_shared_memory(), repr(t.dtype))
|
||||
|
||||
a = self.array(shape, intent.in_.cache, obj)
|
||||
assert_(a.has_shared_memory(), repr(t.dtype))
|
||||
|
||||
try:
|
||||
a = self.array(shape, intent.in_.cache, obj[::-1])
|
||||
except ValueError as msg:
|
||||
if not str(msg).startswith('failed to initialize'
|
||||
' intent(cache) array'):
|
||||
raise
|
||||
else:
|
||||
raise SystemError(
|
||||
'intent(cache) should have failed on multisegmented array')
|
||||
|
||||
def test_in_cache_from_2casttype_failure(self):
|
||||
for t in self.type.all_types():
|
||||
if t.elsize >= self.type.elsize:
|
||||
continue
|
||||
obj = array(self.num2seq, dtype=t.dtype)
|
||||
shape = (len(self.num2seq),)
|
||||
try:
|
||||
self.array(shape, intent.in_.cache, obj) # Should succeed
|
||||
except ValueError as msg:
|
||||
if not str(msg).startswith('failed to initialize'
|
||||
' intent(cache) array'):
|
||||
raise
|
||||
else:
|
||||
raise SystemError(
|
||||
'intent(cache) should have failed on smaller array')
|
||||
|
||||
def test_cache_hidden(self):
|
||||
shape = (2,)
|
||||
a = self.array(shape, intent.cache.hide, None)
|
||||
assert_(a.arr.shape == shape)
|
||||
|
||||
shape = (2, 3)
|
||||
a = self.array(shape, intent.cache.hide, None)
|
||||
assert_(a.arr.shape == shape)
|
||||
|
||||
shape = (-1, 3)
|
||||
try:
|
||||
a = self.array(shape, intent.cache.hide, None)
|
||||
except ValueError as msg:
|
||||
if not str(msg).startswith('failed to create intent'
|
||||
'(cache|hide)|optional array'):
|
||||
raise
|
||||
else:
|
||||
raise SystemError(
|
||||
'intent(cache) should have failed on undefined dimensions')
|
||||
|
||||
def test_hidden(self):
|
||||
shape = (2,)
|
||||
a = self.array(shape, intent.hide, None)
|
||||
assert_(a.arr.shape == shape)
|
||||
assert_(a.arr_equal(a.arr, zeros(shape, dtype=self.type.dtype)))
|
||||
|
||||
shape = (2, 3)
|
||||
a = self.array(shape, intent.hide, None)
|
||||
assert_(a.arr.shape == shape)
|
||||
assert_(a.arr_equal(a.arr, zeros(shape, dtype=self.type.dtype)))
|
||||
assert_(a.arr.flags['FORTRAN'] and not a.arr.flags['CONTIGUOUS'])
|
||||
|
||||
shape = (2, 3)
|
||||
a = self.array(shape, intent.c.hide, None)
|
||||
assert_(a.arr.shape == shape)
|
||||
assert_(a.arr_equal(a.arr, zeros(shape, dtype=self.type.dtype)))
|
||||
assert_(not a.arr.flags['FORTRAN'] and a.arr.flags['CONTIGUOUS'])
|
||||
|
||||
shape = (-1, 3)
|
||||
try:
|
||||
a = self.array(shape, intent.hide, None)
|
||||
except ValueError as msg:
|
||||
if not str(msg).startswith('failed to create intent'
|
||||
'(cache|hide)|optional array'):
|
||||
raise
|
||||
else:
|
||||
raise SystemError('intent(hide) should have failed'
|
||||
' on undefined dimensions')
|
||||
|
||||
def test_optional_none(self):
|
||||
shape = (2,)
|
||||
a = self.array(shape, intent.optional, None)
|
||||
assert_(a.arr.shape == shape)
|
||||
assert_(a.arr_equal(a.arr, zeros(shape, dtype=self.type.dtype)))
|
||||
|
||||
shape = (2, 3)
|
||||
a = self.array(shape, intent.optional, None)
|
||||
assert_(a.arr.shape == shape)
|
||||
assert_(a.arr_equal(a.arr, zeros(shape, dtype=self.type.dtype)))
|
||||
assert_(a.arr.flags['FORTRAN'] and not a.arr.flags['CONTIGUOUS'])
|
||||
|
||||
shape = (2, 3)
|
||||
a = self.array(shape, intent.c.optional, None)
|
||||
assert_(a.arr.shape == shape)
|
||||
assert_(a.arr_equal(a.arr, zeros(shape, dtype=self.type.dtype)))
|
||||
assert_(not a.arr.flags['FORTRAN'] and a.arr.flags['CONTIGUOUS'])
|
||||
|
||||
def test_optional_from_2seq(self):
|
||||
obj = self.num2seq
|
||||
shape = (len(obj),)
|
||||
a = self.array(shape, intent.optional, obj)
|
||||
assert_(a.arr.shape == shape)
|
||||
assert_(not a.has_shared_memory())
|
||||
|
||||
def test_optional_from_23seq(self):
|
||||
obj = self.num23seq
|
||||
shape = (len(obj), len(obj[0]))
|
||||
a = self.array(shape, intent.optional, obj)
|
||||
assert_(a.arr.shape == shape)
|
||||
assert_(not a.has_shared_memory())
|
||||
|
||||
a = self.array(shape, intent.optional.c, obj)
|
||||
assert_(a.arr.shape == shape)
|
||||
assert_(not a.has_shared_memory())
|
||||
|
||||
def test_inplace(self):
|
||||
obj = array(self.num23seq, dtype=self.type.dtype)
|
||||
assert_(not obj.flags['FORTRAN'] and obj.flags['CONTIGUOUS'])
|
||||
shape = obj.shape
|
||||
a = self.array(shape, intent.inplace, obj)
|
||||
assert_(obj[1][2] == a.arr[1][2], repr((obj, a.arr)))
|
||||
a.arr[1][2] = 54
|
||||
assert_(obj[1][2] == a.arr[1][2] ==
|
||||
array(54, dtype=self.type.dtype), repr((obj, a.arr)))
|
||||
assert_(a.arr is obj)
|
||||
assert_(obj.flags['FORTRAN']) # obj attributes are changed inplace!
|
||||
assert_(not obj.flags['CONTIGUOUS'])
|
||||
|
||||
def test_inplace_from_casttype(self):
|
||||
for t in self.type.cast_types():
|
||||
if t is self.type:
|
||||
continue
|
||||
obj = array(self.num23seq, dtype=t.dtype)
|
||||
assert_(obj.dtype.type == t.dtype)
|
||||
assert_(obj.dtype.type is not self.type.dtype)
|
||||
assert_(not obj.flags['FORTRAN'] and obj.flags['CONTIGUOUS'])
|
||||
shape = obj.shape
|
||||
a = self.array(shape, intent.inplace, obj)
|
||||
assert_(obj[1][2] == a.arr[1][2], repr((obj, a.arr)))
|
||||
a.arr[1][2] = 54
|
||||
assert_(obj[1][2] == a.arr[1][2] ==
|
||||
array(54, dtype=self.type.dtype), repr((obj, a.arr)))
|
||||
assert_(a.arr is obj)
|
||||
assert_(obj.flags['FORTRAN']) # obj attributes changed inplace!
|
||||
assert_(not obj.flags['CONTIGUOUS'])
|
||||
assert_(obj.dtype.type is self.type.dtype) # obj changed inplace!
|
||||
@@ -0,0 +1,33 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
import os
|
||||
import pytest
|
||||
|
||||
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'),
|
||||
]
|
||||
|
||||
@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))
|
||||
@@ -0,0 +1,24 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
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 does not modify tp_doc")
|
||||
def test_block_docstring(self):
|
||||
expected = "'i'-array(2,3)\n"
|
||||
assert_equal(self.module.block.__doc__, expected)
|
||||
@@ -0,0 +1,165 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
import math
|
||||
import textwrap
|
||||
import sys
|
||||
import pytest
|
||||
|
||||
import numpy as np
|
||||
from numpy.testing import assert_, assert_equal
|
||||
from . import util
|
||||
|
||||
|
||||
class TestF77Callback(util.F2PyTest):
|
||||
code = """
|
||||
subroutine t(fun,a)
|
||||
integer a
|
||||
cf2py intent(out) a
|
||||
external fun
|
||||
call fun(a)
|
||||
end
|
||||
|
||||
subroutine func(a)
|
||||
cf2py intent(in,out) a
|
||||
integer a
|
||||
a = a + 11
|
||||
end
|
||||
|
||||
subroutine func0(a)
|
||||
cf2py intent(out) a
|
||||
integer a
|
||||
a = 11
|
||||
end
|
||||
|
||||
subroutine t2(a)
|
||||
cf2py intent(callback) fun
|
||||
integer a
|
||||
cf2py intent(out) a
|
||||
external fun
|
||||
call fun(a)
|
||||
end
|
||||
|
||||
subroutine string_callback(callback, a)
|
||||
external callback
|
||||
double precision callback
|
||||
double precision a
|
||||
character*1 r
|
||||
cf2py intent(out) a
|
||||
r = 'r'
|
||||
a = callback(r)
|
||||
end
|
||||
|
||||
subroutine string_callback_array(callback, cu, lencu, a)
|
||||
external callback
|
||||
integer callback
|
||||
integer lencu
|
||||
character*8 cu(lencu)
|
||||
integer a
|
||||
cf2py intent(out) a
|
||||
|
||||
a = callback(cu, lencu)
|
||||
end
|
||||
"""
|
||||
|
||||
@pytest.mark.slow
|
||||
@pytest.mark.parametrize('name', 't,t2'.split(','))
|
||||
def test_all(self, name):
|
||||
self.check_function(name)
|
||||
|
||||
@pytest.mark.slow
|
||||
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(object):
|
||||
|
||||
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))
|
||||
@@ -0,0 +1,27 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
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))
|
||||
@@ -0,0 +1,125 @@
|
||||
"""See https://github.com/numpy/numpy/pull/11937.
|
||||
|
||||
"""
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
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 sys.platform == 'win32' and sys.version_info[0] < 3:
|
||||
pytest.skip('Fails with MinGW64 Gfortran (Issue #9673)')
|
||||
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', '']
|
||||
)
|
||||
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)
|
||||
|
||||
|
||||
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)
|
||||
@@ -0,0 +1,34 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
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)))
|
||||
@@ -0,0 +1,37 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
import os
|
||||
import textwrap
|
||||
import pytest
|
||||
|
||||
from numpy.testing import assert_, assert_equal
|
||||
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')]
|
||||
|
||||
@pytest.mark.slow
|
||||
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.slow
|
||||
def test_docstring(self):
|
||||
expected = textwrap.dedent("""\
|
||||
a = bar11()
|
||||
|
||||
Wrapper for ``bar11``.
|
||||
|
||||
Returns
|
||||
-------
|
||||
a : int
|
||||
""")
|
||||
assert_equal(self.module.bar11.__doc__, expected)
|
||||
@@ -0,0 +1,118 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
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])
|
||||
@@ -0,0 +1,35 @@
|
||||
"""See https://github.com/numpy/numpy/pull/10676.
|
||||
|
||||
"""
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
import sys
|
||||
from importlib import import_module
|
||||
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')'))
|
||||
@@ -0,0 +1,29 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
import os
|
||||
import pytest
|
||||
|
||||
import numpy as np
|
||||
from numpy.testing import assert_raises, assert_equal
|
||||
|
||||
from . import util
|
||||
|
||||
|
||||
def _path(*a):
|
||||
return os.path.join(*((os.path.dirname(__file__),) + a))
|
||||
|
||||
|
||||
class TestIntentInOut(util.F2PyTest):
|
||||
# Check that intent(in out) translates as intent(inout)
|
||||
sources = [_path('src', 'regression', 'inout.f90')]
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_inout(self):
|
||||
# non-contiguous should raise error
|
||||
x = np.arange(6, dtype=np.float32)[::2]
|
||||
assert_raises(ValueError, self.module.foo, x)
|
||||
|
||||
# check values with contiguous array
|
||||
x = np.arange(3, dtype=np.float32)
|
||||
self.module.foo(x)
|
||||
assert_equal(x, [3, 1, 2])
|
||||
@@ -0,0 +1,146 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
import pytest
|
||||
|
||||
from numpy import array
|
||||
from numpy.testing import assert_
|
||||
from . import util
|
||||
|
||||
|
||||
class TestReturnCharacter(util.F2PyTest):
|
||||
|
||||
def check_function(self, t):
|
||||
tname = t.__doc__.split()[0]
|
||||
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.slow
|
||||
@pytest.mark.parametrize('name', 't0,t1,t5,s0,s1,s5,ss'.split(','))
|
||||
def test_all(self, name):
|
||||
self.check_function(getattr(self.module, 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.slow
|
||||
@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))
|
||||
@@ -0,0 +1,169 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
import pytest
|
||||
|
||||
from numpy import array
|
||||
from numpy.compat import long
|
||||
from numpy.testing import assert_, assert_raises
|
||||
from . import util
|
||||
|
||||
|
||||
class TestReturnComplex(util.F2PyTest):
|
||||
|
||||
def check_function(self, t):
|
||||
tname = t.__doc__.split()[0]
|
||||
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(long(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.slow
|
||||
@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))
|
||||
|
||||
|
||||
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.slow
|
||||
@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))
|
||||
@@ -0,0 +1,181 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
import pytest
|
||||
|
||||
from numpy import array
|
||||
from numpy.compat import long
|
||||
from numpy.testing import assert_, assert_raises
|
||||
from . import util
|
||||
|
||||
|
||||
class TestReturnInteger(util.F2PyTest):
|
||||
|
||||
def check_function(self, t):
|
||||
assert_(t(123) == 123, repr(t(123)))
|
||||
assert_(t(123.6) == 123)
|
||||
assert_(t(long(123)) == 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 t.__doc__.split()[0] 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.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, 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.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_integer, name))
|
||||
@@ -0,0 +1,189 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
import pytest
|
||||
|
||||
from numpy import array
|
||||
from numpy.compat import long
|
||||
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(long(234)) == 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))
|
||||
@@ -0,0 +1,210 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
import platform
|
||||
import pytest
|
||||
|
||||
from numpy import array
|
||||
from numpy.compat import long
|
||||
from numpy.testing import assert_, assert_raises
|
||||
from . import util
|
||||
|
||||
|
||||
class TestReturnReal(util.F2PyTest):
|
||||
|
||||
def check_function(self, t):
|
||||
if t.__doc__.split()[0] 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(long(234)) - 234.0) <= 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 t.__doc__.split()[0] 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.slow
|
||||
@pytest.mark.parametrize('name', 't4,t8,s4,s8'.split(','))
|
||||
def test_all(self, name):
|
||||
self.check_function(getattr(self.module, 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.slow
|
||||
@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))
|
||||
|
||||
|
||||
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.slow
|
||||
@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))
|
||||
@@ -0,0 +1,65 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
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)
|
||||
@@ -0,0 +1,51 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
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))
|
||||
@@ -0,0 +1,24 @@
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
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)
|
||||
360
venv/lib/python3.6/site-packages/numpy/f2py/tests/util.py
Normal file
360
venv/lib/python3.6/site-packages/numpy/f2py/tests/util.py
Normal file
@@ -0,0 +1,360 @@
|
||||
"""
|
||||
Utility functions for
|
||||
|
||||
- building and importing modules on test time, using a temporary location
|
||||
- detecting if compilers are present
|
||||
|
||||
"""
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
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
|
||||
|
||||
try:
|
||||
from hashlib import md5
|
||||
except ImportError:
|
||||
from md5 import new as md5 # noqa: F401
|
||||
|
||||
#
|
||||
# Maintaining a temporary module directory
|
||||
#
|
||||
|
||||
_module_dir = None
|
||||
|
||||
|
||||
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
|
||||
d = get_module_dir()
|
||||
for j in range(5403, 9999999):
|
||||
name = "_test_ext_module_%d" % j
|
||||
fn = os.path.join(d, name)
|
||||
if name not in sys.modules and not os.path.isfile(fn + '.py'):
|
||||
return name
|
||||
raise RuntimeError("Failed to create a temporary module 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 = []
|
||||
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)
|
||||
|
||||
fn = os.path.join(os.path.dirname(fn), '.f2py_f2cmap')
|
||||
if os.path.isfile(fn):
|
||||
dst = os.path.join(d, os.path.basename(fn))
|
||||
if not os.path.isfile(dst):
|
||||
shutil.copyfile(fn, dst)
|
||||
|
||||
# Prepare options
|
||||
if module_name is None:
|
||||
module_name = get_temp_module_name()
|
||||
f2py_opts = ['-c', '-m', module_name] + options + dst_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))
|
||||
|
||||
with temppath(suffix='.py') as script:
|
||||
with open(script, 'w') as f:
|
||||
f.write(code)
|
||||
|
||||
cmd = [sys.executable, script, 'config']
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
out, err = p.communicate()
|
||||
|
||||
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)
|
||||
f = open(script, 'wb')
|
||||
f.write(asbytes(code))
|
||||
f.close()
|
||||
|
||||
# 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(object):
|
||||
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