Skip to content

1.7.x backport #472

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Oct 1, 2012
12 changes: 8 additions & 4 deletions doc/release/1.7.0-notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,14 @@ np.diagonal, numpy 1.7 produces a FutureWarning if it detects
that you may be attemping to write to such an array. See the documentation
for array indexing for details.

The default casting rule for UFunc out= parameters has been changed from
'unsafe' to 'same_kind'. Most usages which violate the 'same_kind'
rule are likely bugs, so this change may expose previously undetected
errors in projects that depend on NumPy.
In a future version of numpy, the default casting rule for UFunc out=
parameters will be changed from 'unsafe' to 'same_kind'. (This also
applies to in-place operations like a += b, which is equivalent to
np.add(a, b, out=a).) Most usages which violate the 'same_kind' rule
are likely bugs, so this change may expose previously undetected
errors in projects that depend on NumPy. In this version of numpy,
such usages will continue to succeed, but will raise a
DeprecationWarning.

Full-array boolean indexing has been optimized to use a different,
optimized code path. This code path should produce the same results,
Expand Down
6 changes: 6 additions & 0 deletions doc/source/reference/ufuncs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,12 @@ advanced usage and will not typically be used.
'equiv', 'safe', 'same_kind', or 'unsafe'. See :func:`can_cast` for
explanations of the parameter values.

In a future version of numpy, this argument will default to
'same_kind'. As part of this transition, starting in version 1.7,
ufuncs will produce a DeprecationWarning for calls which are
allowed under the 'unsafe' rules, but not under the 'same_kind'
rules.

*order*

.. versionadded:: 1.6
Expand Down
2 changes: 2 additions & 0 deletions numpy/core/code_generators/numpy_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@

multiarray_global_vars = {
'NPY_NUMUSERTYPES': 7,
'NPY_DEFAULT_ASSIGN_CASTING': 292,
}

multiarray_global_vars_types = {
'NPY_NUMUSERTYPES': 'int',
'NPY_DEFAULT_ASSIGN_CASTING': 'NPY_CASTING',
}

multiarray_scalar_bool_values = {
Expand Down
11 changes: 7 additions & 4 deletions numpy/core/include/numpy/ndarraytypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,14 @@ typedef enum {
/* Allow safe casts or casts within the same kind */
NPY_SAME_KIND_CASTING=3,
/* Allow any casts */
NPY_UNSAFE_CASTING=4
} NPY_CASTING;
NPY_UNSAFE_CASTING=4,

/* The default casting to use for typical assignment operations */
#define NPY_DEFAULT_ASSIGN_CASTING NPY_SAME_KIND_CASTING
/*
* Temporary internal definition only, will be removed in upcoming
* release, see below
* */
NPY_INTERNAL_UNSAFE_CASTING_BUT_WARN_UNLESS_SAME_KIND = 100,
} NPY_CASTING;

typedef enum {
NPY_CLIP=0,
Expand Down
1 change: 1 addition & 0 deletions numpy/core/src/multiarray/array_assign.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ broadcast_error: {
PyUString_ConcatAndDel(&errmsg,
build_shape_string(ndim, shape));
PyErr_SetObject(PyExc_ValueError, errmsg);
Py_DECREF(errmsg);

return -1;
}
Expand Down
1 change: 1 addition & 0 deletions numpy/core/src/multiarray/array_assign_array.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ PyArray_AssignArray(PyArrayObject *dst, PyArrayObject *src,
PyUString_FromFormat(" according to the rule %s",
npy_casting_to_string(casting)));
PyErr_SetObject(PyExc_TypeError, errmsg);
Py_DECREF(errmsg);
goto fail;
}

Expand Down
1 change: 1 addition & 0 deletions numpy/core/src/multiarray/array_assign_scalar.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ PyArray_AssignRawScalar(PyArrayObject *dst,
PyUString_FromFormat(" according to the rule %s",
npy_casting_to_string(casting)));
PyErr_SetObject(PyExc_TypeError, errmsg);
Py_DECREF(errmsg);
return -1;
}

Expand Down
16 changes: 16 additions & 0 deletions numpy/core/src/multiarray/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,22 @@
#include "common.h"
#include "buffer.h"

