summaryrefslogtreecommitdiff
path: root/numpy/core
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/core')
-rw-r--r--numpy/core/code_generators/cversions.txt3
-rw-r--r--numpy/core/code_generators/numpy_api.py2
-rw-r--r--numpy/core/include/numpy/numpyconfig.h1
-rw-r--r--numpy/core/numerictypes.py50
-rw-r--r--numpy/core/setup_common.py4
-rw-r--r--numpy/core/src/multiarray/_multiarray_tests.c.src73
-rw-r--r--numpy/core/src/multiarray/arrayobject.c186
-rw-r--r--numpy/core/src/multiarray/einsum.c.src2
-rw-r--r--numpy/core/src/multiarray/nditer_api.c60
-rw-r--r--numpy/core/src/multiarray/nditer_constr.c23
-rw-r--r--numpy/core/src/multiarray/nditer_pywrap.c104
-rw-r--r--numpy/core/src/multiarray/scalartypes.c.src14
-rw-r--r--numpy/core/src/umath/ufunc_object.c231
-rw-r--r--numpy/core/tests/test_deprecations.py8
-rw-r--r--numpy/core/tests/test_nditer.py13
-rw-r--r--numpy/core/tests/test_numerictypes.py6
-rw-r--r--numpy/core/tests/test_regression.py16
-rw-r--r--numpy/core/tests/test_ufunc.py21
18 files changed, 302 insertions, 515 deletions
diff --git a/numpy/core/code_generators/cversions.txt b/numpy/core/code_generators/cversions.txt
index cc6c3a5fb..43c32eac6 100644
--- a/numpy/core/code_generators/cversions.txt
+++ b/numpy/core/code_generators/cversions.txt
@@ -39,8 +39,7 @@
0x0000000b = edb1ba83730c650fd9bc5772a919cda7
# Version 12 (NumPy 1.14) Added PyArray_ResolveWritebackIfCopy,
+# Version 12 (NumPy 1.15) No change.
# PyArray_SetWritebackIfCopyBase and deprecated PyArray_SetUpdateIfCopyBase.
0x0000000c = a1bc756c5782853ec2e3616cf66869d8
-# Version 13 (NumPy 1.15) Added NpyIter_Close
-0x0000000d = 4386e829d65aafce6bd09a85b142d585
diff --git a/numpy/core/code_generators/numpy_api.py b/numpy/core/code_generators/numpy_api.py
index 6cfbbbcc7..d8a9ee6b4 100644
--- a/numpy/core/code_generators/numpy_api.py
+++ b/numpy/core/code_generators/numpy_api.py
@@ -350,8 +350,6 @@ multiarray_funcs_api = {
'PyArray_ResolveWritebackIfCopy': (302,),
'PyArray_SetWritebackIfCopyBase': (303,),
# End 1.14 API
- 'NpyIter_Close': (304,),
- # End 1.15 API
}
ufunc_types_api = {
diff --git a/numpy/core/include/numpy/numpyconfig.h b/numpy/core/include/numpy/numpyconfig.h
index 04a3738b9..ab198f36b 100644
--- a/numpy/core/include/numpy/numpyconfig.h
+++ b/numpy/core/include/numpy/numpyconfig.h
@@ -36,5 +36,6 @@
#define NPY_1_12_API_VERSION 0x00000008
#define NPY_1_13_API_VERSION 0x00000008
#define NPY_1_14_API_VERSION 0x00000008
+#define NPY_1_15_API_VERSION 0x00000008
#endif
diff --git a/numpy/core/numerictypes.py b/numpy/core/numerictypes.py
index 7cd80f432..727fb66d1 100644
--- a/numpy/core/numerictypes.py
+++ b/numpy/core/numerictypes.py
@@ -323,31 +323,37 @@ def _add_aliases():
# insert bit-width version for this class (if relevant)
base, bit, char = bitname(info.type)
- if base != '':
- myname = "%s%d" % (base, bit)
- if (name not in ('longdouble', 'clongdouble') or
- myname not in allTypes):
- base_capitalize = english_capitalize(base)
- if base == 'complex':
- na_name = '%s%d' % (base_capitalize, bit//2)
- elif base == 'bool':
- na_name = base_capitalize
- else:
- na_name = "%s%d" % (base_capitalize, bit)
- allTypes[myname] = info.type
+ assert base != ''
+ myname = "%s%d" % (base, bit)
+
+ # ensure that (c)longdouble does not overwrite the aliases assigned to
+ # (c)double
+ if name in ('longdouble', 'clongdouble') and myname in allTypes:
+ continue
+
+ base_capitalize = english_capitalize(base)
+ if base == 'complex':
+ na_name = '%s%d' % (base_capitalize, bit//2)
+ elif base == 'bool':
+ na_name = base_capitalize
+ else:
+ na_name = "%s%d" % (base_capitalize, bit)
+
+ allTypes[myname] = info.type
+
+ # add mapping for both the bit name and the numarray name
+ sctypeDict[myname] = info.type
+ sctypeDict[na_name] = info.type
- # add mapping for both the bit name and the numarray name
- sctypeDict[myname] = info.type
- sctypeDict[na_name] = info.type
+ # add forward, reverse, and string mapping to numarray
+ sctypeNA[na_name] = info.type
+ sctypeNA[info.type] = na_name
+ sctypeNA[info.char] = na_name
- # add forward, reverse, and string mapping to numarray
- sctypeNA[na_name] = info.type
- sctypeNA[info.type] = na_name
- sctypeNA[info.char] = na_name
- if char != '':
- sctypeDict[char] = info.type
- sctypeNA[char] = na_name
+ assert char != ''
+ sctypeDict[char] = info.type
+ sctypeNA[char] = na_name
_add_aliases()
def _add_integer_aliases():
diff --git a/numpy/core/setup_common.py b/numpy/core/setup_common.py
index 70a43046c..356482b07 100644
--- a/numpy/core/setup_common.py
+++ b/numpy/core/setup_common.py
@@ -40,8 +40,8 @@ C_ABI_VERSION = 0x01000009
# 0x0000000a - 1.12.x
# 0x0000000b - 1.13.x
# 0x0000000c - 1.14.x
-# 0x0000000d - 1.15.x
-C_API_VERSION = 0x0000000d
+# 0x0000000c - 1.15.x
+C_API_VERSION = 0x0000000c
class MismatchCAPIWarning(Warning):
pass
diff --git a/numpy/core/src/multiarray/_multiarray_tests.c.src b/numpy/core/src/multiarray/_multiarray_tests.c.src
index cba96a4c2..67c9a333c 100644
--- a/numpy/core/src/multiarray/_multiarray_tests.c.src
+++ b/numpy/core/src/multiarray/_multiarray_tests.c.src
@@ -1042,76 +1042,6 @@ test_nditer_too_large(PyObject *NPY_UNUSED(self), PyObject *args) {
}
static PyObject *
-test_nditer_writeback(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
-{
- /* like npyiter_init */
- PyObject *op_in = NULL, *op_dtypes_in = NULL, *value = NULL;
- PyArrayObject * opview;
- int iop, nop = 0;
- PyArrayObject *op[NPY_MAXARGS];
- npy_uint32 flags = 0;
- NPY_ORDER order = NPY_KEEPORDER;
- NPY_CASTING casting = NPY_EQUIV_CASTING;
- npy_uint32 op_flags[NPY_MAXARGS];
- PyArray_Descr *op_request_dtypes[NPY_MAXARGS];
- int retval;
- unsigned char do_close;
- int buffersize = 0;
- NpyIter *iter = NULL;
- static char *kwlist[] = {"value", "do_close", "input", "op_dtypes", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds,
- "ObO|O:test_nditer_writeback", kwlist,
- &value,
- &do_close,
- &op_in,
- &op_dtypes_in)) {
- return NULL;
- }
- /* op and op_flags */
- if (! PyArray_Check(op_in)) {
- return NULL;
- }
- nop = 1;
- op[0] = (PyArrayObject*)op_in;
- op_flags[0] = NPY_ITER_READWRITE|NPY_ITER_UPDATEIFCOPY;
-
- /* Set the dtypes */
- for (iop=0; iop<nop; iop++) {
- PyObject *dtype = PySequence_GetItem(op_dtypes_in, iop);
- PyArray_DescrConverter2(dtype, &op_request_dtypes[iop]);
- }
-
- iter = NpyIter_AdvancedNew(nop, op, flags, order, casting, op_flags,
- op_request_dtypes,
- -1, NULL, NULL,
- buffersize);
- if (iter == NULL) {
- goto fail;
- }
-
- opview = NpyIter_GetIterView(iter, 0);
- retval = PyArray_FillWithScalar(opview, value);
- Py_DECREF(opview);
- if (retval < 0) {
- NpyIter_Deallocate(iter);
- return NULL;
- }
- if (do_close != 0) {
- NpyIter_Close(iter);
- }
- NpyIter_Deallocate(iter);
- Py_RETURN_NONE;
-
-fail:
- for (iop = 0; iop < nop; ++iop) {
- Py_XDECREF(op[iop]);
- Py_XDECREF(op_request_dtypes[iop]);
- }
- return NULL;
-}
-
-static PyObject *
array_solve_diophantine(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
{
PyObject *A = NULL;
@@ -1948,9 +1878,6 @@ static PyMethodDef Multiarray_TestsMethods[] = {
{"test_nditer_too_large",
test_nditer_too_large,
METH_VARARGS, NULL},
- {"test_nditer_writeback",
- (PyCFunction)test_nditer_writeback,
- METH_VARARGS | METH_KEYWORDS, NULL},
{"solve_diophantine",
(PyCFunction)array_solve_diophantine,
METH_VARARGS | METH_KEYWORDS, NULL},
diff --git a/numpy/core/src/multiarray/arrayobject.c b/numpy/core/src/multiarray/arrayobject.c
index 943edc772..368f5ded7 100644
--- a/numpy/core/src/multiarray/arrayobject.c
+++ b/numpy/core/src/multiarray/arrayobject.c
@@ -482,8 +482,7 @@ array_dealloc(PyArrayObject *self)
{
char const * msg = "WRITEBACKIFCOPY detected in array_dealloc. "
" Required call to PyArray_ResolveWritebackIfCopy or "
- "PyArray_DiscardWritebackIfCopy is missing. This could also "
- "be caused by using a nditer without a context manager";
+ "PyArray_DiscardWritebackIfCopy is missing.";
Py_INCREF(self); /* hold on to self in next call since if
* refcount == 0 it will recurse back into
*array_dealloc
@@ -1250,7 +1249,8 @@ PyArray_ChainExceptionsCause(PyObject *exc, PyObject *val, PyObject *tb)
}
}
-/* Silence the current error and emit a deprecation warning instead.
+/*
+ * Silence the current error and emit a deprecation warning instead.
*
* If warnings are raised as errors, this sets the warning __cause__ to the
* silenced error.
@@ -1269,6 +1269,118 @@ DEPRECATE_silence_error(const char *msg) {
return 0;
}
+/*
+ * Comparisons can fail, but we do not always want to pass on the exception
+ * (see comment in array_richcompare below), but rather return NotImplemented.
+ * Here, an exception should be set on entrance.
+ * Returns either NotImplemented with the exception cleared, or NULL
+ * with the exception set.
+ * Raises deprecation warnings for cases where behaviour is meant to change
+ * (2015-05-14, 1.10)
+ */
+
+NPY_NO_EXPORT PyObject *
+_failed_comparison_workaround(PyArrayObject *self, PyObject *other, int cmp_op)
+{
+ PyObject *exc, *val, *tb;
+ PyArrayObject *array_other;
+ int other_is_flexible, ndim_other;
+ int self_is_flexible = PyTypeNum_ISFLEXIBLE(PyArray_DESCR(self)->type_num);
+
+ PyErr_Fetch(&exc, &val, &tb);
+ /*
+ * Determine whether other has a flexible dtype; here, inconvertible
+ * is counted as inflexible. (This repeats work done in the ufunc,
+ * but OK to waste some time in an unlikely path.)
+ */
+ array_other = (PyArrayObject *)PyArray_FROM_O(other);
+ if (array_other) {
+ other_is_flexible = PyTypeNum_ISFLEXIBLE(
+ PyArray_DESCR(array_other)->type_num);
+ ndim_other = PyArray_NDIM(array_other);
+ Py_DECREF(array_other);
+ }
+ else {
+ PyErr_Clear(); /* we restore the original error if needed */
+ other_is_flexible = 0;
+ ndim_other = 0;
+ }
+ if (cmp_op == Py_EQ || cmp_op == Py_NE) {
+ /*
+ * note: for == and !=, a structured dtype self cannot get here,
+ * but a string can. Other can be string or structured.
+ */
+ if (other_is_flexible || self_is_flexible) {
+ /*
+ * For scalars, returning NotImplemented is correct.
+ * For arrays, we emit a future deprecation warning.
+ * When this warning is removed, a correctly shaped
+ * array of bool should be returned.
+ */
+ if (ndim_other != 0 || PyArray_NDIM(self) != 0) {
+ /* 2015-05-14, 1.10 */
+ if (DEPRECATE_FUTUREWARNING(
+ "elementwise comparison failed; returning scalar "
+ "instead, but in the future will perform "
+ "elementwise comparison") < 0) {
+ goto fail;
+ }
+ }
+ }
+ else {
+ /*
+ * If neither self nor other had a flexible dtype, the error cannot
+ * have been caused by a lack of implementation in the ufunc.
+ *
+ * 2015-05-14, 1.10
+ */
+ if (DEPRECATE(
+ "elementwise comparison failed; "
+ "this will raise an error in the future.") < 0) {
+ goto fail;
+ }
+ }
+ Py_XDECREF(exc);
+ Py_XDECREF(val);
+ Py_XDECREF(tb);
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ else if (other_is_flexible || self_is_flexible) {
+ /*
+ * For LE, LT, GT, GE and a flexible self or other, we return
+ * NotImplemented, which is the correct answer since the ufuncs do
+ * not in fact implement loops for those. On python 3 this will
+ * get us the desired TypeError, but on python 2, one gets strange
+ * ordering, so we emit a warning.
+ */
+#if !defined(NPY_PY3K)
+ /* 2015-05-14, 1.10 */
+ if (DEPRECATE(
+ "unorderable dtypes; returning scalar but in "
+ "the future this will be an error") < 0) {
+ goto fail;
+ }
+#endif
+ Py_XDECREF(exc);
+ Py_XDECREF(val);
+ Py_XDECREF(tb);
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ else {
+ /* LE, LT, GT, or GE with non-flexible other; just pass on error */
+ goto fail;
+ }
+
+fail:
+ /*
+ * Reraise the original exception, possibly chaining with a new one.
+ */
+ PyArray_ChainExceptionsCause(exc, val, tb);
+ return NULL;
+}
+
NPY_NO_EXPORT PyObject *
array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
{
@@ -1366,26 +1478,6 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
result = PyArray_GenericBinaryFunction(self,
(PyObject *)other,
n_ops.equal);
- /*
- * If the comparison results in NULL, then the
- * two array objects can not be compared together;
- * indicate that
- */
- if (result == NULL) {
- /*
- * Comparisons should raise errors when element-wise comparison
- * is not possible.
- */
- /* 2015-05-14, 1.10 */
- if (DEPRECATE_silence_error(
- "elementwise == comparison failed; "
- "this will raise an error in the future.") < 0) {
- return NULL;
- }
-
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
break;
case Py_NE:
RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
@@ -1437,21 +1529,6 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
result = PyArray_GenericBinaryFunction(self, (PyObject *)other,
n_ops.not_equal);
- if (result == NULL) {
- /*
- * Comparisons should raise errors when element-wise comparison
- * is not possible.
- */
- /* 2015-05-14, 1.10 */
- if (DEPRECATE_silence_error(
- "elementwise != comparison failed; "
- "this will raise an error in the future.") < 0) {
- return NULL;
- }
-
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
break;
case Py_GT:
RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
@@ -1464,8 +1541,37 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
n_ops.greater_equal);
break;
default:
- result = Py_NotImplemented;
- Py_INCREF(result);
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ if (result == NULL) {
+ /*
+ * 2015-05-14, 1.10; updated 2018-06-18, 1.16.
+ *
+ * Comparisons can raise errors when element-wise comparison is not
+ * possible. Some of these, though, should not be passed on.
+ * In particular, the ufuncs do not have loops for flexible dtype,
+ * so those should be treated separately. Furthermore, for EQ and NE,
+ * we should never fail.
+ *
+ * Our ideal behaviour would be:
+ *
+ * 1. For EQ and NE:
+ * - If self and other are scalars, return NotImplemented,
+ * so that python can assign True of False as appropriate.
+ * - If either is an array, return an array of False or True.
+ *
+ * 2. For LT, LE, GE, GT:
+ * - If self or other was flexible, return NotImplemented
+ * (as is in fact the case), so python can raise a TypeError.
+ * - If other is not convertible to an array, pass on the error
+ * (MHvK, 2018-06-18: not sure about this, but it's what we have).
+ *
+ * However, for backwards compatibilty, we cannot yet return arrays,
+ * so we raise warnings instead. Furthermore, we warn on python2
+ * for LT, LE, GE, GT, since fall-back behaviour is poorly defined.
+ */
+ result = _failed_comparison_workaround(self, other, cmp_op);
}
return result;
}
diff --git a/numpy/core/src/multiarray/einsum.c.src b/numpy/core/src/multiarray/einsum.c.src
index 039bcc15e..33184d99a 100644
--- a/numpy/core/src/multiarray/einsum.c.src
+++ b/numpy/core/src/multiarray/einsum.c.src
@@ -2857,7 +2857,6 @@ PyArray_EinsteinSum(char *subscripts, npy_intp nop,
iternext = NpyIter_GetIterNext(iter, NULL);
if (iternext == NULL) {
- NpyIter_Close(iter);
NpyIter_Deallocate(iter);
Py_DECREF(ret);
goto fail;
@@ -2881,7 +2880,6 @@ PyArray_EinsteinSum(char *subscripts, npy_intp nop,
}
finish:
- NpyIter_Close(iter);
NpyIter_Deallocate(iter);
for (iop = 0; iop < nop; ++iop) {
Py_DECREF(op[iop]);
diff --git a/numpy/core/src/multiarray/nditer_api.c b/numpy/core/src/multiarray/nditer_api.c
index ba9e9f273..7a33ac05e 100644
--- a/numpy/core/src/multiarray/nditer_api.c
+++ b/numpy/core/src/multiarray/nditer_api.c
@@ -1381,47 +1381,6 @@ NpyIter_GetInnerLoopSizePtr(NpyIter *iter)
}
/*NUMPY_API
- * Resolves all writebackifcopy scratch buffers, not safe to use iterator
- * operands after this call, in this iterator as well as any copies.
- * Returns 0 on success, -1 on failure
- */
-NPY_NO_EXPORT int
-NpyIter_Close(NpyIter *iter)
-{
- int ret=0, iop, nop;
- PyArrayObject ** operands;
- npyiter_opitflags *op_itflags;
- if (iter == NULL) {
- return 0;
- }
- nop = NIT_NOP(iter);
- operands = NIT_OPERANDS(iter);
- op_itflags = NIT_OPITFLAGS(iter);
- /* If NPY_OP_ITFLAG_HAS_WRITEBACK flag set on operand, resolve it.
- * If the resolution fails (should never happen), continue from the
- * next operand and discard the writeback scratch buffers, and return
- * failure status
- */
- for (iop=0; iop<nop; iop++) {
- if (op_itflags[iop] & NPY_OP_ITFLAG_HAS_WRITEBACK) {
- op_itflags[iop] &= ~NPY_OP_ITFLAG_HAS_WRITEBACK;
- if (PyArray_ResolveWritebackIfCopy(operands[iop]) < 0) {
- ret = -1;
- iop++;
- break;
- }
- }
- }
- for (; iop<nop; iop++) {
- if (op_itflags[iop] & NPY_OP_ITFLAG_HAS_WRITEBACK) {
- op_itflags[iop] &= ~NPY_OP_ITFLAG_HAS_WRITEBACK;
- PyArray_DiscardWritebackIfCopy(operands[iop]);
- }
- }
- return ret;
-}
-
-/*NUMPY_API
* For debugging
*/
NPY_NO_EXPORT void
@@ -2830,4 +2789,23 @@ npyiter_checkreducesize(NpyIter *iter, npy_intp count,
}
return count * (*reduce_innersize);
}
+
+NPY_NO_EXPORT npy_bool
+npyiter_has_writeback(NpyIter *iter)
+{
+ int iop, nop;
+ npyiter_opitflags *op_itflags;
+ if (iter == NULL) {
+ return 0;
+ }
+ nop = NIT_NOP(iter);
+ op_itflags = NIT_OPITFLAGS(iter);
+
+ for (iop=0; iop<nop; iop++) {
+ if (op_itflags[iop] & NPY_OP_ITFLAG_HAS_WRITEBACK) {
+ return NPY_TRUE;
+ }
+ }
+ return NPY_FALSE;
+}
#undef NPY_ITERATOR_IMPLEMENTATION_CODE
diff --git a/numpy/core/src/multiarray/nditer_constr.c b/numpy/core/src/multiarray/nditer_constr.c
index b07137858..c56376f58 100644
--- a/numpy/core/src/multiarray/nditer_constr.c
+++ b/numpy/core/src/multiarray/nditer_constr.c
@@ -403,7 +403,6 @@ NpyIter_AdvancedNew(int nop, PyArrayObject **op_in, npy_uint32 flags,
*/
if (!npyiter_allocate_arrays(iter, flags, op_dtype, subtype, op_flags,
op_itflags, op_axes)) {
- NpyIter_Close(iter);
NpyIter_Deallocate(iter);
return NULL;
}
@@ -465,14 +464,12 @@ NpyIter_AdvancedNew(int nop, PyArrayObject **op_in, npy_uint32 flags,
/* If buffering is set without delayed allocation */
if (itflags & NPY_ITFLAG_BUFFER) {
if (!npyiter_allocate_transfer_functions(iter)) {
- NpyIter_Close(iter);
NpyIter_Deallocate(iter);
return NULL;
}
if (!(itflags & NPY_ITFLAG_DELAYBUF)) {
/* Allocate the buffers */
if (!npyiter_allocate_buffers(iter, NULL)) {
- NpyIter_Close(iter);
NpyIter_Deallocate(iter);
return NULL;
}
@@ -654,6 +651,8 @@ NpyIter_Deallocate(NpyIter *iter)
int iop, nop;
PyArray_Descr **dtype;
PyArrayObject **object;
+ npyiter_opitflags *op_itflags;
+ npy_bool resolve = 1;
if (iter == NULL) {
return NPY_SUCCEED;
@@ -663,6 +662,7 @@ NpyIter_Deallocate(NpyIter *iter)
nop = NIT_NOP(iter);
dtype = NIT_DTYPES(iter);
object = NIT_OPERANDS(iter);
+ op_itflags = NIT_OPITFLAGS(iter);
/* Deallocate any buffers and buffering data */
if (itflags & NPY_ITFLAG_BUFFER) {
@@ -691,15 +691,28 @@ NpyIter_Deallocate(NpyIter *iter)
}
}
- /* Deallocate all the dtypes and objects that were iterated */
+ /*
+ * Deallocate all the dtypes and objects that were iterated and resolve
+ * any writeback buffers created by the iterator
+ */
for(iop = 0; iop < nop; ++iop, ++dtype, ++object) {
+ if (op_itflags[iop] & NPY_OP_ITFLAG_HAS_WRITEBACK) {
+ if (resolve && PyArray_ResolveWritebackIfCopy(*object) < 0) {
+ resolve = 0;
+ }
+ else {
+ PyArray_DiscardWritebackIfCopy(*object);
+ }
+ }
Py_XDECREF(*dtype);
Py_XDECREF(*object);
}
/* Deallocate the iterator memory */
PyObject_Free(iter);
-
+ if (resolve == 0) {
+ return NPY_FAIL;
+ }
return NPY_SUCCEED;
}
diff --git a/numpy/core/src/multiarray/nditer_pywrap.c b/numpy/core/src/multiarray/nditer_pywrap.c
index 0b6c80c8a..5a9f3c5fa 100644
--- a/numpy/core/src/multiarray/nditer_pywrap.c
+++ b/numpy/core/src/multiarray/nditer_pywrap.c
@@ -1,5 +1,5 @@
/*
- * This file implements the CPython wrapper of the new NumPy iterator.
+ * This file implements the CPython wrapper of NpyIter
*
* Copyright (c) 2010 by Mark Wiebe (mwwiebe@gmail.com)
* The University of British Columbia
@@ -19,6 +19,10 @@
#include "common.h"
#include "ctors.h"
+/* Functions not part of the public NumPy C API */
+npy_bool npyiter_has_writeback(NpyIter *iter);
+
+
typedef struct NewNpyArrayIterObject_tag NewNpyArrayIterObject;
struct NewNpyArrayIterObject_tag {
@@ -27,8 +31,6 @@ struct NewNpyArrayIterObject_tag {
NpyIter *iter;
/* Flag indicating iteration started/stopped */
char started, finished;
- /* iter operands cannot be referenced if iter is closed */
- npy_bool is_closed;
/* Child to update for nested iteration */
NewNpyArrayIterObject *nested_child;
/* Cached values from the iterator */
@@ -88,7 +90,6 @@ npyiter_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
if (self != NULL) {
self->iter = NULL;
self->nested_child = NULL;
- self->is_closed = 0;
}
return (PyObject *)self;
@@ -1173,10 +1174,29 @@ fail:
return NULL;
}
+
static void
npyiter_dealloc(NewNpyArrayIterObject *self)
{
if (self->iter) {
+ if (npyiter_has_writeback(self->iter)) {
+ if (PyErr_WarnEx(PyExc_RuntimeWarning,
+ "Temporary data has not been written back to one of the "
+ "operands. Typically nditer is used as a context manager "
+ "otherwise 'close' must be called before reading iteration "
+ "results.", 1) < 0) {
+ PyObject *s;
+
+ s = PyUString_FromString("npyiter_dealloc");
+ if (s) {
+ PyErr_WriteUnraisable(s);
+ Py_DECREF(s);
+ }
+ else {
+ PyErr_WriteUnraisable(Py_None);
+ }
+ }
+ }
NpyIter_Deallocate(self->iter);
self->iter = NULL;
Py_XDECREF(self->nested_child);
@@ -1418,12 +1438,6 @@ static PyObject *npyiter_value_get(NewNpyArrayIterObject *self)
ret = npyiter_seq_item(self, 0);
}
else {
- if (self->is_closed) {
- PyErr_SetString(PyExc_ValueError,
- "Iterator is closed");
- return NULL;
- }
-
ret = PyTuple_New(nop);
if (ret == NULL) {
return NULL;
@@ -1453,12 +1467,6 @@ static PyObject *npyiter_operands_get(NewNpyArrayIterObject *self)
"Iterator is invalid");
return NULL;
}
- if (self->is_closed) {
- PyErr_SetString(PyExc_ValueError,
- "Iterator is closed");
- return NULL;
- }
-
nop = NpyIter_GetNOp(self->iter);
operands = self->operands;
@@ -1487,13 +1495,6 @@ static PyObject *npyiter_itviews_get(NewNpyArrayIterObject *self)
"Iterator is invalid");
return NULL;
}
-
- if (self->is_closed) {
- PyErr_SetString(PyExc_ValueError,
- "Iterator is closed");
- return NULL;
- }
-
nop = NpyIter_GetNOp(self->iter);
ret = PyTuple_New(nop);
@@ -1517,7 +1518,7 @@ static PyObject *
npyiter_next(NewNpyArrayIterObject *self)
{
if (self->iter == NULL || self->iternext == NULL ||
- self->finished || self->is_closed) {
+ self->finished) {
return NULL;
}
@@ -1911,13 +1912,6 @@ static PyObject *npyiter_dtypes_get(NewNpyArrayIterObject *self)
"Iterator is invalid");
return NULL;
}
-
- if (self->is_closed) {
- PyErr_SetString(PyExc_ValueError,
- "Iterator is closed");
- return NULL;
- }
-
nop = NpyIter_GetNOp(self->iter);
ret = PyTuple_New(nop);
@@ -2011,13 +2005,6 @@ npyiter_seq_item(NewNpyArrayIterObject *self, Py_ssize_t i)
"and no reset has been done yet");
return NULL;
}
-
- if (self->is_closed) {
- PyErr_SetString(PyExc_ValueError,
- "Iterator is closed");
- return NULL;
- }
-
nop = NpyIter_GetNOp(self->iter);
/* Negative indexing */
@@ -2090,13 +2077,6 @@ npyiter_seq_slice(NewNpyArrayIterObject *self,
"and no reset has been done yet");
return NULL;
}
-
- if (self->is_closed) {
- PyErr_SetString(PyExc_ValueError,
- "Iterator is closed");
- return NULL;
- }
-
nop = NpyIter_GetNOp(self->iter);
if (ilow < 0) {
ilow = 0;
@@ -2156,13 +2136,6 @@ npyiter_seq_ass_item(NewNpyArrayIterObject *self, Py_ssize_t i, PyObject *v)
"and no reset has been done yet");
return -1;
}
-
- if (self->is_closed) {
- PyErr_SetString(PyExc_ValueError,
- "Iterator is closed");
- return -1;
- }
-
nop = NpyIter_GetNOp(self->iter);
/* Negative indexing */
@@ -2234,13 +2207,6 @@ npyiter_seq_ass_slice(NewNpyArrayIterObject *self, Py_ssize_t ilow,
"and no reset has been done yet");
return -1;
}
-
- if (self->is_closed) {
- PyErr_SetString(PyExc_ValueError,
- "Iterator is closed");
- return -1;
- }
-
nop = NpyIter_GetNOp(self->iter);
if (ilow < 0) {
ilow = 0;
@@ -2292,12 +2258,6 @@ npyiter_subscript(NewNpyArrayIterObject *self, PyObject *op)
return NULL;
}
- if (self->is_closed) {
- PyErr_SetString(PyExc_ValueError,
- "Iterator is closed");
- return NULL;
- }
-
if (PyInt_Check(op) || PyLong_Check(op) ||
(PyIndex_Check(op) && !PySequence_Check(op))) {
npy_intp i = PyArray_PyIntAsIntp(op);
@@ -2347,12 +2307,6 @@ npyiter_ass_subscript(NewNpyArrayIterObject *self, PyObject *op,
return -1;
}
- if (self->is_closed) {
- PyErr_SetString(PyExc_ValueError,
- "Iterator is closed");
- return -1;
- }
-
if (PyInt_Check(op) || PyLong_Check(op) ||
(PyIndex_Check(op) && !PySequence_Check(op))) {
npy_intp i = PyArray_PyIntAsIntp(op);
@@ -2387,10 +2341,6 @@ npyiter_enter(NewNpyArrayIterObject *self)
PyErr_SetString(PyExc_RuntimeError, "operation on non-initialized iterator");
return NULL;
}
- if (self->is_closed) {
- PyErr_SetString(PyExc_ValueError, "cannot reuse closed iterator");
- return NULL;
- }
Py_INCREF(self);
return (PyObject *)self;
}
@@ -2403,8 +2353,8 @@ npyiter_close(NewNpyArrayIterObject *self)
if (self->iter == NULL) {
Py_RETURN_NONE;
}
- ret = NpyIter_Close(iter);
- self->is_closed = 1;
+ ret = NpyIter_Deallocate(iter);
+ self->iter = NULL;
if (ret < 0) {
return NULL;
}
diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src
index 25e0668ed..a32aa47ab 100644
--- a/numpy/core/src/multiarray/scalartypes.c.src
+++ b/numpy/core/src/multiarray/scalartypes.c.src
@@ -1675,16 +1675,6 @@ gentype_itemset(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args))
return NULL;
}
-static PyObject *
-gentype_squeeze(PyObject *self, PyObject *args)
-{
- if (!PyArg_ParseTuple(args, "")) {
- return NULL;
- }
- Py_INCREF(self);
- return self;
-}
-
static Py_ssize_t
gentype_getreadbuf(PyObject *, Py_ssize_t, void **);
@@ -1738,7 +1728,7 @@ gentype_byteswap(PyObject *self, PyObject *args, PyObject *kwds)
* std, var, sum, cumsum, prod, cumprod, compress, sort, argsort,
* round, argmax, argmin, max, min, ptp, any, all, astype, resize,
* reshape, choose, tostring, tobytes, copy, searchsorted, view,
- * flatten, ravel#
+ * flatten, ravel, squeeze#
*/
static PyObject *
gentype_@name@(PyObject *self, PyObject *args, PyObject *kwds)
@@ -2121,7 +2111,7 @@ static PyMethodDef gentype_methods[] = {
METH_VARARGS | METH_KEYWORDS, NULL},
{"squeeze",
(PyCFunction)gentype_squeeze,
- METH_VARARGS, NULL},
+ METH_VARARGS | METH_KEYWORDS, NULL},
{"view",
(PyCFunction)gentype_view,
METH_VARARGS | METH_KEYWORDS, NULL},
diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index 5e92bc991..b964c568e 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -577,9 +577,6 @@ get_ufunc_arguments(PyUFuncObject *ufunc,
PyObject *obj, *context;
PyObject *str_key_obj = NULL;
const char *ufunc_name = ufunc_get_name_cstr(ufunc);
- int type_num;
-
- int any_flexible = 0, any_object = 0, any_flexible_userloops = 0;
int has_sig = 0;
/*
@@ -638,166 +635,6 @@ get_ufunc_arguments(PyUFuncObject *ufunc,
if (out_op[i] == NULL) {
goto fail;
}
-
- type_num = PyArray_DESCR(out_op[i])->type_num;
- if (!any_flexible &&
- PyTypeNum_ISFLEXIBLE(type_num)) {
- any_flexible = 1;
- }
- if (!any_object &&
- PyTypeNum_ISOBJECT(type_num)) {
- any_object = 1;
- }
-
- /*
- * If any operand is a flexible dtype, check to see if any
- * struct dtype ufuncs are registered. A ufunc has been registered
- * for a struct dtype if ufunc's arg_dtypes array is not NULL.
- */
- if (PyTypeNum_ISFLEXIBLE(type_num) &&
- !any_flexible_userloops &&
- ufunc->userloops != NULL) {
- PyUFunc_Loop1d *funcdata;
- PyObject *key, *obj;
- key = PyInt_FromLong(type_num);
- if (key == NULL) {
- continue;
- }
- obj = PyDict_GetItem(ufunc->userloops, key);
- Py_DECREF(key);
- if (obj == NULL) {
- continue;
- }
- funcdata = (PyUFunc_Loop1d *)NpyCapsule_AsVoidPtr(obj);
- while (funcdata != NULL) {
- if (funcdata->arg_dtypes != NULL) {
- any_flexible_userloops = 1;
- break;
- }
- funcdata = funcdata->next;
- }
- }
- }
-
- if (any_flexible && !any_flexible_userloops && !any_object && nin == 2) {
- /* Traditionally, we return -2 here (meaning "NotImplemented") anytime
- * we hit the above condition.
- *
- * This condition basically means "we are doomed", b/c the "flexible"
- * dtypes -- strings and void -- cannot have their own ufunc loops
- * registered (except via the special "flexible userloops" mechanism),
- * and they can't be cast to anything except object (and we only cast
- * to object if any_object is true). So really we should do nothing
- * here and continue and let the proper error be raised. But, we can't
- * quite yet, b/c of backcompat.
- *
- * Most of the time, this NotImplemented either got returned directly
- * to the user (who can't do anything useful with it), or got passed
- * back out of a special function like __mul__. And fortunately, for
- * almost all special functions, the end result of this was a
- * TypeError. Which is also what we get if we just continue without
- * this special case, so this special case is unnecessary.
- *
- * The only thing that actually depended on the NotImplemented is
- * array_richcompare, which did two things with it. First, it needed
- * to see this NotImplemented in order to implement the special-case
- * comparisons for
- *
- * string < <= == != >= > string
- * void == != void
- *
- * Now it checks for those cases first, before trying to call the
- * ufunc, so that's no problem. What it doesn't handle, though, is
- * cases like
- *
- * float < string
- *
- * or
- *
- * float == void
- *
- * For those, it just let the NotImplemented bubble out, and accepted
- * Python's default handling. And unfortunately, for comparisons,
- * Python's default is *not* to raise an error. Instead, it returns
- * something that depends on the operator:
- *
- * == return False
- * != return True
- * < <= >= > Python 2: use "fallback" (= weird and broken) ordering
- * Python 3: raise TypeError (hallelujah)
- *
- * In most cases this is straightforwardly broken, because comparison
- * of two arrays should always return an array, and here we end up
- * returning a scalar. However, there is an exception: if we are
- * comparing two scalars for equality, then it actually is correct to
- * return a scalar bool instead of raising an error. If we just
- * removed this special check entirely, then "np.float64(1) == 'foo'"
- * would raise an error instead of returning False, which is genuinely
- * wrong.
- *
- * The proper end goal here is:
- * 1) == and != should be implemented in a proper vectorized way for
- * all types. The short-term hack for this is just to add a
- * special case to PyUFunc_DefaultLegacyInnerLoopSelector where
- * if it can't find a comparison loop for the given types, and
- * the ufunc is np.equal or np.not_equal, then it returns a loop
- * that just fills the output array with False (resp. True). Then
- * array_richcompare could trust that whenever its special cases
- * don't apply, simply calling the ufunc will do the right thing,
- * even without this special check.
- * 2) < <= >= > should raise an error if no comparison function can
- * be found. array_richcompare already handles all string <>
- * string cases, and void dtypes don't have ordering, so again
- * this would mean that array_richcompare could simply call the
- * ufunc and it would do the right thing (i.e., raise an error),
- * again without needing this special check.
- *
- * So this means that for the transition period, our goal is:
- * == and != on scalars should simply return NotImplemented like
- * they always did, since everything ends up working out correctly
- * in this case only
- * == and != on arrays should issue a FutureWarning and then return
- * NotImplemented
- * < <= >= > on all flexible dtypes on py2 should raise a
- * DeprecationWarning, and then return NotImplemented. On py3 we
- * skip the warning, though, b/c it would just be immediately be
- * followed by an exception anyway.
- *
- * And for all other operations, we let things continue as normal.
- */
- /* strcmp() is a hack but I think we can get away with it for this
- * temporary measure.
- */
- if (!strcmp(ufunc_name, "equal") ||
- !strcmp(ufunc_name, "not_equal")) {
- /* Warn on non-scalar, return NotImplemented regardless */
- if (PyArray_NDIM(out_op[0]) != 0 ||
- PyArray_NDIM(out_op[1]) != 0) {
- if (DEPRECATE_FUTUREWARNING(
- "elementwise comparison failed; returning scalar "
- "instead, but in the future will perform elementwise "
- "comparison") < 0) {
- goto fail;
- }
- }
- Py_DECREF(out_op[0]);
- Py_DECREF(out_op[1]);
- return -2;
- }
- else if (!strcmp(ufunc_name, "less") ||
- !strcmp(ufunc_name, "less_equal") ||
- !strcmp(ufunc_name, "greater") ||
- !strcmp(ufunc_name, "greater_equal")) {
-#if !defined(NPY_PY3K)
- if (DEPRECATE("unorderable dtypes; returning scalar but in "
- "the future this will be an error") < 0) {
- goto fail;
- }
-#endif
- Py_DECREF(out_op[0]);
- Py_DECREF(out_op[1]);
- return -2;
- }
}
/* Get positional output arguments */
@@ -1281,7 +1118,6 @@ iterator_loop(PyUFuncObject *ufunc,
PyArrayObject **op_it;
npy_uint32 iter_flags;
- int retval;
NPY_BEGIN_THREADS_DEF;
@@ -1355,7 +1191,6 @@ iterator_loop(PyUFuncObject *ufunc,
/* Call the __array_prepare__ functions for the new array */
if (prepare_ufunc_output(ufunc, &op[nin+i],
arr_prep[i], full_args, i) < 0) {
- NpyIter_Close(iter);
NpyIter_Deallocate(iter);
return -1;
}
@@ -1384,7 +1219,6 @@ iterator_loop(PyUFuncObject *ufunc,
baseptrs[i] = PyArray_BYTES(op_it[i]);
}
if (NpyIter_ResetBasePointers(iter, baseptrs, NULL) != NPY_SUCCEED) {
- NpyIter_Close(iter);
NpyIter_Deallocate(iter);
return -1;
}
@@ -1392,7 +1226,6 @@ iterator_loop(PyUFuncObject *ufunc,
/* Get the variables needed for the loop */
iternext = NpyIter_GetIterNext(iter, NULL);
if (iternext == NULL) {
- NpyIter_Close(iter);
NpyIter_Deallocate(iter);
return -1;
}
@@ -1410,9 +1243,7 @@ iterator_loop(PyUFuncObject *ufunc,
NPY_END_THREADS;
}
- retval = NpyIter_Close(iter);
- NpyIter_Deallocate(iter);
- return retval;
+ return NpyIter_Deallocate(iter);
}
/*
@@ -1597,7 +1428,7 @@ execute_fancy_ufunc_loop(PyUFuncObject *ufunc,
PyObject **arr_prep,
ufunc_full_args full_args)
{
- int retval, i, nin = ufunc->nin, nout = ufunc->nout;
+ int i, nin = ufunc->nin, nout = ufunc->nout;
int nop = nin + nout;
npy_uint32 op_flags[NPY_MAXARGS];
NpyIter *iter;
@@ -1709,7 +1540,6 @@ execute_fancy_ufunc_loop(PyUFuncObject *ufunc,
if (prepare_ufunc_output(ufunc, &op_tmp,
arr_prep[i], full_args, i) < 0) {
- NpyIter_Close(iter);
NpyIter_Deallocate(iter);
return -1;
}
@@ -1720,7 +1550,6 @@ execute_fancy_ufunc_loop(PyUFuncObject *ufunc,
"The __array_prepare__ functions modified the data "
"pointer addresses in an invalid fashion");
Py_DECREF(op_tmp);
- NpyIter_Close(iter);
NpyIter_Deallocate(iter);
return -1;
}
@@ -1755,7 +1584,6 @@ execute_fancy_ufunc_loop(PyUFuncObject *ufunc,
wheremask != NULL ? fixed_strides[nop]
: fixed_strides[nop + nin],
&innerloop, &innerloopdata, &needs_api) < 0) {
- NpyIter_Close(iter);
NpyIter_Deallocate(iter);
return -1;
}
@@ -1763,7 +1591,6 @@ execute_fancy_ufunc_loop(PyUFuncObject *ufunc,
/* Get the variables needed for the loop */
iternext = NpyIter_GetIterNext(iter, NULL);
if (iternext == NULL) {
- NpyIter_Close(iter);
NpyIter_Deallocate(iter);
return -1;
}
@@ -1787,9 +1614,7 @@ execute_fancy_ufunc_loop(PyUFuncObject *ufunc,
NPY_AUXDATA_FREE(innerloopdata);
}
- retval = NpyIter_Close(iter);
- NpyIter_Deallocate(iter);
- return retval;
+ return NpyIter_Deallocate(iter);
}
static npy_bool
@@ -2300,7 +2125,7 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc,
int nin, nout;
int i, j, idim, nop;
const char *ufunc_name;
- int retval = 0, subok = 1;
+ int retval, subok = 1;
int needs_api = 0;
PyArray_Descr *dtypes[NPY_MAXARGS];
@@ -2809,16 +2634,11 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc,
goto fail;
}
- /* Write back any temporary data from PyArray_SetWritebackIfCopyBase */
- if (NpyIter_Close(iter) < 0) {
- goto fail;
- }
-
PyArray_free(inner_strides);
- if (NpyIter_Close(iter) < 0) {
- goto fail;
+ if (NpyIter_Deallocate(iter) < 0) {
+ retval = -1;
}
- NpyIter_Deallocate(iter);
+
/* The caller takes ownership of all the references in op */
for (i = 0; i < nop; ++i) {
Py_XDECREF(dtypes[i]);
@@ -2831,14 +2651,13 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc,
Py_XDECREF(full_args.in);
Py_XDECREF(full_args.out);
- NPY_UF_DBG_PRINT("Returning Success\n");
+ NPY_UF_DBG_PRINT1("Returning code %d\n", reval);
- return 0;
+ return retval;
fail:
NPY_UF_DBG_PRINT1("Returning failure code %d\n", retval);
PyArray_free(inner_strides);
- NpyIter_Close(iter);
NpyIter_Deallocate(iter);
for (i = 0; i < nop; ++i) {
Py_XDECREF(op[i]);
@@ -3031,7 +2850,7 @@ PyUFunc_GenericFunction(PyUFuncObject *ufunc,
Py_XDECREF(full_args.out);
Py_XDECREF(wheremask);
- NPY_UF_DBG_PRINT("Returning Success\n");
+ NPY_UF_DBG_PRINT("Returning success code 0\n");
return 0;
@@ -3722,12 +3541,6 @@ PyUFunc_Accumulate(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *out,
}
finish:
- if (NpyIter_Close(iter) < 0) {
- goto fail;
- }
- if (NpyIter_Close(iter_inner) < 0) {
- goto fail;
- }
Py_XDECREF(op_dtypes[0]);
NpyIter_Deallocate(iter);
NpyIter_Deallocate(iter_inner);
@@ -4110,9 +3923,6 @@ PyUFunc_Reduceat(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *ind,
}
finish:
- if (NpyIter_Close(iter) < 0) {
- goto fail;
- }
Py_XDECREF(op_dtypes[0]);
NpyIter_Deallocate(iter);
@@ -4507,22 +4317,7 @@ ufunc_generic_call(PyUFuncObject *ufunc, PyObject *args, PyObject *kwds)
errval = PyUFunc_GenericFunction(ufunc, args, kwds, mps);
if (errval < 0) {
- if (errval == -1) {
- return NULL;
- }
- else if (ufunc->nin == 2 && ufunc->nout == 1) {
- /*
- * For array_richcompare's benefit -- see the long comment in
- * get_ufunc_arguments.
- */
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- else {
- PyErr_SetString(PyExc_TypeError,
- "XX can't happen, please report a bug XX");
- return NULL;
- }
+ return NULL;
}
/* Free the input references */
@@ -5544,7 +5339,6 @@ ufunc_at(PyUFuncObject *ufunc, PyObject *args)
iternext = NpyIter_GetIterNext(iter_buffer, NULL);
if (iternext == NULL) {
- NpyIter_Close(iter_buffer);
NpyIter_Deallocate(iter_buffer);
goto fail;
}
@@ -5614,7 +5408,6 @@ ufunc_at(PyUFuncObject *ufunc, PyObject *args)
PyErr_SetString(PyExc_ValueError, err_msg);
}
- NpyIter_Close(iter_buffer);
NpyIter_Deallocate(iter_buffer);
Py_XDECREF(op2_array);
@@ -5632,7 +5425,7 @@ ufunc_at(PyUFuncObject *ufunc, PyObject *args)
}
fail:
- /* iter_buffer has already been deallocated, don't use NpyIter_Close */
+ /* iter_buffer has already been deallocated, don't use NpyIter_Dealloc */
if (op1_array != (PyArrayObject*)op1) {
PyArray_DiscardWritebackIfCopy(op1_array);
}
diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py
index 285b2de3c..8eb258666 100644
--- a/numpy/core/tests/test_deprecations.py
+++ b/numpy/core/tests/test_deprecations.py
@@ -190,10 +190,10 @@ class TestComparisonDeprecations(_DeprecationTestCase):
b = np.array(['a', 'b', 'c'])
assert_raises(ValueError, lambda x, y: x == y, a, b)
- # The empty list is not cast to string, as this is only to document
- # that fact (it likely should be changed). This means that the
- # following works (and returns False) due to dtype mismatch:
- a == []
+ # The empty list is not cast to string, and this used to pass due
+ # to dtype mismatch; now (2018-06-21) it correctly leads to a
+ # FutureWarning.
+ assert_warns(FutureWarning, lambda: a == [])
def test_void_dtype_equality_failures(self):
class NotArray(object):
diff --git a/numpy/core/tests/test_nditer.py b/numpy/core/tests/test_nditer.py
index a0096efdb..13bc6b34a 100644
--- a/numpy/core/tests/test_nditer.py
+++ b/numpy/core/tests/test_nditer.py
@@ -2830,10 +2830,6 @@ def test_writebacks():
x[:] = 123 # x.data still valid
assert_equal(au, 6) # but not connected to au
- do_close = 1
- # test like above, only in C, and with an option to skip the NpyIter_Close
- _multiarray_tests.test_nditer_writeback(3, do_close, au, op_dtypes=[np.dtype('f4')])
- assert_equal(au, 3)
it = nditer(au, [],
[['readwrite', 'updateifcopy']],
casting='equiv', op_dtypes=[np.dtype('f4')])
@@ -2862,7 +2858,7 @@ def test_writebacks():
x[...] = 123
# make sure we cannot reenter the closed iterator
enter = it.__enter__
- assert_raises(ValueError, enter)
+ assert_raises(RuntimeError, enter)
def test_close_equivalent():
''' using a context amanger and using nditer.close are equivalent
@@ -2897,12 +2893,13 @@ def test_close_raises():
assert_raises(StopIteration, next, it)
assert_raises(ValueError, getattr, it, 'operands')
+@pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts")
def test_warn_noclose():
a = np.arange(6, dtype='f4')
au = a.byteswap().newbyteorder()
- do_close = 0
with suppress_warnings() as sup:
sup.record(RuntimeWarning)
- # test like above, only in C, and with an option to skip the NpyIter_Close
- _multiarray_tests.test_nditer_writeback(3, do_close, au, op_dtypes=[np.dtype('f4')])
+ it = np.nditer(au, [], [['readwrite', 'updateifcopy']],
+ casting='equiv', op_dtypes=[np.dtype('f4')])
+ del it
assert len(sup.log) == 1
diff --git a/numpy/core/tests/test_numerictypes.py b/numpy/core/tests/test_numerictypes.py
index cdf1b0490..4c3cc6c9e 100644
--- a/numpy/core/tests/test_numerictypes.py
+++ b/numpy/core/tests/test_numerictypes.py
@@ -406,3 +406,9 @@ class TestIsSubDType(object):
for w1, w2 in itertools.product(self.wrappers, repeat=2):
assert_(not np.issubdtype(w1(np.float32), w2(np.float64)))
assert_(not np.issubdtype(w1(np.float64), w2(np.float32)))
+
+
+def TestSctypeDict(object):
+ def test_longdouble(self):
+ assert_(np.sctypeDict['f8'] is not np.longdouble)
+ assert_(np.sctypeDict['c16'] is not np.clongdouble)
diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py
index f8f75d9ea..ba4413138 100644
--- a/numpy/core/tests/test_regression.py
+++ b/numpy/core/tests/test_regression.py
@@ -2375,3 +2375,19 @@ class TestRegression(object):
structure = np.array([1], dtype=[(('x', 'X'), np.object_)])
structure[0]['x'] = np.array([2])
gc.collect()
+
+ def test_dtype_scalar_squeeze(self):
+ # gh-11384
+ values = {
+ 'S': b"a",
+ 'M': "2018-06-20",
+ }
+ for ch in np.typecodes['All']:
+ if ch in 'O':
+ continue
+ sctype = np.dtype(ch).type
+ scvalue = sctype(values.get(ch, 3))
+ for axis in [None, ()]:
+ squeezed = scvalue.squeeze(axis=axis)
+ assert_equal(squeezed, scvalue)
+ assert_equal(type(squeezed), type(scvalue))
diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py
index ef9ced354..0e564e305 100644
--- a/numpy/core/tests/test_ufunc.py
+++ b/numpy/core/tests/test_ufunc.py
@@ -1643,6 +1643,16 @@ class TestUfunc(object):
target = np.array([ True, False, False, False], dtype=bool)
assert_equal(np.all(target == (mra == ra[0])), True)
+ def test_scalar_equal(self):
+ # Scalar comparisons should always work, without deprecation warnings.
+ # even when the ufunc fails.
+ a = np.array(0.)
+ b = np.array('a')
+ assert_(a != b)
+ assert_(b != a)
+ assert_(not (a == b))
+ assert_(not (b == a))
+
def test_NotImplemented_not_returned(self):
# See gh-5964 and gh-2091. Some of these functions are not operator
# related and were fixed for other reasons in the past.
@@ -1652,17 +1662,16 @@ class TestUfunc(object):
np.bitwise_xor, np.left_shift, np.right_shift, np.fmax,
np.fmin, np.fmod, np.hypot, np.logaddexp, np.logaddexp2,
np.logical_and, np.logical_or, np.logical_xor, np.maximum,
- np.minimum, np.mod
- ]
-
- # These functions still return NotImplemented. Will be fixed in
- # future.
- # bad = [np.greater, np.greater_equal, np.less, np.less_equal, np.not_equal]
+ np.minimum, np.mod,
+ np.greater, np.greater_equal, np.less, np.less_equal,
+ np.equal, np.not_equal]
a = np.array('1')
b = 1
+ c = np.array([1., 2.])
for f in binary_funcs:
assert_raises(TypeError, f, a, b)
+ assert_raises(TypeError, f, c, a)
def test_reduce_noncontig_output(self):
# Check that reduction deals with non-contiguous output arrays