diff options
author | Eric Wieser <wieser.eric@gmail.com> | 2019-03-16 10:06:39 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-16 10:06:39 -0700 |
commit | 9a35ab439809270dfb582ed1ddf0376512ec4005 (patch) | |
tree | 763e0904dd9e2c370596a40c049e82b3298560a3 /numpy | |
parent | 0764929543c85decde9d664367dbf7d8f137fe1f (diff) | |
parent | df286d00bf6236f0158fc2cedd91dd3905fc05ca (diff) | |
download | numpy-9a35ab439809270dfb582ed1ddf0376512ec4005.tar.gz |
Merge branch 'master' into deprecate-float-order
Diffstat (limited to 'numpy')
29 files changed, 251 insertions, 227 deletions
diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py index d6c784ba1..cd2a6ce4e 100644 --- a/numpy/core/_add_newdocs.py +++ b/numpy/core/_add_newdocs.py @@ -2450,8 +2450,9 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('strides', add_newdoc('numpy.core.multiarray', 'ndarray', ('T', """ - Same as self.transpose(), except that self is returned if - self.ndim < 2. + The transposed array. + + Same as ``self.transpose()``. Examples -------- @@ -2468,6 +2469,10 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('T', >>> x.T array([ 1., 2., 3., 4.]) + See Also + -------- + transpose + """)) diff --git a/numpy/core/fromnumeric.py b/numpy/core/fromnumeric.py index 04b1e9fae..760577890 100644 --- a/numpy/core/fromnumeric.py +++ b/numpy/core/fromnumeric.py @@ -52,17 +52,20 @@ def _wrapit(obj, method, *args, **kwds): def _wrapfunc(obj, method, *args, **kwds): - try: - return getattr(obj, method)(*args, **kwds) - - # An AttributeError occurs if the object does not have - # such a method in its class. + bound = getattr(obj, method, None) + if bound is None: + return _wrapit(obj, method, *args, **kwds) - # A TypeError occurs if the object does have such a method - # in its class, but its signature is not identical to that - # of NumPy's. This situation has occurred in the case of - # a downstream library like 'pandas'. - except (AttributeError, TypeError): + try: + return bound(*args, **kwds) + except TypeError: + # A TypeError occurs if the object does have such a method in its + # class, but its signature is not identical to that of NumPy's. This + # situation has occurred in the case of a downstream library like + # 'pandas'. + # + # Call _wrapit from within the except clause to ensure a potential + # exception has a traceback chain. return _wrapit(obj, method, *args, **kwds) diff --git a/numpy/core/function_base.py b/numpy/core/function_base.py index f8800b83e..296213823 100644 --- a/numpy/core/function_base.py +++ b/numpy/core/function_base.py @@ -6,7 +6,7 @@ import operator from . import numeric as _nx from .numeric import (result_type, NaN, shares_memory, MAY_SHARE_BOUNDS, - TooHardError, asanyarray) + TooHardError, asanyarray, ndim) from numpy.core.multiarray import add_docstring from numpy.core import overrides @@ -140,7 +140,7 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, dtype = dt delta = stop - start - y = _nx.arange(0, num, dtype=dt).reshape((-1,) + (1,) * delta.ndim) + y = _nx.arange(0, num, dtype=dt).reshape((-1,) + (1,) * ndim(delta)) # In-place multiplication y *= delta/div is faster, but prevents the multiplicant # from overriding what class is produced, and thus prevents, e.g. use of Quantities, # see gh-7142. Hence, we multiply in place only for standard scalar types. diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py index 386049410..42fee4eb7 100644 --- a/numpy/core/numeric.py +++ b/numpy/core/numeric.py @@ -1203,20 +1203,18 @@ def _tensordot_dispatcher(a, b, axes=None): @array_function_dispatch(_tensordot_dispatcher) def tensordot(a, b, axes=2): """ - Compute tensor dot product along specified axes for arrays >= 1-D. + Compute tensor dot product along specified axes. - Given two tensors (arrays of dimension greater than or equal to one), - `a` and `b`, and an array_like object containing two array_like - objects, ``(a_axes, b_axes)``, sum the products of `a`'s and `b`'s - elements (components) over the axes specified by ``a_axes`` and - ``b_axes``. The third argument can be a single non-negative - integer_like scalar, ``N``; if it is such, then the last ``N`` - dimensions of `a` and the first ``N`` dimensions of `b` are summed - over. + Given two tensors, `a` and `b`, and an array_like object containing + two array_like objects, ``(a_axes, b_axes)``, sum the products of + `a`'s and `b`'s elements (components) over the axes specified by + ``a_axes`` and ``b_axes``. The third argument can be a single non-negative + integer_like scalar, ``N``; if it is such, then the last ``N`` dimensions + of `a` and the first ``N`` dimensions of `b` are summed over. Parameters ---------- - a, b : array_like, len(shape) >= 1 + a, b : array_like Tensors to "dot". axes : int or (2,) array_like diff --git a/numpy/core/records.py b/numpy/core/records.py index 42aca5b60..2adcdae61 100644 --- a/numpy/core/records.py +++ b/numpy/core/records.py @@ -610,9 +610,7 @@ def fromarrays(arrayList, dtype=None, shape=None, formats=None, # and determine the formats. formats = [] for obj in arrayList: - if not isinstance(obj, ndarray): - raise ValueError("item in the array list must be an ndarray.") - formats.append(obj.dtype.str) + formats.append(obj.dtype) if dtype is not None: descr = sb.dtype(dtype) @@ -768,7 +766,7 @@ def fromfile(fd, dtype=None, shape=None, offset=0, formats=None, >>> r.shape (10,) """ - + if dtype is None and formats is None: raise TypeError("fromfile() needs a 'dtype' or 'formats' argument") diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c index b2e329d45..42cd31069 100644 --- a/numpy/core/src/multiarray/ctors.c +++ b/numpy/core/src/multiarray/ctors.c @@ -2484,7 +2484,7 @@ PyArray_FromInterface(PyObject *origin) } #endif /* Get offset number from interface specification */ - attr = PyDict_GetItemString(origin, "offset"); + attr = PyDict_GetItemString(iface, "offset"); if (attr) { npy_longlong num = PyLong_AsLongLong(attr); if (error_converting(num)) { @@ -3693,32 +3693,12 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type, Py_DECREF(type); return NULL; } - if (Py_TYPE(buf)->tp_as_buffer == NULL -#if defined(NPY_PY3K) - || Py_TYPE(buf)->tp_as_buffer->bf_getbuffer == NULL -#else - || (Py_TYPE(buf)->tp_as_buffer->bf_getwritebuffer == NULL - && Py_TYPE(buf)->tp_as_buffer->bf_getreadbuffer == NULL) -#endif - ) { - PyObject *newbuf; - newbuf = PyObject_GetAttr(buf, npy_ma_str_buffer); - if (newbuf == NULL) { - Py_DECREF(type); - return NULL; - } - buf = newbuf; - } - else { - Py_INCREF(buf); - } #if defined(NPY_PY3K) if (PyObject_GetBuffer(buf, &view, PyBUF_WRITABLE|PyBUF_SIMPLE) < 0) { writeable = 0; PyErr_Clear(); if (PyObject_GetBuffer(buf, &view, PyBUF_SIMPLE) < 0) { - Py_DECREF(buf); Py_DECREF(type); return NULL; } @@ -3738,7 +3718,6 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type, writeable = 0; PyErr_Clear(); if (PyObject_AsReadBuffer(buf, (void *)&data, &ts) == -1) { - Py_DECREF(buf); Py_DECREF(type); return NULL; } @@ -3749,7 +3728,6 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type, PyErr_Format(PyExc_ValueError, "offset must be non-negative and no greater than buffer "\ "length (%" NPY_INTP_FMT ")", (npy_intp)ts); - Py_DECREF(buf); Py_DECREF(type); return NULL; } @@ -3763,7 +3741,6 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type, PyErr_SetString(PyExc_ValueError, "buffer size must be a multiple"\ " of element size"); - Py_DECREF(buf); Py_DECREF(type); return NULL; } @@ -3774,7 +3751,6 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type, PyErr_SetString(PyExc_ValueError, "buffer is smaller than requested"\ " size"); - Py_DECREF(buf); Py_DECREF(type); return NULL; } @@ -3784,7 +3760,6 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type, &PyArray_Type, type, 1, &n, NULL, data, NPY_ARRAY_DEFAULT, NULL, buf); - Py_DECREF(buf); if (ret == NULL) { return NULL; } diff --git a/numpy/core/src/multiarray/datetime.c b/numpy/core/src/multiarray/datetime.c index 54d19d993..a33f643f1 100644 --- a/numpy/core/src/multiarray/datetime.c +++ b/numpy/core/src/multiarray/datetime.c @@ -2468,6 +2468,9 @@ convert_pyobject_to_datetime(PyArray_DatetimeMetaData *meta, PyObject *obj, return -1; } *out = PyLong_AsLongLong(obj); + if (error_converting(*out)) { + return -1; + } return 0; } /* Datetime scalar */ @@ -2666,6 +2669,9 @@ convert_pyobject_to_timedelta(PyArray_DatetimeMetaData *meta, PyObject *obj, } *out = PyLong_AsLongLong(obj); + if (error_converting(*out)) { + return -1; + } return 0; } /* Timedelta scalar */ @@ -2853,6 +2859,9 @@ convert_pyobject_to_timedelta(PyArray_DatetimeMetaData *meta, PyObject *obj, } *out = PyLong_AsLongLong(obj); + if (error_converting(*out)) { + return -1; + } return 0; } else { diff --git a/numpy/core/src/multiarray/lowlevel_strided_loops.c.src b/numpy/core/src/multiarray/lowlevel_strided_loops.c.src index 16bacf1ab..63b2a8842 100644 --- a/numpy/core/src/multiarray/lowlevel_strided_loops.c.src +++ b/numpy/core/src/multiarray/lowlevel_strided_loops.c.src @@ -417,32 +417,31 @@ PyArray_GetStridedCopyFn(int aligned, npy_intp src_stride, #if !NPY_USE_UNALIGNED_ACCESS } else { - /* contiguous dst */ - if (itemsize != 0 && dst_stride == itemsize) { - /* contiguous src */ - if (itemsize != 0 && src_stride == itemsize) { - return &_contig_to_contig; - } - /* general src */ - else { - switch (itemsize) { - case 1: - return &_aligned_strided_to_contig_size1; + if (itemsize != 0) { + if (dst_stride == itemsize) { + /* contiguous dst */ + if (src_stride == itemsize) { + /* contiguous src, dst */ + return &_contig_to_contig; + } + else { + /* general src */ + switch (itemsize) { + case 1: + return &_aligned_strided_to_contig_size1; /**begin repeat * #elsize = 2, 4, 8, 16# */ - case @elsize@: - return &_strided_to_contig_size@elsize@; + case @elsize@: + return &_strided_to_contig_size@elsize@; /**end repeat**/ + } } - } - return &_strided_to_strided; - } - /* general dst */ - else { - /* contiguous src */ - if (itemsize != 0 && src_stride == itemsize) { + return &_strided_to_strided; + } + else if (src_stride == itemsize) { + /* contiguous src, general dst */ switch (itemsize) { case 1: return &_aligned_contig_to_strided_size1; @@ -456,18 +455,18 @@ PyArray_GetStridedCopyFn(int aligned, npy_intp src_stride, return &_strided_to_strided; } - /* general src */ - else { - switch (itemsize) { - case 1: - return &_aligned_strided_to_strided_size1; + } + else { + /* general src, dst */ + switch (itemsize) { + case 1: + return &_aligned_strided_to_strided_size1; /**begin repeat * #elsize = 2, 4, 8, 16# */ - case @elsize@: - return &_strided_to_strided_size@elsize@; + case @elsize@: + return &_strided_to_strided_size@elsize@; /**end repeat**/ - } } } } @@ -592,7 +591,7 @@ NPY_NO_EXPORT PyArray_StridedUnaryOp * /* contiguous dst */ if (itemsize != 0 && dst_stride == itemsize) { /* contiguous src */ - if (itemsize != 0 && src_stride == itemsize) { + if (src_stride == itemsize) { switch (itemsize) { /**begin repeat1 * #elsize = 2, 4, 8, 16# diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index ce6a3870f..1b825d318 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -4492,7 +4492,6 @@ NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_array = NULL; NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_array_prepare = NULL; NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_array_wrap = NULL; NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_array_finalize = NULL; -NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_buffer = NULL; NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_ufunc = NULL; NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_wrapped = NULL; NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_order = NULL; @@ -4509,7 +4508,6 @@ intern_strings(void) npy_ma_str_array_prepare = PyUString_InternFromString("__array_prepare__"); npy_ma_str_array_wrap = PyUString_InternFromString("__array_wrap__"); npy_ma_str_array_finalize = PyUString_InternFromString("__array_finalize__"); - npy_ma_str_buffer = PyUString_InternFromString("__buffer__"); npy_ma_str_ufunc = PyUString_InternFromString("__array_ufunc__"); npy_ma_str_wrapped = PyUString_InternFromString("__wrapped__"); npy_ma_str_order = PyUString_InternFromString("order"); @@ -4521,7 +4519,7 @@ intern_strings(void) return npy_ma_str_array && npy_ma_str_array_prepare && npy_ma_str_array_wrap && npy_ma_str_array_finalize && - npy_ma_str_buffer && npy_ma_str_ufunc && npy_ma_str_wrapped && + npy_ma_str_ufunc && npy_ma_str_wrapped && npy_ma_str_order && npy_ma_str_copy && npy_ma_str_dtype && npy_ma_str_ndmin && npy_ma_str_axis1 && npy_ma_str_axis2; } diff --git a/numpy/core/src/multiarray/multiarraymodule.h b/numpy/core/src/multiarray/multiarraymodule.h index 60a3965c9..6d33c3295 100644 --- a/numpy/core/src/multiarray/multiarraymodule.h +++ b/numpy/core/src/multiarray/multiarraymodule.h @@ -5,7 +5,6 @@ NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_array; NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_array_prepare; NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_array_wrap; NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_array_finalize; -NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_buffer; NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_ufunc; NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_wrapped; NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_order; diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py index 43d29f42d..8d480e7a3 100644 --- a/numpy/core/tests/test_datetime.py +++ b/numpy/core/tests/test_datetime.py @@ -1543,6 +1543,12 @@ class TestDateTime(object): assert_equal(x[0].astype(np.int64), 322689600000000000) + # gh-13062 + with pytest.raises(OverflowError): + np.datetime64(2**64, 'D') + with pytest.raises(OverflowError): + np.timedelta64(2**64, 'D') + def test_datetime_as_string(self): # Check all the units with default string conversion date = '1959-10-13' diff --git a/numpy/core/tests/test_function_base.py b/numpy/core/tests/test_function_base.py index 459bacab0..8b820bd75 100644 --- a/numpy/core/tests/test_function_base.py +++ b/numpy/core/tests/test_function_base.py @@ -362,3 +362,9 @@ class TestLinspace(object): assert_(isinstance(y, tuple) and len(y) == 2 and len(y[0]) == num and isnan(y[1]), 'num={0}, endpoint={1}'.format(num, ept)) + + def test_object(self): + start = array(1, dtype='O') + stop = array(2, dtype='O') + y = linspace(start, stop, 3) + assert_array_equal(y, array([1., 1.5, 2.])) diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index 4f64661bd..b8d5dc71f 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -7105,6 +7105,19 @@ def test_array_interface_empty_shape(): assert_equal(arr1, arr2) assert_equal(arr1, arr3) +def test_array_interface_offset(): + arr = np.array([1, 2, 3], dtype='int32') + interface = dict(arr.__array_interface__) + interface['data'] = memoryview(arr) + interface['shape'] = (2,) + interface['offset'] = 4 + + + class DummyArray(object): + __array_interface__ = interface + + arr1 = np.asarray(DummyArray()) + assert_equal(arr1, arr[1:]) def test_flat_element_deletion(): it = np.ones(3).flat diff --git a/numpy/core/tests/test_records.py b/numpy/core/tests/test_records.py index f0ec38029..878ef2ac9 100644 --- a/numpy/core/tests/test_records.py +++ b/numpy/core/tests/test_records.py @@ -437,6 +437,13 @@ class TestRecord(object): arr = np.zeros((3,), dtype=[('x', int), ('y', int)]) assert_raises(ValueError, lambda: arr[['nofield']]) + def test_fromarrays_nested_structured_arrays(self): + arrays = [ + np.arange(10), + np.ones(10, dtype=[('a', '<u2'), ('b', '<f4')]), + ] + arr = np.rec.fromarrays(arrays) # ValueError? + def test_find_duplicate(): l1 = [1, 2, 3, 4, 5, 6] diff --git a/numpy/core/tests/test_scalarmath.py b/numpy/core/tests/test_scalarmath.py index 51bcf2b8d..ebba457e3 100644 --- a/numpy/core/tests/test_scalarmath.py +++ b/numpy/core/tests/test_scalarmath.py @@ -422,7 +422,7 @@ class TestConversion(object): @pytest.mark.skipif(np.finfo(np.double) == np.finfo(np.longdouble), reason="long double is same as double") - @pytest.mark.skipif(platform.machine().startswith("ppc64"), + @pytest.mark.skipif(platform.machine().startswith("ppc"), reason="IBM double double") def test_int_from_huge_longdouble(self): # Produce a longdouble that would overflow a double, diff --git a/numpy/distutils/ccompiler.py b/numpy/distutils/ccompiler.py index 552b9566f..14451fa66 100644 --- a/numpy/distutils/ccompiler.py +++ b/numpy/distutils/ccompiler.py @@ -796,63 +796,3 @@ for _cc in ['msvc9', 'msvc', '_msvc', 'bcpp', 'cygwinc', 'emxc', 'unixc']: if _m is not None: setattr(_m, 'gen_lib_options', gen_lib_options) - -##Fix distutils.util.split_quoted: -# NOTE: I removed this fix in revision 4481 (see ticket #619), but it appears -# that removing this fix causes f2py problems on Windows XP (see ticket #723). -# Specifically, on WinXP when gfortran is installed in a directory path, which -# contains spaces, then f2py is unable to find it. -import string -_wordchars_re = re.compile(r'[^\\\'\"%s ]*' % string.whitespace) -_squote_re = re.compile(r"'(?:[^'\\]|\\.)*'") -_dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"') -_has_white_re = re.compile(r'\s') -def split_quoted(s): - s = s.strip() - words = [] - pos = 0 - - while s: - m = _wordchars_re.match(s, pos) - end = m.end() - if end == len(s): - words.append(s[:end]) - break - - if s[end] in string.whitespace: # unescaped, unquoted whitespace: now - words.append(s[:end]) # we definitely have a word delimiter - s = s[end:].lstrip() - pos = 0 - - elif s[end] == '\\': # preserve whatever is being escaped; - # will become part of the current word - s = s[:end] + s[end+1:] - pos = end+1 - - else: - if s[end] == "'": # slurp singly-quoted string - m = _squote_re.match(s, end) - elif s[end] == '"': # slurp doubly-quoted string - m = _dquote_re.match(s, end) - else: - raise RuntimeError("this can't happen (bad char '%c')" % s[end]) - - if m is None: - raise ValueError("bad string (mismatched %s quotes?)" % s[end]) - - (beg, end) = m.span() - if _has_white_re.search(s[beg+1:end-1]): - s = s[:beg] + s[beg+1:end-1] + s[end:] - pos = m.end() - 2 - else: - # Keeping quotes when a quoted word does not contain - # white-space. XXX: send a patch to distutils - pos = m.end() - - if pos >= len(s): - words.append(s) - break - - return words -ccompiler.split_quoted = split_quoted -##Fix distutils.util.split_quoted: diff --git a/numpy/distutils/exec_command.py b/numpy/distutils/exec_command.py index ede347b03..2e7b9e463 100644 --- a/numpy/distutils/exec_command.py +++ b/numpy/distutils/exec_command.py @@ -57,6 +57,7 @@ import os import sys import subprocess import locale +import warnings from numpy.distutils.misc_util import is_sequence, make_temp_file from numpy.distutils import log @@ -105,6 +106,9 @@ def forward_bytes_to_stdout(val): def temp_file_name(): + # 2019-01-30, 1.17 + warnings.warn('temp_file_name is deprecated since NumPy v1.17, use ' + 'tempfile.mkstemp instead', DeprecationWarning, stacklevel=1) fo, name = make_temp_file() fo.close() return name @@ -179,24 +183,14 @@ def _update_environment( **env ): for name, value in env.items(): os.environ[name] = value or '' -def _supports_fileno(stream): - """ - Returns True if 'stream' supports the file descriptor and allows fileno(). - """ - if hasattr(stream, 'fileno'): - try: - stream.fileno() - return True - except IOError: - return False - else: - return False - def exec_command(command, execute_in='', use_shell=None, use_tee=None, _with_python = 1, **env ): """ Return (status,output) of executed command. + .. deprecated:: 1.17 + Use subprocess.Popen instead + Parameters ---------- command : str @@ -220,6 +214,9 @@ def exec_command(command, execute_in='', use_shell=None, use_tee=None, Wild cards will not work for non-posix systems or when use_shell=0. """ + # 2019-01-30, 1.17 + warnings.warn('exec_command is deprecated since NumPy v1.17, use ' + 'subprocess.Popen instead', DeprecationWarning, stacklevel=1) log.debug('exec_command(%r,%s)' % (command,\ ','.join(['%s=%r'%kv for kv in env.items()]))) diff --git a/numpy/distutils/fcompiler/environment.py b/numpy/distutils/fcompiler/environment.py index 4238f35cb..73a5e98e1 100644 --- a/numpy/distutils/fcompiler/environment.py +++ b/numpy/distutils/fcompiler/environment.py @@ -51,13 +51,16 @@ class EnvironmentConfig(object): def _get_var(self, name, conf_desc): hook, envvar, confvar, convert, append = conf_desc + if convert is None: + convert = lambda x: x var = self._hook_handler(name, hook) if envvar is not None: envvar_contents = os.environ.get(envvar) if envvar_contents is not None: + envvar_contents = convert(envvar_contents) if var and append: if os.environ.get('NPY_DISTUTILS_APPEND_FLAGS', '0') == '1': - var = var + [envvar_contents] + var.extend(envvar_contents) else: var = envvar_contents if 'NPY_DISTUTILS_APPEND_FLAGS' not in os.environ.keys(): @@ -70,11 +73,12 @@ class EnvironmentConfig(object): else: var = envvar_contents if confvar is not None and self._conf: - var = self._conf.get(confvar, (None, var))[1] - if convert is not None: - var = convert(var) + if confvar in self._conf: + source, confvar_contents = self._conf[confvar] + var = convert(confvar_contents) return var + def clone(self, hook_handler): ec = self.__class__(distutils_section=self._distutils_section, **self._conf_keys) diff --git a/numpy/distutils/system_info.py b/numpy/distutils/system_info.py index 242494331..e723b85b8 100644 --- a/numpy/distutils/system_info.py +++ b/numpy/distutils/system_info.py @@ -1743,6 +1743,8 @@ class blas_info(system_info): res = "blas" except distutils.ccompiler.CompileError: res = None + except distutils.ccompiler.LinkError: + res = None finally: shutil.rmtree(tmpdir) return res diff --git a/numpy/distutils/tests/test_exec_command.py b/numpy/distutils/tests/test_exec_command.py index 8bd265007..37912f5ba 100644 --- a/numpy/distutils/tests/test_exec_command.py +++ b/numpy/distutils/tests/test_exec_command.py @@ -6,7 +6,7 @@ from tempfile import TemporaryFile from numpy.distutils import exec_command from numpy.distutils.exec_command import get_pythonexe -from numpy.testing import tempdir, assert_ +from numpy.testing import tempdir, assert_, assert_warns # In python 3 stdout, stderr are text (unicode compliant) devices, so to # emulate them import StringIO from the io module. @@ -71,27 +71,31 @@ def test_exec_command_stdout(): # Test posix version: with redirect_stdout(StringIO()): with redirect_stderr(TemporaryFile()): - exec_command.exec_command("cd '.'") + with assert_warns(DeprecationWarning): + exec_command.exec_command("cd '.'") if os.name == 'posix': # Test general (non-posix) version: with emulate_nonposix(): with redirect_stdout(StringIO()): with redirect_stderr(TemporaryFile()): - exec_command.exec_command("cd '.'") + with assert_warns(DeprecationWarning): + exec_command.exec_command("cd '.'") def test_exec_command_stderr(): # Test posix version: with redirect_stdout(TemporaryFile(mode='w+')): with redirect_stderr(StringIO()): - exec_command.exec_command("cd '.'") + with assert_warns(DeprecationWarning): + exec_command.exec_command("cd '.'") if os.name == 'posix': # Test general (non-posix) version: with emulate_nonposix(): with redirect_stdout(TemporaryFile()): with redirect_stderr(StringIO()): - exec_command.exec_command("cd '.'") + with assert_warns(DeprecationWarning): + exec_command.exec_command("cd '.'") class TestExecCommand(object): @@ -205,11 +209,12 @@ class TestExecCommand(object): def test_basic(self): with redirect_stdout(StringIO()): with redirect_stderr(StringIO()): - if os.name == "posix": - self.check_posix(use_tee=0) - self.check_posix(use_tee=1) - elif os.name == "nt": - self.check_nt(use_tee=0) - self.check_nt(use_tee=1) - self.check_execute_in(use_tee=0) - self.check_execute_in(use_tee=1) + with assert_warns(DeprecationWarning): + if os.name == "posix": + self.check_posix(use_tee=0) + self.check_posix(use_tee=1) + elif os.name == "nt": + self.check_nt(use_tee=0) + self.check_nt(use_tee=1) + self.check_execute_in(use_tee=0) + self.check_execute_in(use_tee=1) diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py index c4a650585..0e9cba1eb 100755 --- a/numpy/f2py/crackfortran.py +++ b/numpy/f2py/crackfortran.py @@ -2399,7 +2399,7 @@ def _selected_real_kind_func(p, r=0, radix=0): if p < 16: return 8 machine = platform.machine().lower() - if machine.startswith(('aarch64', 'power', 'ppc64', 's390x', 'sparc')): + if machine.startswith(('aarch64', 'power', 'ppc', 'riscv', 's390x', 'sparc')): if p <= 20: return 16 else: diff --git a/numpy/lib/arraypad.py b/numpy/lib/arraypad.py index b236cc449..630767dc5 100644 --- a/numpy/lib/arraypad.py +++ b/numpy/lib/arraypad.py @@ -957,12 +957,12 @@ def _as_pairs(x, ndim, as_index=False): # Public functions -def _pad_dispatcher(array, pad_width, mode, **kwargs): +def _pad_dispatcher(array, pad_width, mode=None, **kwargs): return (array,) @array_function_dispatch(_pad_dispatcher, module='numpy') -def pad(array, pad_width, mode, **kwargs): +def pad(array, pad_width, mode='constant', **kwargs): """ Pads an array. @@ -977,10 +977,10 @@ def pad(array, pad_width, mode, **kwargs): ((before, after),) yields same before and after pad for each axis. (pad,) or int is a shortcut for before = after = pad width for all axes. - mode : str or function + mode : str or function, optional One of the following string values or a user supplied function. - 'constant' + 'constant' (default) Pads with a constant value. 'edge' Pads with the edge values of array. diff --git a/numpy/lib/format.py b/numpy/lib/format.py index 7648be615..4da1022ca 100644 --- a/numpy/lib/format.py +++ b/numpy/lib/format.py @@ -524,7 +524,7 @@ def _read_array_header(fp, version): elif version == (2, 0): hlength_type = '<I' else: - raise ValueError("Invalid version %r" % version) + raise ValueError("Invalid version {!r}".format(version)) hlength_str = _read_bytes(fp, struct.calcsize(hlength_type), "array header length") header_length = struct.unpack(hlength_type, hlength_str)[0] @@ -540,29 +540,29 @@ def _read_array_header(fp, version): try: d = safe_eval(header) except SyntaxError as e: - msg = "Cannot parse header: %r\nException: %r" - raise ValueError(msg % (header, e)) + msg = "Cannot parse header: {!r}\nException: {!r}" + raise ValueError(msg.format(header, e)) if not isinstance(d, dict): - msg = "Header is not a dictionary: %r" - raise ValueError(msg % d) + msg = "Header is not a dictionary: {!r}" + raise ValueError(msg.format(d)) keys = sorted(d.keys()) if keys != ['descr', 'fortran_order', 'shape']: - msg = "Header does not contain the correct keys: %r" - raise ValueError(msg % (keys,)) + msg = "Header does not contain the correct keys: {!r}" + raise ValueError(msg.format(keys)) # Sanity-check the values. if (not isinstance(d['shape'], tuple) or not numpy.all([isinstance(x, (int, long)) for x in d['shape']])): - msg = "shape is not valid: %r" - raise ValueError(msg % (d['shape'],)) + msg = "shape is not valid: {!r}" + raise ValueError(msg.format(d['shape'])) if not isinstance(d['fortran_order'], bool): - msg = "fortran_order is not a valid bool: %r" - raise ValueError(msg % (d['fortran_order'],)) + msg = "fortran_order is not a valid bool: {!r}" + raise ValueError(msg.format(d['fortran_order'])) try: dtype = descr_to_dtype(d['descr']) except TypeError as e: - msg = "descr is not a valid dtype descriptor: %r" - raise ValueError(msg % (d['descr'],)) + msg = "descr is not a valid dtype descriptor: {!r}" + raise ValueError(msg.format(d['descr'])) return d['shape'], d['fortran_order'], dtype diff --git a/numpy/lib/tests/test_arraypad.py b/numpy/lib/tests/test_arraypad.py index a9030e737..b7393294a 100644 --- a/numpy/lib/tests/test_arraypad.py +++ b/numpy/lib/tests/test_arraypad.py @@ -1249,10 +1249,9 @@ def test_kwargs(mode): np.pad([1, 2, 3], 1, mode, **{key: value}) -def test_missing_mode(): - match = "missing 1 required positional argument: 'mode'" - with pytest.raises(TypeError, match=match): - np.pad(np.ones((5, 6)), 4) +def test_constant_zero_default(): + arr = np.array([1, 1]) + assert_array_equal(np.pad(arr, 2), [0, 0, 1, 1, 0, 0]) @pytest.mark.parametrize("mode", _all_modes.keys()) diff --git a/numpy/lib/tests/test_utils.py b/numpy/lib/tests/test_utils.py index 2723f3440..9673a05fa 100644 --- a/numpy/lib/tests/test_utils.py +++ b/numpy/lib/tests/test_utils.py @@ -1,5 +1,6 @@ from __future__ import division, absolute_import, print_function +import inspect import sys import pytest @@ -38,6 +39,32 @@ def old_func3(self, x): new_func3 = deprecate(old_func3, old_name="old_func3", new_name="new_func3") +def old_func4(self, x): + """Summary. + + Further info. + """ + return x +new_func4 = deprecate(old_func4) + + +def old_func5(self, x): + """Summary. + + Bizarre indentation. + """ + return x +new_func5 = deprecate(old_func5) + + +def old_func6(self, x): + """ + Also in PEP-257. + """ + return x +new_func6 = deprecate(old_func6) + + def test_deprecate_decorator(): assert_('deprecated' in old_func.__doc__) @@ -51,6 +78,25 @@ def test_deprecate_fn(): assert_('new_func3' in new_func3.__doc__) +@pytest.mark.skipif(sys.flags.optimize == 2, reason="-OO discards docstrings") +def test_deprecate_help_indentation(): + _compare_docs(old_func4, new_func4) + _compare_docs(old_func5, new_func5) + _compare_docs(old_func6, new_func6) + + +def _compare_docs(old_func, new_func): + old_doc = inspect.getdoc(old_func) + new_doc = inspect.getdoc(new_func) + index = new_doc.index('\n\n') + 2 + assert_equal(new_doc[index:], old_doc) + + +@pytest.mark.skipif(sys.flags.optimize == 2, reason="-OO discards docstrings") +def test_deprecate_preserve_whitespace(): + assert_('\n Bizarre' in new_func5.__doc__) + + def test_safe_eval_nameconstant(): # Test if safe_eval supports Python 3.4 _ast.NameConstant utils.safe_eval('None') diff --git a/numpy/lib/utils.py b/numpy/lib/utils.py index 6b112f37a..718b55c4b 100644 --- a/numpy/lib/utils.py +++ b/numpy/lib/utils.py @@ -105,6 +105,20 @@ class _Deprecate(object): if doc is None: doc = depdoc else: + lines = doc.expandtabs().split('\n') + indent = _get_indent(lines[1:]) + if lines[0].lstrip(): + # Indent the original first line to let inspect.cleandoc() + # dedent the docstring despite the deprecation notice. + doc = indent * ' ' + doc + else: + # Remove the same leading blank lines as cleandoc() would. + skip = len(lines[0]) + 1 + for line in lines[1:]: + if len(line) > indent: + break + skip += len(line) + 1 + doc = doc[skip:] doc = '\n\n'.join([depdoc, doc]) newfunc.__doc__ = doc try: @@ -115,6 +129,21 @@ class _Deprecate(object): newfunc.__dict__.update(d) return newfunc + +def _get_indent(lines): + """ + Determines the leading whitespace that could be removed from all the lines. + """ + indent = sys.maxsize + for line in lines: + content = len(line.lstrip()) + if content: + indent = min(indent, len(line) - content) + if indent == sys.maxsize: + indent = 0 + return indent + + def deprecate(*args, **kwargs): """ Issues a DeprecationWarning, adds warning to `old_name`'s diff --git a/numpy/polynomial/hermite.py b/numpy/polynomial/hermite.py index e925c4304..6dee0b359 100644 --- a/numpy/polynomial/hermite.py +++ b/numpy/polynomial/hermite.py @@ -1211,17 +1211,7 @@ def hermvander2d(x, y, deg): .. versionadded:: 1.7.0 """ - ideg = [int(d) for d in deg] - is_valid = [id == d and id >= 0 for id, d in zip(ideg, deg)] - if is_valid != [1, 1]: - raise ValueError("degrees must be non-negative integers") - degx, degy = ideg - x, y = np.array((x, y), copy=0) + 0.0 - - vx = hermvander(x, degx) - vy = hermvander(y, degy) - v = vx[..., None]*vy[..., None,:] - return v.reshape(v.shape[:-2] + (-1,)) + return pu._vander2d(hermvander, x, y, deg) def hermvander3d(x, y, z, deg): @@ -1275,18 +1265,7 @@ def hermvander3d(x, y, z, deg): .. versionadded:: 1.7.0 """ - ideg = [int(d) for d in deg] - is_valid = [id == d and id >= 0 for id, d in zip(ideg, deg)] - if is_valid != [1, 1, 1]: - raise ValueError("degrees must be non-negative integers") - degx, degy, degz = ideg - x, y, z = np.array((x, y, z), copy=0) + 0.0 - - vx = hermvander(x, degx) - vy = hermvander(y, degy) - vz = hermvander(z, degz) - v = vx[..., None, None]*vy[..., None,:, None]*vz[..., None, None,:] - return v.reshape(v.shape[:-3] + (-1,)) + return pu._vander3d(hermvander, x, y, z, deg) def hermfit(x, y, deg, rcond=None, full=False, w=None): diff --git a/numpy/random/mtrand/mtrand.pyx b/numpy/random/mtrand/mtrand.pyx index a19bdeffb..856198f24 100644 --- a/numpy/random/mtrand/mtrand.pyx +++ b/numpy/random/mtrand/mtrand.pyx @@ -1170,6 +1170,9 @@ cdef class RandomState: raise ValueError("Cannot take a larger sample than " "population when 'replace=False'") + if size < 0: + raise ValueError("negative dimensions are not allowed") + if p is not None: if np.count_nonzero(p > 0) < size: raise ValueError("Fewer non-zero entries in p than size") @@ -1650,11 +1653,11 @@ cdef class RandomState: Verify the mean and the variance: - >>> abs(mu - np.mean(s)) < 0.01 - True + >>> abs(mu - np.mean(s)) + 0.0 # may vary - >>> abs(sigma - np.std(s, ddof=1)) < 0.01 - True + >>> abs(sigma - np.std(s, ddof=1)) + 0.1 # may vary Display the histogram of the samples, along with the probability density function: diff --git a/numpy/random/tests/test_random.py b/numpy/random/tests/test_random.py index 656e38dc8..eb06dc691 100644 --- a/numpy/random/tests/test_random.py +++ b/numpy/random/tests/test_random.py @@ -400,6 +400,10 @@ class TestRandomDist(object): assert_raises(ValueError, sample, [1, 2], 3, p=[1.1, -0.1]) assert_raises(ValueError, sample, [1, 2], 3, p=[0.4, 0.4]) assert_raises(ValueError, sample, [1, 2, 3], 4, replace=False) + # gh-13087 + assert_raises(ValueError, sample, [1, 2, 3], -2, replace=False) + assert_raises(ValueError, sample, [1, 2, 3], (-1,), replace=False) + assert_raises(ValueError, sample, [1, 2, 3], (-1, 1), replace=False) assert_raises(ValueError, sample, [1, 2, 3], 2, replace=False, p=[1, 0, 0]) |