diff options
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/src/multiarray/convert_datatype.c | 8 | ||||
-rw-r--r-- | numpy/core/src/multiarray/scalartypes.c.src | 7 | ||||
-rw-r--r-- | numpy/core/tests/test_datetime.py | 9 | ||||
-rw-r--r-- | numpy/core/tests/test_scalarmath.py | 12 | ||||
-rw-r--r-- | numpy/distutils/misc_util.py | 7 | ||||
-rw-r--r-- | numpy/lib/type_check.py | 10 | ||||
-rw-r--r-- | numpy/ma/core.py | 41 | ||||
-rw-r--r-- | numpy/random/tests/test_extending.py | 6 |
8 files changed, 80 insertions, 20 deletions
diff --git a/numpy/core/src/multiarray/convert_datatype.c b/numpy/core/src/multiarray/convert_datatype.c index 025c66013..4326448dc 100644 --- a/numpy/core/src/multiarray/convert_datatype.c +++ b/numpy/core/src/multiarray/convert_datatype.c @@ -877,7 +877,13 @@ PyArray_CanCastTypeTo(PyArray_Descr *from, PyArray_Descr *to, from_order = dtype_kind_to_ordering(from->kind); to_order = dtype_kind_to_ordering(to->kind); - return from_order != -1 && from_order <= to_order; + if (to->kind == 'm') { + /* both types being timedelta is already handled before. */ + int integer_order = dtype_kind_to_ordering('i'); + return (from_order != -1) && (from_order <= integer_order); + } + + return (from_order != -1) && (from_order <= to_order); } else { return 0; diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src index 32d712e0c..5da7f7738 100644 --- a/numpy/core/src/multiarray/scalartypes.c.src +++ b/numpy/core/src/multiarray/scalartypes.c.src @@ -4060,8 +4060,11 @@ initialize_casting_tables(void) _npy_can_cast_safely_table[_FROM_NUM][NPY_STRING] = 1; _npy_can_cast_safely_table[_FROM_NUM][NPY_UNICODE] = 1; - /* Allow casts from any integer to the TIMEDELTA type */ -#if @from_isint@ || @from_isuint@ +#if @from_isint@ && NPY_SIZEOF_TIMEDELTA >= _FROM_BSIZE + /* Allow casts from smaller or equal signed integers to the TIMEDELTA type */ + _npy_can_cast_safely_table[_FROM_NUM][NPY_TIMEDELTA] = 1; +#elif @from_isuint@ && NPY_SIZEOF_TIMEDELTA > _FROM_BSIZE + /* Allow casts from smaller unsigned integers to the TIMEDELTA type */ _npy_can_cast_safely_table[_FROM_NUM][NPY_TIMEDELTA] = 1; #endif diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py index d1208e8ec..41b84a69f 100644 --- a/numpy/core/tests/test_datetime.py +++ b/numpy/core/tests/test_datetime.py @@ -75,6 +75,15 @@ class TestDateTime(object): # Can cast safely/same_kind from integer to timedelta assert_(np.can_cast('i8', 'm8', casting='same_kind')) assert_(np.can_cast('i8', 'm8', casting='safe')) + assert_(np.can_cast('i4', 'm8', casting='same_kind')) + assert_(np.can_cast('i4', 'm8', casting='safe')) + assert_(np.can_cast('u4', 'm8', casting='same_kind')) + assert_(np.can_cast('u4', 'm8', casting='safe')) + + # Cannot cast safely from unsigned integer of the same size, which + # could overflow + assert_(np.can_cast('u8', 'm8', casting='same_kind')) + assert_(not np.can_cast('u8', 'm8', casting='safe')) # Cannot cast safely/same_kind from float to timedelta assert_(not np.can_cast('f4', 'm8', casting='same_kind')) diff --git a/numpy/core/tests/test_scalarmath.py b/numpy/core/tests/test_scalarmath.py index 854df5590..c84380cd9 100644 --- a/numpy/core/tests/test_scalarmath.py +++ b/numpy/core/tests/test_scalarmath.py @@ -11,7 +11,7 @@ import numpy as np from numpy.testing import ( assert_, assert_equal, assert_raises, assert_almost_equal, assert_array_equal, IS_PYPY, suppress_warnings, _gen_alignment_data, - assert_warns + assert_warns, assert_raises_regex, ) types = [np.bool_, np.byte, np.ubyte, np.short, np.ushort, np.intc, np.uintc, @@ -293,6 +293,16 @@ class TestModulus(object): rem = operator.mod(finf, fone) assert_(np.isnan(rem), 'dt: %s' % dt) + def test_inplace_floordiv_handling(self): + # issue gh-12927 + # this only applies to in-place floordiv //=, because the output type + # promotes to float which does not fit + a = np.array([1, 2], np.int64) + b = np.array([1, 2], np.uint64) + pattern = 'could not be coerced to provided output parameter' + with assert_raises_regex(TypeError, pattern): + a //= b + class TestComplexDivision(object): def test_zero_division(self): diff --git a/numpy/distutils/misc_util.py b/numpy/distutils/misc_util.py index 7ba8ad862..d46ff8981 100644 --- a/numpy/distutils/misc_util.py +++ b/numpy/distutils/misc_util.py @@ -2329,8 +2329,11 @@ def generate_config_py(target): extra_dll_dir = os.path.join(os.path.dirname(__file__), '.libs') if sys.platform == 'win32' and os.path.isdir(extra_dll_dir): - os.environ.setdefault('PATH', '') - os.environ['PATH'] += os.pathsep + extra_dll_dir + if sys.version_info >= (3, 8): + os.add_dll_directory(extra_dll_dir) + else: + os.environ.setdefault('PATH', '') + os.environ['PATH'] += os.pathsep + extra_dll_dir """)) diff --git a/numpy/lib/type_check.py b/numpy/lib/type_check.py index 586824743..8b9e4b8ab 100644 --- a/numpy/lib/type_check.py +++ b/numpy/lib/type_check.py @@ -68,16 +68,14 @@ def mintypecode(typechars, typeset='GDFgdf', default='d'): 'G' """ - typecodes = [(isinstance(t, str) and t) or asarray(t).dtype.char - for t in typechars] - intersection = [t for t in typecodes if t in typeset] + typecodes = ((isinstance(t, str) and t) or asarray(t).dtype.char + for t in typechars) + intersection = set(t for t in typecodes if t in typeset) if not intersection: return default if 'F' in intersection and 'd' in intersection: return 'D' - l = [(_typecodes_by_elsize.index(t), t) for t in intersection] - l.sort() - return l[0][1] + return min((_typecodes_by_elsize.index(t), t) for t in intersection)[1] def _asfarray_dispatcher(a, dtype=None): diff --git a/numpy/ma/core.py b/numpy/ma/core.py index bb0d8d412..2baf547a4 100644 --- a/numpy/ma/core.py +++ b/numpy/ma/core.py @@ -602,8 +602,10 @@ def filled(a, fill_value=None): ---------- a : MaskedArray or array_like An input object. - fill_value : scalar, optional - Filling value. Default is None. + fill_value : array_like, optional. + Can be scalar or non-scalar. If non-scalar, the + resulting filled array should be broadcastable + over input array. Default is None. Returns ------- @@ -623,10 +625,19 @@ def filled(a, fill_value=None): array([[999999, 1, 2], [999999, 4, 5], [ 6, 7, 8]]) + >>> x.filled(fill_value=333) + array([[333, 1, 2], + [333, 4, 5], + [ 6, 7, 8]]) + >>> x.filled(fill_value=np.arange(3)) + array([[0, 1, 2], + [0, 4, 5], + [6, 7, 8]]) """ if hasattr(a, 'filled'): return a.filled(fill_value) + elif isinstance(a, ndarray): # Should we check for contiguity ? and a.flags['CONTIGUOUS']: return a @@ -3653,6 +3664,14 @@ class MaskedArray(ndarray): @fill_value.setter def fill_value(self, value=None): target = _check_fill_value(value, self.dtype) + if not target.ndim == 0: + # 2019-11-12, 1.18.0 + warnings.warn( + "Non-scalar arrays for the fill value are deprecated. Use " + "arrays with scalar values instead. The filled function " + "still supports any array as `fill_value`.", + DeprecationWarning, stacklevel=2) + _fill_value = self._fill_value if _fill_value is None: # Create the attribute if it was undefined @@ -3673,9 +3692,11 @@ class MaskedArray(ndarray): Parameters ---------- - fill_value : scalar, optional - The value to use for invalid entries (None by default). - If None, the `fill_value` attribute of the array is used instead. + fill_value : array_like, optional + The value to use for invalid entries. Can be scalar or non-scalar. + If non-scalar, the resulting ndarray must be broadcastable over + input array. Default is None, in which case, the `fill_value` + attribute of the array is used instead. Returns ------- @@ -3694,6 +3715,8 @@ class MaskedArray(ndarray): >>> x = np.ma.array([1,2,3,4,5], mask=[0,0,1,0,1], fill_value=-999) >>> x.filled() array([ 1, 2, -999, 4, -999]) + >>> x.filled(fill_value=1000) + array([ 1, 2, 1000, 4, 1000]) >>> type(x.filled()) <class 'numpy.ndarray'> @@ -6220,9 +6243,11 @@ class mvoid(MaskedArray): Parameters ---------- - fill_value : scalar, optional - The value to use for invalid entries (None by default). - If None, the `fill_value` attribute is used instead. + fill_value : array_like, optional + The value to use for invalid entries. Can be scalar or + non-scalar. If latter is the case, the filled array should + be broadcastable over input array. Default is None, in + which case the `fill_value` attribute is used instead. Returns ------- diff --git a/numpy/random/tests/test_extending.py b/numpy/random/tests/test_extending.py index 6f0f7a462..efd922ff5 100644 --- a/numpy/random/tests/test_extending.py +++ b/numpy/random/tests/test_extending.py @@ -11,6 +11,12 @@ try: except ImportError: numba = None +try: + import cython +except ImportError: + cython = None + +@pytest.mark.skipif(cython is None, reason="requires cython") def test_cython(): curdir = os.getcwd() argv = sys.argv |