/*
* The casting to use for implicit assignment operations resulting from
* in-place operations (like +=) and out= arguments. (Notice that this
* variable is misnamed, but it's part of the public API so I'm not sure we
* can just change it. Maybe someone should try and see if anyone notices.
*/
/*
* In numpy 1.6 and earlier, this was NPY_UNSAFE_CASTING. In a future
* release, it will become NPY_SAME_KIND_CASTING. Right now, during the
* transitional period, we continue to follow the NPY_UNSAFE_CASTING rules (to
* avoid breaking people's code), but we also check for whether the cast would
* be allowed under the NPY_SAME_KIND_CASTING rules, and if not we issue a
* warning (that people's code will be broken in a future release.)
*/
NPY_NO_EXPORT NPY_CASTING NPY_DEFAULT_ASSIGN_CASTING = NPY_INTERNAL_UNSAFE_CASTING_BUT_WARN_UNLESS_SAME_KIND;


NPY_NO_EXPORT PyArray_Descr *
_array_find_python_scalar_type(PyObject *op)
Expand Down
31 changes: 31 additions & 0 deletions numpy/core/src/multiarray/convert_datatype.c
Original file line number Diff line number Diff line change
Expand Up @@ -503,12 +503,43 @@ type_num_unsigned_to_signed(int type_num)
}
}

/*
* NOTE: once the UNSAFE_CASTING -> SAME_KIND_CASTING transition is over,
* we should remove NPY_INTERNAL_UNSAFE_CASTING_BUT_WARN_UNLESS_SAME_KIND
* and PyArray_CanCastTypeTo_impl should be renamed back to
* PyArray_CanCastTypeTo.
*/
static npy_bool
PyArray_CanCastTypeTo_impl(PyArray_Descr *from, PyArray_Descr *to,
NPY_CASTING casting);

/*NUMPY_API
* Returns true if data of type 'from' may be cast to data of type
* 'to' according to the rule 'casting'.
*/
NPY_NO_EXPORT npy_bool
PyArray_CanCastTypeTo(PyArray_Descr *from, PyArray_Descr *to,
NPY_CASTING casting)
{
if (casting == NPY_INTERNAL_UNSAFE_CASTING_BUT_WARN_UNLESS_SAME_KIND) {
npy_bool unsafe_ok, same_kind_ok;
unsafe_ok = PyArray_CanCastTypeTo_impl(from, to, NPY_UNSAFE_CASTING);
same_kind_ok = PyArray_CanCastTypeTo_impl(from, to,
NPY_SAME_KIND_CASTING);
if (unsafe_ok && !same_kind_ok) {
DEPRECATE("Implicitly casting between incompatible kinds. In "
"a future numpy release, this will raise an error. "
"Use casting=\"unsafe\" if this is intentional.");
}
return unsafe_ok;
}
else {
return PyArray_CanCastTypeTo_impl(from, to, casting);
}
}

static npy_bool
PyArray_CanCastTypeTo_impl(PyArray_Descr *from, PyArray_Descr *to,
NPY_CASTING casting)
{
/* If unsafe casts are allowed */
Expand Down
1 change: 1 addition & 0 deletions numpy/core/src/multiarray/ctors.c
Original file line number Diff line number Diff line change
Expand Up @@ -1818,6 +1818,7 @@ PyArray_FromArray(PyArrayObject *arr, PyArray_Descr *newtype, int flags)
PyUString_FromFormat(" according to the rule %s",
npy_casting_to_string(casting)));
PyErr_SetObject(PyExc_TypeError, errmsg);
Py_DECREF(errmsg);

