aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/numpy/f2py/tests
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/numpy/f2py/tests
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are hereHEADmaster
Diffstat (limited to '.venv/lib/python3.12/site-packages/numpy/f2py/tests')
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/__init__.py0
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/abstract_interface/foo.f9034
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/abstract_interface/gh18403_mod.f906
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c230
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/.f2py_f2cmap1
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/foo_free.f9034
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/foo_mod.f9041
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/foo_use.f9019
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/precision.f904
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/block_docstring/foo.f6
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/foo.f62
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/gh17797.f907
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/gh18335.f9017
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/gh25211.f10
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/gh25211.pyf18
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/cli/gh_22819.pyf6
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/cli/hi77.f3
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/cli/hiworld.f903
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/common/block.f11
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/common/gh19161.f9010
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/accesstype.f9013
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/data_common.f8
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/data_multiplier.f5
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/data_stmts.f9020
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/data_with_comments.f8
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/foo_deps.f906
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh15035.f16
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh17859.f12
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh22648.pyf7
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh23533.f5
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh23598.f904
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh23598Warn.f9011
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh23879.f9020
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh2848.f9013
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/operators.f9049
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/privatemod.f9011
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/publicmod.f9010
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/pubprivmod.f9010
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/unicode_comment.f904
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/f2cmap/.f2py_f2cmap1
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/f2cmap/isoFortranEnvMap.f909
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/isocintrin/isoCtests.f9034
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/kind/foo.f9020
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/mixed/foo.f5
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/mixed/foo_fixed.f908
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/mixed/foo_free.f908
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/module_data/mod.modbin0 -> 412 bytes
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/module_data/module_data_docstring.f9012
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/negative_bounds/issue_20853.f907
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_both.f9057
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_compound.f9015
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_integer.f9022
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_non_compound.f9023
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_real.f9023
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/quoted_character/foo.f14
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/regression/gh25337/data.f908
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/regression/gh25337/use_data.f906
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/regression/inout.f909
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_character/foo77.f45
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_character/foo90.f9048
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_complex/foo77.f45
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_complex/foo90.f9048
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_integer/foo77.f56
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_integer/foo90.f9059
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_logical/foo77.f56
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_logical/foo90.f9059
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_real/foo77.f45
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_real/foo90.f9048
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/size/foo.f9044
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/char.f9029
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/fixed_string.f9034
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh24008.f8
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh24662.f907
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh25286.f9014
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh25286.pyf12
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh25286_bc.pyf12
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/scalar_string.f909
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/string.f12
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/value_attrspec/gh21665.f909
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_abstract_interface.py25
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_array_from_pyobj.py686
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_assumed_shape.py49
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_block_docstring.py17
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_callback.py243
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_character.py636
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_common.py27
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_compile_function.py117
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_crackfortran.py350
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_data.py70
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_docs.py55
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_f2cmap.py15
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_f2py2e.py896
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_isoc.py52
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_kind.py47
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_mixed.py33
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_module_doc.py27
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_parameter.py112
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_pyf_src.py44
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_quoted_character.py16
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_regression.py77
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_character.py45
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_complex.py65
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_integer.py53
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_logical.py64
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_real.py107
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_semicolon_split.py74
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_size.py45
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_string.py100
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_symbolic.py494
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_value_attrspec.py14
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/f2py/tests/util.py440
111 files changed, 6829 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/__init__.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/__init__.py
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/abstract_interface/foo.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/abstract_interface/foo.f90
new file mode 100644
index 00000000..76d16aae
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/abstract_interface/foo.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/abstract_interface/gh18403_mod.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/abstract_interface/gh18403_mod.f90
new file mode 100644
index 00000000..36791e46
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/abstract_interface/gh18403_mod.f90
@@ -0,0 +1,6 @@
+module test
+ abstract interface
+ subroutine foo()
+ end subroutine
+ end interface
+end module test
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c
new file mode 100644
index 00000000..9a8b4a75
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c
@@ -0,0 +1,230 @@
+/*
+ * 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;
+ int elsize = 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,"iiOiO|:wrap.call",\
+ &type_num,&elsize,&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 = ndarray_from_pyobj(type_num,elsize,dims,rank,intent|F2PY_INTENT_OUT,arr_capi,"wrap.call failed");
+ 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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/.f2py_f2cmap b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/.f2py_f2cmap
new file mode 100644
index 00000000..2665f89b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/.f2py_f2cmap
@@ -0,0 +1 @@
+dict(real=dict(rk="double"))
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/foo_free.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/foo_free.f90
new file mode 100644
index 00000000..b301710f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/foo_free.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/foo_mod.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/foo_mod.f90
new file mode 100644
index 00000000..cbe6317e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/foo_mod.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/foo_use.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/foo_use.f90
new file mode 100644
index 00000000..337465ac
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/foo_use.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/precision.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/precision.f90
new file mode 100644
index 00000000..ed6c70cb
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/assumed_shape/precision.f90
@@ -0,0 +1,4 @@
+module precision
+ integer, parameter :: rk = selected_real_kind(8)
+ integer, parameter :: ik = selected_real_kind(4)
+end module
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/block_docstring/foo.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/block_docstring/foo.f
new file mode 100644
index 00000000..c8315f12
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/block_docstring/foo.f
@@ -0,0 +1,6 @@
+ SUBROUTINE FOO()
+ INTEGER BAR(2, 3)
+
+ COMMON /BLOCK/ BAR
+ RETURN
+ END
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/foo.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/foo.f
new file mode 100644
index 00000000..ba397bb3
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/foo.f
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/gh17797.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/gh17797.f90
new file mode 100644
index 00000000..49853afd
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/gh17797.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/gh18335.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/gh18335.f90
new file mode 100644
index 00000000..92b6d754
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/gh18335.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/gh25211.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/gh25211.f
new file mode 100644
index 00000000..ba727a10
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/gh25211.f
@@ -0,0 +1,10 @@
+ SUBROUTINE FOO(FUN,R)
+ EXTERNAL FUN
+ INTEGER I
+ REAL*8 R, FUN
+Cf2py intent(out) r
+ R = 0D0
+ DO I=-5,5
+ R = R + FUN(I)
+ ENDDO
+ END
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/gh25211.pyf b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/gh25211.pyf
new file mode 100644
index 00000000..f1201115
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/callback/gh25211.pyf
@@ -0,0 +1,18 @@
+python module __user__routines
+ interface
+ function fun(i) result (r)
+ integer :: i
+ real*8 :: r
+ end function fun
+ end interface
+end python module __user__routines
+
+python module callback2
+ interface
+ subroutine foo(f,r)
+ use __user__routines, f=>fun
+ external f
+ real*8 intent(out) :: r
+ end subroutine foo
+ end interface
+end python module callback2
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/cli/gh_22819.pyf b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/cli/gh_22819.pyf
new file mode 100644
index 00000000..8eb5bb10
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/cli/gh_22819.pyf
@@ -0,0 +1,6 @@
+python module test_22819
+ interface
+ subroutine hello()
+ end subroutine hello
+ end interface
+end python module test_22819
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/cli/hi77.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/cli/hi77.f
new file mode 100644
index 00000000..8b916ebe
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/cli/hi77.f
@@ -0,0 +1,3 @@
+ SUBROUTINE HI
+ PRINT*, "HELLO WORLD"
+ END SUBROUTINE
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/cli/hiworld.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/cli/hiworld.f90
new file mode 100644
index 00000000..981f8775
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/cli/hiworld.f90
@@ -0,0 +1,3 @@
+function hi()
+ print*, "Hello World"
+end function
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/common/block.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/common/block.f
new file mode 100644
index 00000000..7ea7968f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/common/block.f
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/common/gh19161.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/common/gh19161.f90
new file mode 100644
index 00000000..a2f40735
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/common/gh19161.f90
@@ -0,0 +1,10 @@
+module typedefmod
+ use iso_fortran_env, only: real32
+end module typedefmod
+
+module data
+ use typedefmod, only: real32
+ implicit none
+ real(kind=real32) :: x
+ common/test/x
+end module data
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/accesstype.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/accesstype.f90
new file mode 100644
index 00000000..e2cbd445
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/accesstype.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/data_common.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/data_common.f
new file mode 100644
index 00000000..5ffd865c
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/data_common.f
@@ -0,0 +1,8 @@
+ BLOCK DATA PARAM_INI
+ COMMON /MYCOM/ MYDATA
+ DATA MYDATA /0/
+ END
+ SUBROUTINE SUB1
+ COMMON /MYCOM/ MYDATA
+ MYDATA = MYDATA + 1
+ END
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/data_multiplier.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/data_multiplier.f
new file mode 100644
index 00000000..19ff8a83
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/data_multiplier.f
@@ -0,0 +1,5 @@
+ BLOCK DATA MYBLK
+ IMPLICIT DOUBLE PRECISION (A-H,O-Z)
+ COMMON /MYCOM/ IVAR1, IVAR2, IVAR3, IVAR4, EVAR5
+ DATA IVAR1, IVAR2, IVAR3, IVAR4, EVAR5 /2*3,2*2,0.0D0/
+ END
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/data_stmts.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/data_stmts.f90
new file mode 100644
index 00000000..576c5e48
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/data_stmts.f90
@@ -0,0 +1,20 @@
+! gh-23276
+module cmplxdat
+ implicit none
+ integer :: i, j
+ real :: x, y
+ real, dimension(2) :: z
+ real(kind=8) :: pi
+ complex(kind=8), target :: medium_ref_index
+ complex(kind=8), target :: ref_index_one, ref_index_two
+ complex(kind=8), dimension(2) :: my_array
+ real(kind=8), dimension(3) :: my_real_array = (/1.0d0, 2.0d0, 3.0d0/)
+
+ data i, j / 2, 3 /
+ data x, y / 1.5, 2.0 /
+ data z / 3.5, 7.0 /
+ data medium_ref_index / (1.d0, 0.d0) /
+ data ref_index_one, ref_index_two / (13.0d0, 21.0d0), (-30.0d0, 43.0d0) /
+ data my_array / (1.0d0, 2.0d0), (-3.0d0, 4.0d0) /
+ data pi / 3.1415926535897932384626433832795028841971693993751058209749445923078164062d0 /
+end module cmplxdat
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/data_with_comments.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/data_with_comments.f
new file mode 100644
index 00000000..4128f004
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/data_with_comments.f
@@ -0,0 +1,8 @@
+ BLOCK DATA PARAM_INI
+ COMMON /MYCOM/ MYTAB
+ INTEGER MYTAB(3)
+ DATA MYTAB/
+ * 0, ! 1 and more commenty stuff
+ * 4, ! 2
+ * 0 /
+ END
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/foo_deps.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/foo_deps.f90
new file mode 100644
index 00000000..e327b25c
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/foo_deps.f90
@@ -0,0 +1,6 @@
+module foo
+ type bar
+ character(len = 4) :: text
+ end type bar
+ type(bar), parameter :: abar = bar('abar')
+end module foo
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh15035.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh15035.f
new file mode 100644
index 00000000..1bb2e674
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh15035.f
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh17859.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh17859.f
new file mode 100644
index 00000000..99595384
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh17859.f
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh22648.pyf b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh22648.pyf
new file mode 100644
index 00000000..b3454f18
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh22648.pyf
@@ -0,0 +1,7 @@
+python module iri16py ! in
+ interface ! in :iri16py
+ block data ! in :iri16py:iridreg_modified.for
+ COMMON /fircom/ eden,tabhe,tabla,tabmo,tabza,tabfl
+ end block data
+ end interface
+end python module iri16py
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh23533.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh23533.f
new file mode 100644
index 00000000..db522afa
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh23533.f
@@ -0,0 +1,5 @@
+ SUBROUTINE EXAMPLE( )
+ IF( .TRUE. ) THEN
+ CALL DO_SOMETHING()
+ END IF ! ** .TRUE. **
+ END
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh23598.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh23598.f90
new file mode 100644
index 00000000..e0dffb5e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh23598.f90
@@ -0,0 +1,4 @@
+integer function intproduct(a, b) result(res)
+ integer, intent(in) :: a, b
+ res = a*b
+end function
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh23598Warn.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh23598Warn.f90
new file mode 100644
index 00000000..3b44efc5
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh23598Warn.f90
@@ -0,0 +1,11 @@
+module test_bug
+ implicit none
+ private
+ public :: intproduct
+
+contains
+ integer function intproduct(a, b) result(res)
+ integer, intent(in) :: a, b
+ res = a*b
+ end function
+end module
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh23879.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh23879.f90
new file mode 100644
index 00000000..fac262d5
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh23879.f90
@@ -0,0 +1,20 @@
+module gh23879
+ implicit none
+ private
+ public :: foo
+
+ contains
+
+ subroutine foo(a, b)
+ integer, intent(in) :: a
+ integer, intent(out) :: b
+ b = a
+ call bar(b)
+ end subroutine
+
+ subroutine bar(x)
+ integer, intent(inout) :: x
+ x = 2*x
+ end subroutine
+
+ end module gh23879
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh2848.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh2848.f90
new file mode 100644
index 00000000..31ea9327
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/gh2848.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/operators.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/operators.f90
new file mode 100644
index 00000000..1d060a3d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/operators.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/privatemod.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/privatemod.f90
new file mode 100644
index 00000000..2674c214
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/privatemod.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/publicmod.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/publicmod.f90
new file mode 100644
index 00000000..1db76e3f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/publicmod.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/pubprivmod.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/pubprivmod.f90
new file mode 100644
index 00000000..46bef7cb
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/pubprivmod.f90
@@ -0,0 +1,10 @@
+module foo
+ public
+ integer, private :: a
+ integer :: b
+contains
+ subroutine setA(v)
+ integer, intent(in) :: v
+ a = v
+ end subroutine setA
+end module foo
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/unicode_comment.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/unicode_comment.f90
new file mode 100644
index 00000000..13515ce9
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/crackfortran/unicode_comment.f90
@@ -0,0 +1,4 @@
+subroutine foo(x)
+ real(8), intent(in) :: x
+ ! Écrit à l'écran la valeur de x
+end subroutine
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/f2cmap/.f2py_f2cmap b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/f2cmap/.f2py_f2cmap
new file mode 100644
index 00000000..a4425f88
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/f2cmap/.f2py_f2cmap
@@ -0,0 +1 @@
+dict(real=dict(real32='float', real64='double'), integer=dict(int64='long_long'))
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/f2cmap/isoFortranEnvMap.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/f2cmap/isoFortranEnvMap.f90
new file mode 100644
index 00000000..1e1dc1d4
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/f2cmap/isoFortranEnvMap.f90
@@ -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
+!f2py intent(hide) :: n
+ res = sum(x)
+ end
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/isocintrin/isoCtests.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/isocintrin/isoCtests.f90
new file mode 100644
index 00000000..765f7c1c
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/isocintrin/isoCtests.f90
@@ -0,0 +1,34 @@
+ module coddity
+ use iso_c_binding, only: c_double, c_int, c_int64_t
+ implicit none
+ contains
+ subroutine c_add(a, b, c) bind(c, name="c_add")
+ real(c_double), intent(in) :: a, b
+ real(c_double), intent(out) :: c
+ c = a + b
+ end subroutine c_add
+ ! gh-9693
+ function wat(x, y) result(z) bind(c)
+ integer(c_int), intent(in) :: x, y
+ integer(c_int) :: z
+
+ z = x + 7
+ end function wat
+ ! gh-25207
+ subroutine c_add_int64(a, b, c) bind(c)
+ integer(c_int64_t), intent(in) :: a, b
+ integer(c_int64_t), intent(out) :: c
+ c = a + b
+ end subroutine c_add_int64
+ ! gh-25207
+ subroutine add_arr(A, B, C)
+ integer(c_int64_t), intent(in) :: A(3)
+ integer(c_int64_t), intent(in) :: B(3)
+ integer(c_int64_t), intent(out) :: C(3)
+ integer :: j
+
+ do j = 1, 3
+ C(j) = A(j)+B(j)
+ end do
+ end subroutine
+ end module coddity
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/kind/foo.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/kind/foo.f90
new file mode 100644
index 00000000..d3d15cfb
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/kind/foo.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/mixed/foo.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/mixed/foo.f
new file mode 100644
index 00000000..c3474257
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/mixed/foo.f
@@ -0,0 +1,5 @@
+ subroutine bar11(a)
+cf2py intent(out) a
+ integer a
+ a = 11
+ end
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/mixed/foo_fixed.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/mixed/foo_fixed.f90
new file mode 100644
index 00000000..7543a6ac
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/mixed/foo_fixed.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/mixed/foo_free.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/mixed/foo_free.f90
new file mode 100644
index 00000000..c1b641f1
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/mixed/foo_free.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/module_data/mod.mod b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/module_data/mod.mod
new file mode 100644
index 00000000..8670a97e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/module_data/mod.mod
Binary files differ
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/module_data/module_data_docstring.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/module_data/module_data_docstring.f90
new file mode 100644
index 00000000..4505e0cb
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/module_data/module_data_docstring.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/negative_bounds/issue_20853.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/negative_bounds/issue_20853.f90
new file mode 100644
index 00000000..bf1fa928
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/negative_bounds/issue_20853.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_both.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_both.f90
new file mode 100644
index 00000000..ac90cedc
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_both.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_compound.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_compound.f90
new file mode 100644
index 00000000..e51f5e9b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_compound.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_integer.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_integer.f90
new file mode 100644
index 00000000..aaa83d2e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_integer.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_non_compound.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_non_compound.f90
new file mode 100644
index 00000000..62c9a5b9
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_non_compound.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_real.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_real.f90
new file mode 100644
index 00000000..02ac9dd9
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/parameter/constant_real.f90
@@ -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
+
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/quoted_character/foo.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/quoted_character/foo.f
new file mode 100644
index 00000000..9dc1cfa4
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/quoted_character/foo.f
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/regression/gh25337/data.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/regression/gh25337/data.f90
new file mode 100644
index 00000000..483d13ce
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/regression/gh25337/data.f90
@@ -0,0 +1,8 @@
+module data
+ real(8) :: shift
+contains
+ subroutine set_shift(in_shift)
+ real(8), intent(in) :: in_shift
+ shift = in_shift
+ end subroutine set_shift
+end module data
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/regression/gh25337/use_data.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/regression/gh25337/use_data.f90
new file mode 100644
index 00000000..b3fae8b8
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/regression/gh25337/use_data.f90
@@ -0,0 +1,6 @@
+subroutine shift_a(dim_a, a)
+ use data, only: shift
+ integer, intent(in) :: dim_a
+ real(8), intent(inout), dimension(dim_a) :: a
+ a = a + shift
+end subroutine shift_a
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/regression/inout.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/regression/inout.f90
new file mode 100644
index 00000000..80cdad90
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/regression/inout.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_character/foo77.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_character/foo77.f
new file mode 100644
index 00000000..facae101
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_character/foo77.f
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_character/foo90.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_character/foo90.f90
new file mode 100644
index 00000000..36182bcf
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_character/foo90.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_complex/foo77.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_complex/foo77.f
new file mode 100644
index 00000000..37a1ec84
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_complex/foo77.f
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_complex/foo90.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_complex/foo90.f90
new file mode 100644
index 00000000..adc27b47
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_complex/foo90.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_integer/foo77.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_integer/foo77.f
new file mode 100644
index 00000000..1ab895b9
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_integer/foo77.f
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_integer/foo90.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_integer/foo90.f90
new file mode 100644
index 00000000..ba9249aa
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_integer/foo90.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_logical/foo77.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_logical/foo77.f
new file mode 100644
index 00000000..ef530145
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_logical/foo77.f
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_logical/foo90.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_logical/foo90.f90
new file mode 100644
index 00000000..a4526468
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_logical/foo90.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_real/foo77.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_real/foo77.f
new file mode 100644
index 00000000..bf43dbf1
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_real/foo77.f
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_real/foo90.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_real/foo90.f90
new file mode 100644
index 00000000..df971998
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/return_real/foo90.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/size/foo.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/size/foo.f90
new file mode 100644
index 00000000..5b66f8c4
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/size/foo.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/char.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/char.f90
new file mode 100644
index 00000000..bb7985ce
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/char.f90
@@ -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
+
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/fixed_string.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/fixed_string.f90
new file mode 100644
index 00000000..7fd15854
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/fixed_string.f90
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh24008.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh24008.f
new file mode 100644
index 00000000..ab64cf77
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh24008.f
@@ -0,0 +1,8 @@
+ SUBROUTINE GREET(NAME, GREETING)
+ CHARACTER NAME*(*), GREETING*(*)
+ CHARACTER*(50) MESSAGE
+
+ MESSAGE = 'Hello, ' // NAME // ', ' // GREETING
+c$$$ PRINT *, MESSAGE
+
+ END SUBROUTINE GREET
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh24662.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh24662.f90
new file mode 100644
index 00000000..ca53413c
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh24662.f90
@@ -0,0 +1,7 @@
+subroutine string_inout_optional(output)
+ implicit none
+ character*(32), optional, intent(inout) :: output
+ if (present(output)) then
+ output="output string"
+ endif
+end subroutine
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh25286.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh25286.f90
new file mode 100644
index 00000000..db1c7100
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh25286.f90
@@ -0,0 +1,14 @@
+subroutine charint(trans, info)
+ character, intent(in) :: trans
+ integer, intent(out) :: info
+ if (trans == 'N') then
+ info = 1
+ else if (trans == 'T') then
+ info = 2
+ else if (trans == 'C') then
+ info = 3
+ else
+ info = -1
+ end if
+
+end subroutine charint
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh25286.pyf b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh25286.pyf
new file mode 100644
index 00000000..7b960907
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh25286.pyf
@@ -0,0 +1,12 @@
+python module _char_handling_test
+ interface
+ subroutine charint(trans, info)
+ callstatement (*f2py_func)(&trans, &info)
+ callprotoargument char*, int*
+
+ character, intent(in), check(trans=='N'||trans=='T'||trans=='C') :: trans = 'N'
+ integer intent(out) :: info
+
+ end subroutine charint
+ end interface
+end python module _char_handling_test
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh25286_bc.pyf b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh25286_bc.pyf
new file mode 100644
index 00000000..e7b10fa9
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/gh25286_bc.pyf
@@ -0,0 +1,12 @@
+python module _char_handling_test
+ interface
+ subroutine charint(trans, info)
+ callstatement (*f2py_func)(&trans, &info)
+ callprotoargument char*, int*
+
+ character, intent(in), check(*trans=='N'||*trans=='T'||*trans=='C') :: trans = 'N'
+ integer intent(out) :: info
+
+ end subroutine charint
+ end interface
+end python module _char_handling_test
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/scalar_string.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/scalar_string.f90
new file mode 100644
index 00000000..f8f07617
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/scalar_string.f90
@@ -0,0 +1,9 @@
+MODULE string_test
+
+ character(len=8) :: string
+ character string77 * 8
+
+ character(len=12), dimension(5,7) :: strarr
+ character strarr77(5,7) * 12
+
+END MODULE string_test
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/string.f b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/string.f
new file mode 100644
index 00000000..5210ca4d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/string/string.f
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/value_attrspec/gh21665.f90 b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/value_attrspec/gh21665.f90
new file mode 100644
index 00000000..7d9dc0fd
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/src/value_attrspec/gh21665.f90
@@ -0,0 +1,9 @@
+module fortfuncs
+ implicit none
+contains
+ subroutine square(x,y)
+ integer, intent(in), value :: x
+ integer, intent(out) :: y
+ y = x*x
+ end subroutine square
+end module fortfuncs
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_abstract_interface.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_abstract_interface.py
new file mode 100644
index 00000000..42902913
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_abstract_interface.py
@@ -0,0 +1,25 @@
+from pathlib import Path
+import pytest
+import textwrap
+from . import util
+from numpy.f2py import crackfortran
+from numpy.testing import IS_WASM
+
+
+@pytest.mark.skipif(IS_WASM, reason="Cannot start subprocess")
+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"
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_array_from_pyobj.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_array_from_pyobj.py
new file mode 100644
index 00000000..2b8c8def
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_array_from_pyobj.py
@@ -0,0 +1,686 @@
+import os
+import sys
+import copy
+import platform
+import pytest
+
+import numpy as np
+
+from numpy.testing import assert_, assert_equal
+from numpy.core.multiarray import typeinfo as _typeinfo
+from . import util
+
+wrap = None
+
+# Extend core typeinfo with CHARACTER to test dtype('c')
+_ti = _typeinfo['STRING']
+typeinfo = dict(
+ CHARACTER=type(_ti)(('c', _ti.num, 8, _ti.alignment, _ti.type)),
+ **_typeinfo)
+
+
+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",
+ "UPDATEIFCOPY",
+ "BEHAVED",
+ "BEHAVED_RO",
+ "CARRAY",
+ "FARRAY",
+ ]:
+ if abs(flags) & getattr(wrap, flagname, 0):
+ info.append(flagname)
+ return info
+
+
+class Intent:
+ def __init__(self, intent_list=[]):
+ self.intent_list = intent_list[:]
+ flags = 0
+ for i in intent_list:
+ if i == "optional":
+ flags |= wrap.F2PY_OPTIONAL
+ else:
+ flags |= getattr(wrap, "F2PY_INTENT_" + i.upper())
+ self.flags = flags
+
+ def __getattr__(self, name):
+ name = name.lower()
+ if name == "in_":
+ name = "in"
+ return self.__class__(self.intent_list + [name])
+
+ def __str__(self):
+ return "intent(%s)" % (",".join(self.intent_list))
+
+ def __repr__(self):
+ return "Intent(%r)" % (self.intent_list)
+
+ def is_intent(self, *names):
+ for name in names:
+ if name not in self.intent_list:
+ return False
+ return True
+
+ def is_intent_exact(self, *names):
+ return len(self.intent_list) == len(names) and self.is_intent(*names)
+
+
+intent = Intent()
+
+_type_names = [
+ "BOOL",
+ "BYTE",
+ "UBYTE",
+ "SHORT",
+ "USHORT",
+ "INT",
+ "UINT",
+ "LONG",
+ "ULONG",
+ "LONGLONG",
+ "ULONGLONG",
+ "FLOAT",
+ "DOUBLE",
+ "CFLOAT",
+ "STRING1",
+ "STRING5",
+ "CHARACTER",
+]
+
+_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"]
+
+_cast_dict['STRING1'] = ['STRING1']
+_cast_dict['STRING5'] = ['STRING5']
+_cast_dict['CHARACTER'] = ['CHARACTER']
+
+# 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()
+
+ if self.NAME == 'CHARACTER':
+ info = typeinfo[self.NAME]
+ self.type_num = getattr(wrap, 'NPY_STRING')
+ self.elsize = 1
+ self.dtype = np.dtype('c')
+ elif self.NAME.startswith('STRING'):
+ info = typeinfo[self.NAME[:6]]
+ self.type_num = getattr(wrap, 'NPY_STRING')
+ self.elsize = int(self.NAME[6:] or 0)
+ self.dtype = np.dtype(f'S{self.elsize}')
+ else:
+ info = typeinfo[self.NAME]
+ self.type_num = getattr(wrap, 'NPY_' + self.NAME)
+ self.elsize = info.bits // 8
+ self.dtype = np.dtype(info.type)
+
+ assert self.type_num == info.num
+ self.type = info.type
+ self.dtypechar = info.char
+
+ def __repr__(self):
+ return (f"Type({self.NAME})|type_num={self.type_num},"
+ f" dtype={self.dtype},"
+ f" type={self.type}, elsize={self.elsize},"
+ f" dtypechar={self.dtypechar}")
+
+ 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 __repr__(self):
+ return (f'Array({self.type}, {self.dims}, {self.intent},'
+ f' {self.obj})|arr={self.arr}')
+
+ 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,
+ typ.elsize,
+ 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:], repr((
+ self.arr_attr[5], self.pyarr_attr[5]
+ )) # descr
+ assert self.arr_attr[6] == self.pyarr_attr[6], repr((
+ self.arr_attr[6],
+ self.pyarr_attr[6],
+ flags2names(0 * self.arr_attr[6] - self.pyarr_attr[6]),
+ flags2names(self.arr_attr[6]),
+ intent,
+ )) # flags
+
+ if intent.is_intent("cache"):
+ assert self.arr_attr[5][3] >= self.type.elsize
+ 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:
+
+ @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)
+
+ @property
+ def num2seq(self):
+ if self.type.NAME.startswith('STRING'):
+ elsize = self.type.elsize
+ return ['1' * elsize, '2' * elsize]
+ return [1, 2]
+
+ @property
+ def num23seq(self):
+ if self.type.NAME.startswith('STRING'):
+ elsize = self.type.elsize
+ return [['1' * elsize, '2' * elsize, '3' * elsize],
+ ['4' * elsize, '5' * elsize, '6' * elsize]]
+ return [[1, 2, 3], [4, 5, 6]]
+
+ 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.NAME == 'STRING':
+ # string elsize is 0, so skipping the test
+ continue
+ 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!
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_assumed_shape.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_assumed_shape.py
new file mode 100644
index 00000000..d4664cf8
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_assumed_shape.py
@@ -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_method(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_method()
+
+ def teardown_method(self):
+ os.unlink(self.f2cmap_file.name)
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_block_docstring.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_block_docstring.py
new file mode 100644
index 00000000..e0eacc03
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_block_docstring.py
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_callback.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_callback.py
new file mode 100644
index 00000000..5b6c294d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_callback.py
@@ -0,0 +1,243 @@
+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
+ cu1 = np.zeros((1, ), "S8")
+ cu2 = np.zeros((1, 8), "c")
+ cu3 = np.array([""], "S8")
+
+ def callback(cu, lencu):
+ if cu.shape != (lencu,):
+ return 1
+ if cu.dtype != "S8":
+ return 2
+ if not np.all(cu == b""):
+ return 3
+ return 0
+
+ f = getattr(self.module, "string_callback_array")
+ for cu in [cu1, cu2, cu3]:
+ res = f(callback, cu, cu.size)
+ 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
+
+ r = self.module.gh18335(foo)
+ assert r == 123 + 1
+
+
+class TestGH25211(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "callback", "gh25211.f"),
+ util.getpath("tests", "src", "callback", "gh25211.pyf")]
+ module_name = "callback2"
+
+ def test_gh18335(self):
+ def bar(x):
+ return x*x
+
+ res = self.module.foo(bar)
+ assert res == 110
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_character.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_character.py
new file mode 100644
index 00000000..e55b1b6b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_character.py
@@ -0,0 +1,636 @@
+import pytest
+import textwrap
+from numpy.testing import assert_array_equal, assert_equal, assert_raises
+import numpy as np
+from numpy.f2py.tests import util
+
+
+class TestCharacterString(util.F2PyTest):
+ # options = ['--debug-capi', '--build-dir', '/tmp/test-build-f2py']
+ suffix = '.f90'
+ fprefix = 'test_character_string'
+ length_list = ['1', '3', 'star']
+
+ code = ''
+ for length in length_list:
+ fsuffix = length
+ clength = dict(star='(*)').get(length, length)
+
+ code += textwrap.dedent(f"""
+
+ subroutine {fprefix}_input_{fsuffix}(c, o, n)
+ character*{clength}, intent(in) :: c
+ integer n
+ !f2py integer, depend(c), intent(hide) :: n = slen(c)
+ integer*1, dimension(n) :: o
+ !f2py intent(out) o
+ o = transfer(c, o)
+ end subroutine {fprefix}_input_{fsuffix}
+
+ subroutine {fprefix}_output_{fsuffix}(c, o, n)
+ character*{clength}, intent(out) :: c
+ integer n
+ integer*1, dimension(n), intent(in) :: o
+ !f2py integer, depend(o), intent(hide) :: n = len(o)
+ c = transfer(o, c)
+ end subroutine {fprefix}_output_{fsuffix}
+
+ subroutine {fprefix}_array_input_{fsuffix}(c, o, m, n)
+ integer m, i, n
+ character*{clength}, intent(in), dimension(m) :: c
+ !f2py integer, depend(c), intent(hide) :: m = len(c)
+ !f2py integer, depend(c), intent(hide) :: n = f2py_itemsize(c)
+ integer*1, dimension(m, n), intent(out) :: o
+ do i=1,m
+ o(i, :) = transfer(c(i), o(i, :))
+ end do
+ end subroutine {fprefix}_array_input_{fsuffix}
+
+ subroutine {fprefix}_array_output_{fsuffix}(c, o, m, n)
+ character*{clength}, intent(out), dimension(m) :: c
+ integer n
+ integer*1, dimension(m, n), intent(in) :: o
+ !f2py character(f2py_len=n) :: c
+ !f2py integer, depend(o), intent(hide) :: m = len(o)
+ !f2py integer, depend(o), intent(hide) :: n = shape(o, 1)
+ do i=1,m
+ c(i) = transfer(o(i, :), c(i))
+ end do
+ end subroutine {fprefix}_array_output_{fsuffix}
+
+ subroutine {fprefix}_2d_array_input_{fsuffix}(c, o, m1, m2, n)
+ integer m1, m2, i, j, n
+ character*{clength}, intent(in), dimension(m1, m2) :: c
+ !f2py integer, depend(c), intent(hide) :: m1 = len(c)
+ !f2py integer, depend(c), intent(hide) :: m2 = shape(c, 1)
+ !f2py integer, depend(c), intent(hide) :: n = f2py_itemsize(c)
+ integer*1, dimension(m1, m2, n), intent(out) :: o
+ do i=1,m1
+ do j=1,m2
+ o(i, j, :) = transfer(c(i, j), o(i, j, :))
+ end do
+ end do
+ end subroutine {fprefix}_2d_array_input_{fsuffix}
+ """)
+
+ @pytest.mark.parametrize("length", length_list)
+ def test_input(self, length):
+ fsuffix = {'(*)': 'star'}.get(length, length)
+ f = getattr(self.module, self.fprefix + '_input_' + fsuffix)
+
+ a = {'1': 'a', '3': 'abc', 'star': 'abcde' * 3}[length]
+
+ assert_array_equal(f(a), np.array(list(map(ord, a)), dtype='u1'))
+
+ @pytest.mark.parametrize("length", length_list[:-1])
+ def test_output(self, length):
+ fsuffix = length
+ f = getattr(self.module, self.fprefix + '_output_' + fsuffix)
+
+ a = {'1': 'a', '3': 'abc'}[length]
+
+ assert_array_equal(f(np.array(list(map(ord, a)), dtype='u1')),
+ a.encode())
+
+ @pytest.mark.parametrize("length", length_list)
+ def test_array_input(self, length):
+ fsuffix = length
+ f = getattr(self.module, self.fprefix + '_array_input_' + fsuffix)
+
+ a = np.array([{'1': 'a', '3': 'abc', 'star': 'abcde' * 3}[length],
+ {'1': 'A', '3': 'ABC', 'star': 'ABCDE' * 3}[length],
+ ], dtype='S')
+
+ expected = np.array([[c for c in s] for s in a], dtype='u1')
+ assert_array_equal(f(a), expected)
+
+ @pytest.mark.parametrize("length", length_list)
+ def test_array_output(self, length):
+ fsuffix = length
+ f = getattr(self.module, self.fprefix + '_array_output_' + fsuffix)
+
+ expected = np.array(
+ [{'1': 'a', '3': 'abc', 'star': 'abcde' * 3}[length],
+ {'1': 'A', '3': 'ABC', 'star': 'ABCDE' * 3}[length]], dtype='S')
+
+ a = np.array([[c for c in s] for s in expected], dtype='u1')
+ assert_array_equal(f(a), expected)
+
+ @pytest.mark.parametrize("length", length_list)
+ def test_2d_array_input(self, length):
+ fsuffix = length
+ f = getattr(self.module, self.fprefix + '_2d_array_input_' + fsuffix)
+
+ a = np.array([[{'1': 'a', '3': 'abc', 'star': 'abcde' * 3}[length],
+ {'1': 'A', '3': 'ABC', 'star': 'ABCDE' * 3}[length]],
+ [{'1': 'f', '3': 'fgh', 'star': 'fghij' * 3}[length],
+ {'1': 'F', '3': 'FGH', 'star': 'FGHIJ' * 3}[length]]],
+ dtype='S')
+ expected = np.array([[[c for c in item] for item in row] for row in a],
+ dtype='u1', order='F')
+ assert_array_equal(f(a), expected)
+
+
+class TestCharacter(util.F2PyTest):
+ # options = ['--debug-capi', '--build-dir', '/tmp/test-build-f2py']
+ suffix = '.f90'
+ fprefix = 'test_character'
+
+ code = textwrap.dedent(f"""
+ subroutine {fprefix}_input(c, o)
+ character, intent(in) :: c
+ integer*1 o
+ !f2py intent(out) o
+ o = transfer(c, o)
+ end subroutine {fprefix}_input
+
+ subroutine {fprefix}_output(c, o)
+ character :: c
+ integer*1, intent(in) :: o
+ !f2py intent(out) c
+ c = transfer(o, c)
+ end subroutine {fprefix}_output
+
+ subroutine {fprefix}_input_output(c, o)
+ character, intent(in) :: c
+ character o
+ !f2py intent(out) o
+ o = c
+ end subroutine {fprefix}_input_output
+
+ subroutine {fprefix}_inout(c, n)
+ character :: c, n
+ !f2py intent(in) n
+ !f2py intent(inout) c
+ c = n
+ end subroutine {fprefix}_inout
+
+ function {fprefix}_return(o) result (c)
+ character :: c
+ character, intent(in) :: o
+ c = transfer(o, c)
+ end function {fprefix}_return
+
+ subroutine {fprefix}_array_input(c, o)
+ character, intent(in) :: c(3)
+ integer*1 o(3)
+ !f2py intent(out) o
+ integer i
+ do i=1,3
+ o(i) = transfer(c(i), o(i))
+ end do
+ end subroutine {fprefix}_array_input
+
+ subroutine {fprefix}_2d_array_input(c, o)
+ character, intent(in) :: c(2, 3)
+ integer*1 o(2, 3)
+ !f2py intent(out) o
+ integer i, j
+ do i=1,2
+ do j=1,3
+ o(i, j) = transfer(c(i, j), o(i, j))
+ end do
+ end do
+ end subroutine {fprefix}_2d_array_input
+
+ subroutine {fprefix}_array_output(c, o)
+ character :: c(3)
+ integer*1, intent(in) :: o(3)
+ !f2py intent(out) c
+ do i=1,3
+ c(i) = transfer(o(i), c(i))
+ end do
+ end subroutine {fprefix}_array_output
+
+ subroutine {fprefix}_array_inout(c, n)
+ character :: c(3), n(3)
+ !f2py intent(in) n(3)
+ !f2py intent(inout) c(3)
+ do i=1,3
+ c(i) = n(i)
+ end do
+ end subroutine {fprefix}_array_inout
+
+ subroutine {fprefix}_2d_array_inout(c, n)
+ character :: c(2, 3), n(2, 3)
+ !f2py intent(in) n(2, 3)
+ !f2py intent(inout) c(2. 3)
+ integer i, j
+ do i=1,2
+ do j=1,3
+ c(i, j) = n(i, j)
+ end do
+ end do
+ end subroutine {fprefix}_2d_array_inout
+
+ function {fprefix}_array_return(o) result (c)
+ character, dimension(3) :: c
+ character, intent(in) :: o(3)
+ do i=1,3
+ c(i) = o(i)
+ end do
+ end function {fprefix}_array_return
+
+ function {fprefix}_optional(o) result (c)
+ character, intent(in) :: o
+ !f2py character o = "a"
+ character :: c
+ c = o
+ end function {fprefix}_optional
+ """)
+
+ @pytest.mark.parametrize("dtype", ['c', 'S1'])
+ def test_input(self, dtype):
+ f = getattr(self.module, self.fprefix + '_input')
+
+ assert_equal(f(np.array('a', dtype=dtype)), ord('a'))
+ assert_equal(f(np.array(b'a', dtype=dtype)), ord('a'))
+ assert_equal(f(np.array(['a'], dtype=dtype)), ord('a'))
+ assert_equal(f(np.array('abc', dtype=dtype)), ord('a'))
+ assert_equal(f(np.array([['a']], dtype=dtype)), ord('a'))
+
+ def test_input_varia(self):
+ f = getattr(self.module, self.fprefix + '_input')
+
+ assert_equal(f('a'), ord('a'))
+ assert_equal(f(b'a'), ord(b'a'))
+ assert_equal(f(''), 0)
+ assert_equal(f(b''), 0)
+ assert_equal(f(b'\0'), 0)
+ assert_equal(f('ab'), ord('a'))
+ assert_equal(f(b'ab'), ord('a'))
+ assert_equal(f(['a']), ord('a'))
+
+ assert_equal(f(np.array(b'a')), ord('a'))
+ assert_equal(f(np.array([b'a'])), ord('a'))
+ a = np.array('a')
+ assert_equal(f(a), ord('a'))
+ a = np.array(['a'])
+ assert_equal(f(a), ord('a'))
+
+ try:
+ f([])
+ except IndexError as msg:
+ if not str(msg).endswith(' got 0-list'):
+ raise
+ else:
+ raise SystemError(f'{f.__name__} should have failed on empty list')
+
+ try:
+ f(97)
+ except TypeError as msg:
+ if not str(msg).endswith(' got int instance'):
+ raise
+ else:
+ raise SystemError(f'{f.__name__} should have failed on int value')
+
+ @pytest.mark.parametrize("dtype", ['c', 'S1', 'U1'])
+ def test_array_input(self, dtype):
+ f = getattr(self.module, self.fprefix + '_array_input')
+
+ assert_array_equal(f(np.array(['a', 'b', 'c'], dtype=dtype)),
+ np.array(list(map(ord, 'abc')), dtype='i1'))
+ assert_array_equal(f(np.array([b'a', b'b', b'c'], dtype=dtype)),
+ np.array(list(map(ord, 'abc')), dtype='i1'))
+
+ def test_array_input_varia(self):
+ f = getattr(self.module, self.fprefix + '_array_input')
+ assert_array_equal(f(['a', 'b', 'c']),
+ np.array(list(map(ord, 'abc')), dtype='i1'))
+ assert_array_equal(f([b'a', b'b', b'c']),
+ np.array(list(map(ord, 'abc')), dtype='i1'))
+
+ try:
+ f(['a', 'b', 'c', 'd'])
+ except ValueError as msg:
+ if not str(msg).endswith(
+ 'th dimension must be fixed to 3 but got 4'):
+ raise
+ else:
+ raise SystemError(
+ f'{f.__name__} should have failed on wrong input')
+
+ @pytest.mark.parametrize("dtype", ['c', 'S1', 'U1'])
+ def test_2d_array_input(self, dtype):
+ f = getattr(self.module, self.fprefix + '_2d_array_input')
+
+ a = np.array([['a', 'b', 'c'],
+ ['d', 'e', 'f']], dtype=dtype, order='F')
+ expected = a.view(np.uint32 if dtype == 'U1' else np.uint8)
+ assert_array_equal(f(a), expected)
+
+ def test_output(self):
+ f = getattr(self.module, self.fprefix + '_output')
+
+ assert_equal(f(ord(b'a')), b'a')
+ assert_equal(f(0), b'\0')
+
+ def test_array_output(self):
+ f = getattr(self.module, self.fprefix + '_array_output')
+
+ assert_array_equal(f(list(map(ord, 'abc'))),
+ np.array(list('abc'), dtype='S1'))
+
+ def test_input_output(self):
+ f = getattr(self.module, self.fprefix + '_input_output')
+
+ assert_equal(f(b'a'), b'a')
+ assert_equal(f('a'), b'a')
+ assert_equal(f(''), b'\0')
+
+ @pytest.mark.parametrize("dtype", ['c', 'S1'])
+ def test_inout(self, dtype):
+ f = getattr(self.module, self.fprefix + '_inout')
+
+ a = np.array(list('abc'), dtype=dtype)
+ f(a, 'A')
+ assert_array_equal(a, np.array(list('Abc'), dtype=a.dtype))
+ f(a[1:], 'B')
+ assert_array_equal(a, np.array(list('ABc'), dtype=a.dtype))
+
+ a = np.array(['abc'], dtype=dtype)
+ f(a, 'A')
+ assert_array_equal(a, np.array(['Abc'], dtype=a.dtype))
+
+ def test_inout_varia(self):
+ f = getattr(self.module, self.fprefix + '_inout')
+ a = np.array('abc', dtype='S3')
+ f(a, 'A')
+ assert_array_equal(a, np.array('Abc', dtype=a.dtype))
+
+ a = np.array(['abc'], dtype='S3')
+ f(a, 'A')
+ assert_array_equal(a, np.array(['Abc'], dtype=a.dtype))
+
+ try:
+ f('abc', 'A')
+ except ValueError as msg:
+ if not str(msg).endswith(' got 3-str'):
+ raise
+ else:
+ raise SystemError(f'{f.__name__} should have failed on str value')
+
+ @pytest.mark.parametrize("dtype", ['c', 'S1'])
+ def test_array_inout(self, dtype):
+ f = getattr(self.module, self.fprefix + '_array_inout')
+ n = np.array(['A', 'B', 'C'], dtype=dtype, order='F')
+
+ a = np.array(['a', 'b', 'c'], dtype=dtype, order='F')
+ f(a, n)
+ assert_array_equal(a, n)
+
+ a = np.array(['a', 'b', 'c', 'd'], dtype=dtype)
+ f(a[1:], n)
+ assert_array_equal(a, np.array(['a', 'A', 'B', 'C'], dtype=dtype))
+
+ a = np.array([['a', 'b', 'c']], dtype=dtype, order='F')
+ f(a, n)
+ assert_array_equal(a, np.array([['A', 'B', 'C']], dtype=dtype))
+
+ a = np.array(['a', 'b', 'c', 'd'], dtype=dtype, order='F')
+ try:
+ f(a, n)
+ except ValueError as msg:
+ if not str(msg).endswith(
+ 'th dimension must be fixed to 3 but got 4'):
+ raise
+ else:
+ raise SystemError(
+ f'{f.__name__} should have failed on wrong input')
+
+ @pytest.mark.parametrize("dtype", ['c', 'S1'])
+ def test_2d_array_inout(self, dtype):
+ f = getattr(self.module, self.fprefix + '_2d_array_inout')
+ n = np.array([['A', 'B', 'C'],
+ ['D', 'E', 'F']],
+ dtype=dtype, order='F')
+ a = np.array([['a', 'b', 'c'],
+ ['d', 'e', 'f']],
+ dtype=dtype, order='F')
+ f(a, n)
+ assert_array_equal(a, n)
+
+ def test_return(self):
+ f = getattr(self.module, self.fprefix + '_return')
+
+ assert_equal(f('a'), b'a')
+
+ @pytest.mark.skip('fortran function returning array segfaults')
+ def test_array_return(self):
+ f = getattr(self.module, self.fprefix + '_array_return')
+
+ a = np.array(list('abc'), dtype='S1')
+ assert_array_equal(f(a), a)
+
+ def test_optional(self):
+ f = getattr(self.module, self.fprefix + '_optional')
+
+ assert_equal(f(), b"a")
+ assert_equal(f(b'B'), b"B")
+
+
+class TestMiscCharacter(util.F2PyTest):
+ # options = ['--debug-capi', '--build-dir', '/tmp/test-build-f2py']
+ suffix = '.f90'
+ fprefix = 'test_misc_character'
+
+ code = textwrap.dedent(f"""
+ subroutine {fprefix}_gh18684(x, y, m)
+ character(len=5), dimension(m), intent(in) :: x
+ character*5, dimension(m), intent(out) :: y
+ integer i, m
+ !f2py integer, intent(hide), depend(x) :: m = f2py_len(x)
+ do i=1,m
+ y(i) = x(i)
+ end do
+ end subroutine {fprefix}_gh18684
+
+ subroutine {fprefix}_gh6308(x, i)
+ integer i
+ !f2py check(i>=0 && i<12) i
+ character*5 name, x
+ common name(12)
+ name(i + 1) = x
+ end subroutine {fprefix}_gh6308
+
+ subroutine {fprefix}_gh4519(x)
+ character(len=*), intent(in) :: x(:)
+ !f2py intent(out) x
+ integer :: i
+ ! Uncomment for debug printing:
+ !do i=1, size(x)
+ ! print*, "x(",i,")=", x(i)
+ !end do
+ end subroutine {fprefix}_gh4519
+
+ pure function {fprefix}_gh3425(x) result (y)
+ character(len=*), intent(in) :: x
+ character(len=len(x)) :: y
+ integer :: i
+ do i = 1, len(x)
+ j = iachar(x(i:i))
+ if (j>=iachar("a") .and. j<=iachar("z") ) then
+ y(i:i) = achar(j-32)
+ else
+ y(i:i) = x(i:i)
+ endif
+ end do
+ end function {fprefix}_gh3425
+
+ subroutine {fprefix}_character_bc_new(x, y, z)
+ character, intent(in) :: x
+ character, intent(out) :: y
+ !f2py character, depend(x) :: y = x
+ !f2py character, dimension((x=='a'?1:2)), depend(x), intent(out) :: z
+ character, dimension(*) :: z
+ !f2py character, optional, check(x == 'a' || x == 'b') :: x = 'a'
+ !f2py callstatement (*f2py_func)(&x, &y, z)
+ !f2py callprotoargument character*, character*, character*
+ if (y.eq.x) then
+ y = x
+ else
+ y = 'e'
+ endif
+ z(1) = 'c'
+ end subroutine {fprefix}_character_bc_new
+
+ subroutine {fprefix}_character_bc_old(x, y, z)
+ character, intent(in) :: x
+ character, intent(out) :: y
+ !f2py character, depend(x) :: y = x[0]
+ !f2py character, dimension((*x=='a'?1:2)), depend(x), intent(out) :: z
+ character, dimension(*) :: z
+ !f2py character, optional, check(*x == 'a' || x[0] == 'b') :: x = 'a'
+ !f2py callstatement (*f2py_func)(x, y, z)
+ !f2py callprotoargument char*, char*, char*
+ if (y.eq.x) then
+ y = x
+ else
+ y = 'e'
+ endif
+ z(1) = 'c'
+ end subroutine {fprefix}_character_bc_old
+ """)
+
+ def test_gh18684(self):
+ # Test character(len=5) and character*5 usages
+ f = getattr(self.module, self.fprefix + '_gh18684')
+ x = np.array(["abcde", "fghij"], dtype='S5')
+ y = f(x)
+
+ assert_array_equal(x, y)
+
+ def test_gh6308(self):
+ # Test character string array in a common block
+ f = getattr(self.module, self.fprefix + '_gh6308')
+
+ assert_equal(self.module._BLNK_.name.dtype, np.dtype('S5'))
+ assert_equal(len(self.module._BLNK_.name), 12)
+ f("abcde", 0)
+ assert_equal(self.module._BLNK_.name[0], b"abcde")
+ f("12345", 5)
+ assert_equal(self.module._BLNK_.name[5], b"12345")
+
+ def test_gh4519(self):
+ # Test array of assumed length strings
+ f = getattr(self.module, self.fprefix + '_gh4519')
+
+ for x, expected in [
+ ('a', dict(shape=(), dtype=np.dtype('S1'))),
+ ('text', dict(shape=(), dtype=np.dtype('S4'))),
+ (np.array(['1', '2', '3'], dtype='S1'),
+ dict(shape=(3,), dtype=np.dtype('S1'))),
+ (['1', '2', '34'],
+ dict(shape=(3,), dtype=np.dtype('S2'))),
+ (['', ''], dict(shape=(2,), dtype=np.dtype('S1')))]:
+ r = f(x)
+ for k, v in expected.items():
+ assert_equal(getattr(r, k), v)
+
+ def test_gh3425(self):
+ # Test returning a copy of assumed length string
+ f = getattr(self.module, self.fprefix + '_gh3425')
+ # f is equivalent to bytes.upper
+
+ assert_equal(f('abC'), b'ABC')
+ assert_equal(f(''), b'')
+ assert_equal(f('abC12d'), b'ABC12D')
+
+ @pytest.mark.parametrize("state", ['new', 'old'])
+ def test_character_bc(self, state):
+ f = getattr(self.module, self.fprefix + '_character_bc_' + state)
+
+ c, a = f()
+ assert_equal(c, b'a')
+ assert_equal(len(a), 1)
+
+ c, a = f(b'b')
+ assert_equal(c, b'b')
+ assert_equal(len(a), 2)
+
+ assert_raises(Exception, lambda: f(b'c'))
+
+
+class TestStringScalarArr(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "string", "scalar_string.f90")]
+
+ def test_char(self):
+ for out in (self.module.string_test.string,
+ self.module.string_test.string77):
+ expected = ()
+ assert out.shape == expected
+ expected = '|S8'
+ assert out.dtype == expected
+
+ def test_char_arr(self):
+ for out in (self.module.string_test.strarr,
+ self.module.string_test.strarr77):
+ expected = (5,7)
+ assert out.shape == expected
+ expected = '|S12'
+ assert out.dtype == expected
+
+class TestStringAssumedLength(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "string", "gh24008.f")]
+
+ def test_gh24008(self):
+ self.module.greet("joe", "bob")
+
+class TestStringOptionalInOut(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "string", "gh24662.f90")]
+
+ def test_gh24662(self):
+ self.module.string_inout_optional()
+ a = np.array('hi', dtype='S32')
+ self.module.string_inout_optional(a)
+ assert "output string" in a.tobytes().decode()
+ with pytest.raises(Exception):
+ aa = "Hi"
+ self.module.string_inout_optional(aa)
+
+
+@pytest.mark.slow
+class TestNewCharHandling(util.F2PyTest):
+ # from v1.24 onwards, gh-19388
+ sources = [
+ util.getpath("tests", "src", "string", "gh25286.pyf"),
+ util.getpath("tests", "src", "string", "gh25286.f90")
+ ]
+ module_name = "_char_handling_test"
+
+ def test_gh25286(self):
+ info = self.module.charint('T')
+ assert info == 2
+
+@pytest.mark.slow
+class TestBCCharHandling(util.F2PyTest):
+ # SciPy style, "incorrect" bindings with a hook
+ sources = [
+ util.getpath("tests", "src", "string", "gh25286_bc.pyf"),
+ util.getpath("tests", "src", "string", "gh25286.f90")
+ ]
+ module_name = "_char_handling_test"
+
+ def test_gh25286(self):
+ info = self.module.charint('T')
+ assert info == 2
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_common.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_common.py
new file mode 100644
index 00000000..68c1b3b3
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_common.py
@@ -0,0 +1,27 @@
+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)
+
+
+class TestCommonWithUse(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "common", "gh19161.f90")]
+
+ @pytest.mark.skipif(sys.platform == "win32",
+ reason="Fails with MinGW64 Gfortran (Issue #9673)")
+ def test_common_gh19161(self):
+ assert self.module.data.x == 0
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_compile_function.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_compile_function.py
new file mode 100644
index 00000000..3c16f319
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_compile_function.py
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_crackfortran.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_crackfortran.py
new file mode 100644
index 00000000..c8d9ddb8
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_crackfortran.py
@@ -0,0 +1,350 @@
+import importlib
+import codecs
+import time
+import unicodedata
+import pytest
+import numpy as np
+from numpy.f2py.crackfortran import markinnerspaces, nameargspattern
+from . import util
+from numpy.f2py import crackfortran
+import textwrap
+import contextlib
+import io
+
+
+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'}
+
+ def test_nowrap_private_proceedures(self, tmp_path):
+ fpath = util.getpath("tests", "src", "crackfortran", "gh23879.f90")
+ mod = crackfortran.crackfortran([str(fpath)])
+ assert len(mod) == 1
+ pyf = crackfortran.crack2fortran(mod)
+ assert 'bar' not in pyf
+
+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"]
+
+ def test_notPublicPrivate(self, tmp_path):
+ fpath = util.getpath("tests", "src", "crackfortran", "pubprivmod.f90")
+ mod = crackfortran.crackfortran([str(fpath)])
+ assert len(mod) == 1
+ mod = mod[0]
+ assert mod['vars']['a']['attrspec'] == ['private', ]
+ assert mod['vars']['b']['attrspec'] == ['public', ]
+ assert mod['vars']['seta']['attrspec'] == ['public', ]
+
+
+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
+ 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')"
+
+
+class TestEval(util.F2PyTest):
+ def test_eval_scalar(self):
+ eval_scalar = crackfortran._eval_scalar
+
+ assert eval_scalar('123', {}) == '123'
+ assert eval_scalar('12 + 3', {}) == '15'
+ assert eval_scalar('a + b', dict(a=1, b=2)) == '3'
+ assert eval_scalar('"123"', {}) == "'123'"
+
+
+class TestFortranReader(util.F2PyTest):
+ @pytest.mark.parametrize("encoding",
+ ['ascii', 'utf-8', 'utf-16', 'utf-32'])
+ def test_input_encoding(self, tmp_path, encoding):
+ # gh-635
+ f_path = tmp_path / f"input_with_{encoding}_encoding.f90"
+ with f_path.open('w', encoding=encoding) as ff:
+ ff.write("""
+ subroutine foo()
+ end subroutine foo
+ """)
+ mod = crackfortran.crackfortran([str(f_path)])
+ assert mod[0]['name'] == 'foo'
+
+
+class TestUnicodeComment(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "crackfortran", "unicode_comment.f90")]
+
+ @pytest.mark.skipif(
+ (importlib.util.find_spec("charset_normalizer") is None),
+ reason="test requires charset_normalizer which is not installed",
+ )
+ def test_encoding_comment(self):
+ self.module.foo(3)
+
+
+class TestNameArgsPatternBacktracking:
+ @pytest.mark.parametrize(
+ ['adversary'],
+ [
+ ('@)@bind@(@',),
+ ('@)@bind @(@',),
+ ('@)@bind foo bar baz@(@',)
+ ]
+ )
+ def test_nameargspattern_backtracking(self, adversary):
+ '''address ReDOS vulnerability:
+ https://github.com/numpy/numpy/issues/23338'''
+ trials_per_batch = 12
+ batches_per_regex = 4
+ start_reps, end_reps = 15, 25
+ for ii in range(start_reps, end_reps):
+ repeated_adversary = adversary * ii
+ # test times in small batches.
+ # this gives us more chances to catch a bad regex
+ # while still catching it before too long if it is bad
+ for _ in range(batches_per_regex):
+ times = []
+ for _ in range(trials_per_batch):
+ t0 = time.perf_counter()
+ mtch = nameargspattern.search(repeated_adversary)
+ times.append(time.perf_counter() - t0)
+ # our pattern should be much faster than 0.2s per search
+ # it's unlikely that a bad regex will pass even on fast CPUs
+ assert np.median(times) < 0.2
+ assert not mtch
+ # if the adversary is capped with @)@, it becomes acceptable
+ # according to the old version of the regex.
+ # that should still be true.
+ good_version_of_adversary = repeated_adversary + '@)@'
+ assert nameargspattern.search(good_version_of_adversary)
+
+
+class TestFunctionReturn(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "crackfortran", "gh23598.f90")]
+
+ def test_function_rettype(self):
+ # gh-23598
+ assert self.module.intproduct(3, 4) == 12
+
+
+class TestFortranGroupCounters(util.F2PyTest):
+ def test_end_if_comment(self):
+ # gh-23533
+ fpath = util.getpath("tests", "src", "crackfortran", "gh23533.f")
+ try:
+ crackfortran.crackfortran([str(fpath)])
+ except Exception as exc:
+ assert False, f"'crackfortran.crackfortran' raised an exception {exc}"
+
+
+class TestF77CommonBlockReader():
+ def test_gh22648(self, tmp_path):
+ fpath = util.getpath("tests", "src", "crackfortran", "gh22648.pyf")
+ with contextlib.redirect_stdout(io.StringIO()) as stdout_f2py:
+ mod = crackfortran.crackfortran([str(fpath)])
+ assert "Mismatch" not in stdout_f2py.getvalue()
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_data.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_data.py
new file mode 100644
index 00000000..4e5604c0
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_data.py
@@ -0,0 +1,70 @@
+import os
+import pytest
+import numpy as np
+
+from . import util
+from numpy.f2py.crackfortran import crackfortran
+
+
+class TestData(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "crackfortran", "data_stmts.f90")]
+
+ # For gh-23276
+ def test_data_stmts(self):
+ assert self.module.cmplxdat.i == 2
+ assert self.module.cmplxdat.j == 3
+ assert self.module.cmplxdat.x == 1.5
+ assert self.module.cmplxdat.y == 2.0
+ assert self.module.cmplxdat.pi == 3.1415926535897932384626433832795028841971693993751058209749445923078164062
+ assert self.module.cmplxdat.medium_ref_index == np.array(1.+0.j)
+ assert np.all(self.module.cmplxdat.z == np.array([3.5, 7.0]))
+ assert np.all(self.module.cmplxdat.my_array == np.array([ 1.+2.j, -3.+4.j]))
+ assert np.all(self.module.cmplxdat.my_real_array == np.array([ 1., 2., 3.]))
+ assert np.all(self.module.cmplxdat.ref_index_one == np.array([13.0 + 21.0j]))
+ assert np.all(self.module.cmplxdat.ref_index_two == np.array([-30.0 + 43.0j]))
+
+ def test_crackedlines(self):
+ mod = crackfortran(self.sources)
+ assert mod[0]['vars']['x']['='] == '1.5'
+ assert mod[0]['vars']['y']['='] == '2.0'
+ assert mod[0]['vars']['pi']['='] == '3.1415926535897932384626433832795028841971693993751058209749445923078164062d0'
+ assert mod[0]['vars']['my_real_array']['='] == '(/1.0d0, 2.0d0, 3.0d0/)'
+ assert mod[0]['vars']['ref_index_one']['='] == '(13.0d0, 21.0d0)'
+ assert mod[0]['vars']['ref_index_two']['='] == '(-30.0d0, 43.0d0)'
+ assert mod[0]['vars']['my_array']['='] == '(/(1.0d0, 2.0d0), (-3.0d0, 4.0d0)/)'
+ assert mod[0]['vars']['z']['='] == '(/3.5, 7.0/)'
+
+class TestDataF77(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "crackfortran", "data_common.f")]
+
+ # For gh-23276
+ def test_data_stmts(self):
+ assert self.module.mycom.mydata == 0
+
+ def test_crackedlines(self):
+ mod = crackfortran(str(self.sources[0]))
+ print(mod[0]['vars'])
+ assert mod[0]['vars']['mydata']['='] == '0'
+
+
+class TestDataMultiplierF77(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "crackfortran", "data_multiplier.f")]
+
+ # For gh-23276
+ def test_data_stmts(self):
+ assert self.module.mycom.ivar1 == 3
+ assert self.module.mycom.ivar2 == 3
+ assert self.module.mycom.ivar3 == 2
+ assert self.module.mycom.ivar4 == 2
+ assert self.module.mycom.evar5 == 0
+
+
+class TestDataWithCommentsF77(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "crackfortran", "data_with_comments.f")]
+
+ # For gh-23276
+ def test_data_stmts(self):
+ assert len(self.module.mycom.mytab) == 3
+ assert self.module.mycom.mytab[0] == 0
+ assert self.module.mycom.mytab[1] == 4
+ assert self.module.mycom.mytab[2] == 0
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_docs.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_docs.py
new file mode 100644
index 00000000..6631dd82
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_docs.py
@@ -0,0 +1,55 @@
+import os
+import pytest
+import numpy as np
+from numpy.testing import assert_array_equal, assert_equal
+from . import util
+
+
+def get_docdir():
+ # assuming that documentation tests are run from a source
+ # directory
+ return os.path.abspath(os.path.join(
+ os.path.dirname(__file__),
+ '..', '..', '..',
+ 'doc', 'source', 'f2py', 'code'))
+
+
+pytestmark = pytest.mark.skipif(
+ not os.path.isdir(get_docdir()),
+ reason=('Could not find f2py documentation sources'
+ f' ({get_docdir()} does not exists)'))
+
+
+def _path(*a):
+ return os.path.join(*((get_docdir(),) + a))
+
+
+class TestDocAdvanced(util.F2PyTest):
+ # options = ['--debug-capi', '--build-dir', '/tmp/build-f2py']
+ sources = [_path('asterisk1.f90'), _path('asterisk2.f90'),
+ _path('ftype.f')]
+
+ def test_asterisk1(self):
+ foo = getattr(self.module, 'foo1')
+ assert_equal(foo(), b'123456789A12')
+
+ def test_asterisk2(self):
+ foo = getattr(self.module, 'foo2')
+ assert_equal(foo(2), b'12')
+ assert_equal(foo(12), b'123456789A12')
+ assert_equal(foo(24), b'123456789A123456789B')
+
+ def test_ftype(self):
+ ftype = self.module
+ ftype.foo()
+ assert_equal(ftype.data.a, 0)
+ ftype.data.a = 3
+ ftype.data.x = [1, 2, 3]
+ assert_equal(ftype.data.a, 3)
+ assert_array_equal(ftype.data.x,
+ np.array([1, 2, 3], dtype=np.float32))
+ ftype.data.x[1] = 45
+ assert_array_equal(ftype.data.x,
+ np.array([1, 45, 3], dtype=np.float32))
+
+ # TODO: implement test methods for other example Fortran codes
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_f2cmap.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_f2cmap.py
new file mode 100644
index 00000000..d2967e4f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_f2cmap.py
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_f2py2e.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_f2py2e.py
new file mode 100644
index 00000000..659e0e96
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_f2py2e.py
@@ -0,0 +1,896 @@
+import textwrap, re, sys, subprocess, shlex
+from pathlib import Path
+from collections import namedtuple
+import platform
+
+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 gh23598_warn(tmpdir_factory):
+ """F90 file for testing warnings in gh23598"""
+ fdat = util.getpath("tests", "src", "crackfortran", "gh23598Warn.f90").read_text()
+ fn = tmpdir_factory.getbasetemp() / "gh23598Warn.f90"
+ fn.write_text(fdat, encoding="ascii")
+ return fn
+
+
+@pytest.fixture(scope="session")
+def gh22819_cli(tmpdir_factory):
+ """F90 file for testing disallowed CLI arguments in ghff819"""
+ fdat = util.getpath("tests", "src", "cli", "gh_22819.pyf").read_text()
+ fn = tmpdir_factory.getbasetemp() / "gh_22819.pyf"
+ 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
+
+@pytest.fixture(scope="session")
+def f2cmap_f90(tmpdir_factory):
+ """Generates a single f90 file for testing"""
+ fdat = util.getpath("tests", "src", "f2cmap", "isoFortranEnvMap.f90").read_text()
+ f2cmap = util.getpath("tests", "src", "f2cmap", ".f2py_f2cmap").read_text()
+ fn = tmpdir_factory.getbasetemp() / "f2cmap.f90"
+ fmap = tmpdir_factory.getbasetemp() / "mapfile"
+ fn.write_text(fdat, encoding="ascii")
+ fmap.write_text(f2cmap, encoding="ascii")
+ return fn
+
+
+def test_gh22819_cli(capfd, gh22819_cli, monkeypatch):
+ """Check that module names are handled correctly
+ gh-22819
+ Essentially, the -m name cannot be used to import the module, so the module
+ named in the .pyf needs to be used instead
+
+ CLI :: -m and a .pyf file
+ """
+ ipath = Path(gh22819_cli)
+ monkeypatch.setattr(sys, "argv", f"f2py -m blah {ipath}".split())
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ gen_paths = [item.name for item in ipath.parent.rglob("*") if item.is_file()]
+ assert "blahmodule.c" not in gen_paths # shouldn't be generated
+ assert "blah-f2pywrappers.f" not in gen_paths
+ assert "test_22819-f2pywrappers.f" in gen_paths
+ assert "test_22819module.c" in gen_paths
+ assert "Ignoring blah"
+
+
+def test_gh22819_many_pyf(capfd, gh22819_cli, monkeypatch):
+ """Only one .pyf file allowed
+ gh-22819
+ CLI :: .pyf files
+ """
+ ipath = Path(gh22819_cli)
+ monkeypatch.setattr(sys, "argv", f"f2py -m blah {ipath} hello.pyf".split())
+ with util.switchdir(ipath.parent):
+ with pytest.raises(ValueError, match="Only one .pyf file per call"):
+ f2pycli()
+
+
+def test_gh23598_warn(capfd, gh23598_warn, monkeypatch):
+ foutl = get_io_paths(gh23598_warn, mname="test")
+ ipath = foutl.f90inp
+ monkeypatch.setattr(
+ sys, "argv",
+ f'f2py {ipath} -m test'.split())
+
+ with util.switchdir(ipath.parent):
+ f2pycli() # Generate files
+ wrapper = foutl.wrap90.read_text()
+ assert "intproductf2pywrap, intpr" not in wrapper
+
+
+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
+ assert "function hi() ! in " 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.skipif((platform.system() != 'Linux') or (sys.version_info <= (3, 12)),
+ reason='Compiler and 3.12 required')
+def test_untitled_cli(capfd, hello_world_f90, monkeypatch):
+ """Check that modules are named correctly
+
+ CLI :: defaults
+ """
+ ipath = Path(hello_world_f90)
+ monkeypatch.setattr(sys, "argv", f"f2py --backend meson -c {ipath}".split())
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert "untitledmodule.c" in out
+
+
+@pytest.mark.skipif((platform.system() != 'Linux') or (sys.version_info <= (3, 12)), reason='Compiler and 3.12 required')
+def test_no_py312_distutils_fcompiler(capfd, hello_world_f90, monkeypatch):
+ """Check that no distutils imports are performed on 3.12
+ CLI :: --fcompiler --help-link --backend distutils
+ """
+ MNAME = "hi"
+ foutl = get_io_paths(hello_world_f90, mname=MNAME)
+ ipath = foutl.f90inp
+ monkeypatch.setattr(
+ sys, "argv", f"f2py {ipath} -c --fcompiler=gfortran -m {MNAME}".split()
+ )
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert "--fcompiler cannot be used with meson" in out
+ monkeypatch.setattr(
+ sys, "argv", f"f2py --help-link".split()
+ )
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert "Use --dep for meson builds" in out
+ MNAME = "hi2" # Needs to be different for a new -c
+ monkeypatch.setattr(
+ sys, "argv", f"f2py {ipath} -c -m {MNAME} --backend distutils".split()
+ )
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert "Cannot use distutils backend with Python>=3.12" in out
+
+
+@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_mod_gen_gh25263(capfd, hello_world_f77, monkeypatch):
+ """Check that pyf files are correctly generated with module structure
+ CLI :: -m <name> -h pyf_file
+ BUG: numpy-gh #20520
+ """
+ MNAME = "hi"
+ foutl = get_io_paths(hello_world_f77, mname=MNAME)
+ ipath = foutl.finp
+ monkeypatch.setattr(sys, "argv", f'f2py {ipath} -m {MNAME} -h hi.pyf'.split())
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ with Path('hi.pyf').open() as hipyf:
+ pyfdat = hipyf.read()
+ assert "python module hi" in pyfdat
+
+
+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(capfd, f2cmap_f90, monkeypatch):
+ """Check that Fortran-to-Python KIND specs can be passed
+
+ CLI :: --f2cmap
+ """
+ ipath = Path(f2cmap_f90)
+ monkeypatch.setattr(sys, "argv", f'f2py -m blah {ipath} --f2cmap mapfile'.split())
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert "Reading f2cmap from 'mapfile' ..." in out
+ assert "Mapping \"real(kind=real32)\" to \"float\"" in out
+ assert "Mapping \"real(kind=real64)\" to \"double\"" in out
+ assert "Mapping \"integer(kind=int64)\" to \"long_long\"" in out
+ assert "Successfully applied user defined f2cmap changes" in out
+
+
+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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_isoc.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_isoc.py
new file mode 100644
index 00000000..594bd7ca
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_isoc.py
@@ -0,0 +1,52 @@
+from . import util
+import numpy as np
+import pytest
+from numpy.testing import assert_allclose
+
+class TestISOC(util.F2PyTest):
+ sources = [
+ util.getpath("tests", "src", "isocintrin", "isoCtests.f90"),
+ ]
+
+ # gh-24553
+ def test_c_double(self):
+ out = self.module.coddity.c_add(1, 2)
+ exp_out = 3
+ assert out == exp_out
+
+ # gh-9693
+ def test_bindc_function(self):
+ out = self.module.coddity.wat(1, 20)
+ exp_out = 8
+ assert out == exp_out
+
+ # gh-25207
+ def test_bindc_kinds(self):
+ out = self.module.coddity.c_add_int64(1, 20)
+ exp_out = 21
+ assert out == exp_out
+
+ # gh-25207
+ def test_bindc_add_arr(self):
+ a = np.array([1,2,3])
+ b = np.array([1,2,3])
+ out = self.module.coddity.add_arr(a, b)
+ exp_out = a*2
+ assert_allclose(out, exp_out)
+
+
+def test_process_f2cmap_dict():
+ from numpy.f2py.auxfuncs import process_f2cmap_dict
+
+ f2cmap_all = {"integer": {"8": "rubbish_type"}}
+ new_map = {"INTEGER": {"4": "int"}}
+ c2py_map = {"int": "int", "rubbish_type": "long"}
+
+ exp_map, exp_maptyp = ({"integer": {"8": "rubbish_type", "4": "int"}}, ["int"])
+
+ # Call the function
+ res_map, res_maptyp = process_f2cmap_dict(f2cmap_all, new_map, c2py_map)
+
+ # Assert the result is as expected
+ assert res_map == exp_map
+ assert res_maptyp == exp_maptyp
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_kind.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_kind.py
new file mode 100644
index 00000000..69b85aaa
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_kind.py
@@ -0,0 +1,47 @@
+import os
+import pytest
+import platform
+
+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_int(self):
+ """Test `int` kind_func for integers up to 10**40."""
+ 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}"
+
+ def test_real(self):
+ """
+ Test (processor-dependent) `real` kind_func for real numbers
+ of up to 31 digits precision (extended/quadruple).
+ """
+ selectedrealkind = self.module.selectedrealkind
+
+ for i in range(32):
+ assert selectedrealkind(i) == selected_real_kind(
+ i
+ ), f"selectedrealkind({i}): expected {selected_real_kind(i)!r} but got {selectedrealkind(i)!r}"
+
+ @pytest.mark.xfail(platform.machine().lower().startswith("ppc"),
+ reason="Some PowerPC may not support full IEEE 754 precision")
+ def test_quad_precision(self):
+ """
+ Test kind_func for quadruple precision [`real(16)`] of 32+ digits .
+ """
+ selectedrealkind = self.module.selectedrealkind
+
+ for i in range(32, 40):
+ assert selectedrealkind(i) == selected_real_kind(
+ i
+ ), f"selectedrealkind({i}): expected {selected_real_kind(i)!r} but got {selectedrealkind(i)!r}"
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_mixed.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_mixed.py
new file mode 100644
index 00000000..80653b7d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_mixed.py
@@ -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
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_module_doc.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_module_doc.py
new file mode 100644
index 00000000..28822d40
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_module_doc.py
@@ -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""")
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_parameter.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_parameter.py
new file mode 100644
index 00000000..2f620eaa
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_parameter.py
@@ -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])
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_pyf_src.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_pyf_src.py
new file mode 100644
index 00000000..f77ded2f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_pyf_src.py
@@ -0,0 +1,44 @@
+# This test is ported from numpy.distutils
+from numpy.f2py._src_pyf import process_str
+from numpy.testing import assert_equal
+
+
+pyf_src = """
+python module foo
+ <_rd=real,double precision>
+ interface
+ subroutine <s,d>foosub(tol)
+ <_rd>, intent(in,out) :: tol
+ end subroutine <s,d>foosub
+ end interface
+end python module foo
+"""
+
+expected_pyf = """
+python module foo
+ interface
+ subroutine sfoosub(tol)
+ real, intent(in,out) :: tol
+ end subroutine sfoosub
+ subroutine dfoosub(tol)
+ double precision, intent(in,out) :: tol
+ end subroutine dfoosub
+ end interface
+end python module foo
+"""
+
+
+def normalize_whitespace(s):
+ """
+ Remove leading and trailing whitespace, and convert internal
+ stretches of whitespace to a single space.
+ """
+ return ' '.join(s.split())
+
+
+def test_from_template():
+ """Regression test for gh-10712."""
+ pyf = process_str(pyf_src)
+ normalized_pyf = normalize_whitespace(pyf)
+ normalized_expected_pyf = normalize_whitespace(expected_pyf)
+ assert_equal(normalized_pyf, normalized_expected_pyf)
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_quoted_character.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_quoted_character.py
new file mode 100644
index 00000000..82671cd8
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_quoted_character.py
@@ -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")")
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_regression.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_regression.py
new file mode 100644
index 00000000..1c109783
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_regression.py
@@ -0,0 +1,77 @@
+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
+
+
+class TestModuleAndSubroutine(util.F2PyTest):
+ module_name = "example"
+ sources = [util.getpath("tests", "src", "regression", "gh25337", "data.f90"),
+ util.getpath("tests", "src", "regression", "gh25337", "use_data.f90")]
+
+ @pytest.mark.slow
+ def test_gh25337(self):
+ self.module.data.set_shift(3)
+ assert "data" in dir(self.module)
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_character.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_character.py
new file mode 100644
index 00000000..36c1f10f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_character.py
@@ -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)
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_complex.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_complex.py
new file mode 100644
index 00000000..9df79632
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_complex.py
@@ -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]).astype("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)
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_integer.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_integer.py
new file mode 100644
index 00000000..3b2f42e2
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_integer.py
@@ -0,0 +1,53 @@
+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, "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)
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_logical.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_logical.py
new file mode 100644
index 00000000..92fb902a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_logical.py
@@ -0,0 +1,64 @@
+import pytest
+
+from numpy import array
+from . import util
+
+
+class TestReturnLogical(util.F2PyTest):
+ def check_function(self, t):
+ assert t(True) == 1
+ assert t(False) == 0
+ assert t(0) == 0
+ assert t(None) == 0
+ assert t(0.0) == 0
+ assert t(0j) == 0
+ assert t(1j) == 1
+ assert t(234) == 1
+ assert t(234.6) == 1
+ assert t(234.6 + 3j) == 1
+ assert t("234") == 1
+ assert t("aaa") == 1
+ assert t("") == 0
+ assert t([]) == 0
+ assert t(()) == 0
+ assert t({}) == 0
+ assert t(t) == 1
+ assert t(-234) == 1
+ assert t(10**100) == 1
+ assert t([234]) == 1
+ assert t((234, )) == 1
+ assert t(array(234)) == 1
+ assert t(array([234])) == 1
+ assert t(array([[234]])) == 1
+ assert t(array([127], "b")) == 1
+ assert t(array([234], "h")) == 1
+ assert t(array([234], "i")) == 1
+ assert t(array([234], "l")) == 1
+ assert t(array([234], "f")) == 1
+ assert t(array([234], "d")) == 1
+ assert t(array([234 + 3j], "F")) == 1
+ assert t(array([234], "D")) == 1
+ assert t(array(0)) == 0
+ assert t(array([0])) == 0
+ assert t(array([[0]])) == 0
+ assert t(array([0j])) == 0
+ assert t(array([1])) == 1
+ pytest.raises(ValueError, t, array([0, 0]))
+
+
+class TestFReturnLogical(TestReturnLogical):
+ sources = [
+ util.getpath("tests", "src", "return_logical", "foo77.f"),
+ util.getpath("tests", "src", "return_logical", "foo90.f90"),
+ ]
+
+ @pytest.mark.slow
+ @pytest.mark.parametrize("name", "t0,t1,t2,t4,s0,s1,s2,s4".split(","))
+ def test_all_f77(self, name):
+ self.check_function(getattr(self.module, name))
+
+ @pytest.mark.slow
+ @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_logical, name))
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_real.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_real.py
new file mode 100644
index 00000000..a15d6475
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_return_real.py
@@ -0,0 +1,107 @@
+import platform
+import pytest
+import numpy as np
+
+from numpy import array
+from . import util
+
+
+class TestReturnReal(util.F2PyTest):
+ def check_function(self, t, tname):
+ if tname in ["t0", "t4", "s0", "s4"]:
+ err = 1e-5
+ else:
+ err = 0.0
+ assert abs(t(234) - 234.0) <= err
+ assert abs(t(234.6) - 234.6) <= err
+ assert abs(t("234") - 234) <= err
+ assert abs(t("234.6") - 234.6) <= err
+ assert abs(t(-234) + 234) <= err
+ assert abs(t([234]) - 234) <= err
+ assert abs(t((234, )) - 234.0) <= err
+ assert abs(t(array(234)) - 234.0) <= err
+ assert abs(t(array(234).astype("b")) + 22) <= 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, "B")) - 234.0) <= err
+ assert abs(t(array(234, "f")) - 234.0) <= err
+ assert abs(t(array(234, "d")) - 234.0) <= err
+ if tname in ["t0", "t4", "s0", "s4"]:
+ assert t(1e200) == t(1e300) # inf
+
+ # pytest.raises(ValueError, t, array([234], 'S1'))
+ pytest.raises(ValueError, t, "abc")
+
+ pytest.raises(IndexError, t, [])
+ pytest.raises(IndexError, t, ())
+
+ pytest.raises(Exception, t, t)
+ pytest.raises(Exception, t, {})
+
+ try:
+ r = t(10**400)
+ assert repr(r) in ["inf", "Infinity"]
+ except OverflowError:
+ pass
+
+
+@pytest.mark.skipif(
+ platform.system() == "Darwin",
+ reason="Prone to error when run with numpy/f2py/tests on mac os, "
+ "but not when run in isolation",
+)
+@pytest.mark.skipif(
+ np.dtype(np.intp).itemsize < 8,
+ reason="32-bit builds are buggy"
+)
+class TestCReturnReal(TestReturnReal):
+ suffix = ".pyf"
+ module_name = "c_ext_return_real"
+ code = """
+python module c_ext_return_real
+usercode \'\'\'
+float t4(float value) { return value; }
+void s4(float *t4, float value) { *t4 = value; }
+double t8(double value) { return value; }
+void s8(double *t8, double value) { *t8 = value; }
+\'\'\'
+interface
+ function t4(value)
+ real*4 intent(c) :: t4,value
+ end
+ function t8(value)
+ real*8 intent(c) :: t8,value
+ end
+ subroutine s4(t4,value)
+ intent(c) s4
+ real*4 intent(out) :: t4
+ real*4 intent(c) :: value
+ end
+ subroutine s8(t8,value)
+ intent(c) s8
+ real*8 intent(out) :: t8
+ real*8 intent(c) :: value
+ end
+end interface
+end python module c_ext_return_real
+ """
+
+ @pytest.mark.parametrize("name", "t4,t8,s4,s8".split(","))
+ def test_all(self, name):
+ self.check_function(getattr(self.module, name), name)
+
+
+class TestFReturnReal(TestReturnReal):
+ sources = [
+ util.getpath("tests", "src", "return_real", "foo77.f"),
+ util.getpath("tests", "src", "return_real", "foo90.f90"),
+ ]
+
+ @pytest.mark.parametrize("name", "t0,t4,t8,td,s0,s4,s8,sd".split(","))
+ def test_all_f77(self, name):
+ self.check_function(getattr(self.module, name), name)
+
+ @pytest.mark.parametrize("name", "t0,t4,t8,td,s0,s4,s8,sd".split(","))
+ def test_all_f90(self, name):
+ self.check_function(getattr(self.module.f90_return_real, name), name)
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_semicolon_split.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_semicolon_split.py
new file mode 100644
index 00000000..6d499046
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_semicolon_split.py
@@ -0,0 +1,74 @@
+import platform
+import pytest
+import numpy as np
+
+from . import util
+
+
+@pytest.mark.skipif(
+ platform.system() == "Darwin",
+ reason="Prone to error when run with numpy/f2py/tests on mac os, "
+ "but not when run in isolation",
+)
+@pytest.mark.skipif(
+ np.dtype(np.intp).itemsize < 8,
+ reason="32-bit builds are buggy"
+)
+class TestMultiline(util.F2PyTest):
+ suffix = ".pyf"
+ module_name = "multiline"
+ code = f"""
+python module {module_name}
+ usercode '''
+void foo(int* x) {{
+ char dummy = ';';
+ *x = 42;
+}}
+'''
+ interface
+ subroutine foo(x)
+ intent(c) foo
+ integer intent(out) :: x
+ end subroutine foo
+ end interface
+end python module {module_name}
+ """
+
+ def test_multiline(self):
+ assert self.module.foo() == 42
+
+
+@pytest.mark.skipif(
+ platform.system() == "Darwin",
+ reason="Prone to error when run with numpy/f2py/tests on mac os, "
+ "but not when run in isolation",
+)
+@pytest.mark.skipif(
+ np.dtype(np.intp).itemsize < 8,
+ reason="32-bit builds are buggy"
+)
+class TestCallstatement(util.F2PyTest):
+ suffix = ".pyf"
+ module_name = "callstatement"
+ code = f"""
+python module {module_name}
+ usercode '''
+void foo(int* x) {{
+}}
+'''
+ interface
+ subroutine foo(x)
+ intent(c) foo
+ integer intent(out) :: x
+ callprotoargument int*
+ callstatement {{ &
+ ; &
+ x = 42; &
+ }}
+ end subroutine foo
+ end interface
+end python module {module_name}
+ """
+
+ def test_callstatement(self):
+ assert self.module.foo() == 42
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_size.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_size.py
new file mode 100644
index 00000000..bd2c349d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_size.py
@@ -0,0 +1,45 @@
+import os
+import pytest
+import numpy as np
+
+from . import util
+
+
+class TestSizeSumExample(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "size", "foo.f90")]
+
+ @pytest.mark.slow
+ def test_all(self):
+ r = self.module.foo([[]])
+ assert r == [0]
+
+ r = self.module.foo([[1, 2]])
+ assert r == [3]
+
+ r = self.module.foo([[1, 2], [3, 4]])
+ assert np.allclose(r, [3, 7])
+
+ r = self.module.foo([[1, 2], [3, 4], [5, 6]])
+ assert np.allclose(r, [3, 7, 11])
+
+ @pytest.mark.slow
+ def test_transpose(self):
+ r = self.module.trans([[]])
+ assert np.allclose(r.T, np.array([[]]))
+
+ r = self.module.trans([[1, 2]])
+ assert np.allclose(r, [[1.], [2.]])
+
+ r = self.module.trans([[1, 2, 3], [4, 5, 6]])
+ assert np.allclose(r, [[1, 4], [2, 5], [3, 6]])
+
+ @pytest.mark.slow
+ def test_flatten(self):
+ r = self.module.flatten([[]])
+ assert np.allclose(r, [])
+
+ r = self.module.flatten([[1, 2]])
+ assert np.allclose(r, [1, 2])
+
+ r = self.module.flatten([[1, 2, 3], [4, 5, 6]])
+ assert np.allclose(r, [1, 2, 3, 4, 5, 6])
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_string.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_string.py
new file mode 100644
index 00000000..9e937188
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_string.py
@@ -0,0 +1,100 @@
+import os
+import pytest
+import textwrap
+import numpy as np
+from . import util
+
+
+class TestString(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "string", "char.f90")]
+
+ @pytest.mark.slow
+ def test_char(self):
+ strings = np.array(["ab", "cd", "ef"], dtype="c").T
+ inp, out = self.module.char_test.change_strings(
+ strings, strings.shape[1])
+ assert inp == pytest.approx(strings)
+ expected = strings.copy()
+ expected[1, :] = "AAA"
+ assert out == pytest.approx(expected)
+
+
+class TestDocStringArguments(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "string", "string.f")]
+
+ def test_example(self):
+ a = np.array(b"123\0\0")
+ b = np.array(b"123\0\0")
+ c = np.array(b"123")
+ d = np.array(b"123")
+
+ self.module.foo(a, b, c, d)
+
+ assert a.tobytes() == b"123\0\0"
+ assert b.tobytes() == b"B23\0\0"
+ assert c.tobytes() == b"123"
+ assert d.tobytes() == b"D23"
+
+
+class TestFixedString(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "string", "fixed_string.f90")]
+
+ @staticmethod
+ def _sint(s, start=0, end=None):
+ """Return the content of a string buffer as integer value.
+
+ For example:
+ _sint('1234') -> 4321
+ _sint('123A') -> 17321
+ """
+ if isinstance(s, np.ndarray):
+ s = s.tobytes()
+ elif isinstance(s, str):
+ s = s.encode()
+ assert isinstance(s, bytes)
+ if end is None:
+ end = len(s)
+ i = 0
+ for j in range(start, min(end, len(s))):
+ i += s[j] * 10**j
+ return i
+
+ def _get_input(self, intent="in"):
+ if intent in ["in"]:
+ yield ""
+ yield "1"
+ yield "1234"
+ yield "12345"
+ yield b""
+ yield b"\0"
+ yield b"1"
+ yield b"\01"
+ yield b"1\0"
+ yield b"1234"
+ yield b"12345"
+ yield np.ndarray((), np.bytes_, buffer=b"") # array(b'', dtype='|S0')
+ yield np.array(b"") # array(b'', dtype='|S1')
+ yield np.array(b"\0")
+ yield np.array(b"1")
+ yield np.array(b"1\0")
+ yield np.array(b"\01")
+ yield np.array(b"1234")
+ yield np.array(b"123\0")
+ yield np.array(b"12345")
+
+ def test_intent_in(self):
+ for s in self._get_input():
+ r = self.module.test_in_bytes4(s)
+ # also checks that s is not changed inplace
+ expected = self._sint(s, end=4)
+ assert r == expected, s
+
+ def test_intent_inout(self):
+ for s in self._get_input(intent="inout"):
+ rest = self._sint(s, start=4)
+ r = self.module.test_inout_bytes4(s)
+ expected = self._sint(s, end=4)
+ assert r == expected
+
+ # check that the rest of input string is preserved
+ assert rest == self._sint(s, start=4)
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_symbolic.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_symbolic.py
new file mode 100644
index 00000000..84527831
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_symbolic.py
@@ -0,0 +1,494 @@
+import pytest
+
+from numpy.f2py.symbolic import (
+ Expr,
+ Op,
+ ArithOp,
+ Language,
+ as_symbol,
+ as_number,
+ as_string,
+ as_array,
+ as_complex,
+ as_terms,
+ as_factors,
+ eliminate_quotes,
+ insert_quotes,
+ fromstring,
+ as_expr,
+ as_apply,
+ as_numer_denom,
+ as_ternary,
+ as_ref,
+ as_deref,
+ normalize,
+ as_eq,
+ as_ne,
+ as_lt,
+ as_gt,
+ as_le,
+ as_ge,
+)
+from . import util
+
+
+class TestSymbolic(util.F2PyTest):
+ def test_eliminate_quotes(self):
+ def worker(s):
+ r, d = eliminate_quotes(s)
+ s1 = insert_quotes(r, d)
+ assert s1 == s
+
+ for kind in ["", "mykind_"]:
+ worker(kind + '"1234" // "ABCD"')
+ worker(kind + '"1234" // ' + kind + '"ABCD"')
+ worker(kind + "\"1234\" // 'ABCD'")
+ worker(kind + '"1234" // ' + kind + "'ABCD'")
+ worker(kind + '"1\\"2\'AB\'34"')
+ worker("a = " + kind + "'1\\'2\"AB\"34'")
+
+ def test_sanity(self):
+ x = as_symbol("x")
+ y = as_symbol("y")
+ z = as_symbol("z")
+
+ assert x.op == Op.SYMBOL
+ assert repr(x) == "Expr(Op.SYMBOL, 'x')"
+ assert x == x
+ assert x != y
+ assert hash(x) is not None
+
+ n = as_number(123)
+ m = as_number(456)
+ assert n.op == Op.INTEGER
+ assert repr(n) == "Expr(Op.INTEGER, (123, 4))"
+ assert n == n
+ assert n != m
+ assert hash(n) is not None
+
+ fn = as_number(12.3)
+ fm = as_number(45.6)
+ assert fn.op == Op.REAL
+ assert repr(fn) == "Expr(Op.REAL, (12.3, 4))"
+ assert fn == fn
+ assert fn != fm
+ assert hash(fn) is not None
+
+ c = as_complex(1, 2)
+ c2 = as_complex(3, 4)
+ assert c.op == Op.COMPLEX
+ assert repr(c) == ("Expr(Op.COMPLEX, (Expr(Op.INTEGER, (1, 4)),"
+ " Expr(Op.INTEGER, (2, 4))))")
+ assert c == c
+ assert c != c2
+ assert hash(c) is not None
+
+ s = as_string("'123'")
+ s2 = as_string('"ABC"')
+ assert s.op == Op.STRING
+ assert repr(s) == "Expr(Op.STRING, (\"'123'\", 1))", repr(s)
+ assert s == s
+ assert s != s2
+
+ a = as_array((n, m))
+ b = as_array((n, ))
+ assert a.op == Op.ARRAY
+ assert repr(a) == ("Expr(Op.ARRAY, (Expr(Op.INTEGER, (123, 4)),"
+ " Expr(Op.INTEGER, (456, 4))))")
+ assert a == a
+ assert a != b
+
+ t = as_terms(x)
+ u = as_terms(y)
+ assert t.op == Op.TERMS
+ assert repr(t) == "Expr(Op.TERMS, {Expr(Op.SYMBOL, 'x'): 1})"
+ assert t == t
+ assert t != u
+ assert hash(t) is not None
+
+ v = as_factors(x)
+ w = as_factors(y)
+ assert v.op == Op.FACTORS
+ assert repr(v) == "Expr(Op.FACTORS, {Expr(Op.SYMBOL, 'x'): 1})"
+ assert v == v
+ assert w != v
+ assert hash(v) is not None
+
+ t = as_ternary(x, y, z)
+ u = as_ternary(x, z, y)
+ assert t.op == Op.TERNARY
+ assert t == t
+ assert t != u
+ assert hash(t) is not None
+
+ e = as_eq(x, y)
+ f = as_lt(x, y)
+ assert e.op == Op.RELATIONAL
+ assert e == e
+ assert e != f
+ assert hash(e) is not None
+
+ def test_tostring_fortran(self):
+ x = as_symbol("x")
+ y = as_symbol("y")
+ z = as_symbol("z")
+ n = as_number(123)
+ m = as_number(456)
+ a = as_array((n, m))
+ c = as_complex(n, m)
+
+ assert str(x) == "x"
+ assert str(n) == "123"
+ assert str(a) == "[123, 456]"
+ assert str(c) == "(123, 456)"
+
+ assert str(Expr(Op.TERMS, {x: 1})) == "x"
+ assert str(Expr(Op.TERMS, {x: 2})) == "2 * x"
+ assert str(Expr(Op.TERMS, {x: -1})) == "-x"
+ assert str(Expr(Op.TERMS, {x: -2})) == "-2 * x"
+ assert str(Expr(Op.TERMS, {x: 1, y: 1})) == "x + y"
+ assert str(Expr(Op.TERMS, {x: -1, y: -1})) == "-x - y"
+ assert str(Expr(Op.TERMS, {x: 2, y: 3})) == "2 * x + 3 * y"
+ assert str(Expr(Op.TERMS, {x: -2, y: 3})) == "-2 * x + 3 * y"
+ assert str(Expr(Op.TERMS, {x: 2, y: -3})) == "2 * x - 3 * y"
+
+ assert str(Expr(Op.FACTORS, {x: 1})) == "x"
+ assert str(Expr(Op.FACTORS, {x: 2})) == "x ** 2"
+ assert str(Expr(Op.FACTORS, {x: -1})) == "x ** -1"
+ assert str(Expr(Op.FACTORS, {x: -2})) == "x ** -2"
+ assert str(Expr(Op.FACTORS, {x: 1, y: 1})) == "x * y"
+ assert str(Expr(Op.FACTORS, {x: 2, y: 3})) == "x ** 2 * y ** 3"
+
+ v = Expr(Op.FACTORS, {x: 2, Expr(Op.TERMS, {x: 1, y: 1}): 3})
+ assert str(v) == "x ** 2 * (x + y) ** 3", str(v)
+ v = Expr(Op.FACTORS, {x: 2, Expr(Op.FACTORS, {x: 1, y: 1}): 3})
+ assert str(v) == "x ** 2 * (x * y) ** 3", str(v)
+
+ assert str(Expr(Op.APPLY, ("f", (), {}))) == "f()"
+ assert str(Expr(Op.APPLY, ("f", (x, ), {}))) == "f(x)"
+ assert str(Expr(Op.APPLY, ("f", (x, y), {}))) == "f(x, y)"
+ assert str(Expr(Op.INDEXING, ("f", x))) == "f[x]"
+
+ assert str(as_ternary(x, y, z)) == "merge(y, z, x)"
+ assert str(as_eq(x, y)) == "x .eq. y"
+ assert str(as_ne(x, y)) == "x .ne. y"
+ assert str(as_lt(x, y)) == "x .lt. y"
+ assert str(as_le(x, y)) == "x .le. y"
+ assert str(as_gt(x, y)) == "x .gt. y"
+ assert str(as_ge(x, y)) == "x .ge. y"
+
+ def test_tostring_c(self):
+ language = Language.C
+ x = as_symbol("x")
+ y = as_symbol("y")
+ z = as_symbol("z")
+ n = as_number(123)
+
+ assert Expr(Op.FACTORS, {x: 2}).tostring(language=language) == "x * x"
+ assert (Expr(Op.FACTORS, {
+ x + y: 2
+ }).tostring(language=language) == "(x + y) * (x + y)")
+ assert Expr(Op.FACTORS, {
+ x: 12
+ }).tostring(language=language) == "pow(x, 12)"
+
+ assert as_apply(ArithOp.DIV, x,
+ y).tostring(language=language) == "x / y"
+ assert (as_apply(ArithOp.DIV, x,
+ x + y).tostring(language=language) == "x / (x + y)")
+ assert (as_apply(ArithOp.DIV, x - y, x +
+ y).tostring(language=language) == "(x - y) / (x + y)")
+ assert (x + (x - y) / (x + y) +
+ n).tostring(language=language) == "123 + x + (x - y) / (x + y)"
+
+ assert as_ternary(x, y, z).tostring(language=language) == "(x?y:z)"
+ assert as_eq(x, y).tostring(language=language) == "x == y"
+ assert as_ne(x, y).tostring(language=language) == "x != y"
+ assert as_lt(x, y).tostring(language=language) == "x < y"
+ assert as_le(x, y).tostring(language=language) == "x <= y"
+ assert as_gt(x, y).tostring(language=language) == "x > y"
+ assert as_ge(x, y).tostring(language=language) == "x >= y"
+
+ def test_operations(self):
+ x = as_symbol("x")
+ y = as_symbol("y")
+ z = as_symbol("z")
+
+ assert x + x == Expr(Op.TERMS, {x: 2})
+ assert x - x == Expr(Op.INTEGER, (0, 4))
+ assert x + y == Expr(Op.TERMS, {x: 1, y: 1})
+ assert x - y == Expr(Op.TERMS, {x: 1, y: -1})
+ assert x * x == Expr(Op.FACTORS, {x: 2})
+ assert x * y == Expr(Op.FACTORS, {x: 1, y: 1})
+
+ assert +x == x
+ assert -x == Expr(Op.TERMS, {x: -1}), repr(-x)
+ assert 2 * x == Expr(Op.TERMS, {x: 2})
+ assert 2 + x == Expr(Op.TERMS, {x: 1, as_number(1): 2})
+ assert 2 * x + 3 * y == Expr(Op.TERMS, {x: 2, y: 3})
+ assert (x + y) * 2 == Expr(Op.TERMS, {x: 2, y: 2})
+
+ assert x**2 == Expr(Op.FACTORS, {x: 2})
+ assert (x + y)**2 == Expr(
+ Op.TERMS,
+ {
+ Expr(Op.FACTORS, {x: 2}): 1,
+ Expr(Op.FACTORS, {y: 2}): 1,
+ Expr(Op.FACTORS, {
+ x: 1,
+ y: 1
+ }): 2,
+ },
+ )
+ assert (x + y) * x == x**2 + x * y
+ assert (x + y)**2 == x**2 + 2 * x * y + y**2
+ assert (x + y)**2 + (x - y)**2 == 2 * x**2 + 2 * y**2
+ assert (x + y) * z == x * z + y * z
+ assert z * (x + y) == x * z + y * z
+
+ assert (x / 2) == as_apply(ArithOp.DIV, x, as_number(2))
+ assert (2 * x / 2) == x
+ assert (3 * x / 2) == as_apply(ArithOp.DIV, 3 * x, as_number(2))
+ assert (4 * x / 2) == 2 * x
+ assert (5 * x / 2) == as_apply(ArithOp.DIV, 5 * x, as_number(2))
+ assert (6 * x / 2) == 3 * x
+ assert ((3 * 5) * x / 6) == as_apply(ArithOp.DIV, 5 * x, as_number(2))
+ assert (30 * x**2 * y**4 / (24 * x**3 * y**3)) == as_apply(
+ ArithOp.DIV, 5 * y, 4 * x)
+ assert ((15 * x / 6) / 5) == as_apply(ArithOp.DIV, x,
+ as_number(2)), (15 * x / 6) / 5
+ assert (x / (5 / x)) == as_apply(ArithOp.DIV, x**2, as_number(5))
+
+ assert (x / 2.0) == Expr(Op.TERMS, {x: 0.5})
+
+ s = as_string('"ABC"')
+ t = as_string('"123"')
+
+ assert s // t == Expr(Op.STRING, ('"ABC123"', 1))
+ assert s // x == Expr(Op.CONCAT, (s, x))
+ assert x // s == Expr(Op.CONCAT, (x, s))
+
+ c = as_complex(1.0, 2.0)
+ assert -c == as_complex(-1.0, -2.0)
+ assert c + c == as_expr((1 + 2j) * 2)
+ assert c * c == as_expr((1 + 2j)**2)
+
+ def test_substitute(self):
+ x = as_symbol("x")
+ y = as_symbol("y")
+ z = as_symbol("z")
+ a = as_array((x, y))
+
+ assert x.substitute({x: y}) == y
+ assert (x + y).substitute({x: z}) == y + z
+ assert (x * y).substitute({x: z}) == y * z
+ assert (x**4).substitute({x: z}) == z**4
+ assert (x / y).substitute({x: z}) == z / y
+ assert x.substitute({x: y + z}) == y + z
+ assert a.substitute({x: y + z}) == as_array((y + z, y))
+
+ assert as_ternary(x, y,
+ z).substitute({x: y + z}) == as_ternary(y + z, y, z)
+ assert as_eq(x, y).substitute({x: y + z}) == as_eq(y + z, y)
+
+ def test_fromstring(self):
+
+ x = as_symbol("x")
+ y = as_symbol("y")
+ z = as_symbol("z")
+ f = as_symbol("f")
+ s = as_string('"ABC"')
+ t = as_string('"123"')
+ a = as_array((x, y))
+
+ assert fromstring("x") == x
+ assert fromstring("+ x") == x
+ assert fromstring("- x") == -x
+ assert fromstring("x + y") == x + y
+ assert fromstring("x + 1") == x + 1
+ assert fromstring("x * y") == x * y
+ assert fromstring("x * 2") == x * 2
+ assert fromstring("x / y") == x / y
+ assert fromstring("x ** 2", language=Language.Python) == x**2
+ assert fromstring("x ** 2 ** 3", language=Language.Python) == x**2**3
+ assert fromstring("(x + y) * z") == (x + y) * z
+
+ assert fromstring("f(x)") == f(x)
+ assert fromstring("f(x,y)") == f(x, y)
+ assert fromstring("f[x]") == f[x]
+ assert fromstring("f[x][y]") == f[x][y]
+
+ assert fromstring('"ABC"') == s
+ assert (normalize(
+ fromstring('"ABC" // "123" ',
+ language=Language.Fortran)) == s // t)
+ assert fromstring('f("ABC")') == f(s)
+ assert fromstring('MYSTRKIND_"ABC"') == as_string('"ABC"', "MYSTRKIND")
+
+ assert fromstring("(/x, y/)") == a, fromstring("(/x, y/)")
+ assert fromstring("f((/x, y/))") == f(a)
+ assert fromstring("(/(x+y)*z/)") == as_array(((x + y) * z, ))
+
+ assert fromstring("123") == as_number(123)
+ assert fromstring("123_2") == as_number(123, 2)
+ assert fromstring("123_myintkind") == as_number(123, "myintkind")
+
+ assert fromstring("123.0") == as_number(123.0, 4)
+ assert fromstring("123.0_4") == as_number(123.0, 4)
+ assert fromstring("123.0_8") == as_number(123.0, 8)
+ assert fromstring("123.0e0") == as_number(123.0, 4)
+ assert fromstring("123.0d0") == as_number(123.0, 8)
+ assert fromstring("123d0") == as_number(123.0, 8)
+ assert fromstring("123e-0") == as_number(123.0, 4)
+ assert fromstring("123d+0") == as_number(123.0, 8)
+ assert fromstring("123.0_myrealkind") == as_number(123.0, "myrealkind")
+ assert fromstring("3E4") == as_number(30000.0, 4)
+
+ assert fromstring("(1, 2)") == as_complex(1, 2)
+ assert fromstring("(1e2, PI)") == as_complex(as_number(100.0),
+ as_symbol("PI"))
+
+ assert fromstring("[1, 2]") == as_array((as_number(1), as_number(2)))
+
+ assert fromstring("POINT(x, y=1)") == as_apply(as_symbol("POINT"),
+ x,
+ y=as_number(1))
+ assert fromstring(
+ 'PERSON(name="John", age=50, shape=(/34, 23/))') == as_apply(
+ as_symbol("PERSON"),
+ name=as_string('"John"'),
+ age=as_number(50),
+ shape=as_array((as_number(34), as_number(23))),
+ )
+
+ assert fromstring("x?y:z") == as_ternary(x, y, z)
+
+ assert fromstring("*x") == as_deref(x)
+ assert fromstring("**x") == as_deref(as_deref(x))
+ assert fromstring("&x") == as_ref(x)
+ assert fromstring("(*x) * (*y)") == as_deref(x) * as_deref(y)
+ assert fromstring("(*x) * *y") == as_deref(x) * as_deref(y)
+ assert fromstring("*x * *y") == as_deref(x) * as_deref(y)
+ assert fromstring("*x**y") == as_deref(x) * as_deref(y)
+
+ assert fromstring("x == y") == as_eq(x, y)
+ assert fromstring("x != y") == as_ne(x, y)
+ assert fromstring("x < y") == as_lt(x, y)
+ assert fromstring("x > y") == as_gt(x, y)
+ assert fromstring("x <= y") == as_le(x, y)
+ assert fromstring("x >= y") == as_ge(x, y)
+
+ assert fromstring("x .eq. y", language=Language.Fortran) == as_eq(x, y)
+ assert fromstring("x .ne. y", language=Language.Fortran) == as_ne(x, y)
+ assert fromstring("x .lt. y", language=Language.Fortran) == as_lt(x, y)
+ assert fromstring("x .gt. y", language=Language.Fortran) == as_gt(x, y)
+ assert fromstring("x .le. y", language=Language.Fortran) == as_le(x, y)
+ assert fromstring("x .ge. y", language=Language.Fortran) == as_ge(x, y)
+
+ def test_traverse(self):
+ x = as_symbol("x")
+ y = as_symbol("y")
+ z = as_symbol("z")
+ f = as_symbol("f")
+
+ # Use traverse to substitute a symbol
+ def replace_visit(s, r=z):
+ if s == x:
+ return r
+
+ assert x.traverse(replace_visit) == z
+ assert y.traverse(replace_visit) == y
+ assert z.traverse(replace_visit) == z
+ assert (f(y)).traverse(replace_visit) == f(y)
+ assert (f(x)).traverse(replace_visit) == f(z)
+ assert (f[y]).traverse(replace_visit) == f[y]
+ assert (f[z]).traverse(replace_visit) == f[z]
+ assert (x + y + z).traverse(replace_visit) == (2 * z + y)
+ assert (x +
+ f(y, x - z)).traverse(replace_visit) == (z +
+ f(y, as_number(0)))
+ assert as_eq(x, y).traverse(replace_visit) == as_eq(z, y)
+
+ # Use traverse to collect symbols, method 1
+ function_symbols = set()
+ symbols = set()
+
+ def collect_symbols(s):
+ if s.op is Op.APPLY:
+ oper = s.data[0]
+ function_symbols.add(oper)
+ if oper in symbols:
+ symbols.remove(oper)
+ elif s.op is Op.SYMBOL and s not in function_symbols:
+ symbols.add(s)
+
+ (x + f(y, x - z)).traverse(collect_symbols)
+ assert function_symbols == {f}
+ assert symbols == {x, y, z}
+
+ # Use traverse to collect symbols, method 2
+ def collect_symbols2(expr, symbols):
+ if expr.op is Op.SYMBOL:
+ symbols.add(expr)
+
+ symbols = set()
+ (x + f(y, x - z)).traverse(collect_symbols2, symbols)
+ assert symbols == {x, y, z, f}
+
+ # Use traverse to partially collect symbols
+ def collect_symbols3(expr, symbols):
+ if expr.op is Op.APPLY:
+ # skip traversing function calls
+ return expr
+ if expr.op is Op.SYMBOL:
+ symbols.add(expr)
+
+ symbols = set()
+ (x + f(y, x - z)).traverse(collect_symbols3, symbols)
+ assert symbols == {x}
+
+ def test_linear_solve(self):
+ x = as_symbol("x")
+ y = as_symbol("y")
+ z = as_symbol("z")
+
+ assert x.linear_solve(x) == (as_number(1), as_number(0))
+ assert (x + 1).linear_solve(x) == (as_number(1), as_number(1))
+ assert (2 * x).linear_solve(x) == (as_number(2), as_number(0))
+ assert (2 * x + 3).linear_solve(x) == (as_number(2), as_number(3))
+ assert as_number(3).linear_solve(x) == (as_number(0), as_number(3))
+ assert y.linear_solve(x) == (as_number(0), y)
+ assert (y * z).linear_solve(x) == (as_number(0), y * z)
+
+ assert (x + y).linear_solve(x) == (as_number(1), y)
+ assert (z * x + y).linear_solve(x) == (z, y)
+ assert ((z + y) * x + y).linear_solve(x) == (z + y, y)
+ assert (z * y * x + y).linear_solve(x) == (z * y, y)
+
+ pytest.raises(RuntimeError, lambda: (x * x).linear_solve(x))
+
+ def test_as_numer_denom(self):
+ x = as_symbol("x")
+ y = as_symbol("y")
+ n = as_number(123)
+
+ assert as_numer_denom(x) == (x, as_number(1))
+ assert as_numer_denom(x / n) == (x, n)
+ assert as_numer_denom(n / x) == (n, x)
+ assert as_numer_denom(x / y) == (x, y)
+ assert as_numer_denom(x * y) == (x * y, as_number(1))
+ assert as_numer_denom(n + x / y) == (x + n * y, y)
+ assert as_numer_denom(n + x / (y - x / n)) == (y * n**2, y * n - x)
+
+ def test_polynomial_atoms(self):
+ x = as_symbol("x")
+ y = as_symbol("y")
+ n = as_number(123)
+
+ assert x.polynomial_atoms() == {x}
+ assert n.polynomial_atoms() == set()
+ assert (y[x]).polynomial_atoms() == {y[x]}
+ assert (y(x)).polynomial_atoms() == {y(x)}
+ assert (y(x) + x).polynomial_atoms() == {y(x), x}
+ assert (y(x) * x[y]).polynomial_atoms() == {y(x), x[y]}
+ assert (y(x)**x).polynomial_atoms() == {y(x)}
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_value_attrspec.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_value_attrspec.py
new file mode 100644
index 00000000..83aaf6c9
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/test_value_attrspec.py
@@ -0,0 +1,14 @@
+import os
+import pytest
+
+from . import util
+
+class TestValueAttr(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "value_attrspec", "gh21665.f90")]
+
+ # gh-21665
+ def test_long_long_map(self):
+ inp = 2
+ out = self.module.fortfuncs.square(inp)
+ exp_out = 4
+ assert out == exp_out
diff --git a/.venv/lib/python3.12/site-packages/numpy/f2py/tests/util.py b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/util.py
new file mode 100644
index 00000000..6ed6c085
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/f2py/tests/util.py
@@ -0,0 +1,440 @@
+"""
+Utility functions for
+
+- building and importing modules on test time, using a temporary location
+- detecting if compilers are present
+- determining paths to tests
+
+"""
+import glob
+import os
+import sys
+import subprocess
+import tempfile
+import shutil
+import atexit
+import textwrap
+import re
+import pytest
+import contextlib
+import numpy
+
+from pathlib import Path
+from numpy.compat import asstr
+from numpy._utils import asunicode
+from numpy.testing import temppath, IS_WASM
+from importlib import import_module
+
+#
+# Maintaining a temporary module directory
+#
+
+_module_dir = None
+_module_num = 5403
+
+if sys.platform == "cygwin":
+ NUMPY_INSTALL_ROOT = Path(__file__).parent.parent.parent
+ _module_list = list(NUMPY_INSTALL_ROOT.glob("**/*.dll"))
+
+
+def _cleanup():
+ global _module_dir
+ if _module_dir is not None:
+ try:
+ sys.path.remove(_module_dir)
+ except ValueError:
+ pass
+ try:
+ shutil.rmtree(_module_dir)
+ except OSError:
+ pass
+ _module_dir = None
+
+
+def get_module_dir():
+ global _module_dir
+ if _module_dir is None:
+ _module_dir = tempfile.mkdtemp()
+ atexit.register(_cleanup)
+ if _module_dir not in sys.path:
+ sys.path.insert(0, _module_dir)
+ return _module_dir
+
+
+def get_temp_module_name():
+ # Assume single-threaded, and the module dir usable only by this thread
+ global _module_num
+ get_module_dir()
+ name = "_test_ext_module_%d" % _module_num
+ _module_num += 1
+ if name in sys.modules:
+ # this should not be possible, but check anyway
+ raise RuntimeError("Temporary module name already in use.")
+ return name
+
+
+def _memoize(func):
+ memo = {}
+
+ def wrapper(*a, **kw):
+ key = repr((a, kw))
+ if key not in memo:
+ try:
+ memo[key] = func(*a, **kw)
+ except Exception as e:
+ memo[key] = e
+ raise
+ ret = memo[key]
+ if isinstance(ret, Exception):
+ raise ret
+ return ret
+
+ wrapper.__name__ = func.__name__
+ return wrapper
+
+
+#
+# Building modules
+#
+
+
+@_memoize
+def build_module(source_files, options=[], skip=[], only=[], module_name=None):
+ """
+ Compile and import a f2py module, built from the given files.
+
+ """
+
+ code = f"import sys; sys.path = {sys.path!r}; import numpy.f2py; numpy.f2py.main()"
+
+ d = get_module_dir()
+
+ # Copy files
+ dst_sources = []
+ f2py_sources = []
+ for fn in source_files:
+ if not os.path.isfile(fn):
+ raise RuntimeError("%s is not a file" % fn)
+ dst = os.path.join(d, os.path.basename(fn))
+ shutil.copyfile(fn, dst)
+ dst_sources.append(dst)
+
+ base, ext = os.path.splitext(dst)
+ if ext in (".f90", ".f", ".c", ".pyf"):
+ f2py_sources.append(dst)
+
+ assert f2py_sources
+
+ # Prepare options
+ if module_name is None:
+ module_name = get_temp_module_name()
+ f2py_opts = ["-c", "-m", module_name] + options + f2py_sources
+ if skip:
+ f2py_opts += ["skip:"] + skip
+ if only:
+ f2py_opts += ["only:"] + only
+
+ # Build
+ cwd = os.getcwd()
+ try:
+ os.chdir(d)
+ cmd = [sys.executable, "-c", code] + f2py_opts
+ p = subprocess.Popen(cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ out, err = p.communicate()
+ if p.returncode != 0:
+ raise RuntimeError("Running f2py failed: %s\n%s" %
+ (cmd[4:], asunicode(out)))
+ finally:
+ os.chdir(cwd)
+
+ # Partial cleanup
+ for fn in dst_sources:
+ os.unlink(fn)
+
+ # Rebase (Cygwin-only)
+ if sys.platform == "cygwin":
+ # If someone starts deleting modules after import, this will
+ # need to change to record how big each module is, rather than
+ # relying on rebase being able to find that from the files.
+ _module_list.extend(
+ glob.glob(os.path.join(d, "{:s}*".format(module_name)))
+ )
+ subprocess.check_call(
+ ["/usr/bin/rebase", "--database", "--oblivious", "--verbose"]
+ + _module_list
+ )
+
+
+
+ # Import
+ return import_module(module_name)
+
+
+@_memoize
+def build_code(source_code,
+ options=[],
+ skip=[],
+ only=[],
+ suffix=None,
+ module_name=None):
+ """
+ Compile and import Fortran code using f2py.
+
+ """
+ if suffix is None:
+ suffix = ".f"
+ with temppath(suffix=suffix) as path:
+ with open(path, "w") as f:
+ f.write(source_code)
+ return build_module([path],
+ options=options,
+ skip=skip,
+ only=only,
+ module_name=module_name)
+
+
+#
+# Check if compilers are available at all...
+#
+
+_compiler_status = None
+
+
+def _get_compiler_status():
+ global _compiler_status
+ if _compiler_status is not None:
+ return _compiler_status
+
+ _compiler_status = (False, False, False)
+ if IS_WASM:
+ # Can't run compiler from inside WASM.
+ return _compiler_status
+
+ # XXX: this is really ugly. But I don't know how to invoke Distutils
+ # in a safer way...
+ code = textwrap.dedent(f"""\
+ import os
+ import sys
+ sys.path = {repr(sys.path)}
+
+ def configuration(parent_name='',top_path=None):
+ global config
+ from numpy.distutils.misc_util import Configuration
+ config = Configuration('', parent_name, top_path)
+ return config
+
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
+
+ config_cmd = config.get_config_cmd()
+ have_c = config_cmd.try_compile('void foo() {{}}')
+ print('COMPILERS:%%d,%%d,%%d' %% (have_c,
+ config.have_f77c(),
+ config.have_f90c()))
+ sys.exit(99)
+ """)
+ code = code % dict(syspath=repr(sys.path))
+
+ tmpdir = tempfile.mkdtemp()
+ try:
+ script = os.path.join(tmpdir, "setup.py")
+
+ with open(script, "w") as f:
+ f.write(code)
+
+ cmd = [sys.executable, "setup.py", "config"]
+ p = subprocess.Popen(cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ cwd=tmpdir)
+ out, err = p.communicate()
+ finally:
+ shutil.rmtree(tmpdir)
+
+ m = re.search(br"COMPILERS:(\d+),(\d+),(\d+)", out)
+ if m:
+ _compiler_status = (
+ bool(int(m.group(1))),
+ bool(int(m.group(2))),
+ bool(int(m.group(3))),
+ )
+ # Finished
+ return _compiler_status
+
+
+def has_c_compiler():
+ return _get_compiler_status()[0]
+
+
+def has_f77_compiler():
+ return _get_compiler_status()[1]
+
+
+def has_f90_compiler():
+ return _get_compiler_status()[2]
+
+
+#
+# Building with distutils
+#
+
+
+@_memoize
+def build_module_distutils(source_files, config_code, module_name, **kw):
+ """
+ Build a module via distutils and import it.
+
+ """
+ d = get_module_dir()
+
+ # Copy files
+ dst_sources = []
+ for fn in source_files:
+ if not os.path.isfile(fn):
+ raise RuntimeError("%s is not a file" % fn)
+ dst = os.path.join(d, os.path.basename(fn))
+ shutil.copyfile(fn, dst)
+ dst_sources.append(dst)
+
+ # Build script
+ config_code = textwrap.dedent(config_code).replace("\n", "\n ")
+
+ code = fr"""
+import os
+import sys
+sys.path = {repr(sys.path)}
+
+def configuration(parent_name='',top_path=None):
+ from numpy.distutils.misc_util import Configuration
+ config = Configuration('', parent_name, top_path)
+ {config_code}
+ return config
+
+if __name__ == "__main__":
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
+ """
+ script = os.path.join(d, get_temp_module_name() + ".py")
+ dst_sources.append(script)
+ with open(script, "wb") as f:
+ f.write(code.encode('latin1'))
+
+ # Build
+ cwd = os.getcwd()
+ try:
+ os.chdir(d)
+ cmd = [sys.executable, script, "build_ext", "-i"]
+ p = subprocess.Popen(cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ out, err = p.communicate()
+ if p.returncode != 0:
+ raise RuntimeError("Running distutils build failed: %s\n%s" %
+ (cmd[4:], asstr(out)))
+ finally:
+ os.chdir(cwd)
+
+ # Partial cleanup
+ for fn in dst_sources:
+ os.unlink(fn)
+
+ # Import
+ __import__(module_name)
+ return sys.modules[module_name]
+
+
+#
+# Unittest convenience
+#
+
+
+class F2PyTest:
+ code = None
+ sources = None
+ options = []
+ skip = []
+ only = []
+ suffix = ".f"
+ module = None
+
+ @property
+ def module_name(self):
+ cls = type(self)
+ return f'_{cls.__module__.rsplit(".",1)[-1]}_{cls.__name__}_ext_module'
+
+ def setup_method(self):
+ if sys.platform == "win32":
+ pytest.skip("Fails with MinGW64 Gfortran (Issue #9673)")
+
+ if self.module is not None:
+ return
+
+ # Check compiler availability first
+ if not has_c_compiler():
+ pytest.skip("No C compiler available")
+
+ codes = []
+ if self.sources:
+ codes.extend(self.sources)
+ if self.code is not None:
+ codes.append(self.suffix)
+
+ needs_f77 = False
+ needs_f90 = False
+ needs_pyf = False
+ for fn in codes:
+ if str(fn).endswith(".f"):
+ needs_f77 = True
+ elif str(fn).endswith(".f90"):
+ needs_f90 = True
+ elif str(fn).endswith(".pyf"):
+ needs_pyf = True
+ if needs_f77 and not has_f77_compiler():
+ pytest.skip("No Fortran 77 compiler available")
+ if needs_f90 and not has_f90_compiler():
+ pytest.skip("No Fortran 90 compiler available")
+ if needs_pyf and not (has_f90_compiler() or has_f77_compiler()):
+ pytest.skip("No Fortran compiler available")
+
+ # Build the module
+ if self.code is not None:
+ self.module = build_code(
+ self.code,
+ options=self.options,
+ skip=self.skip,
+ only=self.only,
+ suffix=self.suffix,
+ module_name=self.module_name,
+ )
+
+ if self.sources is not None:
+ self.module = build_module(
+ self.sources,
+ options=self.options,
+ skip=self.skip,
+ only=self.only,
+ module_name=self.module_name,
+ )
+
+
+#
+# Helper functions
+#
+
+
+def getpath(*a):
+ # Package root
+ d = Path(numpy.f2py.__file__).parent.resolve()
+ return d.joinpath(*a)
+
+
+@contextlib.contextmanager
+def switchdir(path):
+ curpath = Path.cwd()
+ os.chdir(path)
+ try:
+ yield
+ finally:
+ os.chdir(curpath)