summaryrefslogtreecommitdiff
path: root/numpy/f2py
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2020-12-13 14:14:49 -0700
committerGitHub <noreply@github.com>2020-12-13 14:14:49 -0700
commit3fe2d9d2627fc0f84aeed293ff8afa7c1f08d899 (patch)
tree2ea27fe06a19c39e8d7a5fe2f87cb7e05363247d /numpy/f2py
parent7d7e446fcbeeff70d905bde2eb0264a797488280 (diff)
parenteff302e5e8678fa17fb3d8156d49eb585b0876d9 (diff)
downloadnumpy-3fe2d9d2627fc0f84aeed293ff8afa7c1f08d899.tar.gz
Merge branch 'master' into fix-issue-10244
Diffstat (limited to 'numpy/f2py')
-rw-r--r--numpy/f2py/__init__.py71
-rw-r--r--numpy/f2py/__init__.pyi5
-rw-r--r--numpy/f2py/__version__.py9
-rw-r--r--numpy/f2py/capi_maps.py2
-rw-r--r--numpy/f2py/cfuncs.py284
-rw-r--r--numpy/f2py/common_rules.py2
-rwxr-xr-xnumpy/f2py/crackfortran.py54
-rwxr-xr-xnumpy/f2py/f2py2e.py26
-rwxr-xr-xnumpy/f2py/rules.py15
-rw-r--r--numpy/f2py/setup.py1
-rw-r--r--numpy/f2py/src/fortranobject.c7
-rw-r--r--numpy/f2py/src/test/foomodule.c2
-rw-r--r--numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c29
-rw-r--r--numpy/f2py/tests/src/module_data/mod.modbin0 -> 412 bytes
-rw-r--r--numpy/f2py/tests/src/module_data/module_data_docstring.f9012
-rw-r--r--numpy/f2py/tests/test_block_docstring.py2
-rw-r--r--numpy/f2py/tests/test_module_doc.py30
-rw-r--r--numpy/f2py/tests/util.py2
18 files changed, 373 insertions, 180 deletions
diff --git a/numpy/f2py/__init__.py b/numpy/f2py/__init__.py
index 949bac0ff..07ab6cd7d 100644
--- a/numpy/f2py/__init__.py
+++ b/numpy/f2py/__init__.py
@@ -9,7 +9,6 @@ import subprocess
import os
from . import f2py2e
-from . import f2py_testing
from . import diagnose
run_main = f2py2e.run_main
@@ -21,7 +20,8 @@ def compile(source,
extra_args='',
verbose=True,
source_fn=None,
- extension='.f'
+ extension='.f',
+ full_output=False
):
"""
Build extension module from a Fortran 77 source string with f2py.
@@ -55,10 +55,19 @@ def compile(source,
.. versionadded:: 1.11.0
+ full_output : bool, optional
+ If True, return a `subprocess.CompletedProcess` containing
+ the stdout and stderr of the compile process, instead of just
+ the status code.
+
+ .. versionadded:: 1.20.0
+
+
Returns
-------
- result : int
- 0 on success
+ result : int or `subprocess.CompletedProcess`
+ 0 on success, or a `subprocess.CompletedProcess` if
+ ``full_output=True``
Examples
--------
@@ -95,24 +104,50 @@ def compile(source,
'-c',
'import numpy.f2py as f2py2e;f2py2e.main()'] + args
try:
- output = subprocess.check_output(c)
- except subprocess.CalledProcessError as exc:
- status = exc.returncode
- output = ''
+ cp = subprocess.run(c, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
except OSError:
# preserve historic status code used by exec_command()
- status = 127
- output = ''
+ cp = subprocess.CompletedProcess(c, 127, stdout=b'', stderr=b'')
else:
- status = 0
- output = output.decode()
- if verbose:
- print(output)
+ if verbose:
+ print(cp.stdout.decode())
finally:
if source_fn is None:
os.remove(fname)
- return status
-from numpy._pytesttester import PytestTester
-test = PytestTester(__name__)
-del PytestTester
+ if full_output:
+ return cp
+ else:
+ return cp.returncode
+
+
+if sys.version_info[:2] >= (3, 7):
+ # module level getattr is only supported in 3.7 onwards
+ # https://www.python.org/dev/peps/pep-0562/
+ def __getattr__(attr):
+
+ # Avoid importing things that aren't needed for building
+ # which might import the main numpy module
+ if attr == "f2py_testing":
+ import numpy.f2py.f2py_testing as f2py_testing
+ return f2py_testing
+
+ elif attr == "test":
+ from numpy._pytesttester import PytestTester
+ test = PytestTester(__name__)
+ return test
+
+ else:
+ raise AttributeError("module {!r} has no attribute "
+ "{!r}".format(__name__, attr))
+
+ def __dir__():
+ return list(globals().keys() | {"f2py_testing", "test"})
+
+else:
+ from . import f2py_testing
+
+ from numpy._pytesttester import PytestTester
+ test = PytestTester(__name__)
+ del PytestTester
diff --git a/numpy/f2py/__init__.pyi b/numpy/f2py/__init__.pyi
new file mode 100644
index 000000000..602517957
--- /dev/null
+++ b/numpy/f2py/__init__.pyi
@@ -0,0 +1,5 @@
+from typing import Any
+
+run_main: Any
+compile: Any
+f2py_testing: Any
diff --git a/numpy/f2py/__version__.py b/numpy/f2py/__version__.py
index 104c2e1a8..e20d7c1db 100644
--- a/numpy/f2py/__version__.py
+++ b/numpy/f2py/__version__.py
@@ -1,8 +1 @@
-major = 2
-
-try:
- from __svn_version__ import version
- version_info = (major, version)
- version = '%s_%s' % version_info
-except (ImportError, ValueError):
- version = str(major)
+from numpy.version import version
diff --git a/numpy/f2py/capi_maps.py b/numpy/f2py/capi_maps.py
index fabbfc4c2..472ddde43 100644
--- a/numpy/f2py/capi_maps.py
+++ b/numpy/f2py/capi_maps.py
@@ -11,8 +11,6 @@ $Date: 2005/05/06 10:57:33 $
Pearu Peterson
"""
-__version__ = "$Revision: 1.60 $"[10:-1]
-
from . import __version__
f2py_version = __version__.version
diff --git a/numpy/f2py/cfuncs.py b/numpy/f2py/cfuncs.py
index ccbc9b0fb..26b43e7e6 100644
--- a/numpy/f2py/cfuncs.py
+++ b/numpy/f2py/cfuncs.py
@@ -286,11 +286,11 @@ static int f2py_size(PyArrayObject* var, ...)
"""
cppmacros[
- 'pyobj_from_char1'] = '#define pyobj_from_char1(v) (PyInt_FromLong(v))'
+ 'pyobj_from_char1'] = '#define pyobj_from_char1(v) (PyLong_FromLong(v))'
cppmacros[
- 'pyobj_from_short1'] = '#define pyobj_from_short1(v) (PyInt_FromLong(v))'
+ 'pyobj_from_short1'] = '#define pyobj_from_short1(v) (PyLong_FromLong(v))'
needs['pyobj_from_int1'] = ['signed_char']
-cppmacros['pyobj_from_int1'] = '#define pyobj_from_int1(v) (PyInt_FromLong(v))'
+cppmacros['pyobj_from_int1'] = '#define pyobj_from_int1(v) (PyLong_FromLong(v))'
cppmacros[
'pyobj_from_long1'] = '#define pyobj_from_long1(v) (PyLong_FromLong(v))'
needs['pyobj_from_long_long1'] = ['long_long']
@@ -320,10 +320,10 @@ cppmacros[
'pyobj_from_complex_float1'] = '#define pyobj_from_complex_float1(v) (PyComplex_FromDoubles(v.r,v.i))'
needs['pyobj_from_string1'] = ['string']
cppmacros[
- 'pyobj_from_string1'] = '#define pyobj_from_string1(v) (PyString_FromString((char *)v))'
+ 'pyobj_from_string1'] = '#define pyobj_from_string1(v) (PyUnicode_FromString((char *)v))'
needs['pyobj_from_string1size'] = ['string']
cppmacros[
- 'pyobj_from_string1size'] = '#define pyobj_from_string1size(v,len) (PyUString_FromStringAndSize((char *)v, len))'
+ 'pyobj_from_string1size'] = '#define pyobj_from_string1size(v,len) (PyUnicode_FromStringAndSize((char *)v, len))'
needs['TRYPYARRAYTEMPLATE'] = ['PRINTPYOBJERR']
cppmacros['TRYPYARRAYTEMPLATE'] = """\
/* New SciPy */
@@ -436,9 +436,9 @@ cppmacros['GETSTRFROMPYTUPLE'] = """\
PyObject *rv_cb_str = PyTuple_GetItem((tuple),(index));\\
if (rv_cb_str == NULL)\\
goto capi_fail;\\
- if (PyString_Check(rv_cb_str)) {\\
+ if (PyBytes_Check(rv_cb_str)) {\\
str[len-1]='\\0';\\
- STRINGCOPYN((str),PyString_AS_STRING((PyStringObject*)rv_cb_str),(len));\\
+ STRINGCOPYN((str),PyBytes_AS_STRING((PyBytesObject*)rv_cb_str),(len));\\
} else {\\
PRINTPYOBJERR(rv_cb_str);\\
PyErr_SetString(#modulename#_error,\"string object expected\");\\
@@ -629,7 +629,9 @@ capi_fail:
"""
needs['string_from_pyobj'] = ['string', 'STRINGMALLOC', 'STRINGCOPYN']
cfuncs['string_from_pyobj'] = """\
-static int string_from_pyobj(string *str,int *len,const string inistr,PyObject *obj,const char *errmess) {
+static int
+string_from_pyobj(string *str,int *len,const string inistr,PyObject *obj,const char *errmess)
+{
PyArrayObject *arr = NULL;
PyObject *tmp = NULL;
#ifdef DEBUGCFUNCS
@@ -655,7 +657,7 @@ fprintf(stderr,\"string_from_pyobj(str='%s',len=%d,inistr='%s',obj=%p)\\n\",(cha
STRINGCOPYN(*str,PyArray_DATA(arr),*len+1);
return 1;
}
- if (PyString_Check(obj)) {
+ if (PyBytes_Check(obj)) {
tmp = obj;
Py_INCREF(tmp);
}
@@ -675,200 +677,244 @@ fprintf(stderr,\"string_from_pyobj(str='%s',len=%d,inistr='%s',obj=%p)\\n\",(cha
}
if (tmp == NULL) goto capi_fail;
if (*len == -1)
- *len = PyString_GET_SIZE(tmp);
+ *len = PyBytes_GET_SIZE(tmp);
STRINGMALLOC(*str,*len);
- STRINGCOPYN(*str,PyString_AS_STRING(tmp),*len+1);
+ STRINGCOPYN(*str,PyBytes_AS_STRING(tmp),*len+1);
Py_DECREF(tmp);
return 1;
capi_fail:
Py_XDECREF(tmp);
{
PyObject* err = PyErr_Occurred();
- if (err==NULL) err = #modulename#_error;
- PyErr_SetString(err,errmess);
+ if (err == NULL) {
+ err = #modulename#_error;
+ }
+ PyErr_SetString(err, errmess);
}
return 0;
}
"""
+
+
needs['char_from_pyobj'] = ['int_from_pyobj']
cfuncs['char_from_pyobj'] = """\
-static int char_from_pyobj(char* v,PyObject *obj,const char *errmess) {
- int i=0;
- if (int_from_pyobj(&i,obj,errmess)) {
+static int
+char_from_pyobj(char* v, PyObject *obj, const char *errmess) {
+ int i = 0;
+ if (int_from_pyobj(&i, obj, errmess)) {
*v = (char)i;
return 1;
}
return 0;
}
"""
+
+
needs['signed_char_from_pyobj'] = ['int_from_pyobj', 'signed_char']
cfuncs['signed_char_from_pyobj'] = """\
-static int signed_char_from_pyobj(signed_char* v,PyObject *obj,const char *errmess) {
- int i=0;
- if (int_from_pyobj(&i,obj,errmess)) {
+static int
+signed_char_from_pyobj(signed_char* v, PyObject *obj, const char *errmess) {
+ int i = 0;
+ if (int_from_pyobj(&i, obj, errmess)) {
*v = (signed_char)i;
return 1;
}
return 0;
}
"""
+
+
needs['short_from_pyobj'] = ['int_from_pyobj']
cfuncs['short_from_pyobj'] = """\
-static int short_from_pyobj(short* v,PyObject *obj,const char *errmess) {
- int i=0;
- if (int_from_pyobj(&i,obj,errmess)) {
+static int
+short_from_pyobj(short* v, PyObject *obj, const char *errmess) {
+ int i = 0;
+ if (int_from_pyobj(&i, obj, errmess)) {
*v = (short)i;
return 1;
}
return 0;
}
"""
+
+
cfuncs['int_from_pyobj'] = """\
-static int int_from_pyobj(int* v,PyObject *obj,const char *errmess) {
+static int
+int_from_pyobj(int* v, PyObject *obj, const char *errmess)
+{
PyObject* tmp = NULL;
- if (PyInt_Check(obj)) {
- *v = (int)PyInt_AS_LONG(obj);
- return 1;
+
+ if (PyLong_Check(obj)) {
+ *v = Npy__PyLong_AsInt(obj);
+ return !(*v == -1 && PyErr_Occurred());
}
- tmp = PyNumber_Int(obj);
+
+ tmp = PyNumber_Long(obj);
if (tmp) {
- *v = PyInt_AS_LONG(tmp);
+ *v = Npy__PyLong_AsInt(tmp);
Py_DECREF(tmp);
- return 1;
+ return !(*v == -1 && PyErr_Occurred());
}
+
if (PyComplex_Check(obj))
tmp = PyObject_GetAttrString(obj,\"real\");
- else if (PyString_Check(obj) || PyUnicode_Check(obj))
+ else if (PyBytes_Check(obj) || PyUnicode_Check(obj))
/*pass*/;
else if (PySequence_Check(obj))
- tmp = PySequence_GetItem(obj,0);
+ tmp = PySequence_GetItem(obj, 0);
if (tmp) {
PyErr_Clear();
- if (int_from_pyobj(v,tmp,errmess)) {Py_DECREF(tmp); return 1;}
+ if (int_from_pyobj(v, tmp, errmess)) {
+ Py_DECREF(tmp);
+ return 1;
+ }
Py_DECREF(tmp);
}
{
PyObject* err = PyErr_Occurred();
- if (err==NULL) err = #modulename#_error;
- PyErr_SetString(err,errmess);
+ if (err == NULL) {
+ err = #modulename#_error;
+ }
+ PyErr_SetString(err, errmess);
}
return 0;
}
"""
+
+
cfuncs['long_from_pyobj'] = """\
-static int long_from_pyobj(long* v,PyObject *obj,const char *errmess) {
+static int
+long_from_pyobj(long* v, PyObject *obj, const char *errmess) {
PyObject* tmp = NULL;
- if (PyInt_Check(obj)) {
- *v = PyInt_AS_LONG(obj);
- return 1;
+
+ if (PyLong_Check(obj)) {
+ *v = PyLong_AsLong(obj);
+ return !(*v == -1 && PyErr_Occurred());
}
- tmp = PyNumber_Int(obj);
+
+ tmp = PyNumber_Long(obj);
if (tmp) {
- *v = PyInt_AS_LONG(tmp);
+ *v = PyLong_AsLong(tmp);
Py_DECREF(tmp);
- return 1;
+ return !(*v == -1 && PyErr_Occurred());
}
+
if (PyComplex_Check(obj))
tmp = PyObject_GetAttrString(obj,\"real\");
- else if (PyString_Check(obj) || PyUnicode_Check(obj))
+ else if (PyBytes_Check(obj) || PyUnicode_Check(obj))
/*pass*/;
else if (PySequence_Check(obj))
tmp = PySequence_GetItem(obj,0);
+
if (tmp) {
PyErr_Clear();
- if (long_from_pyobj(v,tmp,errmess)) {Py_DECREF(tmp); return 1;}
+ if (long_from_pyobj(v, tmp, errmess)) {
+ Py_DECREF(tmp);
+ return 1;
+ }
Py_DECREF(tmp);
}
{
PyObject* err = PyErr_Occurred();
- if (err==NULL) err = #modulename#_error;
- PyErr_SetString(err,errmess);
+ if (err == NULL) {
+ err = #modulename#_error;
+ }
+ PyErr_SetString(err, errmess);
}
return 0;
}
"""
+
+
needs['long_long_from_pyobj'] = ['long_long']
cfuncs['long_long_from_pyobj'] = """\
-static int long_long_from_pyobj(long_long* v,PyObject *obj,const char *errmess) {
+static int
+long_long_from_pyobj(long_long* v, PyObject *obj, const char *errmess)
+{
PyObject* tmp = NULL;
+
if (PyLong_Check(obj)) {
*v = PyLong_AsLongLong(obj);
- return (!PyErr_Occurred());
- }
- if (PyInt_Check(obj)) {
- *v = (long_long)PyInt_AS_LONG(obj);
- return 1;
+ return !(*v == -1 && PyErr_Occurred());
}
+
tmp = PyNumber_Long(obj);
if (tmp) {
*v = PyLong_AsLongLong(tmp);
Py_DECREF(tmp);
- return (!PyErr_Occurred());
+ return !(*v == -1 && PyErr_Occurred());
}
+
if (PyComplex_Check(obj))
tmp = PyObject_GetAttrString(obj,\"real\");
- else if (PyString_Check(obj) || PyUnicode_Check(obj))
+ else if (PyBytes_Check(obj) || PyUnicode_Check(obj))
/*pass*/;
else if (PySequence_Check(obj))
tmp = PySequence_GetItem(obj,0);
if (tmp) {
PyErr_Clear();
- if (long_long_from_pyobj(v,tmp,errmess)) {Py_DECREF(tmp); return 1;}
+ if (long_long_from_pyobj(v, tmp, errmess)) {
+ Py_DECREF(tmp);
+ return 1;
+ }
Py_DECREF(tmp);
}
{
PyObject* err = PyErr_Occurred();
- if (err==NULL) err = #modulename#_error;
+ if (err == NULL) {
+ err = #modulename#_error;
+ }
PyErr_SetString(err,errmess);
}
return 0;
}
"""
+
+
needs['long_double_from_pyobj'] = ['double_from_pyobj', 'long_double']
cfuncs['long_double_from_pyobj'] = """\
-static int long_double_from_pyobj(long_double* v,PyObject *obj,const char *errmess) {
+static int
+long_double_from_pyobj(long_double* v, PyObject *obj, const char *errmess)
+{
double d=0;
if (PyArray_CheckScalar(obj)){
if PyArray_IsScalar(obj, LongDouble) {
PyArray_ScalarAsCtype(obj, v);
return 1;
}
- else if (PyArray_Check(obj) && PyArray_TYPE(obj)==NPY_LONGDOUBLE) {
+ else if (PyArray_Check(obj) && PyArray_TYPE(obj) == NPY_LONGDOUBLE) {
(*v) = *((npy_longdouble *)PyArray_DATA(obj));
return 1;
}
}
- if (double_from_pyobj(&d,obj,errmess)) {
+ if (double_from_pyobj(&d, obj, errmess)) {
*v = (long_double)d;
return 1;
}
return 0;
}
"""
+
+
cfuncs['double_from_pyobj'] = """\
-static int double_from_pyobj(double* v,PyObject *obj,const char *errmess) {
+static int
+double_from_pyobj(double* v, PyObject *obj, const char *errmess)
+{
PyObject* tmp = NULL;
if (PyFloat_Check(obj)) {
-#ifdef __sgi
*v = PyFloat_AsDouble(obj);
-#else
- *v = PyFloat_AS_DOUBLE(obj);
-#endif
- return 1;
+ return !(*v == -1.0 && PyErr_Occurred());
}
+
tmp = PyNumber_Float(obj);
if (tmp) {
-#ifdef __sgi
*v = PyFloat_AsDouble(tmp);
-#else
- *v = PyFloat_AS_DOUBLE(tmp);
-#endif
Py_DECREF(tmp);
- return 1;
+ return !(*v == -1.0 && PyErr_Occurred());
}
if (PyComplex_Check(obj))
tmp = PyObject_GetAttrString(obj,\"real\");
- else if (PyString_Check(obj) || PyUnicode_Check(obj))
+ else if (PyBytes_Check(obj) || PyUnicode_Check(obj))
/*pass*/;
else if (PySequence_Check(obj))
tmp = PySequence_GetItem(obj,0);
@@ -885,9 +931,13 @@ static int double_from_pyobj(double* v,PyObject *obj,const char *errmess) {
return 0;
}
"""
+
+
needs['float_from_pyobj'] = ['double_from_pyobj']
cfuncs['float_from_pyobj'] = """\
-static int float_from_pyobj(float* v,PyObject *obj,const char *errmess) {
+static int
+float_from_pyobj(float* v, PyObject *obj, const char *errmess)
+{
double d=0.0;
if (double_from_pyobj(&d,obj,errmess)) {
*v = (float)d;
@@ -896,11 +946,15 @@ static int float_from_pyobj(float* v,PyObject *obj,const char *errmess) {
return 0;
}
"""
+
+
needs['complex_long_double_from_pyobj'] = ['complex_long_double', 'long_double',
'complex_double_from_pyobj']
cfuncs['complex_long_double_from_pyobj'] = """\
-static int complex_long_double_from_pyobj(complex_long_double* v,PyObject *obj,const char *errmess) {
- complex_double cd={0.0,0.0};
+static int
+complex_long_double_from_pyobj(complex_long_double* v, PyObject *obj, const char *errmess)
+{
+ complex_double cd = {0.0,0.0};
if (PyArray_CheckScalar(obj)){
if PyArray_IsScalar(obj, CLongDouble) {
PyArray_ScalarAsCtype(obj, v);
@@ -920,13 +974,17 @@ static int complex_long_double_from_pyobj(complex_long_double* v,PyObject *obj,c
return 0;
}
"""
+
+
needs['complex_double_from_pyobj'] = ['complex_double']
cfuncs['complex_double_from_pyobj'] = """\
-static int complex_double_from_pyobj(complex_double* v,PyObject *obj,const char *errmess) {
+static int
+complex_double_from_pyobj(complex_double* v, PyObject *obj, const char *errmess) {
Py_complex c;
if (PyComplex_Check(obj)) {
- c=PyComplex_AsCComplex(obj);
- (*v).r=c.real, (*v).i=c.imag;
+ c = PyComplex_AsCComplex(obj);
+ (*v).r = c.real;
+ (*v).i = c.imag;
return 1;
}
if (PyArray_IsScalar(obj, ComplexFloating)) {
@@ -955,30 +1013,24 @@ static int complex_double_from_pyobj(complex_double* v,PyObject *obj,const char
else {
arr = PyArray_FromScalar(obj, PyArray_DescrFromType(NPY_CDOUBLE));
}
- if (arr==NULL) return 0;
+ if (arr == NULL) {
+ return 0;
+ }
(*v).r = ((npy_cdouble *)PyArray_DATA(arr))->real;
(*v).i = ((npy_cdouble *)PyArray_DATA(arr))->imag;
return 1;
}
/* Python does not provide PyNumber_Complex function :-( */
- (*v).i=0.0;
+ (*v).i = 0.0;
if (PyFloat_Check(obj)) {
-#ifdef __sgi
(*v).r = PyFloat_AsDouble(obj);
-#else
- (*v).r = PyFloat_AS_DOUBLE(obj);
-#endif
- return 1;
- }
- if (PyInt_Check(obj)) {
- (*v).r = (double)PyInt_AS_LONG(obj);
- return 1;
+ return !((*v).r == -1.0 && PyErr_Occurred());
}
if (PyLong_Check(obj)) {
(*v).r = PyLong_AsDouble(obj);
- return (!PyErr_Occurred());
+ return !((*v).r == -1.0 && PyErr_Occurred());
}
- if (PySequence_Check(obj) && !(PyString_Check(obj) || PyUnicode_Check(obj))) {
+ if (PySequence_Check(obj) && !(PyBytes_Check(obj) || PyUnicode_Check(obj))) {
PyObject *tmp = PySequence_GetItem(obj,0);
if (tmp) {
if (complex_double_from_pyobj(v,tmp,errmess)) {
@@ -997,10 +1049,14 @@ static int complex_double_from_pyobj(complex_double* v,PyObject *obj,const char
return 0;
}
"""
+
+
needs['complex_float_from_pyobj'] = [
'complex_float', 'complex_double_from_pyobj']
cfuncs['complex_float_from_pyobj'] = """\
-static int complex_float_from_pyobj(complex_float* v,PyObject *obj,const char *errmess) {
+static int
+complex_float_from_pyobj(complex_float* v,PyObject *obj,const char *errmess)
+{
complex_double cd={0.0,0.0};
if (complex_double_from_pyobj(&cd,obj,errmess)) {
(*v).r = (float)cd.r;
@@ -1010,6 +1066,8 @@ static int complex_float_from_pyobj(complex_float* v,PyObject *obj,const char *e
return 0;
}
"""
+
+
needs['try_pyarr_from_char'] = ['pyobj_from_char1', 'TRYPYARRAYTEMPLATE']
cfuncs[
'try_pyarr_from_char'] = 'static int try_pyarr_from_char(PyObject* obj,char* v) {\n TRYPYARRAYTEMPLATE(char,\'c\');\n}\n'
@@ -1047,14 +1105,18 @@ needs['try_pyarr_from_complex_double'] = [
cfuncs[
'try_pyarr_from_complex_double'] = 'static int try_pyarr_from_complex_double(PyObject* obj,complex_double* v) {\n TRYCOMPLEXPYARRAYTEMPLATE(double,\'D\');\n}\n'
-needs['create_cb_arglist'] = ['CFUNCSMESS', 'PRINTPYOBJERR', 'MINMAX']
+needs['create_cb_arglist'] = ['CFUNCSMESS', 'PRINTPYOBJERR', 'MINMAX']
# create the list of arguments to be used when calling back to python
cfuncs['create_cb_arglist'] = """\
-static int create_cb_arglist(PyObject* fun,PyTupleObject* xa,const int maxnofargs,const int nofoptargs,int *nofargs,PyTupleObject **args,const char *errmess) {
+static int
+create_cb_arglist(PyObject* fun, PyTupleObject* xa , const int maxnofargs,
+ const int nofoptargs, int *nofargs, PyTupleObject **args,
+ const char *errmess)
+{
PyObject *tmp = NULL;
PyObject *tmp_fun = NULL;
- int tot,opt,ext,siz,i,di=0;
+ Py_ssize_t tot, opt, ext, siz, i, di = 0;
CFUNCSMESS(\"create_cb_arglist\\n\");
tot=opt=ext=siz=0;
/* Get the total number of arguments */
@@ -1103,10 +1165,15 @@ static int create_cb_arglist(PyObject* fun,PyTupleObject* xa,const int maxnofarg
Py_INCREF(tmp_fun);
}
}
-if (tmp_fun==NULL) {
-fprintf(stderr,\"Call-back argument must be function|instance|instance.__call__|f2py-function but got %s.\\n\",(fun==NULL?\"NULL\":Py_TYPE(fun)->tp_name));
-goto capi_fail;
-}
+
+ if (tmp_fun == NULL) {
+ fprintf(stderr,
+ \"Call-back argument must be function|instance|instance.__call__|f2py-function \"
+ \"but got %s.\\n\",
+ ((fun == NULL) ? \"NULL\" : Py_TYPE(fun)->tp_name));
+ goto capi_fail;
+ }
+
if (PyObject_HasAttrString(tmp_fun,\"__code__\")) {
if (PyObject_HasAttrString(tmp = PyObject_GetAttrString(tmp_fun,\"__code__\"),\"co_argcount\")) {
PyObject *tmp_argcount = PyObject_GetAttrString(tmp,\"co_argcount\");
@@ -1114,7 +1181,7 @@ goto capi_fail;
if (tmp_argcount == NULL) {
goto capi_fail;
}
- tot = PyInt_AsLong(tmp_argcount) - di;
+ tot = PyLong_AsSsize_t(tmp_argcount) - di;
Py_DECREF(tmp_argcount);
}
}
@@ -1130,13 +1197,23 @@ goto capi_fail;
/* Calculate the size of call-backs argument list */
siz = MIN(maxnofargs+ext,tot);
*nofargs = MAX(0,siz-ext);
+
#ifdef DEBUGCFUNCS
- fprintf(stderr,\"debug-capi:create_cb_arglist:maxnofargs(-nofoptargs),tot,opt,ext,siz,nofargs=%d(-%d),%d,%d,%d,%d,%d\\n\",maxnofargs,nofoptargs,tot,opt,ext,siz,*nofargs);
+ fprintf(stderr,
+ \"debug-capi:create_cb_arglist:maxnofargs(-nofoptargs),\"
+ \"tot,opt,ext,siz,nofargs = %d(-%d), %zd, %zd, %zd, %zd, %d\\n\",
+ maxnofargs, nofoptargs, tot, opt, ext, siz, *nofargs);
#endif
- if (siz<tot-opt) {
- fprintf(stderr,\"create_cb_arglist: Failed to build argument list (siz) with enough arguments (tot-opt) required by user-supplied function (siz,tot,opt=%d,%d,%d).\\n\",siz,tot,opt);
+
+ if (siz < tot-opt) {
+ fprintf(stderr,
+ \"create_cb_arglist: Failed to build argument list \"
+ \"(siz) with enough arguments (tot-opt) required by \"
+ \"user-supplied function (siz,tot,opt=%zd, %zd, %zd).\\n\",
+ siz, tot, opt);
goto capi_fail;
}
+
/* Initialize argument list */
*args = (PyTupleObject *)PyTuple_New(siz);
for (i=0;i<*nofargs;i++) {
@@ -1152,9 +1229,10 @@ goto capi_fail;
CFUNCSMESS(\"create_cb_arglist-end\\n\");
Py_DECREF(tmp_fun);
return 1;
+
capi_fail:
- if ((PyErr_Occurred())==NULL)
- PyErr_SetString(#modulename#_error,errmess);
+ if (PyErr_Occurred() == NULL)
+ PyErr_SetString(#modulename#_error, errmess);
Py_XDECREF(tmp_fun);
return 0;
}
diff --git a/numpy/f2py/common_rules.py b/numpy/f2py/common_rules.py
index 90483e55b..937d8bc72 100644
--- a/numpy/f2py/common_rules.py
+++ b/numpy/f2py/common_rules.py
@@ -13,8 +13,6 @@ $Date: 2005/05/06 10:57:33 $
Pearu Peterson
"""
-__version__ = "$Revision: 1.19 $"[10:-1]
-
from . import __version__
f2py_version = __version__.version
diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py
index 3d2f97a56..2e95e4596 100755
--- a/numpy/f2py/crackfortran.py
+++ b/numpy/f2py/crackfortran.py
@@ -2103,8 +2103,9 @@ def buildimplicitrules(block):
def myeval(e, g=None, l=None):
+ """ Like `eval` but returns only integers and floats """
r = eval(e, g, l)
- if type(r) in [type(0), type(0.0)]:
+ if type(r) in [int, float]:
return r
raise ValueError('r=%r' % (r))
@@ -2112,6 +2113,26 @@ getlincoef_re_1 = re.compile(r'\A\b\w+\b\Z', re.I)
def getlincoef(e, xset): # e = a*x+b ; x in xset
+ """
+ Obtain ``a`` and ``b`` when ``e == "a*x+b"``, where ``x`` is a symbol in
+ xset.
+
+ >>> getlincoef('2*x + 1', {'x'})
+ (2, 1, 'x')
+ >>> getlincoef('3*x + x*2 + 2 + 1', {'x'})
+ (5, 3, 'x')
+ >>> getlincoef('0', {'x'})
+ (0, 0, None)
+ >>> getlincoef('0*x', {'x'})
+ (0, 0, 'x')
+ >>> getlincoef('x*x', {'x'})
+ (None, None, None)
+
+ This can be tricked by sufficiently complex expressions
+
+ >>> getlincoef('(x - 0.5)*(x - 1.5)*(x - 1)*x + 2*x + 3', {'x'})
+ (2.0, 3.0, 'x')
+ """
try:
c = int(myeval(e, {}, {}))
return 0, c, None
@@ -2166,6 +2187,37 @@ _varname_match = re.compile(r'\A[a-z]\w*\Z').match
def getarrlen(dl, args, star='*'):
+ """
+ Parameters
+ ----------
+ dl : sequence of two str objects
+ dimensions of the array
+ args : Iterable[str]
+ symbols used in the expression
+ star : Any
+ unused
+
+ Returns
+ -------
+ expr : str
+ Some numeric expression as a string
+ arg : Optional[str]
+ If understood, the argument from `args` present in `expr`
+ expr2 : Optional[str]
+ If understood, an expression fragment that should be used as
+ ``"(%s%s".format(something, expr2)``.
+
+ Examples
+ --------
+ >>> getarrlen(['10*x + 20', '40*x'], {'x'})
+ ('30 * x - 19', 'x', '+19)/(30)')
+ >>> getarrlen(['1', '10*x + 20'], {'x'})
+ ('10 * x + 20', 'x', '-20)/(10)')
+ >>> getarrlen(['10*x + 20', '1'], {'x'})
+ ('-10 * x - 18', 'x', '+18)/(-10)')
+ >>> getarrlen(['20', '1'], {'x'})
+ ('-18', None, None)
+ """
edl = []
try:
edl.append(myeval(dl[0], {}, {}))
diff --git a/numpy/f2py/f2py2e.py b/numpy/f2py/f2py2e.py
index 71a049e41..b45d985aa 100755
--- a/numpy/f2py/f2py2e.py
+++ b/numpy/f2py/f2py2e.py
@@ -29,18 +29,14 @@ from . import __version__
from . import capi_maps
f2py_version = __version__.version
+numpy_version = __version__.version
errmess = sys.stderr.write
# outmess=sys.stdout.write
show = pprint.pprint
outmess = auxfuncs.outmess
-try:
- from numpy import __version__ as numpy_version
-except ImportError:
- numpy_version = 'N/A'
-
-__usage__ = """\
-Usage:
+__usage__ =\
+f"""Usage:
1) To construct extension module sources:
@@ -97,8 +93,8 @@ Options:
--[no-]latex-doc Create (or not) <modulename>module.tex.
Default is --no-latex-doc.
--short-latex Create 'incomplete' LaTeX document (without commands
- \\documentclass, \\tableofcontents, and \\begin{document},
- \\end{document}).
+ \\documentclass, \\tableofcontents, and \\begin{{document}},
+ \\end{{document}}).
--[no-]rest-doc Create (or not) <modulename>module.rst.
Default is --no-rest-doc.
@@ -167,12 +163,12 @@ Extra options (only effective with -c):
array. Integer <int> sets the threshold for array sizes when
a message should be shown.
-Version: %s
-numpy Version: %s
+Version: {f2py_version}
+numpy Version: {numpy_version}
Requires: Python 3.5 or higher.
License: NumPy license (see LICENSE.txt in the NumPy source code)
Copyright 1999 - 2011 Pearu Peterson all rights reserved.
-http://cens.ioc.ee/projects/f2py2e/""" % (f2py_version, numpy_version)
+http://cens.ioc.ee/projects/f2py2e/"""
def scaninputline(inputline):
@@ -604,7 +600,7 @@ def run_compile():
if modulename:
break
- extra_objects, sources = filter_files('', '[.](o|a|so)', sources)
+ extra_objects, sources = filter_files('', '[.](o|a|so|dylib)', sources)
include_dirs, sources = filter_files('-I', '', sources, remove_prefix=1)
library_dirs, sources = filter_files('-L', '', sources, remove_prefix=1)
libraries, sources = filter_files('-l', '', sources, remove_prefix=1)
@@ -650,7 +646,9 @@ def run_compile():
sys.argv.extend(['build',
'--build-temp', build_dir,
'--build-base', build_dir,
- '--build-platlib', '.'])
+ '--build-platlib', '.',
+ # disable CCompilerOpt
+ '--disable-optimization'])
if fc_flags:
sys.argv.extend(['config_fc'] + fc_flags)
if flib_flags:
diff --git a/numpy/f2py/rules.py b/numpy/f2py/rules.py
index 56f2033ff..f1490527e 100755
--- a/numpy/f2py/rules.py
+++ b/numpy/f2py/rules.py
@@ -50,18 +50,15 @@ $Date: 2005/08/30 08:58:42 $
Pearu Peterson
"""
-__version__ = "$Revision: 1.129 $"[10:-1]
-
-from . import __version__
-f2py_version = __version__.version
-
-from .. import version as _numpy_version
-numpy_version = _numpy_version.version
-
import os
import time
import copy
+# __version__.version is now the same as the NumPy version
+from . import __version__
+f2py_version = __version__.version
+numpy_version = __version__.version
+
from .auxfuncs import (
applyrules, debugcapi, dictappend, errmess, gentitle, getargs2,
hascallstatement, hasexternals, hasinitvalue, hasnote, hasresultnote,
@@ -202,7 +199,7 @@ PyMODINIT_FUNC PyInit_#modulename#(void) {
\tif (PyErr_Occurred())
\t\t{PyErr_SetString(PyExc_ImportError, \"can't initialize module #modulename# (failed to import numpy)\"); return m;}
\td = PyModule_GetDict(m);
-\ts = PyString_FromString(\"$R""" + """evision: $\");
+\ts = PyUnicode_FromString(\"#f2py_version#\");
\tPyDict_SetItemString(d, \"__version__\", s);
\tPy_DECREF(s);
\ts = PyUnicode_FromString(
diff --git a/numpy/f2py/setup.py b/numpy/f2py/setup.py
index 80b47e527..0a35db477 100644
--- a/numpy/f2py/setup.py
+++ b/numpy/f2py/setup.py
@@ -30,6 +30,7 @@ def configuration(parent_package='', top_path=None):
config.add_data_files(
'src/fortranobject.c',
'src/fortranobject.h')
+ config.add_data_files('*.pyi')
return config
diff --git a/numpy/f2py/src/fortranobject.c b/numpy/f2py/src/fortranobject.c
index aa46c57d0..3275f90ad 100644
--- a/numpy/f2py/src/fortranobject.c
+++ b/numpy/f2py/src/fortranobject.c
@@ -213,6 +213,8 @@ format_def(char *buf, Py_ssize_t size, FortranDataDef def)
return -1;
}
memcpy(p, notalloc, sizeof(notalloc));
+ p += sizeof(notalloc);
+ size -= sizeof(notalloc);
}
return p - buf;
@@ -255,7 +257,7 @@ fortran_doc(FortranDataDef def)
}
else {
PyArray_Descr *d = PyArray_DescrFromType(def.type);
- n = PyOS_snprintf(p, size, "'%c'-", d->type);
+ n = PyOS_snprintf(p, size, "%s : '%c'-", def.name, d->type);
Py_DECREF(d);
if (n < 0 || n >= size) {
goto fail;
@@ -264,7 +266,7 @@ fortran_doc(FortranDataDef def)
size -= n;
if (def.data == NULL) {
- n = format_def(p, size, def) == -1;
+ n = format_def(p, size, def);
if (n < 0) {
goto fail;
}
@@ -288,6 +290,7 @@ fortran_doc(FortranDataDef def)
p += n;
size -= n;
}
+
}
if (size <= 1) {
goto fail;
diff --git a/numpy/f2py/src/test/foomodule.c b/numpy/f2py/src/test/foomodule.c
index caf3590d4..88ec62440 100644
--- a/numpy/f2py/src/test/foomodule.c
+++ b/numpy/f2py/src/test/foomodule.c
@@ -121,7 +121,7 @@ void initfoo() {
m = Py_InitModule("foo", foo_module_methods);
d = PyModule_GetDict(m);
- s = PyString_FromString("This module 'foo' demonstrates the usage of fortranobject.");
+ s = PyUnicode_FromString("This module 'foo' demonstrates the usage of fortranobject.");
PyDict_SetItemString(d, "__doc__", s);
/* Fortran objects: */
diff --git a/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c b/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c
index 0db33e714..0411b62e0 100644
--- a/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c
+++ b/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c
@@ -1,14 +1,9 @@
-/* File: wrapmodule.c
- * This file is auto-generated with f2py (version:2_1330).
- * Hand edited by Pearu.
- * f2py is a Fortran to Python Interface Generator (FPIG), Second Edition,
- * written by Pearu Peterson <pearu@cens.ioc.ee>.
- * See http://cens.ioc.ee/projects/f2py2e/
- * Generation date: Fri Oct 21 22:41:12 2005
- * $Revision:$
- * $Date:$
- * Do not edit this file directly unless you know what you are doing!!!
+/*
+ * 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
@@ -55,7 +50,7 @@ static PyObject *f2py_rout_wrap_call(PyObject *capi_self,
if (tmp == NULL) {
goto fail;
}
- dims[i] = (npy_intp)PyInt_AsLong(tmp);
+ dims[i] = (npy_intp)PyLong_AsLong(tmp);
Py_DECREF(tmp);
if (dims[i] == -1 && PyErr_Occurred()) {
goto fail;
@@ -107,8 +102,8 @@ static PyObject *f2py_rout_wrap_attrs(PyObject *capi_self,
dimensions = PyTuple_New(PyArray_NDIM(arr));
strides = PyTuple_New(PyArray_NDIM(arr));
for (i=0;i<PyArray_NDIM(arr);++i) {
- PyTuple_SetItem(dimensions,i,PyInt_FromLong(PyArray_DIM(arr,i)));
- PyTuple_SetItem(strides,i,PyInt_FromLong(PyArray_STRIDE(arr,i)));
+ 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,
@@ -149,15 +144,15 @@ PyMODINIT_FUNC PyInit_test_array_from_pyobj_ext(void) {
if (PyErr_Occurred())
Py_FatalError("can't initialize module wrap (failed to import numpy)");
d = PyModule_GetDict(m);
- s = PyString_FromString("This module 'wrap' is auto-generated with f2py (version:2_1330).\nFunctions:\n"
-" arr = call(type_num,dims,intent,obj)\n"
-".");
+ 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 = PyInt_FromLong(CONST); \
+ s = PyLong_FromLong(CONST); \
PyDict_SetItemString(d, NAME, s); \
Py_DECREF(s)
diff --git a/numpy/f2py/tests/src/module_data/mod.mod b/numpy/f2py/tests/src/module_data/mod.mod
new file mode 100644
index 000000000..8670a97e9
--- /dev/null
+++ b/numpy/f2py/tests/src/module_data/mod.mod
Binary files differ
diff --git a/numpy/f2py/tests/src/module_data/module_data_docstring.f90 b/numpy/f2py/tests/src/module_data/module_data_docstring.f90
new file mode 100644
index 000000000..4505e0cbc
--- /dev/null
+++ b/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/numpy/f2py/tests/test_block_docstring.py b/numpy/f2py/tests/test_block_docstring.py
index e431f5ba6..7d725165b 100644
--- a/numpy/f2py/tests/test_block_docstring.py
+++ b/numpy/f2py/tests/test_block_docstring.py
@@ -19,5 +19,5 @@ class TestBlockDocString(util.F2PyTest):
@pytest.mark.xfail(IS_PYPY,
reason="PyPy cannot modify tp_doc after PyType_Ready")
def test_block_docstring(self):
- expected = "'i'-array(2,3)\n"
+ expected = "bar : 'i'-array(2,3)\n"
assert_equal(self.module.block.__doc__, expected)
diff --git a/numpy/f2py/tests/test_module_doc.py b/numpy/f2py/tests/test_module_doc.py
new file mode 100644
index 000000000..4b9555cee
--- /dev/null
+++ b/numpy/f2py/tests/test_module_doc.py
@@ -0,0 +1,30 @@
+import os
+import sys
+import pytest
+import textwrap
+
+from . import util
+from numpy.testing import assert_equal, IS_PYPY
+
+
+def _path(*a):
+ return os.path.join(*((os.path.dirname(__file__),) + a))
+
+
+class TestModuleDocString(util.F2PyTest):
+ sources = [_path('src', 'module_data', 'module_data_docstring.f90')]
+
+ @pytest.mark.skipif(sys.platform=='win32',
+ reason='Fails with MinGW64 Gfortran (Issue #9673)')
+ @pytest.mark.xfail(IS_PYPY,
+ reason="PyPy cannot modify tp_doc after PyType_Ready")
+ def test_module_docstring(self):
+ assert_equal(self.module.mod.__doc__,
+ textwrap.dedent('''\
+ i : 'i'-scalar
+ x : 'i'-array(4)
+ a : 'f'-array(2,3)
+ b : 'f'-array(-1,-1), not allocated\x00
+ foo()\n
+ Wrapper for ``foo``.\n\n''')
+ )
diff --git a/numpy/f2py/tests/util.py b/numpy/f2py/tests/util.py
index c5b06697d..d5fa76fed 100644
--- a/numpy/f2py/tests/util.py
+++ b/numpy/f2py/tests/util.py
@@ -19,8 +19,6 @@ from numpy.compat import asbytes, asstr
from numpy.testing import temppath
from importlib import import_module
-from hashlib import md5
-
#
# Maintaining a temporary module directory
#