Py_DECREF(newtype);
return NULL;
Expand Down
5 changes: 5 additions & 0 deletions numpy/core/src/multiarray/datetime.c
Original file line number Diff line number Diff line change
Expand Up @@ -1489,6 +1489,7 @@ raise_if_datetime64_metadata_cast_error(char *object_type,
PyUString_FromFormat(" according to the rule %s",
npy_casting_to_string(casting)));
PyErr_SetObject(PyExc_TypeError, errmsg);
Py_DECREF(errmsg);
return -1;
}
}
Expand Down Expand Up @@ -1520,6 +1521,7 @@ raise_if_timedelta64_metadata_cast_error(char *object_type,
PyUString_FromFormat(" according to the rule %s",
npy_casting_to_string(casting)));
PyErr_SetObject(PyExc_TypeError, errmsg);
Py_DECREF(errmsg);
return -1;
}
}
Expand Down Expand Up @@ -1654,6 +1656,7 @@ incompatible_units: {
PyUString_FromString(" because they have "
"incompatible nonlinear base time units"));
PyErr_SetObject(PyExc_TypeError, errmsg);
Py_DECREF(errmsg);
return -1;
}
units_overflow: {
Expand All @@ -1666,6 +1669,7 @@ units_overflow: {
PyUString_FromString(" and "));
errmsg = append_metastr_to_string(meta2, 0, errmsg);
PyErr_SetObject(PyExc_OverflowError, errmsg);
Py_DECREF(errmsg);
return -1;
}
}
Expand Down Expand Up @@ -1813,6 +1817,7 @@ convert_datetime_metadata_tuple_to_datetime_metadata(PyObject *tuple,
"datetime metadata conversion, not ");
PyUString_ConcatAndDel(&errmsg, PyObject_Repr(tuple));
PyErr_SetObject(PyExc_TypeError, errmsg);
Py_DECREF(errmsg);
return -1;
}

Expand Down
1 change: 1 addition & 0 deletions numpy/core/src/multiarray/descriptor.c
Original file line number Diff line number Diff line change
Expand Up @@ -2538,6 +2538,7 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args)
errmsg = PyUString_FromString("Invalid datetime dtype (metadata, c_metadata): ");
PyUString_ConcatAndDel(&errmsg, PyObject_Repr(metadata));
PyErr_SetObject(PyExc_ValueError, errmsg);
Py_DECREF(errmsg);
return NULL;
}

Expand Down
1 change: 1 addition & 0 deletions numpy/core/src/multiarray/methods.c
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,7 @@ array_astype(PyArrayObject *self, PyObject *args, PyObject *kwds)
PyUString_FromFormat(" according to the rule %s",
npy_casting_to_string(casting)));
PyErr_SetObject(PyExc_TypeError, errmsg);
Py_DECREF(errmsg);
Py_DECREF(dtype);
return NULL;
}
Expand Down
10 changes: 10 additions & 0 deletions numpy/core/src/multiarray/multiarraymodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,16 @@ PyArray_ConcatenateArrays(int narrays, PyArrayObject **arrays, int axis)
if (axis < 0) {
axis += ndim;
}

if (ndim == 1 & axis != 0) {
char msg[] = "axis != 0 for ndim == 1; this will raise an error in "
"future versions of numpy";
if (DEPRECATE(msg) < 0) {
return NULL;
}
axis = 0;
}

if (axis < 0 || axis >= ndim) {
PyErr_Format(PyExc_IndexError,
"axis %d out of bounds [0, %d)", orig_axis, ndim);
Expand Down
5 changes: 5 additions & 0 deletions numpy/core/src/multiarray/nditer_constr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1337,6 +1337,7 @@ npyiter_check_casting(int nop, PyArrayObject **op,
PyUString_FromFormat(" according to the rule %s",
npyiter_casting_to_string(casting)));
PyErr_SetObject(PyExc_TypeError, errmsg);
Py_DECREF(errmsg);
return 0;
}
/* Check write (temp -> op) casting */
Expand All @@ -1359,6 +1360,7 @@ npyiter_check_casting(int nop, PyArrayObject **op,
(int)iop,
npyiter_casting_to_string(casting)));
PyErr_SetObject(PyExc_TypeError, errmsg);
Py_DECREF(errmsg);
return 0;
}

Expand Down Expand Up @@ -1738,6 +1740,7 @@ broadcast_error: {

}
PyErr_SetObject(PyExc_ValueError, errmsg);
Py_DECREF(errmsg);
}
else {
errmsg = PyUString_FromString("operands could not be broadcast "
Expand Down Expand Up @@ -1804,6 +1807,7 @@ broadcast_error: {

}
PyErr_SetObject(PyExc_ValueError, errmsg);
Py_DECREF(errmsg);
}

return 0;
Expand Down Expand Up @@ -1890,6 +1894,7 @@ operand_different_than_broadcast: {
}

PyErr_SetObject(PyExc_ValueError, errmsg);
Py_DECREF(errmsg);

return 0;
}
Expand Down
3 changes: 3 additions & 0 deletions numpy/core/src/multiarray/shape.c
Original file line number Diff line number Diff line change
Expand Up @@ -1186,4 +1186,7 @@ PyArray_RemoveAxesInPlace(PyArrayObject *arr, npy_bool *flags)

