Adding all project files
This commit is contained in:
parent
6c9e127bdc
commit
cd4316ad0f
42289 changed files with 8009643 additions and 0 deletions
0
venv/Lib/site-packages/numpy/f2py/tests/__init__.py
Normal file
0
venv/Lib/site-packages/numpy/f2py/tests/__init__.py
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,34 @@
|
|||
module ops_module
|
||||
|
||||
abstract interface
|
||||
subroutine op(x, y, z)
|
||||
integer, intent(in) :: x, y
|
||||
integer, intent(out) :: z
|
||||
end subroutine
|
||||
end interface
|
||||
|
||||
contains
|
||||
|
||||
subroutine foo(x, y, r1, r2)
|
||||
integer, intent(in) :: x, y
|
||||
integer, intent(out) :: r1, r2
|
||||
procedure (op) add1, add2
|
||||
procedure (op), pointer::p
|
||||
p=>add1
|
||||
call p(x, y, r1)
|
||||
p=>add2
|
||||
call p(x, y, r2)
|
||||
end subroutine
|
||||
end module
|
||||
|
||||
subroutine add1(x, y, z)
|
||||
integer, intent(in) :: x, y
|
||||
integer, intent(out) :: z
|
||||
z = x + y
|
||||
end subroutine
|
||||
|
||||
subroutine add2(x, y, z)
|
||||
integer, intent(in) :: x, y
|
||||
integer, intent(out) :: z
|
||||
z = x + 2 * y
|
||||
end subroutine
|
|
@ -0,0 +1,6 @@
|
|||
module test
|
||||
abstract interface
|
||||
subroutine foo()
|
||||
end subroutine
|
||||
end interface
|
||||
end module test
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* This file was auto-generated with f2py (version:2_1330) and hand edited by
|
||||
* Pearu for testing purposes. Do not edit this file unless you know what you
|
||||
* are doing!!!
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************** See f2py2e/cfuncs.py: includes ***********************/
|
||||
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include <Python.h>
|
||||
#include "fortranobject.h"
|
||||
#include <math.h>
|
||||
|
||||
static PyObject *wrap_error;
|
||||
static PyObject *wrap_module;
|
||||
|
||||
/************************************ call ************************************/
|
||||
static char doc_f2py_rout_wrap_call[] = "\
|
||||
Function signature:\n\
|
||||
arr = call(type_num,dims,intent,obj)\n\
|
||||
Required arguments:\n"
|
||||
" type_num : input int\n"
|
||||
" dims : input int-sequence\n"
|
||||
" intent : input int\n"
|
||||
" obj : input python object\n"
|
||||
"Return objects:\n"
|
||||
" arr : array";
|
||||
static PyObject *f2py_rout_wrap_call(PyObject *capi_self,
|
||||
PyObject *capi_args) {
|
||||
PyObject * volatile capi_buildvalue = NULL;
|
||||
int type_num = 0;
|
||||
npy_intp *dims = NULL;
|
||||
PyObject *dims_capi = Py_None;
|
||||
int rank = 0;
|
||||
int intent = 0;
|
||||
PyArrayObject *capi_arr_tmp = NULL;
|
||||
PyObject *arr_capi = Py_None;
|
||||
int i;
|
||||
|
||||
if (!PyArg_ParseTuple(capi_args,"iOiO|:wrap.call",\
|
||||
&type_num,&dims_capi,&intent,&arr_capi))
|
||||
return NULL;
|
||||
rank = PySequence_Length(dims_capi);
|
||||
dims = malloc(rank*sizeof(npy_intp));
|
||||
for (i=0;i<rank;++i) {
|
||||
PyObject *tmp;
|
||||
tmp = PySequence_GetItem(dims_capi, i);
|
||||
if (tmp == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
dims[i] = (npy_intp)PyLong_AsLong(tmp);
|
||||
Py_DECREF(tmp);
|
||||
if (dims[i] == -1 && PyErr_Occurred()) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
capi_arr_tmp = array_from_pyobj(type_num,dims,rank,intent|F2PY_INTENT_OUT,arr_capi);
|
||||
if (capi_arr_tmp == NULL) {
|
||||
free(dims);
|
||||
return NULL;
|
||||
}
|
||||
capi_buildvalue = Py_BuildValue("N",capi_arr_tmp);
|
||||
free(dims);
|
||||
return capi_buildvalue;
|
||||
|
||||
fail:
|
||||
free(dims);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char doc_f2py_rout_wrap_attrs[] = "\
|
||||
Function signature:\n\
|
||||
arr = array_attrs(arr)\n\
|
||||
Required arguments:\n"
|
||||
" arr : input array object\n"
|
||||
"Return objects:\n"
|
||||
" data : data address in hex\n"
|
||||
" nd : int\n"
|
||||
" dimensions : tuple\n"
|
||||
" strides : tuple\n"
|
||||
" base : python object\n"
|
||||
" (kind,type,type_num,elsize,alignment) : 4-tuple\n"
|
||||
" flags : int\n"
|
||||
" itemsize : int\n"
|
||||
;
|
||||
static PyObject *f2py_rout_wrap_attrs(PyObject *capi_self,
|
||||
PyObject *capi_args) {
|
||||
PyObject *arr_capi = Py_None;
|
||||
PyArrayObject *arr = NULL;
|
||||
PyObject *dimensions = NULL;
|
||||
PyObject *strides = NULL;
|
||||
char s[100];
|
||||
int i;
|
||||
memset(s,0,100);
|
||||
if (!PyArg_ParseTuple(capi_args,"O!|:wrap.attrs",
|
||||
&PyArray_Type,&arr_capi))
|
||||
return NULL;
|
||||
arr = (PyArrayObject *)arr_capi;
|
||||
sprintf(s,"%p",PyArray_DATA(arr));
|
||||
dimensions = PyTuple_New(PyArray_NDIM(arr));
|
||||
strides = PyTuple_New(PyArray_NDIM(arr));
|
||||
for (i=0;i<PyArray_NDIM(arr);++i) {
|
||||
PyTuple_SetItem(dimensions,i,PyLong_FromLong(PyArray_DIM(arr,i)));
|
||||
PyTuple_SetItem(strides,i,PyLong_FromLong(PyArray_STRIDE(arr,i)));
|
||||
}
|
||||
return Py_BuildValue("siNNO(cciii)ii",s,PyArray_NDIM(arr),
|
||||
dimensions,strides,
|
||||
(PyArray_BASE(arr)==NULL?Py_None:PyArray_BASE(arr)),
|
||||
PyArray_DESCR(arr)->kind,
|
||||
PyArray_DESCR(arr)->type,
|
||||
PyArray_TYPE(arr),
|
||||
PyArray_ITEMSIZE(arr),
|
||||
PyArray_DESCR(arr)->alignment,
|
||||
PyArray_FLAGS(arr),
|
||||
PyArray_ITEMSIZE(arr));
|
||||
}
|
||||
|
||||
static PyMethodDef f2py_module_methods[] = {
|
||||
|
||||
{"call",f2py_rout_wrap_call,METH_VARARGS,doc_f2py_rout_wrap_call},
|
||||
{"array_attrs",f2py_rout_wrap_attrs,METH_VARARGS,doc_f2py_rout_wrap_attrs},
|
||||
{NULL,NULL}
|
||||
};
|
||||
|
||||
static struct PyModuleDef moduledef = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"test_array_from_pyobj_ext",
|
||||
NULL,
|
||||
-1,
|
||||
f2py_module_methods,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC PyInit_test_array_from_pyobj_ext(void) {
|
||||
PyObject *m,*d, *s;
|
||||
m = wrap_module = PyModule_Create(&moduledef);
|
||||
Py_SET_TYPE(&PyFortran_Type, &PyType_Type);
|
||||
import_array();
|
||||
if (PyErr_Occurred())
|
||||
Py_FatalError("can't initialize module wrap (failed to import numpy)");
|
||||
d = PyModule_GetDict(m);
|
||||
s = PyUnicode_FromString("This module 'wrap' is auto-generated with f2py (version:2_1330).\nFunctions:\n"
|
||||
" arr = call(type_num,dims,intent,obj)\n"
|
||||
".");
|
||||
PyDict_SetItemString(d, "__doc__", s);
|
||||
wrap_error = PyErr_NewException ("wrap.error", NULL, NULL);
|
||||
Py_DECREF(s);
|
||||
|
||||
#define ADDCONST(NAME, CONST) \
|
||||
s = PyLong_FromLong(CONST); \
|
||||
PyDict_SetItemString(d, NAME, s); \
|
||||
Py_DECREF(s)
|
||||
|
||||
ADDCONST("F2PY_INTENT_IN", F2PY_INTENT_IN);
|
||||
ADDCONST("F2PY_INTENT_INOUT", F2PY_INTENT_INOUT);
|
||||
ADDCONST("F2PY_INTENT_OUT", F2PY_INTENT_OUT);
|
||||
ADDCONST("F2PY_INTENT_HIDE", F2PY_INTENT_HIDE);
|
||||
ADDCONST("F2PY_INTENT_CACHE", F2PY_INTENT_CACHE);
|
||||
ADDCONST("F2PY_INTENT_COPY", F2PY_INTENT_COPY);
|
||||
ADDCONST("F2PY_INTENT_C", F2PY_INTENT_C);
|
||||
ADDCONST("F2PY_OPTIONAL", F2PY_OPTIONAL);
|
||||
ADDCONST("F2PY_INTENT_INPLACE", F2PY_INTENT_INPLACE);
|
||||
ADDCONST("NPY_BOOL", NPY_BOOL);
|
||||
ADDCONST("NPY_BYTE", NPY_BYTE);
|
||||
ADDCONST("NPY_UBYTE", NPY_UBYTE);
|
||||
ADDCONST("NPY_SHORT", NPY_SHORT);
|
||||
ADDCONST("NPY_USHORT", NPY_USHORT);
|
||||
ADDCONST("NPY_INT", NPY_INT);
|
||||
ADDCONST("NPY_UINT", NPY_UINT);
|
||||
ADDCONST("NPY_INTP", NPY_INTP);
|
||||
ADDCONST("NPY_UINTP", NPY_UINTP);
|
||||
ADDCONST("NPY_LONG", NPY_LONG);
|
||||
ADDCONST("NPY_ULONG", NPY_ULONG);
|
||||
ADDCONST("NPY_LONGLONG", NPY_LONGLONG);
|
||||
ADDCONST("NPY_ULONGLONG", NPY_ULONGLONG);
|
||||
ADDCONST("NPY_FLOAT", NPY_FLOAT);
|
||||
ADDCONST("NPY_DOUBLE", NPY_DOUBLE);
|
||||
ADDCONST("NPY_LONGDOUBLE", NPY_LONGDOUBLE);
|
||||
ADDCONST("NPY_CFLOAT", NPY_CFLOAT);
|
||||
ADDCONST("NPY_CDOUBLE", NPY_CDOUBLE);
|
||||
ADDCONST("NPY_CLONGDOUBLE", NPY_CLONGDOUBLE);
|
||||
ADDCONST("NPY_OBJECT", NPY_OBJECT);
|
||||
ADDCONST("NPY_STRING", NPY_STRING);
|
||||
ADDCONST("NPY_UNICODE", NPY_UNICODE);
|
||||
ADDCONST("NPY_VOID", NPY_VOID);
|
||||
ADDCONST("NPY_NTYPES", NPY_NTYPES);
|
||||
ADDCONST("NPY_NOTYPE", NPY_NOTYPE);
|
||||
ADDCONST("NPY_USERDEF", NPY_USERDEF);
|
||||
|
||||
ADDCONST("CONTIGUOUS", NPY_ARRAY_C_CONTIGUOUS);
|
||||
ADDCONST("FORTRAN", NPY_ARRAY_F_CONTIGUOUS);
|
||||
ADDCONST("OWNDATA", NPY_ARRAY_OWNDATA);
|
||||
ADDCONST("FORCECAST", NPY_ARRAY_FORCECAST);
|
||||
ADDCONST("ENSURECOPY", NPY_ARRAY_ENSURECOPY);
|
||||
ADDCONST("ENSUREARRAY", NPY_ARRAY_ENSUREARRAY);
|
||||
ADDCONST("ALIGNED", NPY_ARRAY_ALIGNED);
|
||||
ADDCONST("WRITEABLE", NPY_ARRAY_WRITEABLE);
|
||||
ADDCONST("WRITEBACKIFCOPY", NPY_ARRAY_WRITEBACKIFCOPY);
|
||||
|
||||
ADDCONST("BEHAVED", NPY_ARRAY_BEHAVED);
|
||||
ADDCONST("BEHAVED_NS", NPY_ARRAY_BEHAVED_NS);
|
||||
ADDCONST("CARRAY", NPY_ARRAY_CARRAY);
|
||||
ADDCONST("FARRAY", NPY_ARRAY_FARRAY);
|
||||
ADDCONST("CARRAY_RO", NPY_ARRAY_CARRAY_RO);
|
||||
ADDCONST("FARRAY_RO", NPY_ARRAY_FARRAY_RO);
|
||||
ADDCONST("DEFAULT", NPY_ARRAY_DEFAULT);
|
||||
ADDCONST("UPDATE_ALL", NPY_ARRAY_UPDATE_ALL);
|
||||
|
||||
#undef ADDCONST(
|
||||
|
||||
if (PyErr_Occurred())
|
||||
Py_FatalError("can't initialize module wrap");
|
||||
|
||||
#ifdef F2PY_REPORT_ATEXIT
|
||||
on_exit(f2py_report_on_exit,(void*)"array_from_pyobj.wrap.call");
|
||||
#endif
|
||||
|
||||
return m;
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -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,6 @@
|
|||
SUBROUTINE FOO()
|
||||
INTEGER BAR(2, 3)
|
||||
|
||||
COMMON /BLOCK/ BAR
|
||||
RETURN
|
||||
END
|
62
venv/Lib/site-packages/numpy/f2py/tests/src/callback/foo.f
Normal file
62
venv/Lib/site-packages/numpy/f2py/tests/src/callback/foo.f
Normal file
|
@ -0,0 +1,62 @@
|
|||
subroutine t(fun,a)
|
||||
integer a
|
||||
cf2py intent(out) a
|
||||
external fun
|
||||
call fun(a)
|
||||
end
|
||||
|
||||
subroutine func(a)
|
||||
cf2py intent(in,out) a
|
||||
integer a
|
||||
a = a + 11
|
||||
end
|
||||
|
||||
subroutine func0(a)
|
||||
cf2py intent(out) a
|
||||
integer a
|
||||
a = 11
|
||||
end
|
||||
|
||||
subroutine t2(a)
|
||||
cf2py intent(callback) fun
|
||||
integer a
|
||||
cf2py intent(out) a
|
||||
external fun
|
||||
call fun(a)
|
||||
end
|
||||
|
||||
subroutine string_callback(callback, a)
|
||||
external callback
|
||||
double precision callback
|
||||
double precision a
|
||||
character*1 r
|
||||
cf2py intent(out) a
|
||||
r = 'r'
|
||||
a = callback(r)
|
||||
end
|
||||
|
||||
subroutine string_callback_array(callback, cu, lencu, a)
|
||||
external callback
|
||||
integer callback
|
||||
integer lencu
|
||||
character*8 cu(lencu)
|
||||
integer a
|
||||
cf2py intent(out) a
|
||||
|
||||
a = callback(cu, lencu)
|
||||
end
|
||||
|
||||
subroutine hidden_callback(a, r)
|
||||
external global_f
|
||||
cf2py intent(callback, hide) global_f
|
||||
integer a, r, global_f
|
||||
cf2py intent(out) r
|
||||
r = global_f(a)
|
||||
end
|
||||
|
||||
subroutine hidden_callback2(a, r)
|
||||
external global_f
|
||||
integer a, r, global_f
|
||||
cf2py intent(out) r
|
||||
r = global_f(a)
|
||||
end
|
|
@ -0,0 +1,7 @@
|
|||
function gh17797(f, y) result(r)
|
||||
external f
|
||||
integer(8) :: r, f
|
||||
integer(8), dimension(:) :: y
|
||||
r = f(0)
|
||||
r = r + sum(y)
|
||||
end function gh17797
|
|
@ -0,0 +1,17 @@
|
|||
! When gh18335_workaround is defined as an extension,
|
||||
! the issue cannot be reproduced.
|
||||
!subroutine gh18335_workaround(f, y)
|
||||
! implicit none
|
||||
! external f
|
||||
! integer(kind=1) :: y(1)
|
||||
! call f(y)
|
||||
!end subroutine gh18335_workaround
|
||||
|
||||
function gh18335(f) result (r)
|
||||
implicit none
|
||||
external f
|
||||
integer(kind=1) :: y(1), r
|
||||
y(1) = 123
|
||||
call f(y)
|
||||
r = y(1)
|
||||
end function gh18335
|
3
venv/Lib/site-packages/numpy/f2py/tests/src/cli/hi77.f
Normal file
3
venv/Lib/site-packages/numpy/f2py/tests/src/cli/hi77.f
Normal file
|
@ -0,0 +1,3 @@
|
|||
SUBROUTINE HI
|
||||
PRINT*, "HELLO WORLD"
|
||||
END SUBROUTINE
|
|
@ -0,0 +1,3 @@
|
|||
function hi()
|
||||
print*, "Hello World"
|
||||
end function
|
11
venv/Lib/site-packages/numpy/f2py/tests/src/common/block.f
Normal file
11
venv/Lib/site-packages/numpy/f2py/tests/src/common/block.f
Normal file
|
@ -0,0 +1,11 @@
|
|||
SUBROUTINE INITCB
|
||||
DOUBLE PRECISION LONG
|
||||
CHARACTER STRING
|
||||
INTEGER OK
|
||||
|
||||
COMMON /BLOCK/ LONG, STRING, OK
|
||||
LONG = 1.0
|
||||
STRING = '2'
|
||||
OK = 3
|
||||
RETURN
|
||||
END
|
|
@ -0,0 +1,13 @@
|
|||
module foo
|
||||
public
|
||||
type, private, bind(c) :: a
|
||||
integer :: i
|
||||
end type a
|
||||
type, bind(c) :: b_
|
||||
integer :: j
|
||||
end type b_
|
||||
public :: b_
|
||||
type :: c
|
||||
integer :: k
|
||||
end type c
|
||||
end module foo
|
|
@ -0,0 +1,6 @@
|
|||
module foo
|
||||
type bar
|
||||
character(len = 4) :: text
|
||||
end type bar
|
||||
type(bar), parameter :: abar = bar('abar')
|
||||
end module foo
|
|
@ -0,0 +1,16 @@
|
|||
subroutine subb(k)
|
||||
real(8), intent(inout) :: k(:)
|
||||
k=k+1
|
||||
endsubroutine
|
||||
|
||||
subroutine subc(w,k)
|
||||
real(8), intent(in) :: w(:)
|
||||
real(8), intent(out) :: k(size(w))
|
||||
k=w+1
|
||||
endsubroutine
|
||||
|
||||
function t0(value)
|
||||
character value
|
||||
character t0
|
||||
t0 = value
|
||||
endfunction
|
|
@ -0,0 +1,12 @@
|
|||
integer(8) function external_as_statement(fcn)
|
||||
implicit none
|
||||
external fcn
|
||||
integer(8) :: fcn
|
||||
external_as_statement = fcn(0)
|
||||
end
|
||||
|
||||
integer(8) function external_as_attribute(fcn)
|
||||
implicit none
|
||||
integer(8), external :: fcn
|
||||
external_as_attribute = fcn(0)
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
subroutine gh2848( &
|
||||
! first 2 parameters
|
||||
par1, par2,&
|
||||
! last 2 parameters
|
||||
par3, par4)
|
||||
|
||||
integer, intent(in) :: par1, par2
|
||||
integer, intent(out) :: par3, par4
|
||||
|
||||
par3 = par1
|
||||
par4 = par2
|
||||
|
||||
end subroutine gh2848
|
|
@ -0,0 +1,49 @@
|
|||
module foo
|
||||
type bar
|
||||
character(len = 32) :: item
|
||||
end type bar
|
||||
interface operator(.item.)
|
||||
module procedure item_int, item_real
|
||||
end interface operator(.item.)
|
||||
interface operator(==)
|
||||
module procedure items_are_equal
|
||||
end interface operator(==)
|
||||
interface assignment(=)
|
||||
module procedure get_int, get_real
|
||||
end interface assignment(=)
|
||||
contains
|
||||
function item_int(val) result(elem)
|
||||
integer, intent(in) :: val
|
||||
type(bar) :: elem
|
||||
|
||||
write(elem%item, "(I32)") val
|
||||
end function item_int
|
||||
|
||||
function item_real(val) result(elem)
|
||||
real, intent(in) :: val
|
||||
type(bar) :: elem
|
||||
|
||||
write(elem%item, "(1PE32.12)") val
|
||||
end function item_real
|
||||
|
||||
function items_are_equal(val1, val2) result(equal)
|
||||
type(bar), intent(in) :: val1, val2
|
||||
logical :: equal
|
||||
|
||||
equal = (val1%item == val2%item)
|
||||
end function items_are_equal
|
||||
|
||||
subroutine get_real(rval, item)
|
||||
real, intent(out) :: rval
|
||||
type(bar), intent(in) :: item
|
||||
|
||||
read(item%item, *) rval
|
||||
end subroutine get_real
|
||||
|
||||
subroutine get_int(rval, item)
|
||||
integer, intent(out) :: rval
|
||||
type(bar), intent(in) :: item
|
||||
|
||||
read(item%item, *) rval
|
||||
end subroutine get_int
|
||||
end module foo
|
|
@ -0,0 +1,11 @@
|
|||
module foo
|
||||
private
|
||||
integer :: a
|
||||
public :: setA
|
||||
integer :: b
|
||||
contains
|
||||
subroutine setA(v)
|
||||
integer, intent(in) :: v
|
||||
a = v
|
||||
end subroutine setA
|
||||
end module foo
|
|
@ -0,0 +1,10 @@
|
|||
module foo
|
||||
public
|
||||
integer, private :: a
|
||||
public :: setA
|
||||
contains
|
||||
subroutine setA(v)
|
||||
integer, intent(in) :: v
|
||||
a = v
|
||||
end subroutine setA
|
||||
end module foo
|
|
@ -0,0 +1 @@
|
|||
dict(real=dict(real32='float', real64='double'), integer=dict(int64='long_long'))
|
|
@ -0,0 +1,9 @@
|
|||
subroutine func1(n, x, res)
|
||||
use, intrinsic :: iso_fortran_env, only: int64, real64
|
||||
implicit none
|
||||
integer(int64), intent(in) :: n
|
||||
real(real64), intent(in) :: x(n)
|
||||
real(real64), intent(out) :: res
|
||||
Cf2py intent(hide) :: n
|
||||
res = sum(x)
|
||||
end
|
20
venv/Lib/site-packages/numpy/f2py/tests/src/kind/foo.f90
Normal file
20
venv/Lib/site-packages/numpy/f2py/tests/src/kind/foo.f90
Normal file
|
@ -0,0 +1,20 @@
|
|||
|
||||
|
||||
subroutine selectedrealkind(p, r, res)
|
||||
implicit none
|
||||
|
||||
integer, intent(in) :: p, r
|
||||
!f2py integer :: r=0
|
||||
integer, intent(out) :: res
|
||||
res = selected_real_kind(p, r)
|
||||
|
||||
end subroutine
|
||||
|
||||
subroutine selectedintkind(p, res)
|
||||
implicit none
|
||||
|
||||
integer, intent(in) :: p
|
||||
integer, intent(out) :: res
|
||||
res = selected_int_kind(p)
|
||||
|
||||
end subroutine
|
5
venv/Lib/site-packages/numpy/f2py/tests/src/mixed/foo.f
Normal file
5
venv/Lib/site-packages/numpy/f2py/tests/src/mixed/foo.f
Normal file
|
@ -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
|
BIN
venv/Lib/site-packages/numpy/f2py/tests/src/module_data/mod.mod
Normal file
BIN
venv/Lib/site-packages/numpy/f2py/tests/src/module_data/mod.mod
Normal file
Binary file not shown.
|
@ -0,0 +1,12 @@
|
|||
module mod
|
||||
integer :: i
|
||||
integer :: x(4)
|
||||
real, dimension(2,3) :: a
|
||||
real, allocatable, dimension(:,:) :: b
|
||||
contains
|
||||
subroutine foo
|
||||
integer :: k
|
||||
k = 1
|
||||
a(1,2) = a(1,2)+3
|
||||
end subroutine foo
|
||||
end module mod
|
|
@ -0,0 +1,7 @@
|
|||
subroutine foo(is_, ie_, arr, tout)
|
||||
implicit none
|
||||
integer :: is_,ie_
|
||||
real, intent(in) :: arr(is_:ie_)
|
||||
real, intent(out) :: tout(is_:ie_)
|
||||
tout = arr
|
||||
end
|
|
@ -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,14 @@
|
|||
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
|
|
@ -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,45 @@
|
|||
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
|
|
@ -0,0 +1,48 @@
|
|||
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
|
|
@ -0,0 +1,45 @@
|
|||
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
|
|
@ -0,0 +1,48 @@
|
|||
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
|
|
@ -0,0 +1,56 @@
|
|||
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
|
|
@ -0,0 +1,59 @@
|
|||
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
|
|
@ -0,0 +1,56 @@
|
|||
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
|
|
@ -0,0 +1,59 @@
|
|||
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
|
|
@ -0,0 +1,45 @@
|
|||
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
|
|
@ -0,0 +1,48 @@
|
|||
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
|
44
venv/Lib/site-packages/numpy/f2py/tests/src/size/foo.f90
Normal file
44
venv/Lib/site-packages/numpy/f2py/tests/src/size/foo.f90
Normal file
|
@ -0,0 +1,44 @@
|
|||
|
||||
subroutine foo(a, n, m, b)
|
||||
implicit none
|
||||
|
||||
real, intent(in) :: a(n, m)
|
||||
integer, intent(in) :: n, m
|
||||
real, intent(out) :: b(size(a, 1))
|
||||
|
||||
integer :: i
|
||||
|
||||
do i = 1, size(b)
|
||||
b(i) = sum(a(i,:))
|
||||
enddo
|
||||
end subroutine
|
||||
|
||||
subroutine trans(x,y)
|
||||
implicit none
|
||||
real, intent(in), dimension(:,:) :: x
|
||||
real, intent(out), dimension( size(x,2), size(x,1) ) :: y
|
||||
integer :: N, M, i, j
|
||||
N = size(x,1)
|
||||
M = size(x,2)
|
||||
DO i=1,N
|
||||
do j=1,M
|
||||
y(j,i) = x(i,j)
|
||||
END DO
|
||||
END DO
|
||||
end subroutine trans
|
||||
|
||||
subroutine flatten(x,y)
|
||||
implicit none
|
||||
real, intent(in), dimension(:,:) :: x
|
||||
real, intent(out), dimension( size(x) ) :: y
|
||||
integer :: N, M, i, j, k
|
||||
N = size(x,1)
|
||||
M = size(x,2)
|
||||
k = 1
|
||||
DO i=1,N
|
||||
do j=1,M
|
||||
y(k) = x(i,j)
|
||||
k = k + 1
|
||||
END DO
|
||||
END DO
|
||||
end subroutine flatten
|
29
venv/Lib/site-packages/numpy/f2py/tests/src/string/char.f90
Normal file
29
venv/Lib/site-packages/numpy/f2py/tests/src/string/char.f90
Normal file
|
@ -0,0 +1,29 @@
|
|||
MODULE char_test
|
||||
|
||||
CONTAINS
|
||||
|
||||
SUBROUTINE change_strings(strings, n_strs, out_strings)
|
||||
IMPLICIT NONE
|
||||
|
||||
! Inputs
|
||||
INTEGER, INTENT(IN) :: n_strs
|
||||
CHARACTER, INTENT(IN), DIMENSION(2,n_strs) :: strings
|
||||
CHARACTER, INTENT(OUT), DIMENSION(2,n_strs) :: out_strings
|
||||
|
||||
!f2py INTEGER, INTENT(IN) :: n_strs
|
||||
!f2py CHARACTER, INTENT(IN), DIMENSION(2,n_strs) :: strings
|
||||
!f2py CHARACTER, INTENT(OUT), DIMENSION(2,n_strs) :: strings
|
||||
|
||||
! Misc.
|
||||
INTEGER*4 :: j
|
||||
|
||||
|
||||
DO j=1, n_strs
|
||||
out_strings(1,j) = strings(1,j)
|
||||
out_strings(2,j) = 'A'
|
||||
END DO
|
||||
|
||||
END SUBROUTINE change_strings
|
||||
|
||||
END MODULE char_test
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
function sint(s) result(i)
|
||||
implicit none
|
||||
character(len=*) :: s
|
||||
integer :: j, i
|
||||
i = 0
|
||||
do j=len(s), 1, -1
|
||||
if (.not.((i.eq.0).and.(s(j:j).eq.' '))) then
|
||||
i = i + ichar(s(j:j)) * 10 ** (j - 1)
|
||||
endif
|
||||
end do
|
||||
return
|
||||
end function sint
|
||||
|
||||
function test_in_bytes4(a) result (i)
|
||||
implicit none
|
||||
integer :: sint
|
||||
character(len=4) :: a
|
||||
integer :: i
|
||||
i = sint(a)
|
||||
a(1:1) = 'A'
|
||||
return
|
||||
end function test_in_bytes4
|
||||
|
||||
function test_inout_bytes4(a) result (i)
|
||||
implicit none
|
||||
integer :: sint
|
||||
character(len=4), intent(inout) :: a
|
||||
integer :: i
|
||||
if (a(1:1).ne.' ') then
|
||||
a(1:1) = 'E'
|
||||
endif
|
||||
i = sint(a)
|
||||
return
|
||||
end function test_inout_bytes4
|
12
venv/Lib/site-packages/numpy/f2py/tests/src/string/string.f
Normal file
12
venv/Lib/site-packages/numpy/f2py/tests/src/string/string.f
Normal file
|
@ -0,0 +1,12 @@
|
|||
C FILE: STRING.F
|
||||
SUBROUTINE FOO(A,B,C,D)
|
||||
CHARACTER*5 A, B
|
||||
CHARACTER*(*) C,D
|
||||
Cf2py intent(in) a,c
|
||||
Cf2py intent(inout) b,d
|
||||
A(1:1) = 'A'
|
||||
B(1:1) = 'B'
|
||||
C(1:1) = 'C'
|
||||
D(1:1) = 'D'
|
||||
END
|
||||
C END OF FILE STRING.F
|
|
@ -0,0 +1,22 @@
|
|||
from pathlib import Path
|
||||
import textwrap
|
||||
from . import util
|
||||
from numpy.f2py import crackfortran
|
||||
|
||||
|
||||
class TestAbstractInterface(util.F2PyTest):
|
||||
sources = [util.getpath("tests", "src", "abstract_interface", "foo.f90")]
|
||||
|
||||
skip = ["add1", "add2"]
|
||||
|
||||
def test_abstract_interface(self):
|
||||
assert self.module.ops_module.foo(3, 5) == (8, 13)
|
||||
|
||||
def test_parse_abstract_interface(self):
|
||||
# Test gh18403
|
||||
fpath = util.getpath("tests", "src", "abstract_interface",
|
||||
"gh18403_mod.f90")
|
||||
mod = crackfortran.crackfortran([str(fpath)])
|
||||
assert len(mod) == 1
|
||||
assert len(mod[0]["body"]) == 1
|
||||
assert mod[0]["body"][0]["block"] == "abstract interface"
|
627
venv/Lib/site-packages/numpy/f2py/tests/test_array_from_pyobj.py
Normal file
627
venv/Lib/site-packages/numpy/f2py/tests/test_array_from_pyobj.py
Normal file
|
@ -0,0 +1,627 @@
|
|||
import os
|
||||
import sys
|
||||
import copy
|
||||
import platform
|
||||
import pytest
|
||||
|
||||
import numpy as np
|
||||
|
||||
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 = [
|
||||
util.getpath("tests", "src", "array_from_pyobj", "wrapmodule.c"),
|
||||
util.getpath("src", "fortranobject.c"),
|
||||
util.getpath("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",
|
||||
"BEHAVED",
|
||||
"BEHAVED_RO",
|
||||
"CARRAY",
|
||||
"FARRAY",
|
||||
]:
|
||||
if abs(flags) & getattr(wrap, flagname, 0):
|
||||
info.append(flagname)
|
||||
return info
|
||||
|
||||
|
||||
class Intent:
|
||||
def __init__(self, intent_list=[]):
|
||||
self.intent_list = intent_list[:]
|
||||
flags = 0
|
||||
for i in intent_list:
|
||||
if i == "optional":
|
||||
flags |= wrap.F2PY_OPTIONAL
|
||||
else:
|
||||
flags |= getattr(wrap, "F2PY_INTENT_" + i.upper())
|
||||
self.flags = flags
|
||||
|
||||
def __getattr__(self, name):
|
||||
name = name.lower()
|
||||
if name == "in_":
|
||||
name = "in"
|
||||
return self.__class__(self.intent_list + [name])
|
||||
|
||||
def __str__(self):
|
||||
return "intent(%s)" % (",".join(self.intent_list))
|
||||
|
||||
def __repr__(self):
|
||||
return "Intent(%r)" % (self.intent_list)
|
||||
|
||||
def is_intent(self, *names):
|
||||
for name in names:
|
||||
if name not in self.intent_list:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_intent_exact(self, *names):
|
||||
return len(self.intent_list) == len(names) and self.is_intent(*names)
|
||||
|
||||
|
||||
intent = Intent()
|
||||
|
||||
_type_names = [
|
||||
"BOOL",
|
||||
"BYTE",
|
||||
"UBYTE",
|
||||
"SHORT",
|
||||
"USHORT",
|
||||
"INT",
|
||||
"UINT",
|
||||
"LONG",
|
||||
"ULONG",
|
||||
"LONGLONG",
|
||||
"ULONGLONG",
|
||||
"FLOAT",
|
||||
"DOUBLE",
|
||||
"CFLOAT",
|
||||
]
|
||||
|
||||
_cast_dict = {"BOOL": ["BOOL"]}
|
||||
_cast_dict["BYTE"] = _cast_dict["BOOL"] + ["BYTE"]
|
||||
_cast_dict["UBYTE"] = _cast_dict["BOOL"] + ["UBYTE"]
|
||||
_cast_dict["BYTE"] = ["BYTE"]
|
||||
_cast_dict["UBYTE"] = ["UBYTE"]
|
||||
_cast_dict["SHORT"] = _cast_dict["BYTE"] + ["UBYTE", "SHORT"]
|
||||
_cast_dict["USHORT"] = _cast_dict["UBYTE"] + ["BYTE", "USHORT"]
|
||||
_cast_dict["INT"] = _cast_dict["SHORT"] + ["USHORT", "INT"]
|
||||
_cast_dict["UINT"] = _cast_dict["USHORT"] + ["SHORT", "UINT"]
|
||||
|
||||
_cast_dict["LONG"] = _cast_dict["INT"] + ["LONG"]
|
||||
_cast_dict["ULONG"] = _cast_dict["UINT"] + ["ULONG"]
|
||||
|
||||
_cast_dict["LONGLONG"] = _cast_dict["LONG"] + ["LONGLONG"]
|
||||
_cast_dict["ULONGLONG"] = _cast_dict["ULONG"] + ["ULONGLONG"]
|
||||
|
||||
_cast_dict["FLOAT"] = _cast_dict["SHORT"] + ["USHORT", "FLOAT"]
|
||||
_cast_dict["DOUBLE"] = _cast_dict["INT"] + ["UINT", "FLOAT", "DOUBLE"]
|
||||
|
||||
_cast_dict["CFLOAT"] = _cast_dict["FLOAT"] + ["CFLOAT"]
|
||||
|
||||
# 32 bit system malloc typically does not provide the alignment required by
|
||||
# 16 byte long double types this means the inout intent cannot be satisfied
|
||||
# and several tests fail as the alignment flag can be randomly true or fals
|
||||
# when numpy gains an aligned allocator the tests could be enabled again
|
||||
#
|
||||
# Furthermore, on macOS ARM64, LONGDOUBLE is an alias for DOUBLE.
|
||||
if ((np.intp().dtype.itemsize != 4 or np.clongdouble().dtype.alignment <= 8)
|
||||
and sys.platform != "win32"
|
||||
and (platform.system(), platform.processor()) != ("Darwin", "arm")):
|
||||
_type_names.extend(["LONGDOUBLE", "CDOUBLE", "CLONGDOUBLE"])
|
||||
_cast_dict["LONGDOUBLE"] = _cast_dict["LONG"] + [
|
||||
"ULONG",
|
||||
"FLOAT",
|
||||
"DOUBLE",
|
||||
"LONGDOUBLE",
|
||||
]
|
||||
_cast_dict["CLONGDOUBLE"] = _cast_dict["LONGDOUBLE"] + [
|
||||
"CFLOAT",
|
||||
"CDOUBLE",
|
||||
"CLONGDOUBLE",
|
||||
]
|
||||
_cast_dict["CDOUBLE"] = _cast_dict["DOUBLE"] + ["CFLOAT", "CDOUBLE"]
|
||||
|
||||
|
||||
class Type:
|
||||
_type_cache = {}
|
||||
|
||||
def __new__(cls, name):
|
||||
if isinstance(name, np.dtype):
|
||||
dtype0 = name
|
||||
name = None
|
||||
for n, i in typeinfo.items():
|
||||
if not isinstance(i, type) and dtype0.type is i.type:
|
||||
name = n
|
||||
break
|
||||
obj = cls._type_cache.get(name.upper(), None)
|
||||
if obj is not None:
|
||||
return obj
|
||||
obj = object.__new__(cls)
|
||||
obj._init(name)
|
||||
cls._type_cache[name.upper()] = obj
|
||||
return obj
|
||||
|
||||
def _init(self, name):
|
||||
self.NAME = name.upper()
|
||||
info = typeinfo[self.NAME]
|
||||
self.type_num = getattr(wrap, "NPY_" + self.NAME)
|
||||
assert self.type_num == info.num
|
||||
self.dtype = np.dtype(info.type)
|
||||
self.type = info.type
|
||||
self.elsize = info.bits / 8
|
||||
self.dtypechar = info.char
|
||||
|
||||
def cast_types(self):
|
||||
return [self.__class__(_m) for _m in _cast_dict[self.NAME]]
|
||||
|
||||
def all_types(self):
|
||||
return [self.__class__(_m) for _m in _type_names]
|
||||
|
||||
def smaller_types(self):
|
||||
bits = typeinfo[self.NAME].alignment
|
||||
types = []
|
||||
for name in _type_names:
|
||||
if typeinfo[name].alignment < bits:
|
||||
types.append(Type(name))
|
||||
return types
|
||||
|
||||
def equal_types(self):
|
||||
bits = typeinfo[self.NAME].alignment
|
||||
types = []
|
||||
for name in _type_names:
|
||||
if name == self.NAME:
|
||||
continue
|
||||
if typeinfo[name].alignment == bits:
|
||||
types.append(Type(name))
|
||||
return types
|
||||
|
||||
def larger_types(self):
|
||||
bits = typeinfo[self.NAME].alignment
|
||||
types = []
|
||||
for name in _type_names:
|
||||
if typeinfo[name].alignment > bits:
|
||||
types.append(Type(name))
|
||||
return types
|
||||
|
||||
|
||||
class Array:
|
||||
def __init__(self, typ, dims, intent, obj):
|
||||
self.type = typ
|
||||
self.dims = dims
|
||||
self.intent = intent
|
||||
self.obj_copy = copy.deepcopy(obj)
|
||||
self.obj = obj
|
||||
|
||||
# arr.dtypechar may be different from typ.dtypechar
|
||||
self.arr = wrap.call(typ.type_num, dims, intent.flags, obj)
|
||||
|
||||
assert isinstance(self.arr, np.ndarray)
|
||||
|
||||
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"]
|
||||
assert self.arr.flags["CONTIGUOUS"]
|
||||
assert (not self.arr_attr[6] & wrap.FORTRAN)
|
||||
else:
|
||||
assert (not intent.flags & wrap.F2PY_INTENT_C)
|
||||
assert self.arr.flags["FORTRAN"]
|
||||
assert not self.arr.flags["CONTIGUOUS"]
|
||||
assert (self.arr_attr[6] & wrap.FORTRAN)
|
||||
|
||||
if obj is None:
|
||||
self.pyarr = None
|
||||
self.pyarr_attr = None
|
||||
return
|
||||
|
||||
if intent.is_intent("cache"):
|
||||
assert isinstance(obj, np.ndarray), repr(type(obj))
|
||||
self.pyarr = np.array(obj).reshape(*dims).copy()
|
||||
else:
|
||||
self.pyarr = np.array(
|
||||
np.array(obj, dtype=typ.dtypechar).reshape(*dims),
|
||||
order=self.intent.is_intent("c") and "C" or "F",
|
||||
)
|
||||
assert self.pyarr.dtype == typ
|
||||
self.pyarr.setflags(write=self.arr.flags["WRITEABLE"])
|
||||
assert self.pyarr.flags["OWNDATA"], (obj, intent)
|
||||
self.pyarr_attr = wrap.array_attrs(self.pyarr)
|
||||
|
||||
if len(dims) > 1:
|
||||
if self.intent.is_intent("c"):
|
||||
assert not self.pyarr.flags["FORTRAN"]
|
||||
assert self.pyarr.flags["CONTIGUOUS"]
|
||||
assert (not self.pyarr_attr[6] & wrap.FORTRAN)
|
||||
else:
|
||||
assert self.pyarr.flags["FORTRAN"]
|
||||
assert not self.pyarr.flags["CONTIGUOUS"]
|
||||
assert (self.pyarr_attr[6] & wrap.FORTRAN)
|
||||
|
||||
assert self.arr_attr[1] == self.pyarr_attr[1] # nd
|
||||
assert self.arr_attr[2] == self.pyarr_attr[2] # dimensions
|
||||
if self.arr_attr[1] <= 1:
|
||||
assert self.arr_attr[3] == self.pyarr_attr[3], repr((
|
||||
self.arr_attr[3],
|
||||
self.pyarr_attr[3],
|
||||
self.arr.tobytes(),
|
||||
self.pyarr.tobytes(),
|
||||
)) # strides
|
||||
assert self.arr_attr[5][-2:] == self.pyarr_attr[5][-2:] # 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
|
||||
else:
|
||||
assert self.arr_attr[5][3] == self.type.elsize
|
||||
assert (self.arr_equal(self.pyarr, self.arr))
|
||||
|
||||
if isinstance(self.obj, np.ndarray):
|
||||
if typ.elsize == Type(obj.dtype).elsize:
|
||||
if not intent.is_intent("copy") and self.arr_attr[1] <= 1:
|
||||
assert self.has_shared_memory()
|
||||
|
||||
def arr_equal(self, arr1, arr2):
|
||||
if arr1.shape != arr2.shape:
|
||||
return False
|
||||
return (arr1 == arr2).all()
|
||||
|
||||
def __str__(self):
|
||||
return str(self.arr)
|
||||
|
||||
def has_shared_memory(self):
|
||||
"""Check that created array shares data with input array."""
|
||||
if self.obj is self.arr:
|
||||
return True
|
||||
if not isinstance(self.obj, np.ndarray):
|
||||
return False
|
||||
obj_attr = wrap.array_attrs(self.obj)
|
||||
return obj_attr[0] == self.arr_attr[0]
|
||||
|
||||
|
||||
class TestIntent:
|
||||
def test_in_out(self):
|
||||
assert str(intent.in_.out) == "intent(in,out)"
|
||||
assert intent.in_.c.is_intent("c")
|
||||
assert not intent.in_.c.is_intent_exact("c")
|
||||
assert intent.in_.c.is_intent_exact("c", "in")
|
||||
assert intent.in_.c.is_intent_exact("in", "c")
|
||||
assert not intent.in_.is_intent("c")
|
||||
|
||||
|
||||
class TestSharedMemory:
|
||||
num2seq = [1, 2]
|
||||
num23seq = [[1, 2, 3], [4, 5, 6]]
|
||||
|
||||
@pytest.fixture(autouse=True, scope="class", params=_type_names)
|
||||
def setup_type(self, request):
|
||||
request.cls.type = Type(request.param)
|
||||
request.cls.array = lambda self, dims, intent, obj: Array(
|
||||
Type(request.param), dims, intent, obj)
|
||||
|
||||
def test_in_from_2seq(self):
|
||||
a = self.array([2], intent.in_, self.num2seq)
|
||||
assert not a.has_shared_memory()
|
||||
|
||||
def test_in_from_2casttype(self):
|
||||
for t in self.type.cast_types():
|
||||
obj = np.array(self.num2seq, dtype=t.dtype)
|
||||
a = self.array([len(self.num2seq)], intent.in_, obj)
|
||||
if t.elsize == self.type.elsize:
|
||||
assert a.has_shared_memory(), repr((self.type.dtype, t.dtype))
|
||||
else:
|
||||
assert not a.has_shared_memory()
|
||||
|
||||
@pytest.mark.parametrize("write", ["w", "ro"])
|
||||
@pytest.mark.parametrize("order", ["C", "F"])
|
||||
@pytest.mark.parametrize("inp", ["2seq", "23seq"])
|
||||
def test_in_nocopy(self, write, order, inp):
|
||||
"""Test if intent(in) array can be passed without copies"""
|
||||
seq = getattr(self, "num" + inp)
|
||||
obj = np.array(seq, dtype=self.type.dtype, order=order)
|
||||
obj.setflags(write=(write == "w"))
|
||||
a = self.array(obj.shape,
|
||||
((order == "C" and intent.in_.c) or intent.in_), obj)
|
||||
assert a.has_shared_memory()
|
||||
|
||||
def test_inout_2seq(self):
|
||||
obj = np.array(self.num2seq, dtype=self.type.dtype)
|
||||
a = self.array([len(self.num2seq)], intent.inout, obj)
|
||||
assert a.has_shared_memory()
|
||||
|
||||
try:
|
||||
a = self.array([2], intent.in_.inout, self.num2seq)
|
||||
except TypeError as msg:
|
||||
if not str(msg).startswith(
|
||||
"failed to initialize intent(inout|inplace|cache) array"):
|
||||
raise
|
||||
else:
|
||||
raise SystemError("intent(inout) should have failed on sequence")
|
||||
|
||||
def test_f_inout_23seq(self):
|
||||
obj = np.array(self.num23seq, dtype=self.type.dtype, order="F")
|
||||
shape = (len(self.num23seq), len(self.num23seq[0]))
|
||||
a = self.array(shape, intent.in_.inout, obj)
|
||||
assert a.has_shared_memory()
|
||||
|
||||
obj = np.array(self.num23seq, dtype=self.type.dtype, order="C")
|
||||
shape = (len(self.num23seq), len(self.num23seq[0]))
|
||||
try:
|
||||
a = self.array(shape, intent.in_.inout, obj)
|
||||
except ValueError as msg:
|
||||
if not str(msg).startswith(
|
||||
"failed to initialize intent(inout) array"):
|
||||
raise
|
||||
else:
|
||||
raise SystemError(
|
||||
"intent(inout) should have failed on improper array")
|
||||
|
||||
def test_c_inout_23seq(self):
|
||||
obj = np.array(self.num23seq, dtype=self.type.dtype)
|
||||
shape = (len(self.num23seq), len(self.num23seq[0]))
|
||||
a = self.array(shape, intent.in_.c.inout, obj)
|
||||
assert a.has_shared_memory()
|
||||
|
||||
def test_in_copy_from_2casttype(self):
|
||||
for t in self.type.cast_types():
|
||||
obj = np.array(self.num2seq, dtype=t.dtype)
|
||||
a = self.array([len(self.num2seq)], intent.in_.copy, obj)
|
||||
assert not a.has_shared_memory()
|
||||
|
||||
def test_c_in_from_23seq(self):
|
||||
a = self.array(
|
||||
[len(self.num23seq), len(self.num23seq[0])], intent.in_,
|
||||
self.num23seq)
|
||||
assert not a.has_shared_memory()
|
||||
|
||||
def test_in_from_23casttype(self):
|
||||
for t in self.type.cast_types():
|
||||
obj = np.array(self.num23seq, dtype=t.dtype)
|
||||
a = self.array(
|
||||
[len(self.num23seq), len(self.num23seq[0])], intent.in_, obj)
|
||||
assert not a.has_shared_memory()
|
||||
|
||||
def test_f_in_from_23casttype(self):
|
||||
for t in self.type.cast_types():
|
||||
obj = np.array(self.num23seq, dtype=t.dtype, order="F")
|
||||
a = self.array(
|
||||
[len(self.num23seq), len(self.num23seq[0])], intent.in_, obj)
|
||||
if t.elsize == self.type.elsize:
|
||||
assert a.has_shared_memory()
|
||||
else:
|
||||
assert not a.has_shared_memory()
|
||||
|
||||
def test_c_in_from_23casttype(self):
|
||||
for t in self.type.cast_types():
|
||||
obj = np.array(self.num23seq, dtype=t.dtype)
|
||||
a = self.array(
|
||||
[len(self.num23seq), len(self.num23seq[0])], intent.in_.c, obj)
|
||||
if t.elsize == self.type.elsize:
|
||||
assert a.has_shared_memory()
|
||||
else:
|
||||
assert not a.has_shared_memory()
|
||||
|
||||
def test_f_copy_in_from_23casttype(self):
|
||||
for t in self.type.cast_types():
|
||||
obj = np.array(self.num23seq, dtype=t.dtype, order="F")
|
||||
a = self.array(
|
||||
[len(self.num23seq), len(self.num23seq[0])], intent.in_.copy,
|
||||
obj)
|
||||
assert not a.has_shared_memory()
|
||||
|
||||
def test_c_copy_in_from_23casttype(self):
|
||||
for t in self.type.cast_types():
|
||||
obj = np.array(self.num23seq, dtype=t.dtype)
|
||||
a = self.array(
|
||||
[len(self.num23seq), len(self.num23seq[0])], intent.in_.c.copy,
|
||||
obj)
|
||||
assert not a.has_shared_memory()
|
||||
|
||||
def test_in_cache_from_2casttype(self):
|
||||
for t in self.type.all_types():
|
||||
if t.elsize != self.type.elsize:
|
||||
continue
|
||||
obj = np.array(self.num2seq, dtype=t.dtype)
|
||||
shape = (len(self.num2seq), )
|
||||
a = self.array(shape, intent.in_.c.cache, obj)
|
||||
assert a.has_shared_memory()
|
||||
|
||||
a = self.array(shape, intent.in_.cache, obj)
|
||||
assert a.has_shared_memory()
|
||||
|
||||
obj = np.array(self.num2seq, dtype=t.dtype, order="F")
|
||||
a = self.array(shape, intent.in_.c.cache, obj)
|
||||
assert a.has_shared_memory()
|
||||
|
||||
a = self.array(shape, intent.in_.cache, obj)
|
||||
assert a.has_shared_memory(), repr(t.dtype)
|
||||
|
||||
try:
|
||||
a = self.array(shape, intent.in_.cache, obj[::-1])
|
||||
except ValueError as msg:
|
||||
if not str(msg).startswith(
|
||||
"failed to initialize intent(cache) array"):
|
||||
raise
|
||||
else:
|
||||
raise SystemError(
|
||||
"intent(cache) should have failed on multisegmented array")
|
||||
|
||||
def test_in_cache_from_2casttype_failure(self):
|
||||
for t in self.type.all_types():
|
||||
if t.elsize >= self.type.elsize:
|
||||
continue
|
||||
obj = np.array(self.num2seq, dtype=t.dtype)
|
||||
shape = (len(self.num2seq), )
|
||||
try:
|
||||
self.array(shape, intent.in_.cache, obj) # Should succeed
|
||||
except ValueError as msg:
|
||||
if not str(msg).startswith(
|
||||
"failed to initialize intent(cache) array"):
|
||||
raise
|
||||
else:
|
||||
raise SystemError(
|
||||
"intent(cache) should have failed on smaller array")
|
||||
|
||||
def test_cache_hidden(self):
|
||||
shape = (2, )
|
||||
a = self.array(shape, intent.cache.hide, None)
|
||||
assert a.arr.shape == shape
|
||||
|
||||
shape = (2, 3)
|
||||
a = self.array(shape, intent.cache.hide, None)
|
||||
assert a.arr.shape == shape
|
||||
|
||||
shape = (-1, 3)
|
||||
try:
|
||||
a = self.array(shape, intent.cache.hide, None)
|
||||
except ValueError as msg:
|
||||
if not str(msg).startswith(
|
||||
"failed to create intent(cache|hide)|optional array"):
|
||||
raise
|
||||
else:
|
||||
raise SystemError(
|
||||
"intent(cache) should have failed on undefined dimensions")
|
||||
|
||||
def test_hidden(self):
|
||||
shape = (2, )
|
||||
a = self.array(shape, intent.hide, None)
|
||||
assert a.arr.shape == shape
|
||||
assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
|
||||
|
||||
shape = (2, 3)
|
||||
a = self.array(shape, intent.hide, None)
|
||||
assert a.arr.shape == shape
|
||||
assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
|
||||
assert a.arr.flags["FORTRAN"] and not a.arr.flags["CONTIGUOUS"]
|
||||
|
||||
shape = (2, 3)
|
||||
a = self.array(shape, intent.c.hide, None)
|
||||
assert a.arr.shape == shape
|
||||
assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
|
||||
assert not a.arr.flags["FORTRAN"] and a.arr.flags["CONTIGUOUS"]
|
||||
|
||||
shape = (-1, 3)
|
||||
try:
|
||||
a = self.array(shape, intent.hide, None)
|
||||
except ValueError as msg:
|
||||
if not str(msg).startswith(
|
||||
"failed to create intent(cache|hide)|optional array"):
|
||||
raise
|
||||
else:
|
||||
raise SystemError(
|
||||
"intent(hide) should have failed on undefined dimensions")
|
||||
|
||||
def test_optional_none(self):
|
||||
shape = (2, )
|
||||
a = self.array(shape, intent.optional, None)
|
||||
assert a.arr.shape == shape
|
||||
assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
|
||||
|
||||
shape = (2, 3)
|
||||
a = self.array(shape, intent.optional, None)
|
||||
assert a.arr.shape == shape
|
||||
assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
|
||||
assert a.arr.flags["FORTRAN"] and not a.arr.flags["CONTIGUOUS"]
|
||||
|
||||
shape = (2, 3)
|
||||
a = self.array(shape, intent.c.optional, None)
|
||||
assert a.arr.shape == shape
|
||||
assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
|
||||
assert not a.arr.flags["FORTRAN"] and a.arr.flags["CONTIGUOUS"]
|
||||
|
||||
def test_optional_from_2seq(self):
|
||||
obj = self.num2seq
|
||||
shape = (len(obj), )
|
||||
a = self.array(shape, intent.optional, obj)
|
||||
assert a.arr.shape == shape
|
||||
assert not a.has_shared_memory()
|
||||
|
||||
def test_optional_from_23seq(self):
|
||||
obj = self.num23seq
|
||||
shape = (len(obj), len(obj[0]))
|
||||
a = self.array(shape, intent.optional, obj)
|
||||
assert a.arr.shape == shape
|
||||
assert not a.has_shared_memory()
|
||||
|
||||
a = self.array(shape, intent.optional.c, obj)
|
||||
assert a.arr.shape == shape
|
||||
assert not a.has_shared_memory()
|
||||
|
||||
def test_inplace(self):
|
||||
obj = np.array(self.num23seq, dtype=self.type.dtype)
|
||||
assert not obj.flags["FORTRAN"] and obj.flags["CONTIGUOUS"]
|
||||
shape = obj.shape
|
||||
a = self.array(shape, intent.inplace, obj)
|
||||
assert obj[1][2] == a.arr[1][2], repr((obj, a.arr))
|
||||
a.arr[1][2] = 54
|
||||
assert obj[1][2] == a.arr[1][2] == np.array(54, dtype=self.type.dtype)
|
||||
assert a.arr is obj
|
||||
assert obj.flags["FORTRAN"] # obj attributes are changed inplace!
|
||||
assert not obj.flags["CONTIGUOUS"]
|
||||
|
||||
def test_inplace_from_casttype(self):
|
||||
for t in self.type.cast_types():
|
||||
if t is self.type:
|
||||
continue
|
||||
obj = np.array(self.num23seq, dtype=t.dtype)
|
||||
assert obj.dtype.type == t.type
|
||||
assert obj.dtype.type is not self.type.type
|
||||
assert not obj.flags["FORTRAN"] and obj.flags["CONTIGUOUS"]
|
||||
shape = obj.shape
|
||||
a = self.array(shape, intent.inplace, obj)
|
||||
assert obj[1][2] == a.arr[1][2], repr((obj, a.arr))
|
||||
a.arr[1][2] = 54
|
||||
assert obj[1][2] == a.arr[1][2] == np.array(54,
|
||||
dtype=self.type.dtype)
|
||||
assert a.arr is obj
|
||||
assert obj.flags["FORTRAN"] # obj attributes changed inplace!
|
||||
assert not obj.flags["CONTIGUOUS"]
|
||||
assert obj.dtype.type is self.type.type # obj changed inplace!
|
|
@ -0,0 +1,49 @@
|
|||
import os
|
||||
import pytest
|
||||
import tempfile
|
||||
|
||||
from . import util
|
||||
|
||||
|
||||
class TestAssumedShapeSumExample(util.F2PyTest):
|
||||
sources = [
|
||||
util.getpath("tests", "src", "assumed_shape", "foo_free.f90"),
|
||||
util.getpath("tests", "src", "assumed_shape", "foo_use.f90"),
|
||||
util.getpath("tests", "src", "assumed_shape", "precision.f90"),
|
||||
util.getpath("tests", "src", "assumed_shape", "foo_mod.f90"),
|
||||
util.getpath("tests", "src", "assumed_shape", ".f2py_f2cmap"),
|
||||
]
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_all(self):
|
||||
r = self.module.fsum([1, 2])
|
||||
assert r == 3
|
||||
r = self.module.sum([1, 2])
|
||||
assert r == 3
|
||||
r = self.module.sum_with_use([1, 2])
|
||||
assert r == 3
|
||||
|
||||
r = self.module.mod.sum([1, 2])
|
||||
assert r == 3
|
||||
r = self.module.mod.fsum([1, 2])
|
||||
assert r == 3
|
||||
|
||||
|
||||
class TestF2cmapOption(TestAssumedShapeSumExample):
|
||||
def setup(self):
|
||||
# Use a custom file name for .f2py_f2cmap
|
||||
self.sources = list(self.sources)
|
||||
f2cmap_src = self.sources.pop(-1)
|
||||
|
||||
self.f2cmap_file = tempfile.NamedTemporaryFile(delete=False)
|
||||
with open(f2cmap_src, "rb") as f:
|
||||
self.f2cmap_file.write(f.read())
|
||||
self.f2cmap_file.close()
|
||||
|
||||
self.sources.append(self.f2cmap_file.name)
|
||||
self.options = ["--f2cmap", self.f2cmap_file.name]
|
||||
|
||||
super().setup()
|
||||
|
||||
def teardown(self):
|
||||
os.unlink(self.f2cmap_file.name)
|
|
@ -0,0 +1,17 @@
|
|||
import sys
|
||||
import pytest
|
||||
from . import util
|
||||
|
||||
from numpy.testing import IS_PYPY
|
||||
|
||||
|
||||
class TestBlockDocString(util.F2PyTest):
|
||||
sources = [util.getpath("tests", "src", "block_docstring", "foo.f")]
|
||||
|
||||
@pytest.mark.skipif(sys.platform == "win32",
|
||||
reason="Fails with MinGW64 Gfortran (Issue #9673)")
|
||||
@pytest.mark.xfail(IS_PYPY,
|
||||
reason="PyPy cannot modify tp_doc after PyType_Ready")
|
||||
def test_block_docstring(self):
|
||||
expected = "bar : 'i'-array(2,3)\n"
|
||||
assert self.module.block.__doc__ == expected
|
228
venv/Lib/site-packages/numpy/f2py/tests/test_callback.py
Normal file
228
venv/Lib/site-packages/numpy/f2py/tests/test_callback.py
Normal file
|
@ -0,0 +1,228 @@
|
|||
import math
|
||||
import textwrap
|
||||
import sys
|
||||
import pytest
|
||||
import threading
|
||||
import traceback
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
from numpy.testing import IS_PYPY
|
||||
from . import util
|
||||
|
||||
|
||||
class TestF77Callback(util.F2PyTest):
|
||||
sources = [util.getpath("tests", "src", "callback", "foo.f")]
|
||||
|
||||
@pytest.mark.parametrize("name", "t,t2".split(","))
|
||||
def test_all(self, name):
|
||||
self.check_function(name)
|
||||
|
||||
@pytest.mark.xfail(IS_PYPY,
|
||||
reason="PyPy cannot modify tp_doc after PyType_Ready")
|
||||
def test_docstring(self):
|
||||
expected = textwrap.dedent("""\
|
||||
a = t(fun,[fun_extra_args])
|
||||
|
||||
Wrapper for ``t``.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
fun : call-back function
|
||||
|
||||
Other Parameters
|
||||
----------------
|
||||
fun_extra_args : input tuple, optional
|
||||
Default: ()
|
||||
|
||||
Returns
|
||||
-------
|
||||
a : int
|
||||
|
||||
Notes
|
||||
-----
|
||||
Call-back functions::
|
||||
|
||||
def fun(): return a
|
||||
Return objects:
|
||||
a : int
|
||||
""")
|
||||
assert self.module.t.__doc__ == expected
|
||||
|
||||
def check_function(self, name):
|
||||
t = getattr(self.module, name)
|
||||
r = t(lambda: 4)
|
||||
assert r == 4
|
||||
r = t(lambda a: 5, fun_extra_args=(6, ))
|
||||
assert r == 5
|
||||
r = t(lambda a: a, fun_extra_args=(6, ))
|
||||
assert r == 6
|
||||
r = t(lambda a: 5 + a, fun_extra_args=(7, ))
|
||||
assert r == 12
|
||||
r = t(lambda a: math.degrees(a), fun_extra_args=(math.pi, ))
|
||||
assert r == 180
|
||||
r = t(math.degrees, fun_extra_args=(math.pi, ))
|
||||
assert r == 180
|
||||
|
||||
r = t(self.module.func, fun_extra_args=(6, ))
|
||||
assert r == 17
|
||||
r = t(self.module.func0)
|
||||
assert r == 11
|
||||
r = t(self.module.func0._cpointer)
|
||||
assert r == 11
|
||||
|
||||
class A:
|
||||
def __call__(self):
|
||||
return 7
|
||||
|
||||
def mth(self):
|
||||
return 9
|
||||
|
||||
a = A()
|
||||
r = t(a)
|
||||
assert r == 7
|
||||
r = t(a.mth)
|
||||
assert r == 9
|
||||
|
||||
@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
|
||||
|
||||
@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
|
||||
|
||||
def test_threadsafety(self):
|
||||
# Segfaults if the callback handling is not threadsafe
|
||||
|
||||
errors = []
|
||||
|
||||
def cb():
|
||||
# Sleep here to make it more likely for another thread
|
||||
# to call their callback at the same time.
|
||||
time.sleep(1e-3)
|
||||
|
||||
# Check reentrancy
|
||||
r = self.module.t(lambda: 123)
|
||||
assert r == 123
|
||||
|
||||
return 42
|
||||
|
||||
def runner(name):
|
||||
try:
|
||||
for j in range(50):
|
||||
r = self.module.t(cb)
|
||||
assert r == 42
|
||||
self.check_function(name)
|
||||
except Exception:
|
||||
errors.append(traceback.format_exc())
|
||||
|
||||
threads = [
|
||||
threading.Thread(target=runner, args=(arg, ))
|
||||
for arg in ("t", "t2") for n in range(20)
|
||||
]
|
||||
|
||||
for t in threads:
|
||||
t.start()
|
||||
|
||||
for t in threads:
|
||||
t.join()
|
||||
|
||||
errors = "\n\n".join(errors)
|
||||
if errors:
|
||||
raise AssertionError(errors)
|
||||
|
||||
def test_hidden_callback(self):
|
||||
try:
|
||||
self.module.hidden_callback(2)
|
||||
except Exception as msg:
|
||||
assert str(msg).startswith("Callback global_f not defined")
|
||||
|
||||
try:
|
||||
self.module.hidden_callback2(2)
|
||||
except Exception as msg:
|
||||
assert str(msg).startswith("cb: Callback global_f not defined")
|
||||
|
||||
self.module.global_f = lambda x: x + 1
|
||||
r = self.module.hidden_callback(2)
|
||||
assert r == 3
|
||||
|
||||
self.module.global_f = lambda x: x + 2
|
||||
r = self.module.hidden_callback(2)
|
||||
assert r == 4
|
||||
|
||||
del self.module.global_f
|
||||
try:
|
||||
self.module.hidden_callback(2)
|
||||
except Exception as msg:
|
||||
assert str(msg).startswith("Callback global_f not defined")
|
||||
|
||||
self.module.global_f = lambda x=0: x + 3
|
||||
r = self.module.hidden_callback(2)
|
||||
assert r == 5
|
||||
|
||||
# reproducer of gh18341
|
||||
r = self.module.hidden_callback2(2)
|
||||
assert r == 3
|
||||
|
||||
|
||||
class TestF77CallbackPythonTLS(TestF77Callback):
|
||||
"""
|
||||
Callback tests using Python thread-local storage instead of
|
||||
compiler-provided
|
||||
"""
|
||||
|
||||
options = ["-DF2PY_USE_PYTHON_TLS"]
|
||||
|
||||
|
||||
class TestF90Callback(util.F2PyTest):
|
||||
sources = [util.getpath("tests", "src", "callback", "gh17797.f90")]
|
||||
|
||||
def test_gh17797(self):
|
||||
def incr(x):
|
||||
return x + 123
|
||||
|
||||
y = np.array([1, 2, 3], dtype=np.int64)
|
||||
r = self.module.gh17797(incr, y)
|
||||
assert r == 123 + 1 + 2 + 3
|
||||
|
||||
|
||||
class TestGH18335(util.F2PyTest):
|
||||
"""The reproduction of the reported issue requires specific input that
|
||||
extensions may break the issue conditions, so the reproducer is
|
||||
implemented as a separate test class. Do not extend this test with
|
||||
other tests!
|
||||
"""
|
||||
sources = [util.getpath("tests", "src", "callback", "gh18335.f90")]
|
||||
|
||||
def test_gh18335(self):
|
||||
def foo(x):
|
||||
x[0] += 1
|
||||
|
||||
y = np.array([1, 2, 3], dtype=np.int8)
|
||||
r = self.module.gh18335(foo)
|
||||
assert r == 123 + 1
|
18
venv/Lib/site-packages/numpy/f2py/tests/test_common.py
Normal file
18
venv/Lib/site-packages/numpy/f2py/tests/test_common.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
import os
|
||||
import sys
|
||||
import pytest
|
||||
|
||||
import numpy as np
|
||||
from . import util
|
||||
|
||||
|
||||
class TestCommonBlock(util.F2PyTest):
|
||||
sources = [util.getpath("tests", "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 self.module.block.long_bn == np.array(1.0, dtype=np.float64)
|
||||
assert self.module.block.string_bn == np.array("2", dtype="|S1")
|
||||
assert self.module.block.ok == np.array(3, dtype=np.int32)
|
117
venv/Lib/site-packages/numpy/f2py/tests/test_compile_function.py
Normal file
117
venv/Lib/site-packages/numpy/f2py/tests/test_compile_function.py
Normal file
|
@ -0,0 +1,117 @@
|
|||
"""See https://github.com/numpy/numpy/pull/11937.
|
||||
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import uuid
|
||||
from importlib import import_module
|
||||
import pytest
|
||||
|
||||
import numpy.f2py
|
||||
|
||||
from . import util
|
||||
|
||||
|
||||
def setup_module():
|
||||
if not util.has_c_compiler():
|
||||
pytest.skip("Needs C compiler")
|
||||
if not util.has_f77_compiler():
|
||||
pytest.skip("Needs FORTRAN 77 compiler")
|
||||
|
||||
|
||||
# extra_args can be a list (since gh-11937) or string.
|
||||
# also test absence of extra_args
|
||||
@pytest.mark.parametrize("extra_args",
|
||||
[["--noopt", "--debug"], "--noopt --debug", ""])
|
||||
@pytest.mark.leaks_references(reason="Imported module seems never deleted.")
|
||||
def test_f2py_init_compile(extra_args):
|
||||
# flush through the f2py __init__ compile() function code path as a
|
||||
# crude test for input handling following migration from
|
||||
# exec_command() to subprocess.check_output() in gh-11937
|
||||
|
||||
# the Fortran 77 syntax requires 6 spaces before any commands, but
|
||||
# more space may be added/
|
||||
fsource = """
|
||||
integer function foo()
|
||||
foo = 10 + 5
|
||||
return
|
||||
end
|
||||
"""
|
||||
# use various helper functions in util.py to enable robust build /
|
||||
# compile and reimport cycle in test suite
|
||||
moddir = util.get_module_dir()
|
||||
modname = util.get_temp_module_name()
|
||||
|
||||
cwd = os.getcwd()
|
||||
target = os.path.join(moddir, str(uuid.uuid4()) + ".f")
|
||||
# try running compile() with and without a source_fn provided so
|
||||
# that the code path where a temporary file for writing Fortran
|
||||
# source is created is also explored
|
||||
for source_fn in [target, None]:
|
||||
# mimic the path changing behavior used by build_module() in
|
||||
# util.py, but don't actually use build_module() because it has
|
||||
# its own invocation of subprocess that circumvents the
|
||||
# f2py.compile code block under test
|
||||
with util.switchdir(moddir):
|
||||
ret_val = numpy.f2py.compile(fsource,
|
||||
modulename=modname,
|
||||
extra_args=extra_args,
|
||||
source_fn=source_fn)
|
||||
|
||||
# check for compile success return value
|
||||
assert 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 calc_result == 15
|
||||
# Removal from sys.modules, is not as such necessary. Even with
|
||||
# removal, the module (dict) stays alive.
|
||||
del sys.modules[modname]
|
||||
|
||||
|
||||
def test_f2py_init_compile_failure():
|
||||
# verify an appropriate integer status value returned by
|
||||
# f2py.compile() when invalid Fortran is provided
|
||||
ret_val = numpy.f2py.compile(b"invalid")
|
||||
assert 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 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
|
||||
with util.switchdir(tmpdir):
|
||||
ret_val = numpy.f2py.compile(fsource,
|
||||
modulename="test_compile_from_strings",
|
||||
extension=".f90")
|
||||
assert ret_val == 0
|
233
venv/Lib/site-packages/numpy/f2py/tests/test_crackfortran.py
Normal file
233
venv/Lib/site-packages/numpy/f2py/tests/test_crackfortran.py
Normal file
|
@ -0,0 +1,233 @@
|
|||
import pytest
|
||||
import numpy as np
|
||||
from numpy.f2py.crackfortran import markinnerspaces
|
||||
from . import util
|
||||
from numpy.f2py import crackfortran
|
||||
import textwrap
|
||||
|
||||
|
||||
class TestNoSpace(util.F2PyTest):
|
||||
# issue gh-15035: add handling for endsubroutine, endfunction with no space
|
||||
# between "end" and the block name
|
||||
sources = [util.getpath("tests", "src", "crackfortran", "gh15035.f")]
|
||||
|
||||
def test_module(self):
|
||||
k = np.array([1, 2, 3], dtype=np.float64)
|
||||
w = np.array([1, 2, 3], dtype=np.float64)
|
||||
self.module.subb(k)
|
||||
assert np.allclose(k, w + 1)
|
||||
self.module.subc([w, k])
|
||||
assert np.allclose(k, w + 1)
|
||||
assert self.module.t0(23) == b"2"
|
||||
|
||||
|
||||
class TestPublicPrivate:
|
||||
def test_defaultPrivate(self):
|
||||
fpath = util.getpath("tests", "src", "crackfortran", "privatemod.f90")
|
||||
mod = crackfortran.crackfortran([str(fpath)])
|
||||
assert len(mod) == 1
|
||||
mod = mod[0]
|
||||
assert "private" in mod["vars"]["a"]["attrspec"]
|
||||
assert "public" not in mod["vars"]["a"]["attrspec"]
|
||||
assert "private" in mod["vars"]["b"]["attrspec"]
|
||||
assert "public" not in mod["vars"]["b"]["attrspec"]
|
||||
assert "private" not in mod["vars"]["seta"]["attrspec"]
|
||||
assert "public" in mod["vars"]["seta"]["attrspec"]
|
||||
|
||||
def test_defaultPublic(self, tmp_path):
|
||||
fpath = util.getpath("tests", "src", "crackfortran", "publicmod.f90")
|
||||
mod = crackfortran.crackfortran([str(fpath)])
|
||||
assert len(mod) == 1
|
||||
mod = mod[0]
|
||||
assert "private" in mod["vars"]["a"]["attrspec"]
|
||||
assert "public" not in mod["vars"]["a"]["attrspec"]
|
||||
assert "private" not in mod["vars"]["seta"]["attrspec"]
|
||||
assert "public" in mod["vars"]["seta"]["attrspec"]
|
||||
|
||||
def test_access_type(self, tmp_path):
|
||||
fpath = util.getpath("tests", "src", "crackfortran", "accesstype.f90")
|
||||
mod = crackfortran.crackfortran([str(fpath)])
|
||||
assert len(mod) == 1
|
||||
tt = mod[0]['vars']
|
||||
assert set(tt['a']['attrspec']) == {'private', 'bind(c)'}
|
||||
assert set(tt['b_']['attrspec']) == {'public', 'bind(c)'}
|
||||
assert set(tt['c']['attrspec']) == {'public'}
|
||||
|
||||
|
||||
class TestModuleProcedure():
|
||||
def test_moduleOperators(self, tmp_path):
|
||||
fpath = util.getpath("tests", "src", "crackfortran", "operators.f90")
|
||||
mod = crackfortran.crackfortran([str(fpath)])
|
||||
assert len(mod) == 1
|
||||
mod = mod[0]
|
||||
assert "body" in mod and len(mod["body"]) == 9
|
||||
assert mod["body"][1]["name"] == "operator(.item.)"
|
||||
assert "implementedby" in mod["body"][1]
|
||||
assert mod["body"][1]["implementedby"] == \
|
||||
["item_int", "item_real"]
|
||||
assert mod["body"][2]["name"] == "operator(==)"
|
||||
assert "implementedby" in mod["body"][2]
|
||||
assert mod["body"][2]["implementedby"] == ["items_are_equal"]
|
||||
assert mod["body"][3]["name"] == "assignment(=)"
|
||||
assert "implementedby" in mod["body"][3]
|
||||
assert mod["body"][3]["implementedby"] == \
|
||||
["get_int", "get_real"]
|
||||
|
||||
|
||||
class TestExternal(util.F2PyTest):
|
||||
# issue gh-17859: add external attribute support
|
||||
sources = [util.getpath("tests", "src", "crackfortran", "gh17859.f")]
|
||||
|
||||
def test_external_as_statement(self):
|
||||
def incr(x):
|
||||
return x + 123
|
||||
|
||||
r = self.module.external_as_statement(incr)
|
||||
assert r == 123
|
||||
|
||||
def test_external_as_attribute(self):
|
||||
def incr(x):
|
||||
return x + 123
|
||||
|
||||
r = self.module.external_as_attribute(incr)
|
||||
assert r == 123
|
||||
|
||||
|
||||
class TestCrackFortran(util.F2PyTest):
|
||||
# gh-2848: commented lines between parameters in subroutine parameter lists
|
||||
sources = [util.getpath("tests", "src", "crackfortran", "gh2848.f90")]
|
||||
|
||||
def test_gh2848(self):
|
||||
r = self.module.gh2848(1, 2)
|
||||
assert r == (1, 2)
|
||||
|
||||
|
||||
class TestMarkinnerspaces:
|
||||
# gh-14118: markinnerspaces does not handle multiple quotations
|
||||
|
||||
def test_do_not_touch_normal_spaces(self):
|
||||
test_list = ["a ", " a", "a b c", "'abcdefghij'"]
|
||||
for i in test_list:
|
||||
assert markinnerspaces(i) == i
|
||||
|
||||
def test_one_relevant_space(self):
|
||||
assert markinnerspaces("a 'b c' \\' \\'") == "a 'b@_@c' \\' \\'"
|
||||
assert markinnerspaces(r'a "b c" \" \"') == r'a "b@_@c" \" \"'
|
||||
|
||||
def test_ignore_inner_quotes(self):
|
||||
assert markinnerspaces("a 'b c\" \" d' e") == "a 'b@_@c\"@_@\"@_@d' e"
|
||||
assert markinnerspaces("a \"b c' ' d\" e") == "a \"b@_@c'@_@'@_@d\" e"
|
||||
|
||||
def test_multiple_relevant_spaces(self):
|
||||
assert markinnerspaces("a 'b c' 'd e'") == "a 'b@_@c' 'd@_@e'"
|
||||
assert markinnerspaces(r'a "b c" "d e"') == r'a "b@_@c" "d@_@e"'
|
||||
|
||||
|
||||
class TestDimSpec(util.F2PyTest):
|
||||
"""This test suite tests various expressions that are used as dimension
|
||||
specifications.
|
||||
|
||||
There exists two usage cases where analyzing dimensions
|
||||
specifications are important.
|
||||
|
||||
In the first case, the size of output arrays must be defined based
|
||||
on the inputs to a Fortran function. Because Fortran supports
|
||||
arbitrary bases for indexing, for instance, `arr(lower:upper)`,
|
||||
f2py has to evaluate an expression `upper - lower + 1` where
|
||||
`lower` and `upper` are arbitrary expressions of input parameters.
|
||||
The evaluation is performed in C, so f2py has to translate Fortran
|
||||
expressions to valid C expressions (an alternative approach is
|
||||
that a developer specifies the corresponding C expressions in a
|
||||
.pyf file).
|
||||
|
||||
In the second case, when user provides an input array with a given
|
||||
size but some hidden parameters used in dimensions specifications
|
||||
need to be determined based on the input array size. This is a
|
||||
harder problem because f2py has to solve the inverse problem: find
|
||||
a parameter `p` such that `upper(p) - lower(p) + 1` equals to the
|
||||
size of input array. In the case when this equation cannot be
|
||||
solved (e.g. because the input array size is wrong), raise an
|
||||
error before calling the Fortran function (that otherwise would
|
||||
likely crash Python process when the size of input arrays is
|
||||
wrong). f2py currently supports this case only when the equation
|
||||
is linear with respect to unknown parameter.
|
||||
|
||||
"""
|
||||
|
||||
suffix = ".f90"
|
||||
|
||||
code_template = textwrap.dedent("""
|
||||
function get_arr_size_{count}(a, n) result (length)
|
||||
integer, intent(in) :: n
|
||||
integer, dimension({dimspec}), intent(out) :: a
|
||||
integer length
|
||||
length = size(a)
|
||||
end function
|
||||
|
||||
subroutine get_inv_arr_size_{count}(a, n)
|
||||
integer :: n
|
||||
! the value of n is computed in f2py wrapper
|
||||
!f2py intent(out) n
|
||||
integer, dimension({dimspec}), intent(in) :: a
|
||||
if (a({first}).gt.0) then
|
||||
print*, "a=", a
|
||||
endif
|
||||
end subroutine
|
||||
""")
|
||||
|
||||
linear_dimspecs = [
|
||||
"n", "2*n", "2:n", "n/2", "5 - n/2", "3*n:20", "n*(n+1):n*(n+5)",
|
||||
"2*n, n"
|
||||
]
|
||||
nonlinear_dimspecs = ["2*n:3*n*n+2*n"]
|
||||
all_dimspecs = linear_dimspecs + nonlinear_dimspecs
|
||||
|
||||
code = ""
|
||||
for count, dimspec in enumerate(all_dimspecs):
|
||||
lst = [(d.split(":")[0] if ":" in d else "1") for d in dimspec.split(',')]
|
||||
code += code_template.format(
|
||||
count=count,
|
||||
dimspec=dimspec,
|
||||
first=", ".join(lst),
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize("dimspec", all_dimspecs)
|
||||
def test_array_size(self, dimspec):
|
||||
|
||||
count = self.all_dimspecs.index(dimspec)
|
||||
get_arr_size = getattr(self.module, f"get_arr_size_{count}")
|
||||
|
||||
for n in [1, 2, 3, 4, 5]:
|
||||
sz, a = get_arr_size(n)
|
||||
assert a.size == sz
|
||||
|
||||
@pytest.mark.parametrize("dimspec", all_dimspecs)
|
||||
def test_inv_array_size(self, dimspec):
|
||||
|
||||
count = self.all_dimspecs.index(dimspec)
|
||||
get_arr_size = getattr(self.module, f"get_arr_size_{count}")
|
||||
get_inv_arr_size = getattr(self.module, f"get_inv_arr_size_{count}")
|
||||
|
||||
for n in [1, 2, 3, 4, 5]:
|
||||
sz, a = get_arr_size(n)
|
||||
if dimspec in self.nonlinear_dimspecs:
|
||||
# one must specify n as input, the call we'll ensure
|
||||
# that a and n are compatible:
|
||||
n1 = get_inv_arr_size(a, n)
|
||||
else:
|
||||
# in case of linear dependence, n can be determined
|
||||
# from the shape of a:
|
||||
n1 = get_inv_arr_size(a)
|
||||
# n1 may be different from n (for instance, when `a` size
|
||||
# is a function of some `n` fraction) but it must produce
|
||||
# the same sized array
|
||||
sz1, _ = get_arr_size(n1)
|
||||
assert sz == sz1, (n, n1, sz, sz1)
|
||||
|
||||
|
||||
class TestModuleDeclaration:
|
||||
def test_dependencies(self, tmp_path):
|
||||
fpath = util.getpath("tests", "src", "crackfortran", "foo_deps.f90")
|
||||
mod = crackfortran.crackfortran([str(fpath)])
|
||||
assert len(mod) == 1
|
||||
assert mod[0]["vars"]["abar"]["="] == "bar('abar')"
|
15
venv/Lib/site-packages/numpy/f2py/tests/test_f2cmap.py
Normal file
15
venv/Lib/site-packages/numpy/f2py/tests/test_f2cmap.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
from . import util
|
||||
import numpy as np
|
||||
|
||||
class TestF2Cmap(util.F2PyTest):
|
||||
sources = [
|
||||
util.getpath("tests", "src", "f2cmap", "isoFortranEnvMap.f90"),
|
||||
util.getpath("tests", "src", "f2cmap", ".f2py_f2cmap")
|
||||
]
|
||||
|
||||
# gh-15095
|
||||
def test_long_long_map(self):
|
||||
inp = np.ones(3)
|
||||
out = self.module.func1(inp)
|
||||
exp_out = 3
|
||||
assert out == exp_out
|
748
venv/Lib/site-packages/numpy/f2py/tests/test_f2py2e.py
Normal file
748
venv/Lib/site-packages/numpy/f2py/tests/test_f2py2e.py
Normal file
|
@ -0,0 +1,748 @@
|
|||
import textwrap, re, sys, subprocess, shlex
|
||||
from pathlib import Path
|
||||
from collections import namedtuple
|
||||
|
||||
import pytest
|
||||
|
||||
from . import util
|
||||
from numpy.f2py.f2py2e import main as f2pycli
|
||||
|
||||
#########################
|
||||
# CLI utils and classes #
|
||||
#########################
|
||||
|
||||
PPaths = namedtuple("PPaths", "finp, f90inp, pyf, wrap77, wrap90, cmodf")
|
||||
|
||||
|
||||
def get_io_paths(fname_inp, mname="untitled"):
|
||||
"""Takes in a temporary file for testing and returns the expected output and input paths
|
||||
|
||||
Here expected output is essentially one of any of the possible generated
|
||||
files.
|
||||
|
||||
..note::
|
||||
|
||||
Since this does not actually run f2py, none of these are guaranteed to
|
||||
exist, and module names are typically incorrect
|
||||
|
||||
Parameters
|
||||
----------
|
||||
fname_inp : str
|
||||
The input filename
|
||||
mname : str, optional
|
||||
The name of the module, untitled by default
|
||||
|
||||
Returns
|
||||
-------
|
||||
genp : NamedTuple PPaths
|
||||
The possible paths which are generated, not all of which exist
|
||||
"""
|
||||
bpath = Path(fname_inp)
|
||||
return PPaths(
|
||||
finp=bpath.with_suffix(".f"),
|
||||
f90inp=bpath.with_suffix(".f90"),
|
||||
pyf=bpath.with_suffix(".pyf"),
|
||||
wrap77=bpath.with_name(f"{mname}-f2pywrappers.f"),
|
||||
wrap90=bpath.with_name(f"{mname}-f2pywrappers2.f90"),
|
||||
cmodf=bpath.with_name(f"{mname}module.c"),
|
||||
)
|
||||
|
||||
|
||||
##############
|
||||
# CLI Fixtures and Tests #
|
||||
#############
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def hello_world_f90(tmpdir_factory):
|
||||
"""Generates a single f90 file for testing"""
|
||||
fdat = util.getpath("tests", "src", "cli", "hiworld.f90").read_text()
|
||||
fn = tmpdir_factory.getbasetemp() / "hello.f90"
|
||||
fn.write_text(fdat, encoding="ascii")
|
||||
return fn
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def hello_world_f77(tmpdir_factory):
|
||||
"""Generates a single f77 file for testing"""
|
||||
fdat = util.getpath("tests", "src", "cli", "hi77.f").read_text()
|
||||
fn = tmpdir_factory.getbasetemp() / "hello.f"
|
||||
fn.write_text(fdat, encoding="ascii")
|
||||
return fn
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def retreal_f77(tmpdir_factory):
|
||||
"""Generates a single f77 file for testing"""
|
||||
fdat = util.getpath("tests", "src", "return_real", "foo77.f").read_text()
|
||||
fn = tmpdir_factory.getbasetemp() / "foo.f"
|
||||
fn.write_text(fdat, encoding="ascii")
|
||||
return fn
|
||||
|
||||
|
||||
def test_gen_pyf(capfd, hello_world_f90, monkeypatch):
|
||||
"""Ensures that a signature file is generated via the CLI
|
||||
CLI :: -h
|
||||
"""
|
||||
ipath = Path(hello_world_f90)
|
||||
opath = Path(hello_world_f90).stem + ".pyf"
|
||||
monkeypatch.setattr(sys, "argv", f'f2py -h {opath} {ipath}'.split())
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli() # Generate wrappers
|
||||
out, _ = capfd.readouterr()
|
||||
assert "Saving signatures to file" in out
|
||||
assert Path(f'{opath}').exists()
|
||||
|
||||
|
||||
def test_gen_pyf_stdout(capfd, hello_world_f90, monkeypatch):
|
||||
"""Ensures that a signature file can be dumped to stdout
|
||||
CLI :: -h
|
||||
"""
|
||||
ipath = Path(hello_world_f90)
|
||||
monkeypatch.setattr(sys, "argv", f'f2py -h stdout {ipath}'.split())
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
out, _ = capfd.readouterr()
|
||||
assert "Saving signatures to file" in out
|
||||
|
||||
|
||||
def test_gen_pyf_no_overwrite(capfd, hello_world_f90, monkeypatch):
|
||||
"""Ensures that the CLI refuses to overwrite signature files
|
||||
CLI :: -h without --overwrite-signature
|
||||
"""
|
||||
ipath = Path(hello_world_f90)
|
||||
monkeypatch.setattr(sys, "argv", f'f2py -h faker.pyf {ipath}'.split())
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
Path("faker.pyf").write_text("Fake news", encoding="ascii")
|
||||
with pytest.raises(SystemExit):
|
||||
f2pycli() # Refuse to overwrite
|
||||
_, err = capfd.readouterr()
|
||||
assert "Use --overwrite-signature to overwrite" in err
|
||||
|
||||
|
||||
@pytest.mark.xfail
|
||||
def test_f2py_skip(capfd, retreal_f77, monkeypatch):
|
||||
"""Tests that functions can be skipped
|
||||
CLI :: skip:
|
||||
"""
|
||||
foutl = get_io_paths(retreal_f77, mname="test")
|
||||
ipath = foutl.finp
|
||||
toskip = "t0 t4 t8 sd s8 s4"
|
||||
remaining = "td s0"
|
||||
monkeypatch.setattr(
|
||||
sys, "argv",
|
||||
f'f2py {ipath} -m test skip: {toskip}'.split())
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
out, err = capfd.readouterr()
|
||||
for skey in toskip.split():
|
||||
assert (
|
||||
f'buildmodule: Could not found the body of interfaced routine "{skey}". Skipping.'
|
||||
in err)
|
||||
for rkey in remaining.split():
|
||||
assert f'Constructing wrapper function "{rkey}"' in out
|
||||
|
||||
|
||||
def test_f2py_only(capfd, retreal_f77, monkeypatch):
|
||||
"""Test that functions can be kept by only:
|
||||
CLI :: only:
|
||||
"""
|
||||
foutl = get_io_paths(retreal_f77, mname="test")
|
||||
ipath = foutl.finp
|
||||
toskip = "t0 t4 t8 sd s8 s4"
|
||||
tokeep = "td s0"
|
||||
monkeypatch.setattr(
|
||||
sys, "argv",
|
||||
f'f2py {ipath} -m test only: {tokeep}'.split())
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
out, err = capfd.readouterr()
|
||||
for skey in toskip.split():
|
||||
assert (
|
||||
f'buildmodule: Could not find the body of interfaced routine "{skey}". Skipping.'
|
||||
in err)
|
||||
for rkey in tokeep.split():
|
||||
assert f'Constructing wrapper function "{rkey}"' in out
|
||||
|
||||
|
||||
def test_file_processing_switch(capfd, hello_world_f90, retreal_f77,
|
||||
monkeypatch):
|
||||
"""Tests that it is possible to return to file processing mode
|
||||
CLI :: :
|
||||
BUG: numpy-gh #20520
|
||||
"""
|
||||
foutl = get_io_paths(retreal_f77, mname="test")
|
||||
ipath = foutl.finp
|
||||
toskip = "t0 t4 t8 sd s8 s4"
|
||||
ipath2 = Path(hello_world_f90)
|
||||
tokeep = "td s0 hi" # hi is in ipath2
|
||||
mname = "blah"
|
||||
monkeypatch.setattr(
|
||||
sys,
|
||||
"argv",
|
||||
f'f2py {ipath} -m {mname} only: {tokeep} : {ipath2}'.split(
|
||||
),
|
||||
)
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
out, err = capfd.readouterr()
|
||||
for skey in toskip.split():
|
||||
assert (
|
||||
f'buildmodule: Could not find the body of interfaced routine "{skey}". Skipping.'
|
||||
in err)
|
||||
for rkey in tokeep.split():
|
||||
assert f'Constructing wrapper function "{rkey}"' in out
|
||||
|
||||
|
||||
def test_mod_gen_f77(capfd, hello_world_f90, monkeypatch):
|
||||
"""Checks the generation of files based on a module name
|
||||
CLI :: -m
|
||||
"""
|
||||
MNAME = "hi"
|
||||
foutl = get_io_paths(hello_world_f90, mname=MNAME)
|
||||
ipath = foutl.f90inp
|
||||
monkeypatch.setattr(sys, "argv", f'f2py {ipath} -m {MNAME}'.split())
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
|
||||
# Always generate C module
|
||||
assert Path.exists(foutl.cmodf)
|
||||
# File contains a function, check for F77 wrappers
|
||||
assert Path.exists(foutl.wrap77)
|
||||
|
||||
|
||||
def test_lower_cmod(capfd, hello_world_f77, monkeypatch):
|
||||
"""Lowers cases by flag or when -h is present
|
||||
|
||||
CLI :: --[no-]lower
|
||||
"""
|
||||
foutl = get_io_paths(hello_world_f77, mname="test")
|
||||
ipath = foutl.finp
|
||||
capshi = re.compile(r"HI\(\)")
|
||||
capslo = re.compile(r"hi\(\)")
|
||||
# Case I: --lower is passed
|
||||
monkeypatch.setattr(sys, "argv", f'f2py {ipath} -m test --lower'.split())
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
out, _ = capfd.readouterr()
|
||||
assert capslo.search(out) is not None
|
||||
assert capshi.search(out) is None
|
||||
# Case II: --no-lower is passed
|
||||
monkeypatch.setattr(sys, "argv",
|
||||
f'f2py {ipath} -m test --no-lower'.split())
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
out, _ = capfd.readouterr()
|
||||
assert capslo.search(out) is None
|
||||
assert capshi.search(out) is not None
|
||||
|
||||
|
||||
def test_lower_sig(capfd, hello_world_f77, monkeypatch):
|
||||
"""Lowers cases in signature files by flag or when -h is present
|
||||
|
||||
CLI :: --[no-]lower -h
|
||||
"""
|
||||
foutl = get_io_paths(hello_world_f77, mname="test")
|
||||
ipath = foutl.finp
|
||||
# Signature files
|
||||
capshi = re.compile(r"Block: HI")
|
||||
capslo = re.compile(r"Block: hi")
|
||||
# Case I: --lower is implied by -h
|
||||
# TODO: Clean up to prevent passing --overwrite-signature
|
||||
monkeypatch.setattr(
|
||||
sys,
|
||||
"argv",
|
||||
f'f2py {ipath} -h {foutl.pyf} -m test --overwrite-signature'.split(),
|
||||
)
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
out, _ = capfd.readouterr()
|
||||
assert capslo.search(out) is not None
|
||||
assert capshi.search(out) is None
|
||||
|
||||
# Case II: --no-lower overrides -h
|
||||
monkeypatch.setattr(
|
||||
sys,
|
||||
"argv",
|
||||
f'f2py {ipath} -h {foutl.pyf} -m test --overwrite-signature --no-lower'
|
||||
.split(),
|
||||
)
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
out, _ = capfd.readouterr()
|
||||
assert capslo.search(out) is None
|
||||
assert capshi.search(out) is not None
|
||||
|
||||
|
||||
def test_build_dir(capfd, hello_world_f90, monkeypatch):
|
||||
"""Ensures that the build directory can be specified
|
||||
|
||||
CLI :: --build-dir
|
||||
"""
|
||||
ipath = Path(hello_world_f90)
|
||||
mname = "blah"
|
||||
odir = "tttmp"
|
||||
monkeypatch.setattr(sys, "argv",
|
||||
f'f2py -m {mname} {ipath} --build-dir {odir}'.split())
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
out, _ = capfd.readouterr()
|
||||
assert f"Wrote C/API module \"{mname}\"" in out
|
||||
|
||||
|
||||
def test_overwrite(capfd, hello_world_f90, monkeypatch):
|
||||
"""Ensures that the build directory can be specified
|
||||
|
||||
CLI :: --overwrite-signature
|
||||
"""
|
||||
ipath = Path(hello_world_f90)
|
||||
monkeypatch.setattr(
|
||||
sys, "argv",
|
||||
f'f2py -h faker.pyf {ipath} --overwrite-signature'.split())
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
Path("faker.pyf").write_text("Fake news", encoding="ascii")
|
||||
f2pycli()
|
||||
out, _ = capfd.readouterr()
|
||||
assert "Saving signatures to file" in out
|
||||
|
||||
|
||||
def test_latexdoc(capfd, hello_world_f90, monkeypatch):
|
||||
"""Ensures that TeX documentation is written out
|
||||
|
||||
CLI :: --latex-doc
|
||||
"""
|
||||
ipath = Path(hello_world_f90)
|
||||
mname = "blah"
|
||||
monkeypatch.setattr(sys, "argv",
|
||||
f'f2py -m {mname} {ipath} --latex-doc'.split())
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
out, _ = capfd.readouterr()
|
||||
assert "Documentation is saved to file" in out
|
||||
with Path(f"{mname}module.tex").open() as otex:
|
||||
assert "\\documentclass" in otex.read()
|
||||
|
||||
|
||||
def test_nolatexdoc(capfd, hello_world_f90, monkeypatch):
|
||||
"""Ensures that TeX documentation is written out
|
||||
|
||||
CLI :: --no-latex-doc
|
||||
"""
|
||||
ipath = Path(hello_world_f90)
|
||||
mname = "blah"
|
||||
monkeypatch.setattr(sys, "argv",
|
||||
f'f2py -m {mname} {ipath} --no-latex-doc'.split())
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
out, _ = capfd.readouterr()
|
||||
assert "Documentation is saved to file" not in out
|
||||
|
||||
|
||||
def test_shortlatex(capfd, hello_world_f90, monkeypatch):
|
||||
"""Ensures that truncated documentation is written out
|
||||
|
||||
TODO: Test to ensure this has no effect without --latex-doc
|
||||
CLI :: --latex-doc --short-latex
|
||||
"""
|
||||
ipath = Path(hello_world_f90)
|
||||
mname = "blah"
|
||||
monkeypatch.setattr(
|
||||
sys,
|
||||
"argv",
|
||||
f'f2py -m {mname} {ipath} --latex-doc --short-latex'.split(),
|
||||
)
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
out, _ = capfd.readouterr()
|
||||
assert "Documentation is saved to file" in out
|
||||
with Path(f"./{mname}module.tex").open() as otex:
|
||||
assert "\\documentclass" not in otex.read()
|
||||
|
||||
|
||||
def test_restdoc(capfd, hello_world_f90, monkeypatch):
|
||||
"""Ensures that RsT documentation is written out
|
||||
|
||||
CLI :: --rest-doc
|
||||
"""
|
||||
ipath = Path(hello_world_f90)
|
||||
mname = "blah"
|
||||
monkeypatch.setattr(sys, "argv",
|
||||
f'f2py -m {mname} {ipath} --rest-doc'.split())
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
out, _ = capfd.readouterr()
|
||||
assert "ReST Documentation is saved to file" in out
|
||||
with Path(f"./{mname}module.rest").open() as orst:
|
||||
assert r".. -*- rest -*-" in orst.read()
|
||||
|
||||
|
||||
def test_norestexdoc(capfd, hello_world_f90, monkeypatch):
|
||||
"""Ensures that TeX documentation is written out
|
||||
|
||||
CLI :: --no-rest-doc
|
||||
"""
|
||||
ipath = Path(hello_world_f90)
|
||||
mname = "blah"
|
||||
monkeypatch.setattr(sys, "argv",
|
||||
f'f2py -m {mname} {ipath} --no-rest-doc'.split())
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
out, _ = capfd.readouterr()
|
||||
assert "ReST Documentation is saved to file" not in out
|
||||
|
||||
|
||||
def test_debugcapi(capfd, hello_world_f90, monkeypatch):
|
||||
"""Ensures that debugging wrappers are written
|
||||
|
||||
CLI :: --debug-capi
|
||||
"""
|
||||
ipath = Path(hello_world_f90)
|
||||
mname = "blah"
|
||||
monkeypatch.setattr(sys, "argv",
|
||||
f'f2py -m {mname} {ipath} --debug-capi'.split())
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
with Path(f"./{mname}module.c").open() as ocmod:
|
||||
assert r"#define DEBUGCFUNCS" in ocmod.read()
|
||||
|
||||
|
||||
@pytest.mark.xfail(reason="Consistently fails on CI.")
|
||||
def test_debugcapi_bld(hello_world_f90, monkeypatch):
|
||||
"""Ensures that debugging wrappers work
|
||||
|
||||
CLI :: --debug-capi -c
|
||||
"""
|
||||
ipath = Path(hello_world_f90)
|
||||
mname = "blah"
|
||||
monkeypatch.setattr(sys, "argv",
|
||||
f'f2py -m {mname} {ipath} -c --debug-capi'.split())
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
cmd_run = shlex.split("python3 -c \"import blah; blah.hi()\"")
|
||||
rout = subprocess.run(cmd_run, capture_output=True, encoding='UTF-8')
|
||||
eout = ' Hello World\n'
|
||||
eerr = textwrap.dedent("""\
|
||||
debug-capi:Python C/API function blah.hi()
|
||||
debug-capi:float hi=:output,hidden,scalar
|
||||
debug-capi:hi=0
|
||||
debug-capi:Fortran subroutine `f2pywraphi(&hi)'
|
||||
debug-capi:hi=0
|
||||
debug-capi:Building return value.
|
||||
debug-capi:Python C/API function blah.hi: successful.
|
||||
debug-capi:Freeing memory.
|
||||
""")
|
||||
assert rout.stdout == eout
|
||||
assert rout.stderr == eerr
|
||||
|
||||
|
||||
def test_wrapfunc_def(capfd, hello_world_f90, monkeypatch):
|
||||
"""Ensures that fortran subroutine wrappers for F77 are included by default
|
||||
|
||||
CLI :: --[no]-wrap-functions
|
||||
"""
|
||||
# Implied
|
||||
ipath = Path(hello_world_f90)
|
||||
mname = "blah"
|
||||
monkeypatch.setattr(sys, "argv", f'f2py -m {mname} {ipath}'.split())
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
out, _ = capfd.readouterr()
|
||||
assert r"Fortran 77 wrappers are saved to" in out
|
||||
|
||||
# Explicit
|
||||
monkeypatch.setattr(sys, "argv",
|
||||
f'f2py -m {mname} {ipath} --wrap-functions'.split())
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
out, _ = capfd.readouterr()
|
||||
assert r"Fortran 77 wrappers are saved to" in out
|
||||
|
||||
|
||||
def test_nowrapfunc(capfd, hello_world_f90, monkeypatch):
|
||||
"""Ensures that fortran subroutine wrappers for F77 can be disabled
|
||||
|
||||
CLI :: --no-wrap-functions
|
||||
"""
|
||||
ipath = Path(hello_world_f90)
|
||||
mname = "blah"
|
||||
monkeypatch.setattr(sys, "argv",
|
||||
f'f2py -m {mname} {ipath} --no-wrap-functions'.split())
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
out, _ = capfd.readouterr()
|
||||
assert r"Fortran 77 wrappers are saved to" not in out
|
||||
|
||||
|
||||
def test_inclheader(capfd, hello_world_f90, monkeypatch):
|
||||
"""Add to the include directories
|
||||
|
||||
CLI :: -include
|
||||
TODO: Document this in the help string
|
||||
"""
|
||||
ipath = Path(hello_world_f90)
|
||||
mname = "blah"
|
||||
monkeypatch.setattr(
|
||||
sys,
|
||||
"argv",
|
||||
f'f2py -m {mname} {ipath} -include<stdbool.h> -include<stdio.h> '.
|
||||
split(),
|
||||
)
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
with Path(f"./{mname}module.c").open() as ocmod:
|
||||
ocmr = ocmod.read()
|
||||
assert "#include <stdbool.h>" in ocmr
|
||||
assert "#include <stdio.h>" in ocmr
|
||||
|
||||
|
||||
def test_inclpath():
|
||||
"""Add to the include directories
|
||||
|
||||
CLI :: --include-paths
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_hlink():
|
||||
"""Add to the include directories
|
||||
|
||||
CLI :: --help-link
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_f2cmap():
|
||||
"""Check that Fortran-to-Python KIND specs can be passed
|
||||
|
||||
CLI :: --f2cmap
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_quiet(capfd, hello_world_f90, monkeypatch):
|
||||
"""Reduce verbosity
|
||||
|
||||
CLI :: --quiet
|
||||
"""
|
||||
ipath = Path(hello_world_f90)
|
||||
monkeypatch.setattr(sys, "argv", f'f2py -m blah {ipath} --quiet'.split())
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
out, _ = capfd.readouterr()
|
||||
assert len(out) == 0
|
||||
|
||||
|
||||
def test_verbose(capfd, hello_world_f90, monkeypatch):
|
||||
"""Increase verbosity
|
||||
|
||||
CLI :: --verbose
|
||||
"""
|
||||
ipath = Path(hello_world_f90)
|
||||
monkeypatch.setattr(sys, "argv", f'f2py -m blah {ipath} --verbose'.split())
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
out, _ = capfd.readouterr()
|
||||
assert "analyzeline" in out
|
||||
|
||||
|
||||
def test_version(capfd, monkeypatch):
|
||||
"""Ensure version
|
||||
|
||||
CLI :: -v
|
||||
"""
|
||||
monkeypatch.setattr(sys, "argv", 'f2py -v'.split())
|
||||
# TODO: f2py2e should not call sys.exit() after printing the version
|
||||
with pytest.raises(SystemExit):
|
||||
f2pycli()
|
||||
out, _ = capfd.readouterr()
|
||||
import numpy as np
|
||||
assert np.__version__ == out.strip()
|
||||
|
||||
|
||||
@pytest.mark.xfail(reason="Consistently fails on CI.")
|
||||
def test_npdistop(hello_world_f90, monkeypatch):
|
||||
"""
|
||||
CLI :: -c
|
||||
"""
|
||||
ipath = Path(hello_world_f90)
|
||||
monkeypatch.setattr(sys, "argv", f'f2py -m blah {ipath} -c'.split())
|
||||
|
||||
with util.switchdir(ipath.parent):
|
||||
f2pycli()
|
||||
cmd_run = shlex.split("python -c \"import blah; blah.hi()\"")
|
||||
rout = subprocess.run(cmd_run, capture_output=True, encoding='UTF-8')
|
||||
eout = ' Hello World\n'
|
||||
assert rout.stdout == eout
|
||||
|
||||
|
||||
# Numpy distutils flags
|
||||
# TODO: These should be tested separately
|
||||
|
||||
|
||||
def test_npd_fcompiler():
|
||||
"""
|
||||
CLI :: -c --fcompiler
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_npd_compiler():
|
||||
"""
|
||||
CLI :: -c --compiler
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_npd_help_fcompiler():
|
||||
"""
|
||||
CLI :: -c --help-fcompiler
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_npd_f77exec():
|
||||
"""
|
||||
CLI :: -c --f77exec
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_npd_f90exec():
|
||||
"""
|
||||
CLI :: -c --f90exec
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_npd_f77flags():
|
||||
"""
|
||||
CLI :: -c --f77flags
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_npd_f90flags():
|
||||
"""
|
||||
CLI :: -c --f90flags
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_npd_opt():
|
||||
"""
|
||||
CLI :: -c --opt
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_npd_arch():
|
||||
"""
|
||||
CLI :: -c --arch
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_npd_noopt():
|
||||
"""
|
||||
CLI :: -c --noopt
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_npd_noarch():
|
||||
"""
|
||||
CLI :: -c --noarch
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_npd_debug():
|
||||
"""
|
||||
CLI :: -c --debug
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_npd_link_auto():
|
||||
"""
|
||||
CLI :: -c --link-<resource>
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_npd_lib():
|
||||
"""
|
||||
CLI :: -c -L/path/to/lib/ -l<libname>
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_npd_define():
|
||||
"""
|
||||
CLI :: -D<define>
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_npd_undefine():
|
||||
"""
|
||||
CLI :: -U<name>
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_npd_incl():
|
||||
"""
|
||||
CLI :: -I/path/to/include/
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
||||
|
||||
|
||||
def test_npd_linker():
|
||||
"""
|
||||
CLI :: <filename>.o <filename>.so <filename>.a
|
||||
"""
|
||||
# TODO: populate
|
||||
pass
|
26
venv/Lib/site-packages/numpy/f2py/tests/test_kind.py
Normal file
26
venv/Lib/site-packages/numpy/f2py/tests/test_kind.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
import os
|
||||
import pytest
|
||||
|
||||
from numpy.f2py.crackfortran import (
|
||||
_selected_int_kind_func as selected_int_kind,
|
||||
_selected_real_kind_func as selected_real_kind,
|
||||
)
|
||||
from . import util
|
||||
|
||||
|
||||
class TestKind(util.F2PyTest):
|
||||
sources = [util.getpath("tests", "src", "kind", "foo.f90")]
|
||||
|
||||
def test_all(self):
|
||||
selectedrealkind = self.module.selectedrealkind
|
||||
selectedintkind = self.module.selectedintkind
|
||||
|
||||
for i in range(40):
|
||||
assert selectedintkind(i) == selected_int_kind(
|
||||
i
|
||||
), f"selectedintkind({i}): expected {selected_int_kind(i)!r} but got {selectedintkind(i)!r}"
|
||||
|
||||
for i in range(20):
|
||||
assert selectedrealkind(i) == selected_real_kind(
|
||||
i
|
||||
), f"selectedrealkind({i}): expected {selected_real_kind(i)!r} but got {selectedrealkind(i)!r}"
|
33
venv/Lib/site-packages/numpy/f2py/tests/test_mixed.py
Normal file
33
venv/Lib/site-packages/numpy/f2py/tests/test_mixed.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
import os
|
||||
import textwrap
|
||||
import pytest
|
||||
|
||||
from numpy.testing import IS_PYPY
|
||||
from . import util
|
||||
|
||||
|
||||
class TestMixed(util.F2PyTest):
|
||||
sources = [
|
||||
util.getpath("tests", "src", "mixed", "foo.f"),
|
||||
util.getpath("tests", "src", "mixed", "foo_fixed.f90"),
|
||||
util.getpath("tests", "src", "mixed", "foo_free.f90"),
|
||||
]
|
||||
|
||||
def test_all(self):
|
||||
assert self.module.bar11() == 11
|
||||
assert self.module.foo_fixed.bar12() == 12
|
||||
assert self.module.foo_free.bar13() == 13
|
||||
|
||||
@pytest.mark.xfail(IS_PYPY,
|
||||
reason="PyPy cannot modify tp_doc after PyType_Ready")
|
||||
def test_docstring(self):
|
||||
expected = textwrap.dedent("""\
|
||||
a = bar11()
|
||||
|
||||
Wrapper for ``bar11``.
|
||||
|
||||
Returns
|
||||
-------
|
||||
a : int
|
||||
""")
|
||||
assert self.module.bar11.__doc__ == expected
|
27
venv/Lib/site-packages/numpy/f2py/tests/test_module_doc.py
Normal file
27
venv/Lib/site-packages/numpy/f2py/tests/test_module_doc.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
import os
|
||||
import sys
|
||||
import pytest
|
||||
import textwrap
|
||||
|
||||
from . import util
|
||||
from numpy.testing import IS_PYPY
|
||||
|
||||
|
||||
class TestModuleDocString(util.F2PyTest):
|
||||
sources = [
|
||||
util.getpath("tests", "src", "module_data",
|
||||
"module_data_docstring.f90")
|
||||
]
|
||||
|
||||
@pytest.mark.skipif(sys.platform == "win32",
|
||||
reason="Fails with MinGW64 Gfortran (Issue #9673)")
|
||||
@pytest.mark.xfail(IS_PYPY,
|
||||
reason="PyPy cannot modify tp_doc after PyType_Ready")
|
||||
def test_module_docstring(self):
|
||||
assert self.module.mod.__doc__ == textwrap.dedent("""\
|
||||
i : 'i'-scalar
|
||||
x : 'i'-array(4)
|
||||
a : 'f'-array(2,3)
|
||||
b : 'f'-array(-1,-1), not allocated\x00
|
||||
foo()\n
|
||||
Wrapper for ``foo``.\n\n""")
|
112
venv/Lib/site-packages/numpy/f2py/tests/test_parameter.py
Normal file
112
venv/Lib/site-packages/numpy/f2py/tests/test_parameter.py
Normal file
|
@ -0,0 +1,112 @@
|
|||
import os
|
||||
import pytest
|
||||
|
||||
import numpy as np
|
||||
|
||||
from . import util
|
||||
|
||||
|
||||
class TestParameters(util.F2PyTest):
|
||||
# Check that intent(in out) translates as intent(inout)
|
||||
sources = [
|
||||
util.getpath("tests", "src", "parameter", "constant_real.f90"),
|
||||
util.getpath("tests", "src", "parameter", "constant_integer.f90"),
|
||||
util.getpath("tests", "src", "parameter", "constant_both.f90"),
|
||||
util.getpath("tests", "src", "parameter", "constant_compound.f90"),
|
||||
util.getpath("tests", "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]
|
||||
pytest.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 np.allclose(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]
|
||||
pytest.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 np.allclose(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]
|
||||
pytest.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 np.allclose(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 np.allclose(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]
|
||||
pytest.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 np.allclose(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]
|
||||
pytest.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 np.allclose(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]
|
||||
pytest.raises(ValueError, self.module.foo, x)
|
||||
|
||||
# check values with contiguous array
|
||||
x = np.arange(3, dtype=np.float64)
|
||||
self.module.foo(x)
|
||||
assert np.allclose(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]
|
||||
pytest.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 np.allclose(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]
|
||||
pytest.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 np.allclose(x, [0 + 1 * 3 * 3 + 2 * 3 * 3, 1 * 3, 2 * 3])
|
|
@ -0,0 +1,16 @@
|
|||
"""See https://github.com/numpy/numpy/pull/10676.
|
||||
|
||||
"""
|
||||
import sys
|
||||
import pytest
|
||||
|
||||
from . import util
|
||||
|
||||
|
||||
class TestQuotedCharacter(util.F2PyTest):
|
||||
sources = [util.getpath("tests", "src", "quoted_character", "foo.f")]
|
||||
|
||||
@pytest.mark.skipif(sys.platform == "win32",
|
||||
reason="Fails with MinGW64 Gfortran (Issue #9673)")
|
||||
def test_quoted_character(self):
|
||||
assert self.module.foo() == (b"'", b'"', b";", b"!", b"(", b")")
|
66
venv/Lib/site-packages/numpy/f2py/tests/test_regression.py
Normal file
66
venv/Lib/site-packages/numpy/f2py/tests/test_regression.py
Normal file
|
@ -0,0 +1,66 @@
|
|||
import os
|
||||
import pytest
|
||||
|
||||
import numpy as np
|
||||
|
||||
from . import util
|
||||
|
||||
|
||||
class TestIntentInOut(util.F2PyTest):
|
||||
# Check that intent(in out) translates as intent(inout)
|
||||
sources = [util.getpath("tests", "src", "regression", "inout.f90")]
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_inout(self):
|
||||
# non-contiguous should raise error
|
||||
x = np.arange(6, dtype=np.float32)[::2]
|
||||
pytest.raises(ValueError, self.module.foo, x)
|
||||
|
||||
# check values with contiguous array
|
||||
x = np.arange(3, dtype=np.float32)
|
||||
self.module.foo(x)
|
||||
assert np.allclose(x, [3, 1, 2])
|
||||
|
||||
|
||||
class TestNegativeBounds(util.F2PyTest):
|
||||
# Check that negative bounds work correctly
|
||||
sources = [util.getpath("tests", "src", "negative_bounds", "issue_20853.f90")]
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_negbound(self):
|
||||
xvec = np.arange(12)
|
||||
xlow = -6
|
||||
xhigh = 4
|
||||
# Calculate the upper bound,
|
||||
# Keeping the 1 index in mind
|
||||
def ubound(xl, xh):
|
||||
return xh - xl + 1
|
||||
rval = self.module.foo(is_=xlow, ie_=xhigh,
|
||||
arr=xvec[:ubound(xlow, xhigh)])
|
||||
expval = np.arange(11, dtype = np.float32)
|
||||
assert np.allclose(rval, expval)
|
||||
|
||||
|
||||
class TestNumpyVersionAttribute(util.F2PyTest):
|
||||
# Check that th attribute __f2py_numpy_version__ is present
|
||||
# in the compiled module and that has the value np.__version__.
|
||||
sources = [util.getpath("tests", "src", "regression", "inout.f90")]
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_numpy_version_attribute(self):
|
||||
|
||||
# Check that self.module has an attribute named "__f2py_numpy_version__"
|
||||
assert hasattr(self.module, "__f2py_numpy_version__")
|
||||
|
||||
# Check that the attribute __f2py_numpy_version__ is a string
|
||||
assert isinstance(self.module.__f2py_numpy_version__, str)
|
||||
|
||||
# Check that __f2py_numpy_version__ has the value numpy.__version__
|
||||
assert np.__version__ == self.module.__f2py_numpy_version__
|
||||
|
||||
|
||||
def test_include_path():
|
||||
incdir = np.f2py.get_include()
|
||||
fnames_in_dir = os.listdir(incdir)
|
||||
for fname in ("fortranobject.c", "fortranobject.h"):
|
||||
assert fname in fnames_in_dir
|
|
@ -0,0 +1,45 @@
|
|||
import pytest
|
||||
|
||||
from numpy import array
|
||||
from . import util
|
||||
import platform
|
||||
|
||||
IS_S390X = platform.machine() == "s390x"
|
||||
|
||||
|
||||
class TestReturnCharacter(util.F2PyTest):
|
||||
def check_function(self, t, tname):
|
||||
if tname in ["t0", "t1", "s0", "s1"]:
|
||||
assert t(23) == b"2"
|
||||
r = t("ab")
|
||||
assert r == b"a"
|
||||
r = t(array("ab"))
|
||||
assert r == b"a"
|
||||
r = t(array(77, "u1"))
|
||||
assert r == b"M"
|
||||
elif tname in ["ts", "ss"]:
|
||||
assert t(23) == b"23"
|
||||
assert t("123456789abcdef") == b"123456789a"
|
||||
elif tname in ["t5", "s5"]:
|
||||
assert t(23) == b"23"
|
||||
assert t("ab") == b"ab"
|
||||
assert t("123456789abcdef") == b"12345"
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class TestFReturnCharacter(TestReturnCharacter):
|
||||
sources = [
|
||||
util.getpath("tests", "src", "return_character", "foo77.f"),
|
||||
util.getpath("tests", "src", "return_character", "foo90.f90"),
|
||||
]
|
||||
|
||||
@pytest.mark.xfail(IS_S390X, reason="callback returns ' '")
|
||||
@pytest.mark.parametrize("name", "t0,t1,t5,s0,s1,s5,ss".split(","))
|
||||
def test_all_f77(self, name):
|
||||
self.check_function(getattr(self.module, name), name)
|
||||
|
||||
@pytest.mark.xfail(IS_S390X, reason="callback returns ' '")
|
||||
@pytest.mark.parametrize("name", "t0,t1,t5,ts,s0,s1,s5,ss".split(","))
|
||||
def test_all_f90(self, name):
|
||||
self.check_function(getattr(self.module.f90_return_char, name), name)
|
|
@ -0,0 +1,65 @@
|
|||
import pytest
|
||||
|
||||
from numpy import array
|
||||
from . import util
|
||||
|
||||
|
||||
class TestReturnComplex(util.F2PyTest):
|
||||
def check_function(self, t, tname):
|
||||
if tname in ["t0", "t8", "s0", "s8"]:
|
||||
err = 1e-5
|
||||
else:
|
||||
err = 0.0
|
||||
assert abs(t(234j) - 234.0j) <= err
|
||||
assert abs(t(234.6) - 234.6) <= err
|
||||
assert abs(t(234) - 234.0) <= err
|
||||
assert abs(t(234.6 + 3j) - (234.6 + 3j)) <= err
|
||||
# assert abs(t('234')-234.)<=err
|
||||
# assert abs(t('234.6')-234.6)<=err
|
||||
assert abs(t(-234) + 234.0) <= err
|
||||
assert abs(t([234]) - 234.0) <= err
|
||||
assert abs(t((234, )) - 234.0) <= err
|
||||
assert abs(t(array(234)) - 234.0) <= err
|
||||
assert abs(t(array(23 + 4j, "F")) - (23 + 4j)) <= err
|
||||
assert abs(t(array([234])) - 234.0) <= err
|
||||
assert abs(t(array([[234]])) - 234.0) <= err
|
||||
assert abs(t(array([234], "b")) + 22.0) <= err
|
||||
assert abs(t(array([234], "h")) - 234.0) <= err
|
||||
assert abs(t(array([234], "i")) - 234.0) <= err
|
||||
assert abs(t(array([234], "l")) - 234.0) <= err
|
||||
assert abs(t(array([234], "q")) - 234.0) <= err
|
||||
assert abs(t(array([234], "f")) - 234.0) <= err
|
||||
assert abs(t(array([234], "d")) - 234.0) <= err
|
||||
assert abs(t(array([234 + 3j], "F")) - (234 + 3j)) <= err
|
||||
assert abs(t(array([234], "D")) - 234.0) <= err
|
||||
|
||||
# pytest.raises(TypeError, t, array([234], 'a1'))
|
||||
pytest.raises(TypeError, t, "abc")
|
||||
|
||||
pytest.raises(IndexError, t, [])
|
||||
pytest.raises(IndexError, t, ())
|
||||
|
||||
pytest.raises(TypeError, t, t)
|
||||
pytest.raises(TypeError, t, {})
|
||||
|
||||
try:
|
||||
r = t(10**400)
|
||||
assert repr(r) in ["(inf+0j)", "(Infinity+0j)"]
|
||||
except OverflowError:
|
||||
pass
|
||||
|
||||
|
||||
class TestFReturnComplex(TestReturnComplex):
|
||||
sources = [
|
||||
util.getpath("tests", "src", "return_complex", "foo77.f"),
|
||||
util.getpath("tests", "src", "return_complex", "foo90.f90"),
|
||||
]
|
||||
|
||||
@pytest.mark.parametrize("name", "t0,t8,t16,td,s0,s8,s16,sd".split(","))
|
||||
def test_all_f77(self, name):
|
||||
self.check_function(getattr(self.module, name), name)
|
||||
|
||||
@pytest.mark.parametrize("name", "t0,t8,t16,td,s0,s8,s16,sd".split(","))
|
||||
def test_all_f90(self, name):
|
||||
self.check_function(getattr(self.module.f90_return_complex, name),
|
||||
name)
|
|
@ -0,0 +1,55 @@
|
|||
import pytest
|
||||
|
||||
from numpy import array
|
||||
from . import util
|
||||
|
||||
|
||||
class TestReturnInteger(util.F2PyTest):
|
||||
def check_function(self, t, tname):
|
||||
assert t(123) == 123
|
||||
assert t(123.6) == 123
|
||||
assert t("123") == 123
|
||||
assert t(-123) == -123
|
||||
assert t([123]) == 123
|
||||
assert t((123, )) == 123
|
||||
assert t(array(123)) == 123
|
||||
assert t(array([123])) == 123
|
||||
assert t(array([[123]])) == 123
|
||||
assert t(array([123], "b")) == 123
|
||||
assert t(array([123], "h")) == 123
|
||||
assert t(array([123], "i")) == 123
|
||||
assert t(array([123], "l")) == 123
|
||||
assert t(array([123], "B")) == 123
|
||||
assert t(array([123], "f")) == 123
|
||||
assert t(array([123], "d")) == 123
|
||||
|
||||
# pytest.raises(ValueError, t, array([123],'S3'))
|
||||
pytest.raises(ValueError, t, "abc")
|
||||
|
||||
pytest.raises(IndexError, t, [])
|
||||
pytest.raises(IndexError, t, ())
|
||||
|
||||
pytest.raises(Exception, t, t)
|
||||
pytest.raises(Exception, t, {})
|
||||
|
||||
if tname in ["t8", "s8"]:
|
||||
pytest.raises(OverflowError, t, 100000000000000000000000)
|
||||
pytest.raises(OverflowError, t, 10000000011111111111111.23)
|
||||
|
||||
|
||||
class TestFReturnInteger(TestReturnInteger):
|
||||
sources = [
|
||||
util.getpath("tests", "src", "return_integer", "foo77.f"),
|
||||
util.getpath("tests", "src", "return_integer", "foo90.f90"),
|
||||
]
|
||||
|
||||
@pytest.mark.parametrize("name",
|
||||
"t0,t1,t2,t4,t8,s0,s1,s2,s4,s8".split(","))
|
||||
def test_all_f77(self, name):
|
||||
self.check_function(getattr(self.module, name), name)
|
||||
|
||||
@pytest.mark.parametrize("name",
|
||||
"t0,t1,t2,t4,t8,s0,s1,s2,s4,s8".split(","))
|
||||
def test_all_f90(self, name):
|
||||
self.check_function(getattr(self.module.f90_return_integer, name),
|
||||
name)
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue