summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/release/1.13.0-notes.rst3
-rw-r--r--numpy/core/include/numpy/ndarraytypes.h15
-rw-r--r--numpy/core/src/multiarray/arraytypes.c.src12
-rw-r--r--numpy/core/src/multiarray/multiarray_tests.c.src11
-rw-r--r--numpy/core/tests/test_deprecations.py8
-rw-r--r--numpy/f2py/capi_maps.py9
-rw-r--r--numpy/f2py/cfuncs.py3
-rw-r--r--numpy/f2py/src/fortranobject.c28
-rw-r--r--numpy/f2py/tests/src/string/char.f9029
-rw-r--r--numpy/f2py/tests/test_string.py26
10 files changed, 132 insertions, 12 deletions
diff --git a/doc/release/1.13.0-notes.rst b/doc/release/1.13.0-notes.rst
index 5362dc091..48b9adc9b 100644
--- a/doc/release/1.13.0-notes.rst
+++ b/doc/release/1.13.0-notes.rst
@@ -25,6 +25,9 @@ Deprecations
* Calling ``np.fix``, ``np.isposinf``, and ``np.isneginf`` with ``f(x, y=out)``
is deprecated - the argument should be passed as ``f(x, out=out)``, which
matches other ufunc-like interfaces.
+* Use of the C-API ``NPY_CHAR`` type number deprecated since version 1.7 will
+ now raise deprecation warnings at runtime. Extensions built with older f2py
+ versions need to be recompiled to remove the warning.
Build System Changes
diff --git a/numpy/core/include/numpy/ndarraytypes.h b/numpy/core/include/numpy/ndarraytypes.h
index 7f6fe6524..e0df189f9 100644
--- a/numpy/core/include/numpy/ndarraytypes.h
+++ b/numpy/core/include/numpy/ndarraytypes.h
@@ -15,7 +15,17 @@
#define NPY_ALLOW_THREADS 0
#endif
+#ifndef __has_extension
+#define __has_extension(x) 0
+#endif
+#if !defined(_NPY_NO_DEPRECATIONS) && \
+ ((defined(__GNUC__)&& __GNUC__ >= 6) || \
+ __has_extension(attribute_deprecated_with_message))
+#define NPY_ATTR_DEPRECATE(text) __attribute__ ((deprecated (text)))
+#else
+#define NPY_ATTR_DEPRECATE(text)
+#endif
/*
* There are several places in the code where an array of dimensions
@@ -71,12 +81,15 @@ enum NPY_TYPES { NPY_BOOL=0,
NPY_NTYPES,
NPY_NOTYPE,
- NPY_CHAR, /* special flag */
+ NPY_CHAR NPY_ATTR_DEPRECATE("Use NPY_STRING"),
NPY_USERDEF=256, /* leave room for characters */
/* The number of types not including the new 1.6 types */
NPY_NTYPES_ABI_COMPATIBLE=21
};
+#ifdef _MSC_VER
+#pragma deprecated(NPY_CHAR)
+#endif
/* basetype array priority */
#define NPY_PRIORITY 0.0
diff --git a/numpy/core/src/multiarray/arraytypes.c.src b/numpy/core/src/multiarray/arraytypes.c.src
index 49d6ae1d2..b11134305 100644
--- a/numpy/core/src/multiarray/arraytypes.c.src
+++ b/numpy/core/src/multiarray/arraytypes.c.src
@@ -6,6 +6,7 @@
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
#define _MULTIARRAYMODULE
+#define _NPY_NO_DEPRECATIONS /* for NPY_CHAR */
#include "numpy/npy_common.h"
#include "numpy/arrayobject.h"
@@ -4415,6 +4416,17 @@ PyArray_DescrFromType(int type)
return NULL;
}
else if ((type == NPY_CHAR) || (type == NPY_CHARLTR)) {
+ if (type == NPY_CHAR) {
+ /*
+ * warning added 2017-04-25, 1.13
+ * deprecated in 1.7
+ * */
+ if (DEPRECATE("The NPY_CHAR type_num is deprecated. "
+ "Please port your code to use "
+ "NPY_STRING instead.") < 0) {
+ return NULL;
+ }
+ }
ret = PyArray_DescrNew(_builtin_descrs[NPY_STRING]);
if (ret == NULL) {
return NULL;
diff --git a/numpy/core/src/multiarray/multiarray_tests.c.src b/numpy/core/src/multiarray/multiarray_tests.c.src
index 45092dc0c..de05cc280 100644
--- a/numpy/core/src/multiarray/multiarray_tests.c.src
+++ b/numpy/core/src/multiarray/multiarray_tests.c.src
@@ -1,6 +1,7 @@
/* -*-c-*- */
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
#include <Python.h>
+#define _NPY_NO_DEPRECATIONS /* for NPY_CHAR */
#include "numpy/arrayobject.h"
#include "mem_overlap.h"
#include "npy_extint128.h"
@@ -608,6 +609,13 @@ incref_elide_l(PyObject *dummy, PyObject *args)
return res;
}
+/* used to test NPY_CHAR usage emits deprecation warning */
+static PyObject*
+npy_char_deprecation(PyObject* NPY_UNUSED(self), PyObject* NPY_UNUSED(args))
+{
+ PyArray_Descr * descr = PyArray_DescrFromType(NPY_CHAR);
+ return (PyObject *)descr;
+}
#if !defined(NPY_PY3K)
static PyObject *
@@ -1576,6 +1584,9 @@ static PyMethodDef Multiarray_TestsMethods[] = {
{"incref_elide_l",
incref_elide_l,
METH_VARARGS, NULL},
+ {"npy_char_deprecation",
+ npy_char_deprecation,
+ METH_NOARGS, NULL},
#if !defined(NPY_PY3K)
{"test_int_subclass",
int_subclass,
diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py
index 46b2c79aa..8e35f7e54 100644
--- a/numpy/core/tests/test_deprecations.py
+++ b/numpy/core/tests/test_deprecations.py
@@ -421,5 +421,13 @@ class TestClassicIntDivision(_DeprecationTestCase):
dt2 = dt1
+class TestNPY_CHAR(_DeprecationTestCase):
+ # 2017-05-03, 1.13.0
+ def test_npy_char_deprecation(self):
+ from numpy.core.multiarray_tests import npy_char_deprecation
+ self.assert_deprecated(npy_char_deprecation)
+ assert_(npy_char_deprecation() == 'S1')
+
+
if __name__ == "__main__":
run_module_suite()
diff --git a/numpy/f2py/capi_maps.py b/numpy/f2py/capi_maps.py
index 441629faa..5b2e6a9b9 100644
--- a/numpy/f2py/capi_maps.py
+++ b/numpy/f2py/capi_maps.py
@@ -65,7 +65,7 @@ c2py_map = {'double': 'float',
c2capi_map = {'double': 'NPY_DOUBLE',
'float': 'NPY_FLOAT',
'long_double': 'NPY_DOUBLE', # forced casting
- 'char': 'NPY_CHAR',
+ 'char': 'NPY_STRING',
'unsigned_char': 'NPY_UBYTE',
'signed_char': 'NPY_BYTE',
'short': 'NPY_SHORT',
@@ -77,7 +77,7 @@ c2capi_map = {'double': 'NPY_DOUBLE',
'complex_float': 'NPY_CFLOAT',
'complex_double': 'NPY_CDOUBLE',
'complex_long_double': 'NPY_CDOUBLE', # forced casting
- 'string': 'NPY_CHAR'}
+ 'string': 'NPY_STRING'}
# These new maps aren't used anyhere yet, but should be by default
# unless building numeric or numarray extensions.
@@ -99,10 +99,7 @@ if using_newcore:
'complex_float': 'NPY_CFLOAT',
'complex_double': 'NPY_CDOUBLE',
'complex_long_double': 'NPY_CDOUBLE',
- # f2py 2e is not ready for NPY_STRING (must set itemisize
- # etc)
- 'string': 'NPY_CHAR',
- #'string':'NPY_STRING'
+ 'string':'NPY_STRING'
}
c2pycode_map = {'double': 'd',
diff --git a/numpy/f2py/cfuncs.py b/numpy/f2py/cfuncs.py
index 0d0a52764..1632a0d47 100644
--- a/numpy/f2py/cfuncs.py
+++ b/numpy/f2py/cfuncs.py
@@ -1153,8 +1153,9 @@ def buildcfuncs():
m] = '#define %s(v) (PyArray_SimpleNewFromData(0,NULL,%s,(char *)v))' % (m, c2capi_map[k])
k = 'string'
m = 'pyarr_from_p_%s1' % k
+ # NPY_CHAR compatibility, NPY_STRING with itemsize 1
cppmacros[
- m] = '#define %s(v,dims) (PyArray_SimpleNewFromData(1,dims,NPY_CHAR,(char *)v))' % (m)
+ m] = '#define %s(v,dims) (PyArray_New(&PyArray_Type, 1, dims, NPY_STRING, NULL, v, 1, NPY_ARRAY_CARRAY, NULL))' % (m)
############ Auxiliary functions for sorting needs ###################
diff --git a/numpy/f2py/src/fortranobject.c b/numpy/f2py/src/fortranobject.c
index 9024dd5b3..0209cb1be 100644
--- a/numpy/f2py/src/fortranobject.c
+++ b/numpy/f2py/src/fortranobject.c
@@ -691,7 +691,7 @@ PyArrayObject* array_from_pyobj(const int type_num,
}
arr = (PyArrayObject *)
PyArray_New(&PyArray_Type, rank, dims, type_num,
- NULL,NULL,0,
+ NULL,NULL,1,
!(intent&F2PY_INTENT_C),
NULL);
if (arr==NULL) return NULL;
@@ -701,6 +701,15 @@ PyArrayObject* array_from_pyobj(const int type_num,
}
descr = PyArray_DescrFromType(type_num);
+ /* compatibility with NPY_CHAR */
+ if (type_num == NPY_STRING) {
+ PyArray_DESCR_REPLACE(descr);
+ if (descr == NULL) {
+ return NULL;
+ }
+ descr->elsize = 1;
+ descr->type = NPY_CHARLTR;
+ }
elsize = descr->elsize;
typechar = descr->type;
Py_DECREF(descr);
@@ -781,9 +790,10 @@ PyArrayObject* array_from_pyobj(const int type_num,
/* here we have always intent(in) or intent(inplace) */
{
- PyArrayObject *retarr = (PyArrayObject *) \
+ PyArrayObject * retarr;
+ retarr = (PyArrayObject *) \
PyArray_New(&PyArray_Type, PyArray_NDIM(arr), PyArray_DIMS(arr), type_num,
- NULL,NULL,0,
+ NULL,NULL,1,
!(intent&F2PY_INTENT_C),
NULL);
if (retarr==NULL)
@@ -816,9 +826,19 @@ PyArrayObject* array_from_pyobj(const int type_num,
}
{
+ PyArray_Descr * descr = PyArray_DescrFromType(type_num);
+ /* compatibility with NPY_CHAR */
+ if (type_num == NPY_STRING) {
+ PyArray_DESCR_REPLACE(descr);
+ if (descr == NULL) {
+ return NULL;
+ }
+ descr->elsize = 1;
+ descr->type = NPY_CHARLTR;
+ }
F2PY_REPORT_ON_ARRAY_COPY_FROMANY;
arr = (PyArrayObject *) \
- PyArray_FromAny(obj,PyArray_DescrFromType(type_num), 0,0,
+ PyArray_FromAny(obj, descr, 0,0,
((intent & F2PY_INTENT_C)?NPY_ARRAY_CARRAY:NPY_ARRAY_FARRAY) \
| NPY_ARRAY_FORCECAST, NULL);
if (arr==NULL)
diff --git a/numpy/f2py/tests/src/string/char.f90 b/numpy/f2py/tests/src/string/char.f90
new file mode 100644
index 000000000..bb7985ce5
--- /dev/null
+++ b/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/numpy/f2py/tests/test_string.py b/numpy/f2py/tests/test_string.py
new file mode 100644
index 000000000..10022ebb1
--- /dev/null
+++ b/numpy/f2py/tests/test_string.py
@@ -0,0 +1,26 @@
+from __future__ import division, absolute_import, print_function
+
+import os
+
+from numpy.testing import run_module_suite, assert_array_equal, dec
+import numpy as np
+import util
+
+
+def _path(*a):
+ return os.path.join(*((os.path.dirname(__file__),) + a))
+
+class TestString(util.F2PyTest):
+ sources = [_path('src', 'string', 'char.f90')]
+
+ @dec.slow
+ def test_char(self):
+ strings = np.array(['ab', 'cd', 'ef'], dtype='c').T
+ inp, out = self.module.char_test.change_strings(strings, strings.shape[1])
+ assert_array_equal(inp, strings)
+ expected = strings.copy()
+ expected[1, :] = 'AAA'
+ assert_array_equal(out, expected)
+
+if __name__ == "__main__":
+ run_module_suite()