/* The final number of dimensions */
fa->nd = idim_out;

/* Update contiguous flags */
PyArray_UpdateFlags(arr, NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_F_CONTIGUOUS);
}
7 changes: 7 additions & 0 deletions numpy/core/src/umath/ufunc_type_resolution.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ PyUFunc_ValidateCasting(PyUFuncObject *ufunc,
PyUString_FromFormat(" with casting rule %s",
npy_casting_to_string(casting)));
PyErr_SetObject(PyExc_TypeError, errmsg);
Py_DECREF(errmsg);
return -1;
}
} else if (operands[i] != NULL) {
Expand All @@ -95,6 +96,7 @@ PyUFunc_ValidateCasting(PyUFuncObject *ufunc,
PyUString_FromFormat(" with casting rule %s",
npy_casting_to_string(casting)));
PyErr_SetObject(PyExc_TypeError, errmsg);
Py_DECREF(errmsg);
return -1;
}
}
Expand Down Expand Up @@ -725,6 +727,7 @@ type_reso_error: {
PyUString_ConcatAndDel(&errmsg,
PyObject_Repr((PyObject *)PyArray_DESCR(operands[1])));
PyErr_SetObject(PyExc_TypeError, errmsg);
Py_DECREF(errmsg);
return -1;
}
}
Expand Down Expand Up @@ -895,6 +898,7 @@ type_reso_error: {
PyUString_ConcatAndDel(&errmsg,
PyObject_Repr((PyObject *)PyArray_DESCR(operands[1])));
PyErr_SetObject(PyExc_TypeError, errmsg);
Py_DECREF(errmsg);
return -1;
}
}
Expand Down Expand Up @@ -1038,6 +1042,7 @@ type_reso_error: {
PyUString_ConcatAndDel(&errmsg,
PyObject_Repr((PyObject *)PyArray_DESCR(operands[1])));
PyErr_SetObject(PyExc_TypeError, errmsg);
Py_DECREF(errmsg);
return -1;
}
}
Expand Down Expand Up @@ -1157,6 +1162,7 @@ type_reso_error: {
PyUString_ConcatAndDel(&errmsg,
PyObject_Repr((PyObject *)PyArray_DESCR(operands[1])));
PyErr_SetObject(PyExc_TypeError, errmsg);
Py_DECREF(errmsg);
return -1;
}
}
Expand Down Expand Up @@ -1273,6 +1279,7 @@ PyUFunc_DefaultLegacyInnerLoopSelector(PyUFuncObject *ufunc,
}
}
PyErr_SetObject(PyExc_TypeError, errmsg);
Py_DECREF(errmsg);

return -1;
}
Expand Down
16 changes: 16 additions & 0 deletions numpy/core/tests/test_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -1528,6 +1528,22 @@ def test_array_scalar_contiguous(self):
assert_(np.array(np.float32(1.0)).flags.c_contiguous)
assert_(np.array(np.float32(1.0)).flags.f_contiguous)

def test_squeeze_contiguous(self):
"""Similar to GitHub issue #387"""
a = np.zeros((1,2)).squeeze()
b = np.zeros((2,2,2), order='F')[:,:,::2].squeeze()
assert_(a.flags.c_contiguous)
assert_(a.flags.f_contiguous)
assert_(b.flags.f_contiguous)

def test_reduce_contiguous(self):
"""GitHub issue #387"""
a = np.add.reduce(np.zeros((2,1,2)), (0,1))
b = np.add.reduce(np.zeros((2,1,2)), 1)
assert_(a.flags.c_contiguous)
assert_(a.flags.f_contiguous)
assert_(b.flags.c_contiguous)

def test_object_array_self_reference(self):
# Object arrays with references to themselves can cause problems
a = np.array(0, dtype=object)
Expand Down
Loading