diff options
author | Stephan Hoyer <shoyer@google.com> | 2018-11-13 09:38:07 -0800 |
---|---|---|
committer | Stephan Hoyer <shoyer@google.com> | 2018-11-13 20:24:31 -0800 |
commit | 4d24bbda32d133d51940b0691bd9b428d4198eaa (patch) | |
tree | c018ac1ada700494f1bb404a8ae9f1346720ebfe /numpy/core | |
parent | cd39348e8593dc2b41e2516fbdd8a69b0f0bda6e (diff) | |
download | numpy-4d24bbda32d133d51940b0691bd9b428d4198eaa.tar.gz |
ENH: set correct __module__ for objects in numpy's public API
Fixes GH-12271
Tests verify that everything in ``dir(numpy)`` either has ``__module__`` set to
``'numpy'``, or appears in an explicit whitelist of undocumented functions and
exported bulitins. These should eventually be documented or removed.
I also identified a handful of functions for which I had accidentally not setup
dispatch for with ``__array_function__`` before, because they were listed under
"ndarray methods" in ``_add_newdocs.py``. I guess that should be a lesson in
trusting code comments :).
Diffstat (limited to 'numpy/core')
-rw-r--r-- | numpy/core/_add_newdocs.py | 178 | ||||
-rw-r--r-- | numpy/core/_internal.py | 3 | ||||
-rw-r--r-- | numpy/core/arrayprint.py | 10 | ||||
-rw-r--r-- | numpy/core/defchararray.py | 2 | ||||
-rw-r--r-- | numpy/core/function_base.py | 4 | ||||
-rw-r--r-- | numpy/core/getlimits.py | 3 | ||||
-rw-r--r-- | numpy/core/machar.py | 2 | ||||
-rw-r--r-- | numpy/core/memmap.py | 3 | ||||
-rw-r--r-- | numpy/core/multiarray.py | 479 | ||||
-rw-r--r-- | numpy/core/numeric.py | 23 | ||||
-rw-r--r-- | numpy/core/numerictypes.py | 14 | ||||
-rw-r--r-- | numpy/core/overrides.py | 6 | ||||
-rw-r--r-- | numpy/core/records.py | 3 | ||||
-rw-r--r-- | numpy/core/tests/test_overrides.py | 3 |
14 files changed, 550 insertions, 183 deletions
diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py index f67964d84..78ff15ba4 100644 --- a/numpy/core/_add_newdocs.py +++ b/numpy/core/_add_newdocs.py @@ -4552,184 +4552,6 @@ add_newdoc('numpy.core.umath', 'seterrobj', # ############################################################################## -add_newdoc('numpy.core.multiarray', 'bincount', - """ - bincount(x, weights=None, minlength=0) - - Count number of occurrences of each value in array of non-negative ints. - - The number of bins (of size 1) is one larger than the largest value in - `x`. If `minlength` is specified, there will be at least this number - of bins in the output array (though it will be longer if necessary, - depending on the contents of `x`). - Each bin gives the number of occurrences of its index value in `x`. - If `weights` is specified the input array is weighted by it, i.e. if a - value ``n`` is found at position ``i``, ``out[n] += weight[i]`` instead - of ``out[n] += 1``. - - Parameters - ---------- - x : array_like, 1 dimension, nonnegative ints - Input array. - weights : array_like, optional - Weights, array of the same shape as `x`. - minlength : int, optional - A minimum number of bins for the output array. - - .. versionadded:: 1.6.0 - - Returns - ------- - out : ndarray of ints - The result of binning the input array. - The length of `out` is equal to ``np.amax(x)+1``. - - Raises - ------ - ValueError - If the input is not 1-dimensional, or contains elements with negative - values, or if `minlength` is negative. - TypeError - If the type of the input is float or complex. - - See Also - -------- - histogram, digitize, unique - - Examples - -------- - >>> np.bincount(np.arange(5)) - array([1, 1, 1, 1, 1]) - >>> np.bincount(np.array([0, 1, 1, 3, 2, 1, 7])) - array([1, 3, 1, 1, 0, 0, 0, 1]) - - >>> x = np.array([0, 1, 1, 3, 2, 1, 7, 23]) - >>> np.bincount(x).size == np.amax(x)+1 - True - - The input array needs to be of integer dtype, otherwise a - TypeError is raised: - - >>> np.bincount(np.arange(5, dtype=float)) - Traceback (most recent call last): - File "<stdin>", line 1, in <module> - TypeError: array cannot be safely cast to required type - - A possible use of ``bincount`` is to perform sums over - variable-size chunks of an array, using the ``weights`` keyword. - - >>> w = np.array([0.3, 0.5, 0.2, 0.7, 1., -0.6]) # weights - >>> x = np.array([0, 1, 1, 2, 2, 2]) - >>> np.bincount(x, weights=w) - array([ 0.3, 0.7, 1.1]) - - """) - -add_newdoc('numpy.core.multiarray', 'ravel_multi_index', - """ - ravel_multi_index(multi_index, dims, mode='raise', order='C') - - Converts a tuple of index arrays into an array of flat - indices, applying boundary modes to the multi-index. - - Parameters - ---------- - multi_index : tuple of array_like - A tuple of integer arrays, one array for each dimension. - dims : tuple of ints - The shape of array into which the indices from ``multi_index`` apply. - mode : {'raise', 'wrap', 'clip'}, optional - Specifies how out-of-bounds indices are handled. Can specify - either one mode or a tuple of modes, one mode per index. - - * 'raise' -- raise an error (default) - * 'wrap' -- wrap around - * 'clip' -- clip to the range - - In 'clip' mode, a negative index which would normally - wrap will clip to 0 instead. - order : {'C', 'F'}, optional - Determines whether the multi-index should be viewed as - indexing in row-major (C-style) or column-major - (Fortran-style) order. - - Returns - ------- - raveled_indices : ndarray - An array of indices into the flattened version of an array - of dimensions ``dims``. - - See Also - -------- - unravel_index - - Notes - ----- - .. versionadded:: 1.6.0 - - Examples - -------- - >>> arr = np.array([[3,6,6],[4,5,1]]) - >>> np.ravel_multi_index(arr, (7,6)) - array([22, 41, 37]) - >>> np.ravel_multi_index(arr, (7,6), order='F') - array([31, 41, 13]) - >>> np.ravel_multi_index(arr, (4,6), mode='clip') - array([22, 23, 19]) - >>> np.ravel_multi_index(arr, (4,4), mode=('clip','wrap')) - array([12, 13, 13]) - - >>> np.ravel_multi_index((3,1,4,1), (6,7,8,9)) - 1621 - """) - -add_newdoc('numpy.core.multiarray', 'unravel_index', - """ - unravel_index(indices, shape, order='C') - - Converts a flat index or array of flat indices into a tuple - of coordinate arrays. - - Parameters - ---------- - indices : array_like - An integer array whose elements are indices into the flattened - version of an array of dimensions ``shape``. Before version 1.6.0, - this function accepted just one index value. - shape : tuple of ints - The shape of the array to use for unraveling ``indices``. - - .. versionchanged:: 1.16.0 - Renamed from ``dims`` to ``shape``. - - order : {'C', 'F'}, optional - Determines whether the indices should be viewed as indexing in - row-major (C-style) or column-major (Fortran-style) order. - - .. versionadded:: 1.6.0 - - Returns - ------- - unraveled_coords : tuple of ndarray - Each array in the tuple has the same shape as the ``indices`` - array. - - See Also - -------- - ravel_multi_index - - Examples - -------- - >>> np.unravel_index([22, 41, 37], (7,6)) - (array([3, 6, 6]), array([4, 5, 1])) - >>> np.unravel_index([31, 41, 13], (7,6), order='F') - (array([3, 6, 6]), array([4, 5, 1])) - - >>> np.unravel_index(1621, (6,7,8,9)) - (3, 1, 4, 1) - - """) - add_newdoc('numpy.core.multiarray', 'add_docstring', """ add_docstring(obj, docstring) diff --git a/numpy/core/_internal.py b/numpy/core/_internal.py index 30069f0ca..b44494822 100644 --- a/numpy/core/_internal.py +++ b/numpy/core/_internal.py @@ -10,6 +10,7 @@ import re import sys from numpy.compat import unicode +from numpy.core.overrides import set_module from .multiarray import dtype, array, ndarray try: import ctypes @@ -718,9 +719,11 @@ def _lcm(a, b): return a // _gcd(a, b) * b # Exception used in shares_memory() +@set_module('numpy') class TooHardError(RuntimeError): pass +@set_module('numpy') class AxisError(ValueError, IndexError): """ Axis supplied was invalid. """ def __init__(self, axis, ndim=None, msg_prefix=None): diff --git a/numpy/core/arrayprint.py b/numpy/core/arrayprint.py index b578fab54..075d75340 100644 --- a/numpy/core/arrayprint.py +++ b/numpy/core/arrayprint.py @@ -48,7 +48,7 @@ from .fromnumeric import ravel, any from .numeric import concatenate, asarray, errstate from .numerictypes import (longlong, intc, int_, float_, complex_, bool_, flexible) -from .overrides import array_function_dispatch +from .overrides import array_function_dispatch, set_module import warnings import contextlib @@ -89,6 +89,8 @@ def _make_options_dict(precision=None, threshold=None, edgeitems=None, return options + +@set_module('numpy') def set_printoptions(precision=None, threshold=None, edgeitems=None, linewidth=None, suppress=None, nanstr=None, infstr=None, formatter=None, sign=None, floatmode=None, **kwarg): @@ -250,6 +252,7 @@ def set_printoptions(precision=None, threshold=None, edgeitems=None, set_legacy_print_mode(0) +@set_module('numpy') def get_printoptions(): """ Return the current print options. @@ -279,6 +282,7 @@ def get_printoptions(): return _format_options.copy() +@set_module('numpy') @contextlib.contextmanager def printoptions(*args, **kwargs): """Context manager for setting print options. @@ -976,6 +980,8 @@ class LongFloatFormat(FloatingFormat): DeprecationWarning, stacklevel=2) super(LongFloatFormat, self).__init__(*args, **kwargs) + +@set_module('numpy') def format_float_scientific(x, precision=None, unique=True, trim='k', sign=False, pad_left=None, exp_digits=None): """ @@ -1043,6 +1049,8 @@ def format_float_scientific(x, precision=None, unique=True, trim='k', trim=trim, sign=sign, pad_left=pad_left, exp_digits=exp_digits) + +@set_module('numpy') def format_float_positional(x, precision=None, unique=True, fractional=True, trim='k', sign=False, pad_left=None, pad_right=None): diff --git a/numpy/core/defchararray.py b/numpy/core/defchararray.py index e86086012..12ba3f02e 100644 --- a/numpy/core/defchararray.py +++ b/numpy/core/defchararray.py @@ -23,6 +23,7 @@ from .numerictypes import string_, unicode_, integer, object_, bool_, character from .numeric import ndarray, compare_chararrays from .numeric import array as narray from numpy.core.multiarray import _vec_string +from numpy.core.overrides import set_module from numpy.core import overrides from numpy.compat import asbytes, long import numpy @@ -1820,6 +1821,7 @@ def isdecimal(a): return _vec_string(a, bool_, 'isdecimal') +@set_module('numpy') class chararray(ndarray): """ chararray(shape, itemsize=1, unicode=False, buffer=None, offset=0, diff --git a/numpy/core/function_base.py b/numpy/core/function_base.py index 799b1418d..b3dd313cf 100644 --- a/numpy/core/function_base.py +++ b/numpy/core/function_base.py @@ -7,6 +7,7 @@ from . import numeric as _nx from .numeric import (result_type, NaN, shares_memory, MAY_SHARE_BOUNDS, TooHardError,asanyarray) from numpy.core.multiarray import add_docstring +from numpy.core.overrides import set_module __all__ = ['logspace', 'linspace', 'geomspace'] @@ -23,6 +24,7 @@ def _index_deprecate(i, stacklevel=2): return i +@set_module('numpy') def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None): """ Return evenly spaced numbers over a specified interval. @@ -154,6 +156,7 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None): return y.astype(dtype, copy=False) +@set_module('numpy') def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None): """ Return numbers spaced evenly on a log scale. @@ -238,6 +241,7 @@ def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None): return _nx.power(base, y).astype(dtype) +@set_module('numpy') def geomspace(start, stop, num=50, endpoint=True, dtype=None): """ Return numbers spaced evenly on a log scale (a geometric progression). diff --git a/numpy/core/getlimits.py b/numpy/core/getlimits.py index 389f16ff5..544b8b35f 100644 --- a/numpy/core/getlimits.py +++ b/numpy/core/getlimits.py @@ -8,6 +8,7 @@ __all__ = ['finfo', 'iinfo'] import warnings from .machar import MachAr +from .overrides import set_module from . import numeric from . import numerictypes as ntypes from .numeric import array, inf @@ -289,6 +290,7 @@ def _discovered_machar(ftype): params['title']) +@set_module('numpy') class finfo(object): """ finfo(dtype) @@ -439,6 +441,7 @@ class finfo(object): " max=%(_str_max)s, dtype=%(dtype)s)") % d) +@set_module('numpy') class iinfo(object): """ iinfo(type) diff --git a/numpy/core/machar.py b/numpy/core/machar.py index 7578544fe..91fb4eda8 100644 --- a/numpy/core/machar.py +++ b/numpy/core/machar.py @@ -11,9 +11,11 @@ __all__ = ['MachAr'] from numpy.core.fromnumeric import any from numpy.core.numeric import errstate +from numpy.core.overrides import set_module # Need to speed this up...especially for longfloat +@set_module('numpy') class MachAr(object): """ Diagnosing machine parameters. diff --git a/numpy/core/memmap.py b/numpy/core/memmap.py index f5cc68bb9..82bc4707c 100644 --- a/numpy/core/memmap.py +++ b/numpy/core/memmap.py @@ -5,6 +5,7 @@ from .numeric import uint8, ndarray, dtype from numpy.compat import ( long, basestring, os_fspath, contextlib_nullcontext, is_pathlib_path ) +from numpy.core.overrides import set_module __all__ = ['memmap'] @@ -19,6 +20,8 @@ mode_equivalents = { "write":"w+" } + +@set_module('numpy') class memmap(ndarray): """Create a memory-map to an array stored in a *binary* file on disk. diff --git a/numpy/core/multiarray.py b/numpy/core/multiarray.py index 25debd2f8..2b3633c97 100644 --- a/numpy/core/multiarray.py +++ b/numpy/core/multiarray.py @@ -39,6 +39,26 @@ __all__ = [ 'tracemalloc_domain', 'typeinfo', 'unpackbits', 'unravel_index', 'vdot', 'where', 'zeros'] + +arange.__module__ = 'numpy' +array.__module__ = 'numpy' +datetime_data.__module__ = 'numpy' +empty.__module__ = 'numpy' +frombuffer.__module__ = 'numpy' +fromfile.__module__ = 'numpy' +fromiter.__module__ = 'numpy' +frompyfunc.__module__ = 'numpy' +fromstring.__module__ = 'numpy' +geterrobj.__module__ = 'numpy' +matmul.__module__ = 'numpy' +may_share_memory.__module__ = 'numpy' +nested_iters.__module__ = 'numpy' +promote_types.__module__ = 'numpy' +set_numeric_ops.__module__ = 'numpy' +seterrobj.__module__ = 'numpy' +zeros.__module__ = 'numpy' + + array_function_dispatch = functools.partial( overrides.array_function_dispatch, module='numpy') @@ -832,6 +852,464 @@ def vdot(a, b): return _multiarray_umath.vdot(a, b) +def _bincount_dispatcher(x, weights=None, minlength=None): + return (x, weights) + + +@array_function_dispatch(_bincount_dispatcher) +def bincount(x, weights=None, minlength=0): + """ + Count number of occurrences of each value in array of non-negative ints. + + The number of bins (of size 1) is one larger than the largest value in + `x`. If `minlength` is specified, there will be at least this number + of bins in the output array (though it will be longer if necessary, + depending on the contents of `x`). + Each bin gives the number of occurrences of its index value in `x`. + If `weights` is specified the input array is weighted by it, i.e. if a + value ``n`` is found at position ``i``, ``out[n] += weight[i]`` instead + of ``out[n] += 1``. + + Parameters + ---------- + x : array_like, 1 dimension, nonnegative ints + Input array. + weights : array_like, optional + Weights, array of the same shape as `x`. + minlength : int, optional + A minimum number of bins for the output array. + + .. versionadded:: 1.6.0 + + Returns + ------- + out : ndarray of ints + The result of binning the input array. + The length of `out` is equal to ``np.amax(x)+1``. + + Raises + ------ + ValueError + If the input is not 1-dimensional, or contains elements with negative + values, or if `minlength` is negative. + TypeError + If the type of the input is float or complex. + + See Also + -------- + histogram, digitize, unique + + Examples + -------- + >>> np.bincount(np.arange(5)) + array([1, 1, 1, 1, 1]) + >>> np.bincount(np.array([0, 1, 1, 3, 2, 1, 7])) + array([1, 3, 1, 1, 0, 0, 0, 1]) + + >>> x = np.array([0, 1, 1, 3, 2, 1, 7, 23]) + >>> np.bincount(x).size == np.amax(x)+1 + True + + The input array needs to be of integer dtype, otherwise a + TypeError is raised: + + >>> np.bincount(np.arange(5, dtype=float)) + Traceback (most recent call last): + File "<stdin>", line 1, in <module> + TypeError: array cannot be safely cast to required type + + A possible use of ``bincount`` is to perform sums over + variable-size chunks of an array, using the ``weights`` keyword. + + >>> w = np.array([0.3, 0.5, 0.2, 0.7, 1., -0.6]) # weights + >>> x = np.array([0, 1, 1, 2, 2, 2]) + >>> np.bincount(x, weights=w) + array([ 0.3, 0.7, 1.1]) + + """ + return _multiarray_umath.bincount(x, weights=weights, minlength=minlength) + + +def _ravel_multi_index_dispatcher(multi_index, dims, mode=None, order=None): + return multi_index + + +@array_function_dispatch(_ravel_multi_index_dispatcher) +def ravel_multi_index(multi_index, dims, mode='raise', order='C'): + """ + Converts a tuple of index arrays into an array of flat + indices, applying boundary modes to the multi-index. + + Parameters + ---------- + multi_index : tuple of array_like + A tuple of integer arrays, one array for each dimension. + dims : tuple of ints + The shape of array into which the indices from ``multi_index`` apply. + mode : {'raise', 'wrap', 'clip'}, optional + Specifies how out-of-bounds indices are handled. Can specify + either one mode or a tuple of modes, one mode per index. + + * 'raise' -- raise an error (default) + * 'wrap' -- wrap around + * 'clip' -- clip to the range + + In 'clip' mode, a negative index which would normally + wrap will clip to 0 instead. + order : {'C', 'F'}, optional + Determines whether the multi-index should be viewed as + indexing in row-major (C-style) or column-major + (Fortran-style) order. + + Returns + ------- + raveled_indices : ndarray + An array of indices into the flattened version of an array + of dimensions ``dims``. + + See Also + -------- + unravel_index + + Notes + ----- + .. versionadded:: 1.6.0 + + Examples + -------- + >>> arr = np.array([[3,6,6],[4,5,1]]) + >>> np.ravel_multi_index(arr, (7,6)) + array([22, 41, 37]) + >>> np.ravel_multi_index(arr, (7,6), order='F') + array([31, 41, 13]) + >>> np.ravel_multi_index(arr, (4,6), mode='clip') + array([22, 23, 19]) + >>> np.ravel_multi_index(arr, (4,4), mode=('clip','wrap')) + array([12, 13, 13]) + + >>> np.ravel_multi_index((3,1,4,1), (6,7,8,9)) + 1621 + """ + return _multiarray_umath.ravel_multi_index( + multi_index, dims, mode=mode, order=order) + + +def _unravel_index_dispatcher(indices, shape, order=None): + return (indices,) + + +@array_function_dispatch(_unravel_index_dispatcher) +def unravel_index(indices, shape, order='C'): + """ + Converts a flat index or array of flat indices into a tuple + of coordinate arrays. + + Parameters + ---------- + indices : array_like + An integer array whose elements are indices into the flattened + version of an array of dimensions ``shape``. Before version 1.6.0, + this function accepted just one index value. + shape : tuple of ints + The shape of the array to use for unraveling ``indices``. + + .. versionchanged:: 1.16.0 + Renamed from ``dims`` to ``shape``. + + order : {'C', 'F'}, optional + Determines whether the indices should be viewed as indexing in + row-major (C-style) or column-major (Fortran-style) order. + + .. versionadded:: 1.6.0 + + Returns + ------- + unraveled_coords : tuple of ndarray + Each array in the tuple has the same shape as the ``indices`` + array. + + See Also + -------- + ravel_multi_index + + Examples + -------- + >>> np.unravel_index([22, 41, 37], (7,6)) + (array([3, 6, 6]), array([4, 5, 1])) + >>> np.unravel_index([31, 41, 13], (7,6), order='F') + (array([3, 6, 6]), array([4, 5, 1])) + + >>> np.unravel_index(1621, (6,7,8,9)) + (3, 1, 4, 1) + + """ + return _multiarray_umath.unravel_index(indices, shape, order=order) + + +def _copyto_dispatcher(dst, src, casting=None, where=None): + return (dst, src, where) + + +@array_function_dispatch(_copyto_dispatcher) +def copyto(dst, src, casting='same_kind', where=True): + """ + Copies values from one array to another, broadcasting as necessary. + + Raises a TypeError if the `casting` rule is violated, and if + `where` is provided, it selects which elements to copy. + + .. versionadded:: 1.7.0 + + Parameters + ---------- + dst : ndarray + The array into which values are copied. + src : array_like + The array from which values are copied. + casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional + Controls what kind of data casting may occur when copying. + + * 'no' means the data types should not be cast at all. + * 'equiv' means only byte-order changes are allowed. + * 'safe' means only casts which can preserve values are allowed. + * 'same_kind' means only safe casts or casts within a kind, + like float64 to float32, are allowed. + * 'unsafe' means any data conversions may be done. + where : array_like of bool, optional + A boolean array which is broadcasted to match the dimensions + of `dst`, and selects elements to copy from `src` to `dst` + wherever it contains the value True. + """ + return _multiarray_umath.copyto(dst, src, casting=casting, where=where) + + +def _putmask_dispatcher(a, mask, values): + return (a, mask, values) + + +@array_function_dispatch(_putmask_dispatcher) +def putmask(a, mask, values): + """ + Changes elements of an array based on conditional and input values. + + Sets ``a.flat[n] = values[n]`` for each n where ``mask.flat[n]==True``. + + If `values` is not the same size as `a` and `mask` then it will repeat. + This gives behavior different from ``a[mask] = values``. + + Parameters + ---------- + a : array_like + Target array. + mask : array_like + Boolean mask array. It has to be the same shape as `a`. + values : array_like + Values to put into `a` where `mask` is True. If `values` is smaller + than `a` it will be repeated. + + See Also + -------- + place, put, take, copyto + + Examples + -------- + >>> x = np.arange(6).reshape(2, 3) + >>> np.putmask(x, x>2, x**2) + >>> x + array([[ 0, 1, 2], + [ 9, 16, 25]]) + + If `values` is smaller than `a` it is repeated: + + >>> x = np.arange(5) + >>> np.putmask(x, x>1, [-33, -44]) + >>> x + array([ 0, 1, -33, -44, -33]) + + """ + return _multiarray_umath.putmask(a, mask, values) + + +def _packbits_and_unpackbits_dispatcher(myarray, axis=None): + return (myarray,) + + +@array_function_dispatch(_packbits_and_unpackbits_dispatcher) +def packbits(myarray, axis=None): + """ + Packs the elements of a binary-valued array into bits in a uint8 array. + + The result is padded to full bytes by inserting zero bits at the end. + + Parameters + ---------- + myarray : array_like + An array of integers or booleans whose elements should be packed to + bits. + axis : int, optional + The dimension over which bit-packing is done. + ``None`` implies packing the flattened array. + + Returns + ------- + packed : ndarray + Array of type uint8 whose elements represent bits corresponding to the + logical (0 or nonzero) value of the input elements. The shape of + `packed` has the same number of dimensions as the input (unless `axis` + is None, in which case the output is 1-D). + + See Also + -------- + unpackbits: Unpacks elements of a uint8 array into a binary-valued output + array. + + Examples + -------- + >>> a = np.array([[[1,0,1], + ... [0,1,0]], + ... [[1,1,0], + ... [0,0,1]]]) + >>> b = np.packbits(a, axis=-1) + >>> b + array([[[160],[64]],[[192],[32]]], dtype=uint8) + + Note that in binary 160 = 1010 0000, 64 = 0100 0000, 192 = 1100 0000, + and 32 = 0010 0000. + + """ + return _multiarray_umath.packbits(myarray, axis) + + +@array_function_dispatch(_packbits_and_unpackbits_dispatcher) +def unpackbits(myarray, axis=None): + """ + Unpacks elements of a uint8 array into a binary-valued output array. + + Each element of `myarray` represents a bit-field that should be unpacked + into a binary-valued output array. The shape of the output array is either + 1-D (if `axis` is None) or the same shape as the input array with unpacking + done along the axis specified. + + Parameters + ---------- + myarray : ndarray, uint8 type + Input array. + axis : int, optional + The dimension over which bit-unpacking is done. + ``None`` implies unpacking the flattened array. + + Returns + ------- + unpacked : ndarray, uint8 type + The elements are binary-valued (0 or 1). + + See Also + -------- + packbits : Packs the elements of a binary-valued array into bits in a uint8 + array. + + Examples + -------- + >>> a = np.array([[2], [7], [23]], dtype=np.uint8) + >>> a + array([[ 2], + [ 7], + [23]], dtype=uint8) + >>> b = np.unpackbits(a, axis=1) + >>> b + array([[0, 0, 0, 0, 0, 0, 1, 0], + [0, 0, 0, 0, 0, 1, 1, 1], + [0, 0, 0, 1, 0, 1, 1, 1]], dtype=uint8) + + """ + return _multiarray_umath.unpackfdbits(myarray, axis) + + +def _shares_memory_dispatcher(a, b, max_work=None): + return (a, b) + + +@array_function_dispatch(_shares_memory_dispatcher) +def shares_memory(a, b, max_work=None): + """ + Determine if two arrays share memory + + Parameters + ---------- + a, b : ndarray + Input arrays + max_work : int, optional + Effort to spend on solving the overlap problem (maximum number + of candidate solutions to consider). The following special + values are recognized: + + max_work=MAY_SHARE_EXACT (default) + The problem is solved exactly. In this case, the function returns + True only if there is an element shared between the arrays. + max_work=MAY_SHARE_BOUNDS + Only the memory bounds of a and b are checked. + + Raises + ------ + numpy.TooHardError + Exceeded max_work. + + Returns + ------- + out : bool + + See Also + -------- + may_share_memory + + Examples + -------- + >>> np.may_share_memory(np.array([1,2]), np.array([5,8,9])) + False + + """ + return _multiarray_umath.shares_memory(a, b, max_work=max_work) + + +@array_function_dispatch(_shares_memory_dispatcher) +def may_share_memory(a, b, max_work=None): + """ + Determine if two arrays might share memory + + A return of True does not necessarily mean that the two arrays + share any element. It just means that they *might*. + + Only the memory bounds of a and b are checked by default. + + Parameters + ---------- + a, b : ndarray + Input arrays + max_work : int, optional + Effort to spend on solving the overlap problem. See + `shares_memory` for details. Default for ``may_share_memory`` + is to do a bounds check. + + Returns + ------- + out : bool + + See Also + -------- + shares_memory + + Examples + -------- + >>> np.may_share_memory(np.array([1,2]), np.array([5,8,9])) + False + >>> x = np.zeros([3, 4]) + >>> np.may_share_memory(x[:,0], x[:,1]) + True + + """ + return _multiarray_umath.may_share_memory(a, b, max_work=max_work) + + def _is_busday_dispatcher( dates, weekmask=None, holidays=None, busdaycal=None, out=None): return (dates, weekmask, holidays, out) @@ -1156,3 +1634,4 @@ def datetime_as_string(arr, unit=None, timezone='naive', casting='same_kind'): datetime with units 'm' according to the rule 'safe' """ return _multiarray_umath.datetime_as_string(arr, unit, timezone, casting) + diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py index 265c3636f..aa5be1af3 100644 --- a/numpy/core/numeric.py +++ b/numpy/core/numeric.py @@ -30,6 +30,7 @@ if sys.version_info[0] < 3: from . import overrides from . import umath +from .overrides import set_module from .umath import (multiply, invert, sin, UFUNC_BUFSIZE_DEFAULT, ERR_IGNORE, ERR_WARN, ERR_RAISE, ERR_CALL, ERR_PRINT, ERR_LOG, ERR_DEFAULT, PINF, NAN) @@ -92,6 +93,7 @@ if sys.version_info[0] < 3: __all__.extend(['getbuffer', 'newbuffer']) +@set_module('numpy') class ComplexWarning(RuntimeWarning): """ The warning raised when casting a complex dtype to a real dtype. @@ -170,6 +172,7 @@ def zeros_like(a, dtype=None, order='K', subok=True): return res +@set_module('numpy') def ones(shape, dtype=None, order='C'): """ Return a new array of given shape and type, filled with ones. @@ -287,6 +290,7 @@ def ones_like(a, dtype=None, order='K', subok=True): return res +@set_module('numpy') def full(shape, fill_value, dtype=None, order='C'): """ Return a new array of given shape and type, filled with `fill_value`. @@ -462,6 +466,7 @@ def count_nonzero(a, axis=None): return a_bool.sum(axis=axis, dtype=np.intp) +@set_module('numpy') def asarray(a, dtype=None, order=None): """Convert the input to an array. @@ -533,6 +538,7 @@ def asarray(a, dtype=None, order=None): return array(a, dtype, copy=False, order=order) +@set_module('numpy') def asanyarray(a, dtype=None, order=None): """Convert the input to an ndarray, but pass ndarray subclasses through. @@ -585,6 +591,7 @@ def asanyarray(a, dtype=None, order=None): return array(a, dtype, copy=False, order=order, subok=True) +@set_module('numpy') def ascontiguousarray(a, dtype=None): """ Return a contiguous array (ndim >= 1) in memory (C order). @@ -625,6 +632,7 @@ def ascontiguousarray(a, dtype=None): return array(a, dtype, copy=False, order='C', ndmin=1) +@set_module('numpy') def asfortranarray(a, dtype=None): """ Return an array (ndim >= 1) laid out in Fortran order in memory. @@ -665,6 +673,7 @@ def asfortranarray(a, dtype=None): return array(a, dtype, copy=False, order='F', ndmin=1) +@set_module('numpy') def require(a, dtype=None, requirements=None): """ Return an ndarray of the provided type that satisfies requirements. @@ -763,6 +772,7 @@ def require(a, dtype=None, requirements=None): return arr +@set_module('numpy') def isfortran(a): """ Returns True if the array is Fortran contiguous but *not* C contiguous. @@ -1889,6 +1899,7 @@ def cross(a, b, axisa=-1, axisb=-1, axisc=-1, axis=None): little_endian = (sys.byteorder == 'little') +@set_module('numpy') def indices(dimensions, dtype=int): """ Return an array representing the indices of a grid. @@ -1960,6 +1971,7 @@ def indices(dimensions, dtype=int): return res +@set_module('numpy') def fromfunction(function, shape, **kwargs): """ Construct an array by executing a function over each coordinate. @@ -2020,6 +2032,7 @@ def _frombuffer(buf, dtype, shape, order): return frombuffer(buf, dtype=dtype).reshape(shape, order=order) +@set_module('numpy') def isscalar(num): """ Returns True if the type of `num` is a scalar type. @@ -2096,6 +2109,7 @@ def isscalar(num): or isinstance(num, numbers.Number)) +@set_module('numpy') def binary_repr(num, width=None): """ Return the binary representation of the input number as a string. @@ -2206,6 +2220,7 @@ def binary_repr(num, width=None): return '1' * (outwidth - binwidth) + binary +@set_module('numpy') def base_repr(number, base=2, padding=0): """ Return a string representation of a number in the given base system. @@ -2300,6 +2315,7 @@ def _maketup(descr, val): return tuple(res) +@set_module('numpy') def identity(n, dtype=None): """ Return the identity array. @@ -2640,6 +2656,7 @@ for key in _errdict.keys(): del key +@set_module('numpy') def seterr(all=None, divide=None, over=None, under=None, invalid=None): """ Set how floating-point errors are handled. @@ -2741,6 +2758,7 @@ def seterr(all=None, divide=None, over=None, under=None, invalid=None): return old +@set_module('numpy') def geterr(): """ Get the current way of handling floating-point errors. @@ -2792,6 +2810,7 @@ def geterr(): return res +@set_module('numpy') def setbufsize(size): """ Set the size of the buffer used in ufuncs. @@ -2816,6 +2835,7 @@ def setbufsize(size): return old +@set_module('numpy') def getbufsize(): """ Return the size of the buffer used in ufuncs. @@ -2829,6 +2849,7 @@ def getbufsize(): return umath.geterrobj()[0] +@set_module('numpy') def seterrcall(func): """ Set the floating-point error callback function or log object. @@ -2921,6 +2942,7 @@ def seterrcall(func): return old +@set_module('numpy') def geterrcall(): """ Return the current callback function used on floating-point errors. @@ -2973,6 +2995,7 @@ class _unspecified(object): _Unspecified = _unspecified() +@set_module('numpy') class errstate(object): """ errstate(**kwargs) diff --git a/numpy/core/numerictypes.py b/numpy/core/numerictypes.py index 2fb841f7c..f00f92286 100644 --- a/numpy/core/numerictypes.py +++ b/numpy/core/numerictypes.py @@ -92,6 +92,7 @@ from numpy.core.multiarray import ( datetime_as_string, busday_offset, busday_count, is_busday, busdaycalendar ) +from numpy.core.overrides import set_module # we add more at the bottom __all__ = ['sctypeDict', 'sctypeNA', 'typeDict', 'typeNA', 'sctypes', @@ -187,6 +188,8 @@ def maximum_sctype(t): else: return t + +@set_module('numpy') def issctype(rep): """ Determines whether the given object represents a scalar data-type. @@ -231,6 +234,8 @@ def issctype(rep): except Exception: return False + +@set_module('numpy') def obj2sctype(rep, default=None): """ Return the scalar dtype or NumPy equivalent of Python type of an object. @@ -285,6 +290,7 @@ def obj2sctype(rep, default=None): return res.type +@set_module('numpy') def issubclass_(arg1, arg2): """ Determine if a class is a subclass of a second class. @@ -323,6 +329,8 @@ def issubclass_(arg1, arg2): except TypeError: return False + +@set_module('numpy') def issubsctype(arg1, arg2): """ Determine if the first argument is a subclass of the second argument. @@ -353,6 +361,8 @@ def issubsctype(arg1, arg2): """ return issubclass(obj2sctype(arg1), obj2sctype(arg2)) + +@set_module('numpy') def issubdtype(arg1, arg2): """ Returns True if first argument is a typecode lower/equal in type hierarchy. @@ -446,6 +456,8 @@ def _construct_lookups(): _construct_lookups() + +@set_module('numpy') def sctype2char(sctype): """ Return the string representation of a scalar dtype. @@ -586,6 +598,8 @@ def _register_types(): _register_types() + +@set_module('numpy') def find_common_type(array_types, scalar_types): """ Determine common type following standard coercion rules. diff --git a/numpy/core/overrides.py b/numpy/core/overrides.py index e4d505f06..1cc1ff8d8 100644 --- a/numpy/core/overrides.py +++ b/numpy/core/overrides.py @@ -150,12 +150,12 @@ def verify_matching_signatures(implementation, dispatcher): 'default argument values') -def override_module(module): +def set_module(module): """Decorator for overriding __module__ on a function or class. Example usage:: - @override_module('numpy') + @set_module('numpy') def example(): pass @@ -198,7 +198,7 @@ def array_function_dispatch(dispatcher, module=None, verify=True): if not ENABLE_ARRAY_FUNCTION: # __array_function__ requires an explicit opt-in for now - return override_module(module) + return set_module(module) def decorator(implementation): if verify: diff --git a/numpy/core/records.py b/numpy/core/records.py index 1b596e4de..6fc282500 100644 --- a/numpy/core/records.py +++ b/numpy/core/records.py @@ -43,6 +43,7 @@ import warnings from . import numeric as sb from . import numerictypes as nt from numpy.compat import isfileobj, bytes, long, unicode, os_fspath +from numpy.core.overrides import set_module from .arrayprint import get_printoptions # All of the functions allow formats to be a dtype @@ -82,6 +83,8 @@ def find_duplicate(list): dup.append(list[i]) return dup + +@set_module('numpy') class format_parser(object): """ Class to convert formats, names, titles description to a dtype. diff --git a/numpy/core/tests/test_overrides.py b/numpy/core/tests/test_overrides.py index a32049ea1..7db551801 100644 --- a/numpy/core/tests/test_overrides.py +++ b/numpy/core/tests/test_overrides.py @@ -312,6 +312,7 @@ class TestArrayFunctionImplementation(object): array = np.array(1) assert_(func(array) is array) + assert_equal(func.__module__, 'my') with assert_raises_regex( TypeError, "no implementation found for 'my.func'"): @@ -335,7 +336,7 @@ class TestNDArrayMethods(object): class TestNumPyFunctions(object): - def test_module(self): + def test_set_module(self): assert_equal(np.sum.__module__, 'numpy') assert_equal(np.char.equal.__module__, 'numpy.char') assert_equal(np.fft.fft.__module__, 'numpy.fft') |