diff options
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/include/numpy/ndarraytypes.h | 37 | ||||
-rw-r--r-- | numpy/core/include/numpy/npy_1_7_deprecated_api.h (renamed from numpy/core/include/numpy/npy_deprecated_api.h) | 21 | ||||
-rw-r--r-- | numpy/core/setup.py | 2 | ||||
-rw-r--r-- | numpy/core/src/multiarray/mapping.c | 4 | ||||
-rw-r--r-- | numpy/core/src/umath/ufunc_object.c | 4 | ||||
-rw-r--r-- | numpy/core/tests/test_indexing.py | 23 | ||||
-rw-r--r-- | numpy/lib/format.py | 2 | ||||
-rw-r--r-- | numpy/lib/function_base.py | 7 | ||||
-rw-r--r-- | numpy/lib/tests/test_function_base.py | 11 |
9 files changed, 82 insertions, 29 deletions
diff --git a/numpy/core/include/numpy/ndarraytypes.h b/numpy/core/include/numpy/ndarraytypes.h index bb3f1065c..fc8dca950 100644 --- a/numpy/core/include/numpy/ndarraytypes.h +++ b/numpy/core/include/numpy/ndarraytypes.h @@ -627,8 +627,8 @@ typedef struct _arr_descr { * (PyArray_DATA and friends) to access fields here for a number of * releases. Direct access to the members themselves is deprecated. * To ensure that your code does not use deprecated access, - * #define NPY_NO_DEPRECATED_API NPY_1_7_VERSION - * (or NPY_1_8_VERSION or higher as required). + * #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION + * (or NPY_1_8_API_VERSION or higher as required). */ /* This struct will be moved to a private header in a future release */ typedef struct tagPyArrayObject_fields { @@ -675,7 +675,8 @@ typedef struct tagPyArrayObject_fields { * To hide the implementation details, we only expose * the Python struct HEAD. */ -#if !(defined(NPY_NO_DEPRECATED_API) && (NPY_API_VERSION <= NPY_NO_DEPRECATED_API)) +#if !defined(NPY_NO_DEPRECATED_API) || \ + (NPY_NO_DEPRECATED_API < NPY_1_7_API_VERSION) /* * Can't put this in npy_deprecated_api.h like the others. * PyArrayObject field access is deprecated as of NumPy 1.7. @@ -921,6 +922,8 @@ typedef int (PyArray_FinalizeFunc)(PyArrayObject *, PyObject *); #define NPY_BEGIN_THREADS_DEF PyThreadState *_save=NULL; #define NPY_BEGIN_THREADS do {_save = PyEval_SaveThread();} while (0); #define NPY_END_THREADS do {if (_save) PyEval_RestoreThread(_save);} while (0); +#define NPY_BEGIN_THREADS_THRESHOLDED(loop_size) do { if (loop_size > 500) \ + { _save = PyEval_SaveThread();} } while (0); #define NPY_BEGIN_THREADS_DESCR(dtype) \ do {if (!(PyDataType_FLAGCHK(dtype, NPY_NEEDS_PYAPI))) \ @@ -1383,7 +1386,7 @@ PyArrayNeighborhoodIter_Next2D(PyArrayNeighborhoodIterObject* iter); #define PyArray_FORTRAN_IF(m) ((PyArray_CHKFLAGS(m, NPY_ARRAY_F_CONTIGUOUS) ? \ NPY_ARRAY_F_CONTIGUOUS : 0)) -#if (defined(NPY_NO_DEPRECATED_API) && (NPY_API_VERSION <= NPY_NO_DEPRECATED_API)) +#if (defined(NPY_NO_DEPRECATED_API) && (NPY_1_7_API_VERSION <= NPY_NO_DEPRECATED_API)) /* * Changing access macros into functions, to allow for future hiding * of the internal memory layout. This later hiding will allow the 2.x series @@ -1732,8 +1735,30 @@ typedef struct { typedef void (PyDataMem_EventHookFunc)(void *inp, void *outp, size_t size, void *user_data); -#if !(defined(NPY_NO_DEPRECATED_API) && (NPY_API_VERSION <= NPY_NO_DEPRECATED_API)) -#include "npy_deprecated_api.h" +/* + * Use the keyword NPY_DEPRECATED_INCLUDES to ensure that the header files + * npy_*_*_deprecated_api.h are only included from here and nowhere else. + */ +#ifdef NPY_DEPRECATED_INCLUDES +#error "Do not use the reserved keyword NPY_DEPRECATED_INCLUDES." #endif +#define NPY_DEPRECATED_INCLUDES +#if !defined(NPY_NO_DEPRECATED_API) || \ + (NPY_NO_DEPRECATED_API < NPY_1_7_API_VERSION) +#include "npy_1_7_deprecated_api.h" +#endif +/* + * There is no file npy_1_8_deprecated_api.h since there are no additional + * deprecated API features in NumPy 1.8. + * + * Note to maintainers: insert code like the following in future NumPy + * versions. + * + * #if !defined(NPY_NO_DEPRECATED_API) || \ + * (NPY_NO_DEPRECATED_API < NPY_1_9_API_VERSION) + * #include "npy_1_9_deprecated_api.h" + * #endif + */ +#undef NPY_DEPRECATED_INCLUDES #endif /* NPY_ARRAYTYPES_H */ diff --git a/numpy/core/include/numpy/npy_deprecated_api.h b/numpy/core/include/numpy/npy_1_7_deprecated_api.h index f082d0827..6c576d138 100644 --- a/numpy/core/include/numpy/npy_deprecated_api.h +++ b/numpy/core/include/numpy/npy_1_7_deprecated_api.h @@ -1,28 +1,30 @@ -#ifndef _NPY_DEPRECATED_API_H -#define _NPY_DEPRECATED_API_H +#ifndef _NPY_1_7_DEPRECATED_API_H +#define _NPY_1_7_DEPRECATED_API_H + +#ifndef NPY_DEPRECATED_INCLUDES +#error "Should never include npy_*_*_deprecated_api directly." +#endif #if defined(_WIN32) #define _WARN___STR2__(x) #x #define _WARN___STR1__(x) _WARN___STR2__(x) #define _WARN___LOC__ __FILE__ "("_WARN___STR1__(__LINE__)") : Warning Msg: " #pragma message(_WARN___LOC__"Using deprecated NumPy API, disable it by " \ - "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION") + "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION") #elif defined(__GNUC__) -#warning "Using deprecated NumPy API, disable it by #defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" +#warning "Using deprecated NumPy API, disable it by " \ + "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" #endif /* TODO: How to do this warning message for other compilers? */ /* - * This header exists to collect all dangerous/deprecated NumPy API. + * This header exists to collect all dangerous/deprecated NumPy API + * as of NumPy 1.7. * * This is an attempt to remove bad API, the proliferation of macros, * and namespace pollution currently produced by the NumPy headers. */ -#if defined(NPY_NO_DEPRECATED_API) -#error Should never include npy_deprecated_api directly. -#endif - /* These array flags are deprecated as of NumPy 1.7 */ #define NPY_CONTIGUOUS NPY_ARRAY_C_CONTIGUOUS #define NPY_FORTRAN NPY_ARRAY_F_CONTIGUOUS @@ -125,5 +127,4 @@ */ #include "old_defines.h" - #endif diff --git a/numpy/core/setup.py b/numpy/core/setup.py index 05e20a09a..0c58abfa7 100644 --- a/numpy/core/setup.py +++ b/numpy/core/setup.py @@ -766,7 +766,7 @@ def configuration(parent_package='',top_path=None): join('include', 'numpy', 'npy_cpu.h'), join('include', 'numpy', 'numpyconfig.h'), join('include', 'numpy', 'ndarraytypes.h'), - join('include', 'numpy', 'npy_deprecated_api.h'), + join('include', 'numpy', 'npy_1_7_deprecated_api.h'), join('include', 'numpy', '_numpyconfig.h.in'), ] diff --git a/numpy/core/src/multiarray/mapping.c b/numpy/core/src/multiarray/mapping.c index 8b3e5b5a9..25f3dad9b 100644 --- a/numpy/core/src/multiarray/mapping.c +++ b/numpy/core/src/multiarray/mapping.c @@ -806,8 +806,7 @@ array_ass_boolean_subscript(PyArrayObject *self, } /* Tweak the strides for 0-dim and broadcasting cases */ - if (PyArray_NDIM(v) > 0 && PyArray_DIMS(v)[0] > 1) { - v_stride = PyArray_STRIDES(v)[0]; + if (PyArray_NDIM(v) > 0 && PyArray_DIMS(v)[0] != 1) { if (size != PyArray_DIMS(v)[0]) { PyErr_Format(PyExc_ValueError, "NumPy boolean array indexing assignment " @@ -816,6 +815,7 @@ array_ass_boolean_subscript(PyArrayObject *self, (int)PyArray_DIMS(v)[0], (int)size); return -1; } + v_stride = PyArray_STRIDES(v)[0]; } else { v_stride = 0; diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c index c3d804b2a..bea15c65c 100644 --- a/numpy/core/src/umath/ufunc_object.c +++ b/numpy/core/src/umath/ufunc_object.c @@ -1098,7 +1098,7 @@ trivial_two_operand_loop(PyArrayObject **op, NPY_UF_DBG_PRINT1("two operand loop count %d\n", (int)count[0]); if (!needs_api) { - NPY_BEGIN_THREADS; + NPY_BEGIN_THREADS_THRESHOLDED(count[0]); } innerloop(data, count, stride, innerloopdata); @@ -1131,7 +1131,7 @@ trivial_three_operand_loop(PyArrayObject **op, NPY_UF_DBG_PRINT1("three operand loop count %d\n", (int)count[0]); if (!needs_api) { - NPY_BEGIN_THREADS; + NPY_BEGIN_THREADS_THRESHOLDED(count[0]); } innerloop(data, count, stride, innerloopdata); diff --git a/numpy/core/tests/test_indexing.py b/numpy/core/tests/test_indexing.py index fa44900c7..3c74bc466 100644 --- a/numpy/core/tests/test_indexing.py +++ b/numpy/core/tests/test_indexing.py @@ -84,7 +84,7 @@ class TestIndexing(TestCase): assert_equal(a[np.array(False)], a[0]) def test_boolean_indexing_onedim(self): - # Indexing a 2-dimensional array with + # Indexing a 2-dimensional array with # boolean array of length one a = np.array([[ 0., 0., 0.]]) b = np.array([ True], dtype=bool) @@ -93,8 +93,19 @@ class TestIndexing(TestCase): a[b] = 1. assert_equal(a, [[1., 1., 1.]]) + def test_boolean_assignment_value_mismatch(self): + # A boolean assignment should fail when the shape of the values + # cannot be broadcasted to the subscription. (see also gh-3458) + a = np.arange(4) + def f(a, v): + a[a > -1] = v + + assert_raises(ValueError, f, a, []) + assert_raises(ValueError, f, a, [1, 2, 3]) + assert_raises(ValueError, f, a[:1], [1, 2, 3]) + def test_boolean_indexing_twodim(self): - # Indexing a 2-dimensional array with + # Indexing a 2-dimensional array with # 2-dimensional boolean array a = np.array([[1, 2, 3], [4 ,5, 6], @@ -116,7 +127,7 @@ class TestIndexing(TestCase): class TestMultiIndexingAutomated(TestCase): """ These test use code to mimic the C-Code indexing for selection. - + NOTE: * This still lacks tests for complex item setting. * If you change behavoir of indexing, you might want to modify these tests to try more combinations. @@ -160,7 +171,7 @@ class TestMultiIndexingAutomated(TestCase): def _get_multi_index(self, arr, indices): """Mimic multi dimensional indexing. - + Parameters ---------- arr : ndarray @@ -185,7 +196,7 @@ class TestMultiIndexingAutomated(TestCase): in_indices = list(indices) indices = [] # if False, this is a fancy or boolean index - no_copy = True + no_copy = True # number of fancy/scalar indexes that are not consecutive num_fancy = 0 # number of dimensions indexed by a "fancy" index @@ -487,7 +498,7 @@ class TestMultiIndexingAutomated(TestCase): self._check_multi_index(self.b, index) # Check very simple item getting: self._check_multi_index(self.a, (0,0,0,0)) - self._check_multi_index(self.b, (0,0,0,0)) + self._check_multi_index(self.b, (0,0,0,0)) # Also check (simple cases of) too many indices: assert_raises(IndexError, self.a.__getitem__, (0,0,0,0,0)) assert_raises(IndexError, self.a.__setitem__, (0,0,0,0,0), 0) diff --git a/numpy/lib/format.py b/numpy/lib/format.py index ff3b95d6e..fd459e84e 100644 --- a/numpy/lib/format.py +++ b/numpy/lib/format.py @@ -35,7 +35,7 @@ Capabilities - Is straightforward to reverse engineer. Datasets often live longer than the programs that created them. A competent developer should be - able create a solution in his preferred programming language to + able to create a solution in his preferred programming language to read most ``.npy`` files that he has been given without much documentation. diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index 5e433d3ab..17f99a065 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -3696,6 +3696,11 @@ def insert(arr, obj, values, axis=None): arr = arr.ravel() ndim = arr.ndim axis = ndim-1 + else: + if ndim > 0 and (axis < -ndim or axis >= ndim): + raise IndexError("axis %i is out of bounds for an array " + "of dimension %i" % (axis, ndim)) + if (axis < 0): axis += ndim if (ndim == 0): warnings.warn("in the future the special handling of scalars " "will be removed from insert and raise an error", @@ -3742,7 +3747,7 @@ def insert(arr, obj, values, axis=None): # broadcasting is very different here, since a[:,0,:] = ... behaves # very different from a[:,[0],:] = ...! This changes values so that # it works likes the second case. (here a[:,0:1,:]) - values = np.rollaxis(values, 0, axis+1) + values = np.rollaxis(values, 0, axis + 1) numnew = values.shape[axis] newshape[axis] += numnew new = empty(newshape, arr.dtype, arr.flags.fnc) diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index a23e406e3..de561e55a 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -211,6 +211,17 @@ class TestInsert(TestCase): assert_equal(insert(a[:,:1], 1, a[:,1], axis=1), a) assert_equal(insert(a[:1,:], 1, a[1,:], axis=0), a) + # negative axis value + a = np.arange(24).reshape((2,3,4)) + assert_equal(insert(a, 1, a[:,:,3], axis=-1), + insert(a, 1, a[:,:,3], axis=2)) + assert_equal(insert(a, 1, a[:,2,:], axis=-2), + insert(a, 1, a[:,2,:], axis=1)) + + # invalid axis value + assert_raises(IndexError, insert, a, 1, a[:,2,:], axis=3) + assert_raises(IndexError, insert, a, 1, a[:,2,:], axis=-4) + def test_0d(self): # This is an error in the future a = np.array(1) |