diff options
author | Charles Harris <charlesr.harris@gmail.com> | 2017-05-03 11:00:28 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-03 11:00:28 -0600 |
commit | 1d592c12ca7f9c7f471aa8d20b538c5cb4f2cdce (patch) | |
tree | 42db2edf05c0d6c6fb3c43f33f39370c1dbe0705 | |
parent | 43914a4421fbabdd63a1cb73ef4c48d626498aaa (diff) | |
parent | 7dbdbfaaa19c84ffcfa2987a05ca603483dfa54f (diff) | |
download | numpy-1d592c12ca7f9c7f471aa8d20b538c5cb4f2cdce.tar.gz |
Merge pull request #8948 from juliantaylor/deprecate-NPY_CHAR
DEP: Deprecate NPY_CHAR
-rw-r--r-- | doc/release/1.13.0-notes.rst | 3 | ||||
-rw-r--r-- | numpy/core/include/numpy/ndarraytypes.h | 15 | ||||
-rw-r--r-- | numpy/core/src/multiarray/arraytypes.c.src | 12 | ||||
-rw-r--r-- | numpy/core/src/multiarray/multiarray_tests.c.src | 11 | ||||
-rw-r--r-- | numpy/core/tests/test_deprecations.py | 8 | ||||
-rw-r--r-- | numpy/f2py/capi_maps.py | 9 | ||||
-rw-r--r-- | numpy/f2py/cfuncs.py | 3 | ||||
-rw-r--r-- | numpy/f2py/src/fortranobject.c | 28 | ||||
-rw-r--r-- | numpy/f2py/tests/src/string/char.f90 | 29 | ||||
-rw-r--r-- | numpy/f2py/tests/test_string.py | 26 |
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() |