From 2391866e421a97b1f28d0221100aa5f037344857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Sok=C3=B3=C5=82?= Date: Wed, 30 Aug 2023 13:51:17 +0200 Subject: [PATCH 01/11] API: Remove chararray, compare_chararrays, recarray and format_parser from main namespace --- doc/source/reference/arrays.classes.rst | 4 +- doc/source/reference/routines.dtype.rst | 2 +- doc/source/user/basics.rec.rst | 6 +- numpy/__init__.py | 8 +- numpy/__init__.pyi | 500 ------------------ numpy/_expired_attrs_2_0.py | 5 + numpy/core/__init__.py | 4 +- numpy/core/_add_newdocs.py | 10 +- numpy/core/defchararray.py | 8 +- numpy/core/defchararray.pyi | 3 +- numpy/core/numeric.py | 4 +- numpy/core/records.py | 41 +- numpy/core/records.pyi | 12 +- numpy/core/tests/test_arraymethod.py | 4 +- numpy/core/tests/test_defchararray.py | 52 +- numpy/core/tests/test_dtype.py | 2 +- numpy/core/tests/test_records.py | 54 +- numpy/core/tests/test_regression.py | 10 +- numpy/core/tests/test_strings.py | 12 +- numpy/lib/_npyio_impl.py | 4 +- numpy/lib/recfunctions.py | 9 +- numpy/lib/tests/test_arraysetops.py | 2 +- numpy/lib/tests/test_io.py | 12 +- numpy/lib/tests/test_recfunctions.py | 6 +- numpy/ma/core.py | 3 +- numpy/ma/mrecords.py | 4 +- numpy/ma/tests/test_core.py | 8 +- numpy/random/tests/test_generator_mt19937.py | 2 +- numpy/random/tests/test_random.py | 2 +- numpy/random/tests/test_randomstate.py | 2 +- numpy/tests/test_public_api.py | 1 - numpy/typing/__init__.py | 2 +- numpy/typing/tests/data/fail/chararray.pyi | 4 +- numpy/typing/tests/data/fail/multiarray.pyi | 2 +- numpy/typing/tests/data/reveal/chararray.pyi | 4 +- .../tests/data/reveal/lib_function_base.pyi | 2 +- numpy/typing/tests/data/reveal/multiarray.pyi | 4 +- numpy/typing/tests/data/reveal/rec.pyi | 50 +- 38 files changed, 196 insertions(+), 668 deletions(-) diff --git a/doc/source/reference/arrays.classes.rst b/doc/source/reference/arrays.classes.rst index f1b98c5b9567..dc16aca7693b 100644 --- a/doc/source/reference/arrays.classes.rst +++ b/doc/source/reference/arrays.classes.rst @@ -494,13 +494,13 @@ executing them on an element-by-element basis. Perhaps the easiest way to create a chararray is to use :meth:`self.view(chararray) ` where *self* is an ndarray of str or unicode data-type. However, a chararray can also be created using the -:meth:`numpy.chararray` constructor, or via the +:meth:`numpy.char.chararray` constructor, or via the :func:`numpy.char.array ` function: .. autosummary:: :toctree: generated/ - chararray + char.chararray core.defchararray.array Another difference with the standard ndarray of str data-type is diff --git a/doc/source/reference/routines.dtype.rst b/doc/source/reference/routines.dtype.rst index 4da9831a9298..35fd431587b4 100644 --- a/doc/source/reference/routines.dtype.rst +++ b/doc/source/reference/routines.dtype.rst @@ -20,7 +20,7 @@ Creating data types :toctree: generated/ dtype - format_parser + rec.format_parser Data type information --------------------- diff --git a/doc/source/user/basics.rec.rst b/doc/source/user/basics.rec.rst index f7e06fa4fada..b28b436d5bff 100644 --- a/doc/source/user/basics.rec.rst +++ b/doc/source/user/basics.rec.rst @@ -673,13 +673,13 @@ appropriate `view `_:: >>> arr = np.array([(1, 2., 'Hello'), (2, 3., "World")], ... dtype=[('foo', 'i4'),('bar', 'f4'), ('baz', 'a10')]) >>> recordarr = arr.view(dtype=np.dtype((np.record, arr.dtype)), - ... type=np.recarray) + ... type=np.rec.recarray) -For convenience, viewing an ndarray as type :class:`numpy.recarray` will +For convenience, viewing an ndarray as type :class:`numpy.rec.recarray` will automatically convert to :class:`numpy.record` datatype, so the dtype can be left out of the view:: - >>> recordarr = arr.view(np.recarray) + >>> recordarr = arr.view(np.rec.recarray) >>> recordarr.dtype dtype((numpy.record, [('foo', ' iinfo[Any]: ... -class format_parser: - dtype: dtype[void] - def __init__( - self, - formats: DTypeLike, - names: None | str | Sequence[str], - titles: None | str | Sequence[str], - aligned: bool = ..., - byteorder: None | _ByteOrder = ..., - ) -> None: ... - -class recarray(ndarray[_ShapeType, _DType_co]): - # NOTE: While not strictly mandatory, we're demanding here that arguments - # for the `format_parser`- and `dtype`-based dtype constructors are - # mutually exclusive - @overload - def __new__( - subtype, - shape: _ShapeLike, - dtype: None = ..., - buf: None | _SupportsBuffer = ..., - offset: SupportsIndex = ..., - strides: None | _ShapeLike = ..., - *, - formats: DTypeLike, - names: None | str | Sequence[str] = ..., - titles: None | str | Sequence[str] = ..., - byteorder: None | _ByteOrder = ..., - aligned: bool = ..., - order: _OrderKACF = ..., - ) -> recarray[Any, dtype[record]]: ... - @overload - def __new__( - subtype, - shape: _ShapeLike, - dtype: DTypeLike, - buf: None | _SupportsBuffer = ..., - offset: SupportsIndex = ..., - strides: None | _ShapeLike = ..., - formats: None = ..., - names: None = ..., - titles: None = ..., - byteorder: None = ..., - aligned: L[False] = ..., - order: _OrderKACF = ..., - ) -> recarray[Any, dtype[Any]]: ... - def __array_finalize__(self, obj: object) -> None: ... - def __getattribute__(self, attr: str) -> Any: ... - def __setattr__(self, attr: str, val: ArrayLike) -> None: ... - @overload - def __getitem__(self, indx: ( - SupportsIndex - | _ArrayLikeInt_co - | tuple[SupportsIndex | _ArrayLikeInt_co, ...] - )) -> Any: ... - @overload - def __getitem__(self: recarray[Any, dtype[void]], indx: ( - None - | slice - | ellipsis - | SupportsIndex - | _ArrayLikeInt_co - | tuple[None | slice | ellipsis | _ArrayLikeInt_co | SupportsIndex, ...] - )) -> recarray[Any, _DType_co]: ... - @overload - def __getitem__(self, indx: ( - None - | slice - | ellipsis - | SupportsIndex - | _ArrayLikeInt_co - | tuple[None | slice | ellipsis | _ArrayLikeInt_co | SupportsIndex, ...] - )) -> ndarray[Any, _DType_co]: ... - @overload - def __getitem__(self, indx: str) -> NDArray[Any]: ... - @overload - def __getitem__(self, indx: list[str]) -> recarray[_ShapeType, dtype[record]]: ... - @overload - def field(self, attr: int | str, val: None = ...) -> Any: ... - @overload - def field(self, attr: int | str, val: ArrayLike) -> None: ... - class record(void): def __getattribute__(self, attr: str) -> Any: ... def __setattr__(self, attr: str, val: ArrayLike) -> None: ... @@ -3876,423 +3793,6 @@ class matrix(ndarray[_ShapeType, _DType_co]): _CharType = TypeVar("_CharType", str_, bytes_) _CharDType = TypeVar("_CharDType", dtype[str_], dtype[bytes_]) -_CharArray = chararray[Any, dtype[_CharType]] - -class chararray(ndarray[_ShapeType, _CharDType]): - @overload - def __new__( - subtype, - shape: _ShapeLike, - itemsize: SupportsIndex | SupportsInt = ..., - unicode: L[False] = ..., - buffer: _SupportsBuffer = ..., - offset: SupportsIndex = ..., - strides: _ShapeLike = ..., - order: _OrderKACF = ..., - ) -> chararray[Any, dtype[bytes_]]: ... - @overload - def __new__( - subtype, - shape: _ShapeLike, - itemsize: SupportsIndex | SupportsInt = ..., - unicode: L[True] = ..., - buffer: _SupportsBuffer = ..., - offset: SupportsIndex = ..., - strides: _ShapeLike = ..., - order: _OrderKACF = ..., - ) -> chararray[Any, dtype[str_]]: ... - - def __array_finalize__(self, obj: object) -> None: ... - def __mul__(self, other: _ArrayLikeInt_co) -> chararray[Any, _CharDType]: ... - def __rmul__(self, other: _ArrayLikeInt_co) -> chararray[Any, _CharDType]: ... - def __mod__(self, i: Any) -> chararray[Any, _CharDType]: ... - - @overload - def __eq__( - self: _CharArray[str_], - other: _ArrayLikeStr_co, - ) -> NDArray[bool_]: ... - @overload - def __eq__( - self: _CharArray[bytes_], - other: _ArrayLikeBytes_co, - ) -> NDArray[bool_]: ... - - @overload - def __ne__( - self: _CharArray[str_], - other: _ArrayLikeStr_co, - ) -> NDArray[bool_]: ... - @overload - def __ne__( - self: _CharArray[bytes_], - other: _ArrayLikeBytes_co, - ) -> NDArray[bool_]: ... - - @overload - def __ge__( - self: _CharArray[str_], - other: _ArrayLikeStr_co, - ) -> NDArray[bool_]: ... - @overload - def __ge__( - self: _CharArray[bytes_], - other: _ArrayLikeBytes_co, - ) -> NDArray[bool_]: ... - - @overload - def __le__( - self: _CharArray[str_], - other: _ArrayLikeStr_co, - ) -> NDArray[bool_]: ... - @overload - def __le__( - self: _CharArray[bytes_], - other: _ArrayLikeBytes_co, - ) -> NDArray[bool_]: ... - - @overload - def __gt__( - self: _CharArray[str_], - other: _ArrayLikeStr_co, - ) -> NDArray[bool_]: ... - @overload - def __gt__( - self: _CharArray[bytes_], - other: _ArrayLikeBytes_co, - ) -> NDArray[bool_]: ... - - @overload - def __lt__( - self: _CharArray[str_], - other: _ArrayLikeStr_co, - ) -> NDArray[bool_]: ... - @overload - def __lt__( - self: _CharArray[bytes_], - other: _ArrayLikeBytes_co, - ) -> NDArray[bool_]: ... - - @overload - def __add__( - self: _CharArray[str_], - other: _ArrayLikeStr_co, - ) -> _CharArray[str_]: ... - @overload - def __add__( - self: _CharArray[bytes_], - other: _ArrayLikeBytes_co, - ) -> _CharArray[bytes_]: ... - - @overload - def __radd__( - self: _CharArray[str_], - other: _ArrayLikeStr_co, - ) -> _CharArray[str_]: ... - @overload - def __radd__( - self: _CharArray[bytes_], - other: _ArrayLikeBytes_co, - ) -> _CharArray[bytes_]: ... - - @overload - def center( - self: _CharArray[str_], - width: _ArrayLikeInt_co, - fillchar: _ArrayLikeStr_co = ..., - ) -> _CharArray[str_]: ... - @overload - def center( - self: _CharArray[bytes_], - width: _ArrayLikeInt_co, - fillchar: _ArrayLikeBytes_co = ..., - ) -> _CharArray[bytes_]: ... - - @overload - def count( - self: _CharArray[str_], - sub: _ArrayLikeStr_co, - start: _ArrayLikeInt_co = ..., - end: None | _ArrayLikeInt_co = ..., - ) -> NDArray[int_]: ... - @overload - def count( - self: _CharArray[bytes_], - sub: _ArrayLikeBytes_co, - start: _ArrayLikeInt_co = ..., - end: None | _ArrayLikeInt_co = ..., - ) -> NDArray[int_]: ... - - def decode( - self: _CharArray[bytes_], - encoding: None | str = ..., - errors: None | str = ..., - ) -> _CharArray[str_]: ... - - def encode( - self: _CharArray[str_], - encoding: None | str = ..., - errors: None | str = ..., - ) -> _CharArray[bytes_]: ... - - @overload - def endswith( - self: _CharArray[str_], - suffix: _ArrayLikeStr_co, - start: _ArrayLikeInt_co = ..., - end: None | _ArrayLikeInt_co = ..., - ) -> NDArray[bool_]: ... - @overload - def endswith( - self: _CharArray[bytes_], - suffix: _ArrayLikeBytes_co, - start: _ArrayLikeInt_co = ..., - end: None | _ArrayLikeInt_co = ..., - ) -> NDArray[bool_]: ... - - def expandtabs( - self, - tabsize: _ArrayLikeInt_co = ..., - ) -> chararray[Any, _CharDType]: ... - - @overload - def find( - self: _CharArray[str_], - sub: _ArrayLikeStr_co, - start: _ArrayLikeInt_co = ..., - end: None | _ArrayLikeInt_co = ..., - ) -> NDArray[int_]: ... - @overload - def find( - self: _CharArray[bytes_], - sub: _ArrayLikeBytes_co, - start: _ArrayLikeInt_co = ..., - end: None | _ArrayLikeInt_co = ..., - ) -> NDArray[int_]: ... - - @overload - def index( - self: _CharArray[str_], - sub: _ArrayLikeStr_co, - start: _ArrayLikeInt_co = ..., - end: None | _ArrayLikeInt_co = ..., - ) -> NDArray[int_]: ... - @overload - def index( - self: _CharArray[bytes_], - sub: _ArrayLikeBytes_co, - start: _ArrayLikeInt_co = ..., - end: None | _ArrayLikeInt_co = ..., - ) -> NDArray[int_]: ... - - @overload - def join( - self: _CharArray[str_], - seq: _ArrayLikeStr_co, - ) -> _CharArray[str_]: ... - @overload - def join( - self: _CharArray[bytes_], - seq: _ArrayLikeBytes_co, - ) -> _CharArray[bytes_]: ... - - @overload - def ljust( - self: _CharArray[str_], - width: _ArrayLikeInt_co, - fillchar: _ArrayLikeStr_co = ..., - ) -> _CharArray[str_]: ... - @overload - def ljust( - self: _CharArray[bytes_], - width: _ArrayLikeInt_co, - fillchar: _ArrayLikeBytes_co = ..., - ) -> _CharArray[bytes_]: ... - - @overload - def lstrip( - self: _CharArray[str_], - chars: None | _ArrayLikeStr_co = ..., - ) -> _CharArray[str_]: ... - @overload - def lstrip( - self: _CharArray[bytes_], - chars: None | _ArrayLikeBytes_co = ..., - ) -> _CharArray[bytes_]: ... - - @overload - def partition( - self: _CharArray[str_], - sep: _ArrayLikeStr_co, - ) -> _CharArray[str_]: ... - @overload - def partition( - self: _CharArray[bytes_], - sep: _ArrayLikeBytes_co, - ) -> _CharArray[bytes_]: ... - - @overload - def replace( - self: _CharArray[str_], - old: _ArrayLikeStr_co, - new: _ArrayLikeStr_co, - count: None | _ArrayLikeInt_co = ..., - ) -> _CharArray[str_]: ... - @overload - def replace( - self: _CharArray[bytes_], - old: _ArrayLikeBytes_co, - new: _ArrayLikeBytes_co, - count: None | _ArrayLikeInt_co = ..., - ) -> _CharArray[bytes_]: ... - - @overload - def rfind( - self: _CharArray[str_], - sub: _ArrayLikeStr_co, - start: _ArrayLikeInt_co = ..., - end: None | _ArrayLikeInt_co = ..., - ) -> NDArray[int_]: ... - @overload - def rfind( - self: _CharArray[bytes_], - sub: _ArrayLikeBytes_co, - start: _ArrayLikeInt_co = ..., - end: None | _ArrayLikeInt_co = ..., - ) -> NDArray[int_]: ... - - @overload - def rindex( - self: _CharArray[str_], - sub: _ArrayLikeStr_co, - start: _ArrayLikeInt_co = ..., - end: None | _ArrayLikeInt_co = ..., - ) -> NDArray[int_]: ... - @overload - def rindex( - self: _CharArray[bytes_], - sub: _ArrayLikeBytes_co, - start: _ArrayLikeInt_co = ..., - end: None | _ArrayLikeInt_co = ..., - ) -> NDArray[int_]: ... - - @overload - def rjust( - self: _CharArray[str_], - width: _ArrayLikeInt_co, - fillchar: _ArrayLikeStr_co = ..., - ) -> _CharArray[str_]: ... - @overload - def rjust( - self: _CharArray[bytes_], - width: _ArrayLikeInt_co, - fillchar: _ArrayLikeBytes_co = ..., - ) -> _CharArray[bytes_]: ... - - @overload - def rpartition( - self: _CharArray[str_], - sep: _ArrayLikeStr_co, - ) -> _CharArray[str_]: ... - @overload - def rpartition( - self: _CharArray[bytes_], - sep: _ArrayLikeBytes_co, - ) -> _CharArray[bytes_]: ... - - @overload - def rsplit( - self: _CharArray[str_], - sep: None | _ArrayLikeStr_co = ..., - maxsplit: None | _ArrayLikeInt_co = ..., - ) -> NDArray[object_]: ... - @overload - def rsplit( - self: _CharArray[bytes_], - sep: None | _ArrayLikeBytes_co = ..., - maxsplit: None | _ArrayLikeInt_co = ..., - ) -> NDArray[object_]: ... - - @overload - def rstrip( - self: _CharArray[str_], - chars: None | _ArrayLikeStr_co = ..., - ) -> _CharArray[str_]: ... - @overload - def rstrip( - self: _CharArray[bytes_], - chars: None | _ArrayLikeBytes_co = ..., - ) -> _CharArray[bytes_]: ... - - @overload - def split( - self: _CharArray[str_], - sep: None | _ArrayLikeStr_co = ..., - maxsplit: None | _ArrayLikeInt_co = ..., - ) -> NDArray[object_]: ... - @overload - def split( - self: _CharArray[bytes_], - sep: None | _ArrayLikeBytes_co = ..., - maxsplit: None | _ArrayLikeInt_co = ..., - ) -> NDArray[object_]: ... - - def splitlines(self, keepends: None | _ArrayLikeBool_co = ...) -> NDArray[object_]: ... - - @overload - def startswith( - self: _CharArray[str_], - prefix: _ArrayLikeStr_co, - start: _ArrayLikeInt_co = ..., - end: None | _ArrayLikeInt_co = ..., - ) -> NDArray[bool_]: ... - @overload - def startswith( - self: _CharArray[bytes_], - prefix: _ArrayLikeBytes_co, - start: _ArrayLikeInt_co = ..., - end: None | _ArrayLikeInt_co = ..., - ) -> NDArray[bool_]: ... - - @overload - def strip( - self: _CharArray[str_], - chars: None | _ArrayLikeStr_co = ..., - ) -> _CharArray[str_]: ... - @overload - def strip( - self: _CharArray[bytes_], - chars: None | _ArrayLikeBytes_co = ..., - ) -> _CharArray[bytes_]: ... - - @overload - def translate( - self: _CharArray[str_], - table: _ArrayLikeStr_co, - deletechars: None | _ArrayLikeStr_co = ..., - ) -> _CharArray[str_]: ... - @overload - def translate( - self: _CharArray[bytes_], - table: _ArrayLikeBytes_co, - deletechars: None | _ArrayLikeBytes_co = ..., - ) -> _CharArray[bytes_]: ... - - def zfill(self, width: _ArrayLikeInt_co) -> chararray[Any, _CharDType]: ... - def capitalize(self) -> chararray[_ShapeType, _CharDType]: ... - def title(self) -> chararray[_ShapeType, _CharDType]: ... - def swapcase(self) -> chararray[_ShapeType, _CharDType]: ... - def lower(self) -> chararray[_ShapeType, _CharDType]: ... - def upper(self) -> chararray[_ShapeType, _CharDType]: ... - def isalnum(self) -> ndarray[_ShapeType, dtype[bool_]]: ... - def isalpha(self) -> ndarray[_ShapeType, dtype[bool_]]: ... - def isdigit(self) -> ndarray[_ShapeType, dtype[bool_]]: ... - def islower(self) -> ndarray[_ShapeType, dtype[bool_]]: ... - def isspace(self) -> ndarray[_ShapeType, dtype[bool_]]: ... - def istitle(self) -> ndarray[_ShapeType, dtype[bool_]]: ... - def isupper(self) -> ndarray[_ShapeType, dtype[bool_]]: ... - def isnumeric(self) -> ndarray[_ShapeType, dtype[bool_]]: ... - def isdecimal(self) -> ndarray[_ShapeType, dtype[bool_]]: ... # NOTE: Deprecated # class MachAr: ... diff --git a/numpy/_expired_attrs_2_0.py b/numpy/_expired_attrs_2_0.py index 8cf0ae95a297..019d01a90145 100644 --- a/numpy/_expired_attrs_2_0.py +++ b/numpy/_expired_attrs_2_0.py @@ -69,4 +69,9 @@ "DataSource": "It's still available as `np.lib.npyio.DataSource`.", "nbytes": "Use `np.dtype().itemsize` instead.", "byte_bounds": "Now it's available under `np.lib.array_utils.byte_bounds`", + "compare_chararrays": + "It's still available as `np.char.compare_chararrays`.", + "chararray": "It's still available as `np.char.chararray`.", + "format_parser": "It's still available as `np.rec.format_parser`.", + "recarray": "It's still available as `np.rec.recarray`.", } diff --git a/numpy/core/__init__.py b/numpy/core/__init__.py index fc1483dd82ac..e5979d50ec38 100644 --- a/numpy/core/__init__.py +++ b/numpy/core/__init__.py @@ -82,7 +82,6 @@ from .records import record, recarray, format_parser # Note: module name memmap is overwritten by a class with same name from .memmap import * -from .defchararray import chararray from . import function_base from .function_base import * from . import _machar @@ -106,9 +105,8 @@ from . import _dtype from . import _methods -__all__ = ['char', 'rec', 'memmap', 'sctypeDict'] +__all__ = ['char', 'rec', 'memmap', 'sctypeDict', 'record', 'abs'] __all__ += numeric.__all__ -__all__ += ['record', 'recarray', 'format_parser', 'chararray', 'abs'] __all__ += function_base.__all__ __all__ += getlimits.__all__ __all__ += shape_base.__all__ diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py index 0c6d7d5a59aa..d5cffaa31f5e 100644 --- a/numpy/core/_add_newdocs.py +++ b/numpy/core/_add_newdocs.py @@ -978,9 +978,9 @@ Contrary to `asanyarray`, ndarray subclasses are not passed through: - >>> issubclass(np.recarray, np.ndarray) + >>> issubclass(np.rec.recarray, np.ndarray) True - >>> a = np.array([(1.0, 2), (3.0, 4)], dtype='f4,i4').view(np.recarray) + >>> a = np.array([(1., 2), (3., 4)], dtype='f4,i4').view(np.rec.recarray) >>> np.asarray(a) is a False >>> np.asanyarray(a) is a @@ -1044,7 +1044,7 @@ Instances of `ndarray` subclasses are passed through as-is: - >>> a = np.array([(1.0, 2), (3.0, 4)], dtype='f4,i4').view(np.recarray) + >>> a = np.array([(1., 2), (3., 4)], dtype='f4,i4').view(np.rec.recarray) >>> np.asanyarray(a) is a True @@ -1419,7 +1419,7 @@ -------- >>> a = np.array(["a", "b", "cde"]) >>> b = np.array(["a", "a", "dec"]) - >>> np.compare_chararrays(a, b, ">", True) + >>> np.char.compare_chararrays(a, b, ">", True) array([False, True, False]) """) @@ -4645,7 +4645,7 @@ Using a view to convert an array to a recarray: - >>> z = x.view(np.recarray) + >>> z = x.view(np.rec.recarray) >>> z.a array([1, 3], dtype=int8) diff --git a/numpy/core/defchararray.py b/numpy/core/defchararray.py index c93581214c6c..cc2a7d1d0d1f 100644 --- a/numpy/core/defchararray.py +++ b/numpy/core/defchararray.py @@ -20,9 +20,8 @@ from .._utils import set_module from .numerictypes import ( bytes_, str_, integer, int_, object_, bool_, character) -from .numeric import ndarray, compare_chararrays -from .numeric import array as narray -from numpy.core.multiarray import _vec_string +from .numeric import ndarray, array as narray +from numpy.core.multiarray import _vec_string, compare_chararrays from numpy.core import overrides from numpy._utils import asbytes import numpy @@ -36,7 +35,7 @@ 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill', 'isnumeric', 'isdecimal', - 'array', 'asarray' + 'array', 'asarray', 'compare_chararrays' ] @@ -1920,7 +1919,6 @@ 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/defchararray.pyi b/numpy/core/defchararray.pyi index 73d90bb2fc53..fe0699a98623 100644 --- a/numpy/core/defchararray.pyi +++ b/numpy/core/defchararray.pyi @@ -6,7 +6,6 @@ from typing import ( ) from numpy import ( - chararray as chararray, dtype, str_, bytes_, @@ -24,6 +23,8 @@ from numpy._typing import ( _ArrayLikeBool_co as b_co, ) +from numpy.core.defchararray import chararray + from numpy.core.multiarray import compare_chararrays as compare_chararrays _SCT = TypeVar("_SCT", str_, bytes_) diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py index ea3aeaf5f513..5d44b18bd3bd 100644 --- a/numpy/core/numeric.py +++ b/numpy/core/numeric.py @@ -12,7 +12,7 @@ ALLOW_THREADS, BUFSIZE, CLIP, MAXDIMS, MAY_SHARE_BOUNDS, MAY_SHARE_EXACT, RAISE, WRAP, arange, array, asarray, asanyarray, ascontiguousarray, - asfortranarray, broadcast, can_cast, compare_chararrays, + asfortranarray, broadcast, can_cast, concatenate, copyto, dot, dtype, empty, empty_like, flatiter, frombuffer, from_dlpack, fromfile, fromiter, fromstring, inner, lexsort, matmul, may_share_memory, @@ -50,7 +50,7 @@ 'rollaxis', 'moveaxis', 'cross', 'tensordot', 'little_endian', 'fromiter', 'array_equal', 'array_equiv', 'indices', 'fromfunction', 'isclose', 'isscalar', 'binary_repr', 'base_repr', 'ones', - 'identity', 'allclose', 'compare_chararrays', 'putmask', + 'identity', 'allclose', 'putmask', 'flatnonzero', 'inf', 'nan', 'False_', 'True_', 'bitwise_not', 'full', 'full_like', 'matmul', 'shares_memory', 'may_share_memory', '_get_promotion_state', '_set_promotion_state'] diff --git a/numpy/core/records.py b/numpy/core/records.py index 14f8f0836f86..0a6e8f1bbbf3 100644 --- a/numpy/core/records.py +++ b/numpy/core/records.py @@ -45,8 +45,8 @@ # All of the functions allow formats to be a dtype __all__ = [ - 'record', 'recarray', 'format_parser', - 'fromarrays', 'fromrecords', 'fromstring', 'fromfile', 'array', + 'record', 'recarray', 'format_parser', 'fromarrays', 'fromrecords', + 'fromstring', 'fromfile', 'array', ] @@ -84,7 +84,7 @@ def find_duplicate(list): ] -@set_module('numpy') +@set_module('numpy.rec') class format_parser: """ Class to convert formats, names, titles description to a dtype. @@ -128,18 +128,18 @@ class format_parser: Examples -------- - >>> np.format_parser(['>> np.rec.format_parser(['>> np.format_parser(['f8', 'i4', 'a5'], ['col1', 'col2', 'col3'], - ... []).dtype + >>> np.rec.format_parser(['f8', 'i4', 'a5'], ['col1', 'col2', 'col3'], + ... []).dtype dtype([('col1', '>> np.format_parser(['>> np.rec.format_parser(['>> x = x.view(np.recarray) + >>> x = x.view(np.rec.recarray) >>> x.x array([1., 3.]) @@ -402,7 +402,7 @@ class recarray(ndarray): Create a new, empty record array: - >>> np.recarray((2,), + >>> np.rec.recarray((2,), ... dtype=[('x', int), ('y', float), ('z', int)]) #doctest: +SKIP rec.array([(-1073741821, 1.2249118382103472e-301, 24547520), (3471280, 1.2134086255804012e-316, 0)], @@ -410,11 +410,6 @@ class recarray(ndarray): """ - # manually set name and module so that this class's type shows - # up as "numpy.recarray" when printed - __name__ = 'recarray' - __module__ = 'numpy' - def __new__(subtype, shape, dtype=None, buf=None, offset=0, strides=None, formats=None, names=None, titles=None, byteorder=None, aligned=False, order='C'): @@ -607,7 +602,7 @@ def fromarrays(arrayList, dtype=None, shape=None, formats=None, Returns ------- - np.recarray + np.rec.recarray Record array consisting of given arrayList columns. Examples @@ -705,7 +700,7 @@ def fromrecords(recList, dtype=None, shape=None, formats=None, names=None, Returns ------- - np.recarray + np.rec.recarray record array consisting of given recList rows. Examples @@ -791,7 +786,7 @@ def fromstring(datastring, dtype=None, shape=None, offset=0, formats=None, Returns ------- - np.recarray + np.rec.recarray Record array view into the data in datastring. This will be readonly if `datastring` is readonly. @@ -873,7 +868,7 @@ def fromfile(fd, dtype=None, shape=None, offset=0, formats=None, Returns ------- - np.recarray + np.rec.recarray record array consisting of data enclosed in file. Examples @@ -985,16 +980,16 @@ def array(obj, dtype=None, shape=None, offset=0, strides=None, formats=None, Returns ------- - np.recarray + np.rec.recarray Record array created from the specified object. Notes ----- - If `obj` is ``None``, then call the `~numpy.recarray` constructor. If + If `obj` is ``None``, then call the `~numpy.rec.recarray` constructor. If `obj` is a string, then call the `fromstring` constructor. If `obj` is a list or a tuple, then if the first object is an `~numpy.ndarray`, call `fromarrays`, otherwise call `fromrecords`. If `obj` is a - `~numpy.recarray`, then make a copy of the data in the recarray + `~numpy.rec.recarray`, then make a copy of the data in the recarray (if ``copy=True``) and use the new formats, names, and titles. If `obj` is a file, then call `fromfile`. Finally, if obj is an `ndarray`, then return ``obj.view(recarray)``, making a copy of the data if ``copy=True``. diff --git a/numpy/core/records.pyi b/numpy/core/records.pyi index d3bbe0e70eef..02a64a7661ed 100644 --- a/numpy/core/records.pyi +++ b/numpy/core/records.pyi @@ -8,7 +8,6 @@ from typing import ( ) from numpy import ( - format_parser as format_parser, record as record, recarray as recarray, dtype, @@ -36,6 +35,17 @@ class _SupportsReadInto(Protocol): def tell(self, /) -> int: ... def readinto(self, buffer: memoryview, /) -> int: ... +class format_parser: + dtype: dtype[void] + def __init__( + self, + formats: DTypeLike, + names: None | str | Sequence[str], + titles: None | str | Sequence[str], + aligned: bool = ..., + byteorder: None | _ByteOrder = ..., + ) -> None: ... + __all__: list[str] @overload diff --git a/numpy/core/tests/test_arraymethod.py b/numpy/core/tests/test_arraymethod.py index 4fd4d555845a..1e2319fc6f94 100644 --- a/numpy/core/tests/test_arraymethod.py +++ b/numpy/core/tests/test_arraymethod.py @@ -65,7 +65,9 @@ def test_invalid_arguments(self, args, error): @pytest.mark.parametrize( - "cls", [np.ndarray, np.recarray, np.chararray, np.matrix, np.memmap] + "cls", [ + np.ndarray, np.rec.recarray, np.char.chararray, np.matrix, np.memmap + ] ) class TestClassGetItem: def test_class_getitem(self, cls: type[np.ndarray]) -> None: diff --git a/numpy/core/tests/test_defchararray.py b/numpy/core/tests/test_defchararray.py index d6692a23ac14..9f4432879e80 100644 --- a/numpy/core/tests/test_defchararray.py +++ b/numpy/core/tests/test_defchararray.py @@ -135,9 +135,9 @@ def fail(): class TestWhitespace: def setup_method(self): self.A = np.array([['abc ', '123 '], - ['789 ', 'xyz ']]).view(np.chararray) + ['789 ', 'xyz ']]).view(np.char.chararray) self.B = np.array([['abc', '123'], - ['789', 'xyz']]).view(np.chararray) + ['789', 'xyz']]).view(np.char.chararray) def test1(self): assert_(np.all(self.A == self.B)) @@ -149,7 +149,7 @@ def test1(self): class TestChar: def setup_method(self): - self.A = np.array('abc1', dtype='c').view(np.chararray) + self.A = np.array('abc1', dtype='c').view(np.char.chararray) def test_it(self): assert_equal(self.A.shape, (4,)) @@ -158,9 +158,9 @@ def test_it(self): class TestComparisons: def setup_method(self): self.A = np.array([['abc', '123'], - ['789', 'xyz']]).view(np.chararray) + ['789', 'xyz']]).view(np.char.chararray) self.B = np.array([['efg', '123 '], - ['051', 'tuv']]).view(np.chararray) + ['051', 'tuv']]).view(np.char.chararray) def test_not_equal(self): assert_array_equal((self.A != self.B), [[True, False], [True, True]]) @@ -192,7 +192,7 @@ class TestComparisonsMixed1(TestComparisons): def setup_method(self): TestComparisons.setup_method(self) self.B = np.array([['efg', '123 '], - ['051', 'tuv']], np.str_).view(np.chararray) + ['051', 'tuv']], np.str_).view(np.char.chararray) class TestComparisonsMixed2(TestComparisons): """Ticket #1276""" @@ -200,16 +200,19 @@ class TestComparisonsMixed2(TestComparisons): def setup_method(self): TestComparisons.setup_method(self) self.A = np.array([['abc', '123'], - ['789', 'xyz']], np.str_).view(np.chararray) + ['789', 'xyz']], np.str_) \ + .view(np.char.chararray) class TestInformation: def setup_method(self): self.A = np.array([[' abc ', ''], ['12345', 'MixedCase'], - ['123 \t 345 \0 ', 'UPPER']]).view(np.chararray) + ['123 \t 345 \0 ', 'UPPER']]) \ + .view(np.char.chararray) self.B = np.array([[' \u03a3 ', ''], ['12345', 'MixedCase'], - ['123 \t 345 \0 ', 'UPPER']]).view(np.chararray) + ['123 \t 345 \0 ', 'UPPER']]) \ + .view(np.char.chararray) def test_len(self): assert_(issubclass(np.char.str_len(self.A).dtype.type, np.integer)) @@ -313,10 +316,11 @@ def setup_method(self): self.A = np.array([[' abc ', ''], ['12345', 'MixedCase'], ['123 \t 345 \0 ', 'UPPER']], - dtype='S').view(np.chararray) + dtype='S').view(np.char.chararray) self.B = np.array([[' \u03a3 ', ''], ['12345', 'MixedCase'], - ['123 \t 345 \0 ', 'UPPER']]).view(np.chararray) + ['123 \t 345 \0 ', 'UPPER']]).view( + np.char.chararray) def test_capitalize(self): tgt = [[b' abc ', b''], @@ -584,26 +588,26 @@ def fail(): class TestOperations: def setup_method(self): self.A = np.array([['abc', '123'], - ['789', 'xyz']]).view(np.chararray) + ['789', 'xyz']]).view(np.char.chararray) self.B = np.array([['efg', '456'], - ['051', 'tuv']]).view(np.chararray) + ['051', 'tuv']]).view(np.char.chararray) def test_add(self): AB = np.array([['abcefg', '123456'], - ['789051', 'xyztuv']]).view(np.chararray) + ['789051', 'xyztuv']]).view(np.char.chararray) assert_array_equal(AB, (self.A + self.B)) assert_(len((self.A + self.B)[0][0]) == 6) def test_radd(self): QA = np.array([['qabc', 'q123'], - ['q789', 'qxyz']]).view(np.chararray) + ['q789', 'qxyz']]).view(np.char.chararray) assert_array_equal(QA, ('q' + self.A)) def test_mul(self): A = self.A for r in (2, 3, 5, 7, 197): Ar = np.array([[A[0, 0]*r, A[0, 1]*r], - [A[1, 0]*r, A[1, 1]*r]]).view(np.chararray) + [A[1, 0]*r, A[1, 1]*r]]).view(np.char.chararray) assert_array_equal(Ar, (self.A * r)) @@ -616,7 +620,7 @@ def test_rmul(self): A = self.A for r in (2, 3, 5, 7, 197): Ar = np.array([[A[0, 0]*r, A[0, 1]*r], - [A[1, 0]*r, A[1, 1]*r]]).view(np.chararray) + [A[1, 0]*r, A[1, 1]*r]]).view(np.char.chararray) assert_array_equal(Ar, (r * self.A)) for ob in [object(), 'qrs']: @@ -626,19 +630,19 @@ def test_rmul(self): def test_mod(self): """Ticket #856""" - F = np.array([['%d', '%f'], ['%s', '%r']]).view(np.chararray) + F = np.array([['%d', '%f'], ['%s', '%r']]).view(np.char.chararray) C = np.array([[3, 7], [19, 1]], dtype=np.int64) FC = np.array([['3', '7.000000'], - ['19', 'np.int64(1)']]).view(np.chararray) + ['19', 'np.int64(1)']]).view(np.char.chararray) assert_array_equal(FC, F % C) - A = np.array([['%.3f', '%d'], ['%s', '%r']]).view(np.chararray) + A = np.array([['%.3f', '%d'], ['%s', '%r']]).view(np.char.chararray) A1 = np.array([['1.000', '1'], - ['1', repr(np.array(1)[()])]]).view(np.chararray) + ['1', repr(np.array(1)[()])]]).view(np.char.chararray) assert_array_equal(A1, (A % 1)) A2 = np.array([['1.000', '2'], - ['3', repr(np.array(4)[()])]]).view(np.chararray) + ['3', repr(np.array(4)[()])]]).view(np.char.chararray) assert_array_equal(A2, (A % [[1, 2], [3, 4]])) def test_rmod(self): @@ -654,7 +658,7 @@ def test_slice(self): """Regression test for https://github.com/numpy/numpy/issues/5982""" arr = np.array([['abc ', 'def '], ['geh ', 'ijk ']], - dtype='S4').view(np.chararray) + dtype='S4').view(np.char.chararray) sl1 = arr[:] assert_array_equal(sl1, arr) assert_(sl1.base is arr) @@ -672,7 +676,7 @@ def test_empty_indexing(): """Regression test for ticket 1948.""" # Check that indexing a chararray with an empty list/array returns an # empty chararray instead of a chararray with a single empty string in it. - s = np.chararray((4,)) + s = np.char.chararray((4,)) assert_(s[[]].size == 0) diff --git a/numpy/core/tests/test_dtype.py b/numpy/core/tests/test_dtype.py index 2db170d09c4e..a50f58581499 100644 --- a/numpy/core/tests/test_dtype.py +++ b/numpy/core/tests/test_dtype.py @@ -569,7 +569,7 @@ def test_fieldless_views(self): def test_nonstructured_with_object(self): # See gh-23277, the dtype here thinks it contain objects, if the # assert about that fails, the test becomes meaningless (which is OK) - arr = np.recarray((0,), dtype="O") + arr = np.rec.recarray((0,), dtype="O") assert arr.dtype.names is None # no fields assert arr.dtype.hasobject # but claims to contain objects del arr # the deletion failed previously. diff --git a/numpy/core/tests/test_records.py b/numpy/core/tests/test_records.py index 1b6ae7cf4cef..76993c8972e5 100644 --- a/numpy/core/tests/test_records.py +++ b/numpy/core/tests/test_records.py @@ -146,7 +146,7 @@ def test_recarray_from_repr(self): a = np.array([(1,'ABC'), (2, "DEF")], dtype=[('foo', int), ('bar', 'S4')]) recordarr = np.rec.array(a) - recarr = a.view(np.recarray) + recarr = a.view(np.rec.recarray) recordview = a.view(np.dtype((np.record, a.dtype))) recordarr_r = eval("np." + repr(recordarr), {'np': np}) @@ -154,11 +154,11 @@ def test_recarray_from_repr(self): # Prints the type `numpy.record` as part of the dtype: recordview_r = eval("np." + repr(recordview), {'np': np, 'numpy': np}) - assert_equal(type(recordarr_r), np.recarray) + assert_equal(type(recordarr_r), np.rec.recarray) assert_equal(recordarr_r.dtype.type, np.record) assert_equal(recordarr, recordarr_r) - assert_equal(type(recarr_r), np.recarray) + assert_equal(type(recarr_r), np.rec.recarray) assert_equal(recarr_r.dtype.type, np.record) assert_equal(recarr, recarr_r) @@ -173,30 +173,30 @@ def test_recarray_views(self): #check that np.rec.array gives right dtypes assert_equal(np.rec.array(a).dtype.type, np.record) - assert_equal(type(np.rec.array(a)), np.recarray) + assert_equal(type(np.rec.array(a)), np.rec.recarray) assert_equal(np.rec.array(b).dtype.type, np.int64) - assert_equal(type(np.rec.array(b)), np.recarray) + assert_equal(type(np.rec.array(b)), np.rec.recarray) #check that viewing as recarray does the same - assert_equal(a.view(np.recarray).dtype.type, np.record) - assert_equal(type(a.view(np.recarray)), np.recarray) - assert_equal(b.view(np.recarray).dtype.type, np.int64) - assert_equal(type(b.view(np.recarray)), np.recarray) + assert_equal(a.view(np.rec.recarray).dtype.type, np.record) + assert_equal(type(a.view(np.rec.recarray)), np.rec.recarray) + assert_equal(b.view(np.rec.recarray).dtype.type, np.int64) + assert_equal(type(b.view(np.rec.recarray)), np.rec.recarray) - #check that view to non-structured dtype preserves type=np.recarray + #check that view to non-structured dtype preserves type=np.rec.recarray r = np.rec.array(np.ones(4, dtype="f4,i4")) rv = r.view('f8').view('f4,i4') - assert_equal(type(rv), np.recarray) + assert_equal(type(rv), np.rec.recarray) assert_equal(rv.dtype.type, np.record) - #check that getitem also preserves np.recarray and np.record + #check that getitem also preserves np.rec.recarray and np.record r = np.rec.array(np.ones(4, dtype=[('a', 'i4'), ('b', 'i4'), ('c', 'i4,i4')])) assert_equal(r['c'].dtype.type, np.record) - assert_equal(type(r['c']), np.recarray) + assert_equal(type(r['c']), np.rec.recarray) #and that it preserves subclasses (gh-6949) - class C(np.recarray): + class C(np.rec.recarray): pass c = r.view(C) @@ -278,7 +278,7 @@ def test_recarray_stringtypes(self): # Issue #3993 a = np.array([('abc ', 1), ('abc', 2)], dtype=[('foo', 'S4'), ('bar', int)]) - a = a.view(np.recarray) + a = a.view(np.rec.recarray) assert_equal(a.foo[0] == a.foo[1], False) def test_recarray_returntypes(self): @@ -290,10 +290,10 @@ def test_recarray_returntypes(self): ('baz', int), ('qux', qux_fields)]) assert_equal(type(a.foo), np.ndarray) assert_equal(type(a['foo']), np.ndarray) - assert_equal(type(a.bar), np.recarray) - assert_equal(type(a['bar']), np.recarray) + assert_equal(type(a.bar), np.rec.recarray) + assert_equal(type(a['bar']), np.rec.recarray) assert_equal(a.bar.dtype.type, np.record) - assert_equal(type(a['qux']), np.recarray) + assert_equal(type(a['qux']), np.rec.recarray) assert_equal(a.qux.dtype.type, np.record) assert_equal(dict(a.qux.dtype.fields), qux_fields) assert_equal(type(a.baz), np.ndarray) @@ -442,16 +442,18 @@ def test_pickle_void(self): def test_objview_record(self): # https://github.com/numpy/numpy/issues/2599 dt = np.dtype([('foo', 'i8'), ('bar', 'O')]) - r = np.zeros((1,3), dtype=dt).view(np.recarray) + r = np.zeros((1, 3), dtype=dt).view(np.rec.recarray) r.foo = np.array([1, 2, 3]) # TypeError? # https://github.com/numpy/numpy/issues/3256 - ra = np.recarray((2,), dtype=[('x', object), ('y', float), ('z', int)]) + ra = np.rec.recarray( + (2,), dtype=[('x', object), ('y', float), ('z', int)] + ) ra[['x','y']] # TypeError? def test_record_scalar_setitem(self): # https://github.com/numpy/numpy/issues/3561 - rec = np.recarray(1, dtype=[('x', float, 5)]) + rec = np.rec.recarray(1, dtype=[('x', float, 5)]) rec[0].x = 1 assert_equal(rec[0].x, np.ones(5)) @@ -470,7 +472,7 @@ def test_fromarrays_nested_structured_arrays(self): @pytest.mark.parametrize('nfields', [0, 1, 2]) def test_assign_dtype_attribute(self, nfields): dt = np.dtype([('a', np.uint8), ('b', np.uint8), ('c', np.uint8)][:nfields]) - data = np.zeros(3, dt).view(np.recarray) + data = np.zeros(3, dt).view(np.rec.recarray) # the original and resulting dtypes differ on whether they are records assert data.dtype.type == np.record @@ -486,9 +488,9 @@ def test_nested_fields_are_records(self, nfields): dt = np.dtype([('a', np.uint8), ('b', np.uint8), ('c', np.uint8)][:nfields]) dt_outer = np.dtype([('inner', dt)]) - data = np.zeros(3, dt_outer).view(np.recarray) - assert isinstance(data, np.recarray) - assert isinstance(data['inner'], np.recarray) + data = np.zeros(3, dt_outer).view(np.rec.recarray) + assert isinstance(data, np.rec.recarray) + assert isinstance(data['inner'], np.rec.recarray) data0 = data[0] assert isinstance(data0, np.record) @@ -503,7 +505,7 @@ def test_nested_dtype_padding(self): dt_outer = np.dtype([('inner', dt_padded_end)]) - data = np.zeros(3, dt_outer).view(np.recarray) + data = np.zeros(3, dt_outer).view(np.rec.recarray) assert_equal(data['inner'].dtype, dt_padded_end) data0 = data[0] diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py index 6899cb1c4bec..346a59407537 100644 --- a/numpy/core/tests/test_regression.py +++ b/numpy/core/tests/test_regression.py @@ -179,7 +179,7 @@ def test_endian_recarray(self): ('head', '>u4'), ('data', '>u4', 2), ]) - buf = np.recarray(1, dtype=dt) + buf = np.rec.recarray(1, dtype=dt) buf[0]['head'] = 1 buf[0]['data'][:] = [1, 1] @@ -378,7 +378,7 @@ def index_tmp(): def test_chararray_rstrip(self): # Ticket #222 - x = np.chararray((1,), 5) + x = np.char.chararray((1,), 5) x[0] = b'a ' x = x.rstrip() assert_equal(x[0], b'a') @@ -1169,7 +1169,7 @@ def test_recarray_tolist(self): # Comparisons fail for NaN, so we can't use random memory # for the test. buf = np.zeros(40, dtype=np.int8) - a = np.recarray(2, formats="i4,f8,f8", names="id,x,y", buf=buf) + a = np.rec.recarray(2, formats="i4,f8,f8", names="id,x,y", buf=buf) b = a.tolist() assert_( a[0].tolist() == b[0]) assert_( a[1].tolist() == b[1]) @@ -2079,8 +2079,8 @@ def test_searchsorted_wrong_dtype(self): a = np.array([('a', 1)], dtype='S1, int') assert_raises(TypeError, np.searchsorted, a, 1.2) # Ticket #2066, similar problem: - dtype = np.format_parser(['i4', 'i4'], [], []) - a = np.recarray((2,), dtype) + dtype = np.rec.format_parser(['i4', 'i4'], [], []) + a = np.rec.recarray((2,), dtype) a[...] = [(1, 2), (3, 4)] assert_raises(TypeError, np.searchsorted, a, 1) diff --git a/numpy/core/tests/test_strings.py b/numpy/core/tests/test_strings.py index 29a7bb93cadf..7e8b33eab3c2 100644 --- a/numpy/core/tests/test_strings.py +++ b/numpy/core/tests/test_strings.py @@ -64,12 +64,16 @@ def test_string_comparisons(op, ufunc, sym, dtypes, aligned): expected = [op(d1, d2) for d1, d2 in zip(arr.tolist(), arr2.tolist())] assert_array_equal(op(arr, arr2), expected) assert_array_equal(ufunc(arr, arr2), expected) - assert_array_equal(np.compare_chararrays(arr, arr2, sym, False), expected) + assert_array_equal( + np.char.compare_chararrays(arr, arr2, sym, False), expected + ) expected = [op(d2, d1) for d1, d2 in zip(arr.tolist(), arr2.tolist())] assert_array_equal(op(arr2, arr), expected) assert_array_equal(ufunc(arr2, arr), expected) - assert_array_equal(np.compare_chararrays(arr2, arr, sym, False), expected) + assert_array_equal( + np.char.compare_chararrays(arr2, arr, sym, False), expected + ) @pytest.mark.parametrize(["op", "ufunc", "sym"], COMPARISONS) @@ -82,7 +86,9 @@ def test_string_comparisons_empty(op, ufunc, sym, dtypes): expected = np.empty(np.broadcast_shapes(arr.shape, arr2.shape), dtype=bool) assert_array_equal(op(arr, arr2), expected) assert_array_equal(ufunc(arr, arr2), expected) - assert_array_equal(np.compare_chararrays(arr, arr2, sym, False), expected) + assert_array_equal( + np.char.compare_chararrays(arr, arr2, sym, False), expected + ) @pytest.mark.parametrize("str_dt", ["S", "U"]) diff --git a/numpy/lib/_npyio_impl.py b/numpy/lib/_npyio_impl.py index 87a08bec9138..c2f05c9efa90 100644 --- a/numpy/lib/_npyio_impl.py +++ b/numpy/lib/_npyio_impl.py @@ -2500,7 +2500,7 @@ def recfromtxt(fname, **kwargs): from numpy.ma.mrecords import MaskedRecords output = output.view(MaskedRecords) else: - output = output.view(np.recarray) + output = output.view(np.rec.recarray) return output @@ -2551,5 +2551,5 @@ def recfromcsv(fname, **kwargs): from numpy.ma.mrecords import MaskedRecords output = output.view(MaskedRecords) else: - output = output.view(np.recarray) + output = output.view(np.rec.recarray) return output diff --git a/numpy/lib/recfunctions.py b/numpy/lib/recfunctions.py index 2637f6419d90..c0a1638c1303 100644 --- a/numpy/lib/recfunctions.py +++ b/numpy/lib/recfunctions.py @@ -8,10 +8,11 @@ import itertools import numpy as np import numpy.ma as ma -from numpy import ndarray, recarray +from numpy import ndarray from numpy.ma import MaskedArray from numpy.ma.mrecords import MaskedRecords from numpy.core.overrides import array_function_dispatch +from numpy.core.records import recarray from numpy.lib._iotools import _is_string_like _check_fill_value = np.ma.core._check_fill_value @@ -755,7 +756,7 @@ def rec_append_fields(base, names, data, dtypes=None): Returns ------- - appended_array : np.recarray + appended_array : np.rec.recarray """ return append_fields(base, names, data=data, dtypes=dtypes, asrecarray=True, usemask=False) @@ -1025,7 +1026,7 @@ def structured_to_unstructured(arr, dtype=None, copy=False, casting='unsafe'): # we only allow a few types to be unstructured by manipulating the # strides, because we know it won't work with, for example, np.matrix nor # np.ma.MaskedArray. - can_view = type(arr) in (np.ndarray, np.recarray, np.memmap) + can_view = type(arr) in (np.ndarray, np.rec.recarray, np.memmap) if (not copy) and can_view and all(dt.base == out_dtype for dt in dts): # all elements have the right dtype already; if they have a common # stride, we can just return a view @@ -1662,7 +1663,7 @@ def rec_join(key, r1, r2, jointype='inner', r1postfix='1', r2postfix='2', defaults=None): """ Join arrays `r1` and `r2` on keys. - Alternative to join_by, that always returns a np.recarray. + Alternative to join_by, that always returns a np.rec.recarray. See Also -------- diff --git a/numpy/lib/tests/test_arraysetops.py b/numpy/lib/tests/test_arraysetops.py index 9d8784d0fe13..56e48b94b692 100644 --- a/numpy/lib/tests/test_arraysetops.py +++ b/numpy/lib/tests/test_arraysetops.py @@ -694,7 +694,7 @@ def check_all(a, b, i1, i2, c, dt): assert_array_equal(a2_inv, inv) # test for chararrays with return_inverse (gh-5099) - a = np.chararray(5) + a = np.char.chararray(5) a[...] = '' a2, a2_inv = np.unique(a, return_inverse=True) assert_array_equal(a2_inv, np.zeros(5)) diff --git a/numpy/lib/tests/test_io.py b/numpy/lib/tests/test_io.py index 36505b34a515..c6ca81b07e72 100644 --- a/numpy/lib/tests/test_io.py +++ b/numpy/lib/tests/test_io.py @@ -2302,7 +2302,7 @@ def test_recfromtxt(self): test = recfromtxt(data, **kwargs) control = np.array([(0, 1), (2, 3)], dtype=[('A', int), ('B', int)]) - assert_(isinstance(test, np.recarray)) + assert_(isinstance(test, np.rec.recarray)) assert_equal(test, control) # data = TextIO('A,B\n0,1\n2,N/A') @@ -2322,7 +2322,7 @@ def test_recfromcsv(self): test = recfromcsv(data, dtype=None, **kwargs) control = np.array([(0, 1), (2, 3)], dtype=[('A', int), ('B', int)]) - assert_(isinstance(test, np.recarray)) + assert_(isinstance(test, np.rec.recarray)) assert_equal(test, control) # data = TextIO('A,B\n0,1\n2,N/A') @@ -2338,7 +2338,7 @@ def test_recfromcsv(self): test = recfromcsv(data, missing_values='N/A',) control = np.array([(0, 1), (2, 3)], dtype=[('a', int), ('b', int)]) - assert_(isinstance(test, np.recarray)) + assert_(isinstance(test, np.rec.recarray)) assert_equal(test, control) # data = TextIO('A,B\n0,1\n2,3') @@ -2346,7 +2346,7 @@ def test_recfromcsv(self): test = recfromcsv(data, missing_values='N/A', dtype=dtype) control = np.array([(0, 1), (2, 3)], dtype=dtype) - assert_(isinstance(test, np.recarray)) + assert_(isinstance(test, np.rec.recarray)) assert_equal(test, control) #gh-10394 @@ -2626,7 +2626,7 @@ def test_recfromtxt(self, filename_type): test = recfromtxt(path, **kwargs) control = np.array([(0, 1), (2, 3)], dtype=[('A', int), ('B', int)]) - assert_(isinstance(test, np.recarray)) + assert_(isinstance(test, np.rec.recarray)) assert_equal(test, control) @pytest.mark.parametrize("filename_type", [Path, str]) @@ -2643,7 +2643,7 @@ def test_recfromcsv(self, filename_type): test = recfromcsv(path, dtype=None, **kwargs) control = np.array([(0, 1), (2, 3)], dtype=[('A', int), ('B', int)]) - assert_(isinstance(test, np.recarray)) + assert_(isinstance(test, np.rec.recarray)) assert_equal(test, control) diff --git a/numpy/lib/tests/test_recfunctions.py b/numpy/lib/tests/test_recfunctions.py index 98860dfdab77..3c84a2abd633 100644 --- a/numpy/lib/tests/test_recfunctions.py +++ b/numpy/lib/tests/test_recfunctions.py @@ -350,13 +350,13 @@ def inspect(dt, dtype=None): dd_expected = structured_to_unstructured(d_plain, copy=True) # recarray - d = d_plain.view(np.recarray) + d = d_plain.view(np.rec.recarray) dd = structured_to_unstructured(d, copy=False) ddd = structured_to_unstructured(d, copy=True) assert_(np.shares_memory(d, dd)) - assert_(type(dd) is np.recarray) - assert_(type(ddd) is np.recarray) + assert_(type(dd) is np.rec.recarray) + assert_(type(ddd) is np.rec.recarray) assert_equal(dd, dd_expected) assert_equal(ddd, dd_expected) diff --git a/numpy/ma/core.py b/numpy/ma/core.py index 57728c3220ce..f5bbd85af8f5 100644 --- a/numpy/ma/core.py +++ b/numpy/ma/core.py @@ -3818,7 +3818,8 @@ def filled(self, fill_value=None): Subclassing is preserved. This means that if, e.g., the data part of the masked array is a recarray, `filled` returns a recarray: - >>> x = np.array([(-1, 2), (-3, 4)], dtype='i8,i8').view(np.recarray) + >>> from numpy import rec + >>> x = np.array([(-1, 2), (-3, 4)], dtype='i8,i8').view(rec.recarray) >>> m = np.ma.array(x, mask=[(True, False), (False, True)]) >>> m.filled() rec.array([(999999, 2), ( -3, 999999)], diff --git a/numpy/ma/mrecords.py b/numpy/ma/mrecords.py index 1e8103bcf632..82b2ff79c6b4 100644 --- a/numpy/ma/mrecords.py +++ b/numpy/ma/mrecords.py @@ -22,10 +22,10 @@ import numpy as np from numpy import ( - bool_, dtype, ndarray, recarray, array as narray + bool_, dtype, ndarray, array as narray ) from numpy.core.records import ( - fromarrays as recfromarrays, fromrecords as recfromrecords + recarray, fromarrays as recfromarrays, fromrecords as recfromrecords ) _byteorderconv = np.core.records._byteorderconv diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py index a4f8deb93ab5..7a6d17fb314c 100644 --- a/numpy/ma/tests/test_core.py +++ b/numpy/ma/tests/test_core.py @@ -645,13 +645,13 @@ def test_pickling(self): def test_pickling_subbaseclass(self): # Test pickling w/ a subclass of ndarray x = np.array([(1.0, 2), (3.0, 4)], - dtype=[('x', float), ('y', int)]).view(np.recarray) + dtype=[('x', float), ('y', int)]).view(np.rec.recarray) a = masked_array(x, mask=[(True, False), (False, True)]) for proto in range(2, pickle.HIGHEST_PROTOCOL + 1): a_pickled = pickle.loads(pickle.dumps(a, protocol=proto)) assert_equal(a_pickled._mask, a._mask) assert_equal(a_pickled, a) - assert_(isinstance(a_pickled._data, np.recarray)) + assert_(isinstance(a_pickled._data, np.rec.recarray)) def test_pickling_maskedconstant(self): # Test pickling MaskedConstant @@ -5220,9 +5220,9 @@ def test_view_to_subdtype(self): def test_view_to_dtype_and_type(self): (data, a, controlmask) = self.data - test = a.view((float, 2), np.recarray) + test = a.view((float, 2), np.rec.recarray) assert_equal(test, data) - assert_(isinstance(test, np.recarray)) + assert_(isinstance(test, np.rec.recarray)) assert_(not isinstance(test, MaskedArray)) diff --git a/numpy/random/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py index 21345b0d6c72..912a3c849f82 100644 --- a/numpy/random/tests/test_generator_mt19937.py +++ b/numpy/random/tests/test_generator_mt19937.py @@ -953,7 +953,7 @@ def test_shuffle(self): # gh-11442 lambda x: (np.asarray([(i, i) for i in x], [("a", int), ("b", int)]) - .view(np.recarray)), + .view(np.rec.recarray)), # gh-4270 lambda x: np.asarray([(i, i) for i in x], [("a", object, (1,)), diff --git a/numpy/random/tests/test_random.py b/numpy/random/tests/test_random.py index e64ace711953..c0562f6960d2 100644 --- a/numpy/random/tests/test_random.py +++ b/numpy/random/tests/test_random.py @@ -487,7 +487,7 @@ def test_shuffle(self): # gh-11442 lambda x: (np.asarray([(i, i) for i in x], [("a", int), ("b", int)]) - .view(np.recarray)), + .view(np.rec.recarray)), # gh-4270 lambda x: np.asarray([(i, i) for i in x], [("a", object), ("b", np.int32)])]: diff --git a/numpy/random/tests/test_randomstate.py b/numpy/random/tests/test_randomstate.py index 524ac7b7c5e0..b4f28ade1217 100644 --- a/numpy/random/tests/test_randomstate.py +++ b/numpy/random/tests/test_randomstate.py @@ -689,7 +689,7 @@ def test_shuffle(self): # gh-11442 lambda x: (np.asarray([(i, i) for i in x], [("a", int), ("b", int)]) - .view(np.recarray)), + .view(np.rec.recarray)), # gh-4270 lambda x: np.asarray([(i, i) for i in x], [("a", object, (1,)), diff --git a/numpy/tests/test_public_api.py b/numpy/tests/test_public_api.py index 4aded7fdde6e..2f302cc8e5b9 100644 --- a/numpy/tests/test_public_api.py +++ b/numpy/tests/test_public_api.py @@ -34,7 +34,6 @@ def test_numpy_namespace(): # None of these objects are publicly documented to be part of the main # NumPy namespace (some are useful though, others need to be cleaned up) undocumented = { - 'compare_chararrays': 'numpy.core._multiarray_umath.compare_chararrays', 'show_config': 'numpy.__config__.show', 'row_stack': 'numpy.lib._shape_base_impl.row_stack' } diff --git a/numpy/typing/__init__.py b/numpy/typing/__init__.py index fa8e86af83d6..0388a2009f4b 100644 --- a/numpy/typing/__init__.py +++ b/numpy/typing/__init__.py @@ -139,7 +139,7 @@ functions in general, can be specified in one of two ways: * Directly via the ``dtype`` argument. -* With up to five helper arguments that operate via `numpy.format_parser`: +* With up to five helper arguments that operate via `numpy.rec.format_parser`: ``formats``, ``names``, ``titles``, ``aligned`` and ``byteorder``. These two approaches are currently typed as being mutually exclusive, diff --git a/numpy/typing/tests/data/fail/chararray.pyi b/numpy/typing/tests/data/fail/chararray.pyi index ebc182ec2f04..d334f689d121 100644 --- a/numpy/typing/tests/data/fail/chararray.pyi +++ b/numpy/typing/tests/data/fail/chararray.pyi @@ -1,8 +1,8 @@ import numpy as np from typing import Any -AR_U: np.chararray[Any, np.dtype[np.str_]] -AR_S: np.chararray[Any, np.dtype[np.bytes_]] +AR_U: np.char.chararray[Any, np.dtype[np.str_]] +AR_S: np.char.chararray[Any, np.dtype[np.bytes_]] AR_S.encode() # E: Invalid self argument AR_U.decode() # E: Invalid self argument diff --git a/numpy/typing/tests/data/fail/multiarray.pyi b/numpy/typing/tests/data/fail/multiarray.pyi index 16cc4a3e9770..ccf020e0cd74 100644 --- a/numpy/typing/tests/data/fail/multiarray.pyi +++ b/numpy/typing/tests/data/fail/multiarray.pyi @@ -43,7 +43,7 @@ np.busday_offset("2012", 10) # E: No overload variant np.datetime_as_string("2012") # E: No overload variant -np.compare_chararrays("a", b"a", "==", False) # E: No overload variant +np.char.compare_chararrays("a", b"a", "==", False) # E: No overload variant np.nested_iters([AR_i8, AR_i8]) # E: Missing positional argument np.nested_iters([AR_i8, AR_i8], 0) # E: incompatible type diff --git a/numpy/typing/tests/data/reveal/chararray.pyi b/numpy/typing/tests/data/reveal/chararray.pyi index 4bcbeda2e6ad..9760eaab541a 100644 --- a/numpy/typing/tests/data/reveal/chararray.pyi +++ b/numpy/typing/tests/data/reveal/chararray.pyi @@ -9,8 +9,8 @@ if sys.version_info >= (3, 11): else: from typing_extensions import assert_type -AR_U: np.chararray[Any, np.dtype[np.str_]] -AR_S: np.chararray[Any, np.dtype[np.bytes_]] +AR_U: np.char.chararray[Any, np.dtype[np.str_]] +AR_S: np.char.chararray[Any, np.dtype[np.bytes_]] assert_type(AR_U == AR_U, npt.NDArray[np.bool_]) assert_type(AR_S == AR_S, npt.NDArray[np.bool_]) diff --git a/numpy/typing/tests/data/reveal/lib_function_base.pyi b/numpy/typing/tests/data/reveal/lib_function_base.pyi index 670ac9833d04..80a9afd45aec 100644 --- a/numpy/typing/tests/data/reveal/lib_function_base.pyi +++ b/numpy/typing/tests/data/reveal/lib_function_base.pyi @@ -23,7 +23,7 @@ AR_M: npt.NDArray[np.datetime64] AR_O: npt.NDArray[np.object_] AR_b: npt.NDArray[np.bool_] AR_U: npt.NDArray[np.str_] -CHAR_AR_U: np.chararray[Any, np.dtype[np.str_]] +CHAR_AR_U: np.char.chararray[Any, np.dtype[np.str_]] def func(*args: Any, **kwargs: Any) -> Any: ... diff --git a/numpy/typing/tests/data/reveal/multiarray.pyi b/numpy/typing/tests/data/reveal/multiarray.pyi index ec8a5234cb24..6afc1dc57e0a 100644 --- a/numpy/typing/tests/data/reveal/multiarray.pyi +++ b/numpy/typing/tests/data/reveal/multiarray.pyi @@ -134,8 +134,8 @@ assert_type(np.datetime_as_string(AR_M), npt.NDArray[np.str_]) assert_type(np.busdaycalendar(holidays=date_seq), np.busdaycalendar) assert_type(np.busdaycalendar(holidays=[M]), np.busdaycalendar) -assert_type(np.compare_chararrays("a", "b", "!=", rstrip=False), npt.NDArray[np.bool_]) -assert_type(np.compare_chararrays(b"a", b"a", "==", True), npt.NDArray[np.bool_]) +assert_type(np.char.compare_chararrays("a", "b", "!=", rstrip=False), npt.NDArray[np.bool_]) +assert_type(np.char.compare_chararrays(b"a", b"a", "==", True), npt.NDArray[np.bool_]) assert_type(np.nested_iters([AR_i8, AR_i8], [[0], [1]], flags=["c_index"]), tuple[np.nditer, ...]) assert_type(np.nested_iters([AR_i8, AR_i8], [[0], [1]], op_flags=[["readonly", "readonly"]]), tuple[np.nditer, ...]) diff --git a/numpy/typing/tests/data/reveal/rec.pyi b/numpy/typing/tests/data/reveal/rec.pyi index 37408d839f51..e6f96c01d275 100644 --- a/numpy/typing/tests/data/reveal/rec.pyi +++ b/numpy/typing/tests/data/reveal/rec.pyi @@ -11,14 +11,14 @@ else: from typing_extensions import assert_type AR_i8: npt.NDArray[np.int64] -REC_AR_V: np.recarray[Any, np.dtype[np.record]] +REC_AR_V: np.rec.recarray[Any, np.dtype[np.record]] AR_LIST: list[npt.NDArray[np.int64]] -format_parser: np.format_parser +format_parser: np.rec.format_parser record: np.record file_obj: io.BufferedIOBase -assert_type(np.format_parser( +assert_type(format_parser( formats=[np.float64, np.int64, np.bool_], names=["f8", "i8", "?"], titles=None, @@ -42,28 +42,28 @@ assert_type(REC_AR_V.field_a, Any) assert_type(REC_AR_V.__array_finalize__(object()), None) assert_type( - np.recarray( + np.rec.recarray( shape=(10, 5), formats=[np.float64, np.int64, np.bool_], order="K", byteorder="|", ), - np.recarray[Any, np.dtype[np.record]], + np.rec.recarray[Any, np.dtype[np.record]], ) assert_type( - np.recarray( + np.rec.recarray( shape=(10, 5), dtype=[("f8", np.float64), ("i8", np.int64)], strides=(5, 5), ), - np.recarray[Any, np.dtype[Any]], + np.rec.recarray[Any, np.dtype[Any]], ) assert_type(np.rec.fromarrays(AR_LIST), np.recarray[Any, np.dtype[Any]]) assert_type( np.rec.fromarrays(AR_LIST, dtype=np.int64), - np.recarray[Any, np.dtype[Any]], + np.rec.recarray[Any, np.dtype[Any]], ) assert_type( np.rec.fromarrays( @@ -71,24 +71,29 @@ assert_type( formats=[np.int64, np.float64], names=["i8", "f8"] ), - np.recarray[Any, np.dtype[np.record]], + np.rec.recarray[Any, np.dtype[np.record]], +) + +assert_type( + np.rec.fromrecords((1, 1.5)), + np.recarray[Any, np.dtype[np.record]] ) -assert_type(np.rec.fromrecords((1, 1.5)), np.recarray[Any, np.dtype[np.record]]) assert_type( np.rec.fromrecords( [(1, 1.5)], dtype=[("i8", np.int64), ("f8", np.float64)], ), - np.recarray[Any, np.dtype[np.record]], + np.rec.recarray[Any, np.dtype[np.record]], ) + assert_type( np.rec.fromrecords( REC_AR_V, formats=[np.int64, np.float64], names=["i8", "f8"] ), - np.recarray[Any, np.dtype[np.record]], + np.rec.recarray[Any, np.dtype[np.record]], ) assert_type( @@ -96,21 +101,22 @@ assert_type( b"(1, 1.5)", dtype=[("i8", np.int64), ("f8", np.float64)], ), - np.recarray[Any, np.dtype[np.record]], + np.rec.recarray[Any, np.dtype[np.record]], ) + assert_type( np.rec.fromstring( REC_AR_V, formats=[np.int64, np.float64], names=["i8", "f8"] ), - np.recarray[Any, np.dtype[np.record]], + np.rec.recarray[Any, np.dtype[np.record]], ) assert_type(np.rec.fromfile( "test_file.txt", dtype=[("i8", np.int64), ("f8", np.float64)], -), np.recarray[Any, np.dtype[Any]]) +), np.rec.recarray[Any, np.dtype[Any]]) assert_type( np.rec.fromfile( @@ -118,14 +124,14 @@ assert_type( formats=[np.int64, np.float64], names=["i8", "f8"] ), - np.recarray[Any, np.dtype[np.record]], + np.rec.recarray[Any, np.dtype[np.record]], ) assert_type(np.rec.array(AR_i8), np.recarray[Any, np.dtype[np.int64]]) assert_type( np.rec.array([(1, 1.5)], dtype=[("i8", np.int64), ("f8", np.float64)]), - np.recarray[Any, np.dtype[Any]], + np.rec.recarray[Any, np.dtype[Any]], ) assert_type( @@ -134,7 +140,7 @@ assert_type( formats=[np.int64, np.float64], names=["i8", "f8"] ), - np.recarray[Any, np.dtype[np.record]], + np.rec.recarray[Any, np.dtype[np.record]], ) assert_type( @@ -143,7 +149,7 @@ assert_type( dtype=np.float64, shape=(10, 3), ), - np.recarray[Any, np.dtype[Any]], + np.rec.recarray[Any, np.dtype[Any]], ) assert_type( @@ -153,15 +159,15 @@ assert_type( names=["i8", "f8"], shape=(10, 3), ), - np.recarray[Any, np.dtype[np.record]], + np.rec.recarray[Any, np.dtype[np.record]], ) assert_type( np.rec.array(file_obj, dtype=np.float64), - np.recarray[Any, np.dtype[Any]], + np.rec.recarray[Any, np.dtype[Any]], ) assert_type( np.rec.array(file_obj, formats=[np.int64, np.float64], names=["i8", "f8"]), - np.recarray[Any, np.dtype[np.record]], + np.rec.recarray[Any, np.dtype[np.record]], ) From 2a7aebd96d3528d7d0cd49bcd82a6be94ee68f9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Sok=C3=B3=C5=82?= Date: Wed, 30 Aug 2023 14:23:51 +0200 Subject: [PATCH 02/11] Add pyi class definitions --- numpy/core/defchararray.pyi | 425 ++++++++++++++++++++++++- numpy/core/records.pyi | 79 ++++- numpy/typing/tests/data/reveal/rec.pyi | 7 +- 3 files changed, 504 insertions(+), 7 deletions(-) diff --git a/numpy/core/defchararray.pyi b/numpy/core/defchararray.pyi index fe0699a98623..e79aa3b468f4 100644 --- a/numpy/core/defchararray.pyi +++ b/numpy/core/defchararray.pyi @@ -3,9 +3,12 @@ from typing import ( overload, TypeVar, Any, + SupportsIndex, + SupportsInt, ) from numpy import ( + ndarray, dtype, str_, bytes_, @@ -13,23 +16,441 @@ from numpy import ( bool_, object_, _OrderKACF, + _ShapeType, + _CharDType, + _SupportsBuffer, ) from numpy._typing import ( NDArray, + _ShapeLike, _ArrayLikeStr_co as U_co, _ArrayLikeBytes_co as S_co, _ArrayLikeInt_co as i_co, _ArrayLikeBool_co as b_co, ) -from numpy.core.defchararray import chararray - from numpy.core.multiarray import compare_chararrays as compare_chararrays _SCT = TypeVar("_SCT", str_, bytes_) _CharArray = chararray[Any, dtype[_SCT]] +class chararray(ndarray[_ShapeType, _CharDType]): + @overload + def __new__( + subtype, + shape: _ShapeLike, + itemsize: SupportsIndex | SupportsInt = ..., + unicode: L[False] = ..., + buffer: _SupportsBuffer = ..., + offset: SupportsIndex = ..., + strides: _ShapeLike = ..., + order: _OrderKACF = ..., + ) -> chararray[Any, dtype[bytes_]]: ... + @overload + def __new__( + subtype, + shape: _ShapeLike, + itemsize: SupportsIndex | SupportsInt = ..., + unicode: L[True] = ..., + buffer: _SupportsBuffer = ..., + offset: SupportsIndex = ..., + strides: _ShapeLike = ..., + order: _OrderKACF = ..., + ) -> chararray[Any, dtype[str_]]: ... + + def __array_finalize__(self, obj: object) -> None: ... + def __mul__(self, other: i_co) -> chararray[Any, _CharDType]: ... + def __rmul__(self, other: i_co) -> chararray[Any, _CharDType]: ... + def __mod__(self, i: Any) -> chararray[Any, _CharDType]: ... + + @overload + def __eq__( + self: _CharArray[str_], + other: U_co, + ) -> NDArray[bool_]: ... + @overload + def __eq__( + self: _CharArray[bytes_], + other: S_co, + ) -> NDArray[bool_]: ... + + @overload + def __ne__( + self: _CharArray[str_], + other: U_co, + ) -> NDArray[bool_]: ... + @overload + def __ne__( + self: _CharArray[bytes_], + other: S_co, + ) -> NDArray[bool_]: ... + + @overload + def __ge__( + self: _CharArray[str_], + other: U_co, + ) -> NDArray[bool_]: ... + @overload + def __ge__( + self: _CharArray[bytes_], + other: S_co, + ) -> NDArray[bool_]: ... + + @overload + def __le__( + self: _CharArray[str_], + other: U_co, + ) -> NDArray[bool_]: ... + @overload + def __le__( + self: _CharArray[bytes_], + other: S_co, + ) -> NDArray[bool_]: ... + + @overload + def __gt__( + self: _CharArray[str_], + other: U_co, + ) -> NDArray[bool_]: ... + @overload + def __gt__( + self: _CharArray[bytes_], + other: S_co, + ) -> NDArray[bool_]: ... + + @overload + def __lt__( + self: _CharArray[str_], + other: U_co, + ) -> NDArray[bool_]: ... + @overload + def __lt__( + self: _CharArray[bytes_], + other: S_co, + ) -> NDArray[bool_]: ... + + @overload + def __add__( + self: _CharArray[str_], + other: U_co, + ) -> _CharArray[str_]: ... + @overload + def __add__( + self: _CharArray[bytes_], + other: S_co, + ) -> _CharArray[bytes_]: ... + + @overload + def __radd__( + self: _CharArray[str_], + other: U_co, + ) -> _CharArray[str_]: ... + @overload + def __radd__( + self: _CharArray[bytes_], + other: S_co, + ) -> _CharArray[bytes_]: ... + + @overload + def center( + self: _CharArray[str_], + width: i_co, + fillchar: U_co = ..., + ) -> _CharArray[str_]: ... + @overload + def center( + self: _CharArray[bytes_], + width: i_co, + fillchar: S_co = ..., + ) -> _CharArray[bytes_]: ... + + @overload + def count( + self: _CharArray[str_], + sub: U_co, + start: i_co = ..., + end: None | i_co = ..., + ) -> NDArray[int_]: ... + @overload + def count( + self: _CharArray[bytes_], + sub: S_co, + start: i_co = ..., + end: None | i_co = ..., + ) -> NDArray[int_]: ... + + def decode( + self: _CharArray[bytes_], + encoding: None | str = ..., + errors: None | str = ..., + ) -> _CharArray[str_]: ... + + def encode( + self: _CharArray[str_], + encoding: None | str = ..., + errors: None | str = ..., + ) -> _CharArray[bytes_]: ... + + @overload + def endswith( + self: _CharArray[str_], + suffix: U_co, + start: i_co = ..., + end: None | i_co = ..., + ) -> NDArray[bool_]: ... + @overload + def endswith( + self: _CharArray[bytes_], + suffix: S_co, + start: i_co = ..., + end: None | i_co = ..., + ) -> NDArray[bool_]: ... + + def expandtabs( + self, + tabsize: i_co = ..., + ) -> chararray[Any, _CharDType]: ... + + @overload + def find( + self: _CharArray[str_], + sub: U_co, + start: i_co = ..., + end: None | i_co = ..., + ) -> NDArray[int_]: ... + @overload + def find( + self: _CharArray[bytes_], + sub: S_co, + start: i_co = ..., + end: None | i_co = ..., + ) -> NDArray[int_]: ... + + @overload + def index( + self: _CharArray[str_], + sub: U_co, + start: i_co = ..., + end: None | i_co = ..., + ) -> NDArray[int_]: ... + @overload + def index( + self: _CharArray[bytes_], + sub: S_co, + start: i_co = ..., + end: None | i_co = ..., + ) -> NDArray[int_]: ... + + @overload + def join( + self: _CharArray[str_], + seq: U_co, + ) -> _CharArray[str_]: ... + @overload + def join( + self: _CharArray[bytes_], + seq: S_co, + ) -> _CharArray[bytes_]: ... + + @overload + def ljust( + self: _CharArray[str_], + width: i_co, + fillchar: U_co = ..., + ) -> _CharArray[str_]: ... + @overload + def ljust( + self: _CharArray[bytes_], + width: i_co, + fillchar: S_co = ..., + ) -> _CharArray[bytes_]: ... + + @overload + def lstrip( + self: _CharArray[str_], + chars: None | U_co = ..., + ) -> _CharArray[str_]: ... + @overload + def lstrip( + self: _CharArray[bytes_], + chars: None | S_co = ..., + ) -> _CharArray[bytes_]: ... + + @overload + def partition( + self: _CharArray[str_], + sep: U_co, + ) -> _CharArray[str_]: ... + @overload + def partition( + self: _CharArray[bytes_], + sep: S_co, + ) -> _CharArray[bytes_]: ... + + @overload + def replace( + self: _CharArray[str_], + old: U_co, + new: U_co, + count: None | i_co = ..., + ) -> _CharArray[str_]: ... + @overload + def replace( + self: _CharArray[bytes_], + old: S_co, + new: S_co, + count: None | i_co = ..., + ) -> _CharArray[bytes_]: ... + + @overload + def rfind( + self: _CharArray[str_], + sub: U_co, + start: i_co = ..., + end: None | i_co = ..., + ) -> NDArray[int_]: ... + @overload + def rfind( + self: _CharArray[bytes_], + sub: S_co, + start: i_co = ..., + end: None | i_co = ..., + ) -> NDArray[int_]: ... + + @overload + def rindex( + self: _CharArray[str_], + sub: U_co, + start: i_co = ..., + end: None | i_co = ..., + ) -> NDArray[int_]: ... + @overload + def rindex( + self: _CharArray[bytes_], + sub: S_co, + start: i_co = ..., + end: None | i_co = ..., + ) -> NDArray[int_]: ... + + @overload + def rjust( + self: _CharArray[str_], + width: i_co, + fillchar: U_co = ..., + ) -> _CharArray[str_]: ... + @overload + def rjust( + self: _CharArray[bytes_], + width: i_co, + fillchar: S_co = ..., + ) -> _CharArray[bytes_]: ... + + @overload + def rpartition( + self: _CharArray[str_], + sep: U_co, + ) -> _CharArray[str_]: ... + @overload + def rpartition( + self: _CharArray[bytes_], + sep: S_co, + ) -> _CharArray[bytes_]: ... + + @overload + def rsplit( + self: _CharArray[str_], + sep: None | U_co = ..., + maxsplit: None | i_co = ..., + ) -> NDArray[object_]: ... + @overload + def rsplit( + self: _CharArray[bytes_], + sep: None | S_co = ..., + maxsplit: None | i_co = ..., + ) -> NDArray[object_]: ... + + @overload + def rstrip( + self: _CharArray[str_], + chars: None | U_co = ..., + ) -> _CharArray[str_]: ... + @overload + def rstrip( + self: _CharArray[bytes_], + chars: None | S_co = ..., + ) -> _CharArray[bytes_]: ... + + @overload + def split( + self: _CharArray[str_], + sep: None | U_co = ..., + maxsplit: None | i_co = ..., + ) -> NDArray[object_]: ... + @overload + def split( + self: _CharArray[bytes_], + sep: None | S_co = ..., + maxsplit: None | i_co = ..., + ) -> NDArray[object_]: ... + + def splitlines(self, keepends: None | b_co = ...) -> NDArray[object_]: ... + + @overload + def startswith( + self: _CharArray[str_], + prefix: U_co, + start: i_co = ..., + end: None | i_co = ..., + ) -> NDArray[bool_]: ... + @overload + def startswith( + self: _CharArray[bytes_], + prefix: S_co, + start: i_co = ..., + end: None | i_co = ..., + ) -> NDArray[bool_]: ... + + @overload + def strip( + self: _CharArray[str_], + chars: None | U_co = ..., + ) -> _CharArray[str_]: ... + @overload + def strip( + self: _CharArray[bytes_], + chars: None | S_co = ..., + ) -> _CharArray[bytes_]: ... + + @overload + def translate( + self: _CharArray[str_], + table: U_co, + deletechars: None | U_co = ..., + ) -> _CharArray[str_]: ... + @overload + def translate( + self: _CharArray[bytes_], + table: S_co, + deletechars: None | S_co = ..., + ) -> _CharArray[bytes_]: ... + + def zfill(self, width: _ArrayLikeInt_co) -> chararray[Any, _CharDType]: ... + def capitalize(self) -> chararray[_ShapeType, _CharDType]: ... + def title(self) -> chararray[_ShapeType, _CharDType]: ... + def swapcase(self) -> chararray[_ShapeType, _CharDType]: ... + def lower(self) -> chararray[_ShapeType, _CharDType]: ... + def upper(self) -> chararray[_ShapeType, _CharDType]: ... + def isalnum(self) -> ndarray[_ShapeType, dtype[bool_]]: ... + def isalpha(self) -> ndarray[_ShapeType, dtype[bool_]]: ... + def isdigit(self) -> ndarray[_ShapeType, dtype[bool_]]: ... + def islower(self) -> ndarray[_ShapeType, dtype[bool_]]: ... + def isspace(self) -> ndarray[_ShapeType, dtype[bool_]]: ... + def istitle(self) -> ndarray[_ShapeType, dtype[bool_]]: ... + def isupper(self) -> ndarray[_ShapeType, dtype[bool_]]: ... + def isnumeric(self) -> ndarray[_ShapeType, dtype[bool_]]: ... + def isdecimal(self) -> ndarray[_ShapeType, dtype[bool_]]: ... + __all__: list[str] # Comparison diff --git a/numpy/core/records.pyi b/numpy/core/records.pyi index 02a64a7661ed..05a8da1305b2 100644 --- a/numpy/core/records.pyi +++ b/numpy/core/records.pyi @@ -5,16 +5,21 @@ from typing import ( TypeVar, overload, Protocol, + SupportsIndex, + Literal ) from numpy import ( record as record, - recarray as recarray, + ndarray, dtype, generic, void, _ByteOrder, _SupportsBuffer, + _ShapeType, + _DType_co, + _OrderKACF, ) from numpy._typing import ( @@ -22,6 +27,7 @@ from numpy._typing import ( DTypeLike, NDArray, _ShapeLike, + _ArrayLikeInt_co, _ArrayLikeVoid_co, _NestedSequence, ) @@ -35,6 +41,77 @@ class _SupportsReadInto(Protocol): def tell(self, /) -> int: ... def readinto(self, buffer: memoryview, /) -> int: ... +class recarray(ndarray[_ShapeType, _DType_co]): + # NOTE: While not strictly mandatory, we're demanding here that arguments + # for the `format_parser`- and `dtype`-based dtype constructors are + # mutually exclusive + @overload + def __new__( + subtype, + shape: _ShapeLike, + dtype: None = ..., + buf: None | _SupportsBuffer = ..., + offset: SupportsIndex = ..., + strides: None | _ShapeLike = ..., + *, + formats: DTypeLike, + names: None | str | Sequence[str] = ..., + titles: None | str | Sequence[str] = ..., + byteorder: None | _ByteOrder = ..., + aligned: bool = ..., + order: _OrderKACF = ..., + ) -> recarray[Any, dtype[record]]: ... + @overload + def __new__( + subtype, + shape: _ShapeLike, + dtype: DTypeLike, + buf: None | _SupportsBuffer = ..., + offset: SupportsIndex = ..., + strides: None | _ShapeLike = ..., + formats: None = ..., + names: None = ..., + titles: None = ..., + byteorder: None = ..., + aligned: Literal[False] = ..., + order: _OrderKACF = ..., + ) -> recarray[Any, dtype[Any]]: ... + def __array_finalize__(self, obj: object) -> None: ... + def __getattribute__(self, attr: str) -> Any: ... + def __setattr__(self, attr: str, val: ArrayLike) -> None: ... + @overload + def __getitem__(self, indx: ( + SupportsIndex + | _ArrayLikeInt_co + | tuple[SupportsIndex | _ArrayLikeInt_co, ...] + )) -> Any: ... + @overload + def __getitem__(self: recarray[Any, dtype[void]], indx: ( + None + | slice + | ellipsis + | SupportsIndex + | _ArrayLikeInt_co + | tuple[None | slice | ellipsis | _ArrayLikeInt_co | SupportsIndex, ...] + )) -> recarray[Any, _DType_co]: ... + @overload + def __getitem__(self, indx: ( + None + | slice + | ellipsis + | SupportsIndex + | _ArrayLikeInt_co + | tuple[None | slice | ellipsis | _ArrayLikeInt_co | SupportsIndex, ...] + )) -> ndarray[Any, _DType_co]: ... + @overload + def __getitem__(self, indx: str) -> NDArray[Any]: ... + @overload + def __getitem__(self, indx: list[str]) -> recarray[_ShapeType, dtype[record]]: ... + @overload + def field(self, attr: int | str, val: None = ...) -> Any: ... + @overload + def field(self, attr: int | str, val: ArrayLike) -> None: ... + class format_parser: dtype: dtype[void] def __init__( diff --git a/numpy/typing/tests/data/reveal/rec.pyi b/numpy/typing/tests/data/reveal/rec.pyi index e6f96c01d275..045039968294 100644 --- a/numpy/typing/tests/data/reveal/rec.pyi +++ b/numpy/typing/tests/data/reveal/rec.pyi @@ -14,17 +14,16 @@ AR_i8: npt.NDArray[np.int64] REC_AR_V: np.rec.recarray[Any, np.dtype[np.record]] AR_LIST: list[npt.NDArray[np.int64]] -format_parser: np.rec.format_parser record: np.record file_obj: io.BufferedIOBase -assert_type(format_parser( +assert_type(np.rec.format_parser( formats=[np.float64, np.int64, np.bool_], names=["f8", "i8", "?"], titles=None, aligned=True, -), np.format_parser) -assert_type(format_parser.dtype, np.dtype[np.void]) +), np.rec.format_parser) +assert_type(np.rec.format_parser.dtype, np.dtype[np.void]) assert_type(record.field_a, Any) assert_type(record.field_b, Any) From 6d3051eb033bd2dcdf840ab0125fd0f6f5708d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Sok=C3=B3=C5=82?= Date: Wed, 30 Aug 2023 14:45:42 +0200 Subject: [PATCH 03/11] Add changelog file --- doc/release/upcoming_changes/24587.python_removal.rst | 11 +++++++++++ numpy/ma/tests/test_mrecords.py | 3 +-- 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 doc/release/upcoming_changes/24587.python_removal.rst diff --git a/doc/release/upcoming_changes/24587.python_removal.rst b/doc/release/upcoming_changes/24587.python_removal.rst new file mode 100644 index 000000000000..4e19fc9a9f0a --- /dev/null +++ b/doc/release/upcoming_changes/24587.python_removal.rst @@ -0,0 +1,11 @@ +* ``np.compare_chararrays`` has been removed from the main namespace. + Use ``np.char.compare_chararrays`` instead. + +* ``np.chararray`` has been removed from the main namespace. + Use ``np.char.chararray`` instead. + +* ``np.format_parser`` has been removed from the main namespace. + Use ``np.rec.format_parser`` instead. + +* ``np.recarray`` has been removed from the main namespace. + Use ``np.rec.recarray`` instead. diff --git a/numpy/ma/tests/test_mrecords.py b/numpy/ma/tests/test_mrecords.py index 761bd77cf0c3..83099a4b7376 100644 --- a/numpy/ma/tests/test_mrecords.py +++ b/numpy/ma/tests/test_mrecords.py @@ -9,11 +9,10 @@ import numpy as np import numpy.ma as ma -from numpy import recarray from numpy.ma import masked, nomask from numpy.testing import temppath from numpy.core.records import ( - fromrecords as recfromrecords, fromarrays as recfromarrays + recarray, fromrecords as recfromrecords, fromarrays as recfromarrays ) from numpy.ma.mrecords import ( MaskedRecords, mrecarray, fromarrays, fromtextfile, fromrecords, From 6643c0e1594dc5ec34541ab9b66898d6a1fbc348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Sok=C3=B3=C5=82?= Date: Thu, 31 Aug 2023 15:26:33 +0200 Subject: [PATCH 04/11] MAINT: Create rec and char submodules --- doc/source/glossary.rst | 2 +- doc/source/reference/arrays.classes.rst | 4 +- doc/source/user/basics.io.genfromtxt.rst | 2 +- doc/source/user/basics.rec.rst | 6 +-- numpy/__init__.py | 13 ++++-- numpy/__init__.pyi | 2 + numpy/char/__init__.py | 2 + numpy/char/__init__.pyi | 55 ++++++++++++++++++++++++ numpy/core/__init__.py | 7 +-- numpy/core/defchararray.py | 3 +- numpy/core/records.py | 7 ++- numpy/lib/recfunctions.py | 4 +- numpy/ma/mrecords.py | 2 +- numpy/meson.build | 4 +- numpy/rec/__init__.py | 2 + numpy/rec/__init__.pyi | 10 +++++ 16 files changed, 102 insertions(+), 23 deletions(-) create mode 100644 numpy/char/__init__.py create mode 100644 numpy/char/__init__.pyi create mode 100644 numpy/rec/__init__.py create mode 100644 numpy/rec/__init__.pyi diff --git a/doc/source/glossary.rst b/doc/source/glossary.rst index ae2ab6ea4247..98aebcac28ab 100644 --- a/doc/source/glossary.rst +++ b/doc/source/glossary.rst @@ -442,7 +442,7 @@ Glossary record array A :term:`structured array` with allowing access in an attribute style (``a.field``) in addition to ``a['field']``. For details, see - :doc:`numpy.recarray. ` + :doc:`numpy.rec.recarray. ` row-major diff --git a/doc/source/reference/arrays.classes.rst b/doc/source/reference/arrays.classes.rst index dc16aca7693b..26cf1bd02445 100644 --- a/doc/source/reference/arrays.classes.rst +++ b/doc/source/reference/arrays.classes.rst @@ -501,7 +501,7 @@ data-type. However, a chararray can also be created using the :toctree: generated/ char.chararray - core.defchararray.array + char.array Another difference with the standard ndarray of str data-type is that the chararray inherits the feature introduced by Numarray that @@ -526,7 +526,7 @@ scalar data type object :class:`record`. .. autosummary:: :toctree: generated/ - recarray + rec.recarray record .. note:: diff --git a/doc/source/user/basics.io.genfromtxt.rst b/doc/source/user/basics.io.genfromtxt.rst index 1f44bea22582..5f6657bfbbc7 100644 --- a/doc/source/user/basics.io.genfromtxt.rst +++ b/doc/source/user/basics.io.genfromtxt.rst @@ -323,7 +323,7 @@ Validating names ---------------- NumPy arrays with a structured dtype can also be viewed as -:class:`~numpy.recarray`, where a field can be accessed as if it were an +:class:`~numpy.rec.recarray`, where a field can be accessed as if it were an attribute. For that reason, we may need to make sure that the field name doesn't contain any space or invalid character, or that it does not correspond to the name of a standard attribute (like ``size`` or diff --git a/doc/source/user/basics.rec.rst b/doc/source/user/basics.rec.rst index b28b436d5bff..69ad4a46025a 100644 --- a/doc/source/user/basics.rec.rst +++ b/doc/source/user/basics.rec.rst @@ -630,8 +630,8 @@ Record Arrays ============= As an optional convenience numpy provides an ndarray subclass, -:class:`numpy.recarray` that allows access to fields of structured arrays by -attribute instead of only by index. +:class:`numpy.rec.recarray` that allows access to fields of structured arrays +by attribute instead of only by index. Record arrays use a special datatype, :class:`numpy.record`, that allows field access by attribute on the structured scalars obtained from the array. The ``numpy.rec`` module provides functions for creating recarrays from @@ -697,7 +697,7 @@ array if the field has a structured type but as a plain ndarray otherwise. :: >>> type(recordarr.foo) >>> type(recordarr.bar) - + Note that if a field has the same name as an ndarray attribute, the ndarray attribute takes precedence. Such fields will be inaccessible by attribute but diff --git a/numpy/__init__.py b/numpy/__init__.py index 9ac70b1dd982..596b0256da9f 100644 --- a/numpy/__init__.py +++ b/numpy/__init__.py @@ -129,8 +129,7 @@ atleast_1d, atleast_2d, atleast_3d, base_repr, binary_repr, bitwise_and, bitwise_not, bitwise_or, bitwise_xor, block, bool_, broadcast, busday_count, busday_offset, busdaycalendar, byte, bytes_, - can_cast, cbrt, cdouble, ceil, char, character, - choose, clip, clongdouble, + can_cast, cbrt, cdouble, ceil, character, choose, clip, clongdouble, complexfloating, compress, concatenate, conj, conjugate, convolve, copysign, copyto, correlate, cos, cosh, count_nonzero, cross, csingle, cumprod, cumproduct, cumsum, datetime64, datetime_as_string, @@ -156,7 +155,7 @@ negative, nested_iters, newaxis, nextafter, nonzero, not_equal, number, object_, ones, ones_like, outer, partition, pi, positive, power, printoptions, prod, product, promote_types, - ptp, put, putmask, rad2deg, radians, ravel, rec, reciprocal, + ptp, put, putmask, rad2deg, radians, ravel, reciprocal, record, remainder, repeat, require, reshape, resize, result_type, right_shift, rint, roll, rollaxis, round, searchsorted, set_printoptions, @@ -248,7 +247,7 @@ __numpy_submodules__ = { "linalg", "fft", "dtypes", "random", "polynomial", "ma", "exceptions", "lib", "ctypeslib", "testing", "typing", - "f2py", "test" + "f2py", "test", "rec", "char" } # We build warning messages for former attributes @@ -358,6 +357,12 @@ def __getattr__(attr): elif attr == "typing": import numpy.typing as typing return typing + elif attr == "rec": + import numpy.rec as rec + return rec + elif attr == "char": + import numpy.char as char + return char elif attr == "array_api": import numpy.array_api as array_api return array_api diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi index 430ee88d03b7..463b4f0e2b54 100644 --- a/numpy/__init__.pyi +++ b/numpy/__init__.pyi @@ -207,6 +207,8 @@ from numpy import ( version as version, exceptions as exceptions, dtypes as dtypes, + rec as rec, + char as char, ) from numpy.core import defchararray, records diff --git a/numpy/char/__init__.py b/numpy/char/__init__.py new file mode 100644 index 000000000000..f9e3eaf3466b --- /dev/null +++ b/numpy/char/__init__.py @@ -0,0 +1,2 @@ +from numpy.core.defchararray import __all__, __doc__ +from numpy.core.defchararray import * diff --git a/numpy/char/__init__.pyi b/numpy/char/__init__.pyi new file mode 100644 index 000000000000..adddd65675b1 --- /dev/null +++ b/numpy/char/__init__.pyi @@ -0,0 +1,55 @@ +from numpy.core.defchararray import ( + equal as equal, + not_equal as not_equal, + greater_equal as greater_equal, + less_equal as less_equal, + greater as greater, + less as less, + str_len as str_len, + add as add, + multiply as multiply, + mod as mod, + capitalize as capitalize, + center as center, + count as count, + decode as decode, + encode as encode, + endswith as endswith, + expandtabs as expandtabs, + find as find, + index as index, + isalnum as isalnum, + isalpha as isalpha, + isdigit as isdigit, + islower as islower, + isspace as isspace, + istitle as istitle, + isupper as isupper, + join as join, + ljust as ljust, + lower as lower, + lstrip as lstrip, + partition as partition, + replace as replace, + rfind as rfind, + rindex as rindex, + rjust as rjust, + rpartition as rpartition, + rsplit as rsplit, + rstrip as rstrip, + split as split, + splitlines as splitlines, + startswith as startswith, + strip as strip, + swapcase as swapcase, + title as title, + translate as translate, + upper as upper, + zfill as zfill, + isnumeric as isnumeric, + isdecimal as isdecimal, + array as array, + asarray as asarray, + compare_chararrays as compare_chararrays, + chararray as chararray +) diff --git a/numpy/core/__init__.py b/numpy/core/__init__.py index e5979d50ec38..1fc724b73f59 100644 --- a/numpy/core/__init__.py +++ b/numpy/core/__init__.py @@ -76,10 +76,7 @@ from .numeric import * from . import fromnumeric from .fromnumeric import * -from . import defchararray as char -from . import records -from . import records as rec -from .records import record, recarray, format_parser +from .records import record # Note: module name memmap is overwritten by a class with same name from .memmap import * from . import function_base @@ -105,7 +102,7 @@ from . import _dtype from . import _methods -__all__ = ['char', 'rec', 'memmap', 'sctypeDict', 'record', 'abs'] +__all__ = ['memmap', 'sctypeDict', 'record', 'abs'] __all__ += numeric.__all__ __all__ += function_base.__all__ __all__ += getlimits.__all__ diff --git a/numpy/core/defchararray.py b/numpy/core/defchararray.py index cc2a7d1d0d1f..49b274cb868d 100644 --- a/numpy/core/defchararray.py +++ b/numpy/core/defchararray.py @@ -35,7 +35,7 @@ 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill', 'isnumeric', 'isdecimal', - 'array', 'asarray', 'compare_chararrays' + 'array', 'asarray', 'compare_chararrays', 'chararray' ] @@ -1919,6 +1919,7 @@ def isdecimal(a): return _vec_string(a, bool_, 'isdecimal') +@set_module("numpy.char") class chararray(ndarray): """ chararray(shape, itemsize=1, unicode=False, buffer=None, offset=0, diff --git a/numpy/core/records.py b/numpy/core/records.py index 0a6e8f1bbbf3..83dcb12d9598 100644 --- a/numpy/core/records.py +++ b/numpy/core/records.py @@ -46,7 +46,7 @@ # All of the functions allow formats to be a dtype __all__ = [ 'record', 'recarray', 'format_parser', 'fromarrays', 'fromrecords', - 'fromstring', 'fromfile', 'array', + 'fromstring', 'fromfile', 'array', 'find_duplicate', ] @@ -75,6 +75,7 @@ numfmt = nt.sctypeDict +@set_module('numpy.rec') def find_duplicate(list): """Find duplication in a list, return a list of duplicated elements""" return [ @@ -305,6 +306,8 @@ def pprint(self): # If byteorder is given it forces a particular byteorder on all # the fields (and any subfields) + +@set_module("numpy.rec") class recarray(ndarray): """Construct an ndarray that allows field access using attributes. @@ -535,7 +538,7 @@ def __repr__(self): # This should only happen if the user is playing # strange games with dtypes. prefix = "array(" - fmt = 'array(%s,%sdtype=%s).view(numpy.recarray)' + fmt = 'array(%s,%sdtype=%s).view(numpy.rec.recarray)' # get data/shape string. logic taken from numeric.array_repr if self.size > 0 or self.shape == (0,): diff --git a/numpy/lib/recfunctions.py b/numpy/lib/recfunctions.py index c0a1638c1303..9b924473bc8a 100644 --- a/numpy/lib/recfunctions.py +++ b/numpy/lib/recfunctions.py @@ -596,7 +596,7 @@ def _rec_drop_fields_dispatcher(base, drop_names): @array_function_dispatch(_rec_drop_fields_dispatcher) def rec_drop_fields(base, drop_names): """ - Returns a new numpy.recarray with fields in `drop_names` dropped. + Returns a new numpy.rec.recarray with fields in `drop_names` dropped. """ return drop_fields(base, drop_names, usemask=False, asrecarray=True) @@ -958,7 +958,7 @@ def structured_to_unstructured(arr, dtype=None, copy=False, casting='unsafe'): If true, always return a copy. If false, a view is returned if possible, such as when the `dtype` and strides of the fields are suitable and the array subtype is one of `numpy.ndarray`, - `numpy.recarray` or `numpy.memmap`. + `numpy.rec.recarray` or `numpy.memmap`. .. versionchanged:: 1.25.0 A view can now be returned if the fields are separated by a diff --git a/numpy/ma/mrecords.py b/numpy/ma/mrecords.py index 82b2ff79c6b4..c554f6ba68ca 100644 --- a/numpy/ma/mrecords.py +++ b/numpy/ma/mrecords.py @@ -1,6 +1,6 @@ """:mod:`numpy.ma..mrecords` -Defines the equivalent of :class:`numpy.recarrays` for masked arrays, +Defines the equivalent of :class:`numpy.rec.recarrays` for masked arrays, where fields can be accessed as attributes. Note that :class:`numpy.ma.MaskedArray` already supports structured datatypes and the masking of individual fields. diff --git a/numpy/meson.build b/numpy/meson.build index a4509bc33067..e2dc683bfea5 100644 --- a/numpy/meson.build +++ b/numpy/meson.build @@ -293,7 +293,9 @@ pure_subdirs = [ 'polynomial', 'testing', 'tests', - 'typing' + 'typing', + 'rec', + 'char' ] if py.version().version_compare('<3.12') pure_subdirs += 'distutils' diff --git a/numpy/rec/__init__.py b/numpy/rec/__init__.py new file mode 100644 index 000000000000..dd5bd9d16062 --- /dev/null +++ b/numpy/rec/__init__.py @@ -0,0 +1,2 @@ +from numpy.core.records import __all__, __doc__ +from numpy.core.records import * diff --git a/numpy/rec/__init__.pyi b/numpy/rec/__init__.pyi new file mode 100644 index 000000000000..b9f493a63226 --- /dev/null +++ b/numpy/rec/__init__.pyi @@ -0,0 +1,10 @@ +from numpy.core.records import ( + record as record, + recarray as recarray, + format_parser as format_parser, + fromarrays as fromarrays, + fromrecords as fromrecords, + fromstring as fromstring, + fromfile as fromfile, + array as array +) From 4727fb1e794d8d42cb389ee5a54b7d9b3da54ae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Sok=C3=B3=C5=82?= Date: Thu, 31 Aug 2023 16:11:23 +0200 Subject: [PATCH 05/11] Update numpy/setup.py --- numpy/char/__init__.pyi | 3 +++ numpy/rec/__init__.pyi | 3 +++ numpy/setup.py | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 numpy/setup.py diff --git a/numpy/char/__init__.pyi b/numpy/char/__init__.pyi index adddd65675b1..4d475bf31b71 100644 --- a/numpy/char/__init__.pyi +++ b/numpy/char/__init__.pyi @@ -53,3 +53,6 @@ from numpy.core.defchararray import ( compare_chararrays as compare_chararrays, chararray as chararray ) + +__all__: list[str] +__path__: list[str] diff --git a/numpy/rec/__init__.pyi b/numpy/rec/__init__.pyi index b9f493a63226..3e5d6713b244 100644 --- a/numpy/rec/__init__.pyi +++ b/numpy/rec/__init__.pyi @@ -8,3 +8,6 @@ from numpy.core.records import ( fromfile as fromfile, array as array ) + +__all__: list[str] +__path__: list[str] diff --git a/numpy/setup.py b/numpy/setup.py new file mode 100644 index 000000000000..d3c0d3464c0e --- /dev/null +++ b/numpy/setup.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 + +def configuration(parent_package='',top_path=None): + from numpy.distutils.misc_util import Configuration + config = Configuration('numpy', parent_package, top_path) + + config.add_subpackage('array_api') + config.add_subpackage('compat') + config.add_subpackage('core') + config.add_subpackage('distutils') + config.add_subpackage('doc') + config.add_subpackage('f2py') + config.add_subpackage('fft') + config.add_subpackage('lib') + config.add_subpackage('linalg') + config.add_subpackage('ma') + config.add_subpackage('matrixlib') + config.add_subpackage('polynomial') + config.add_subpackage('random') + config.add_subpackage('rec') + config.add_subpackage('char') + config.add_subpackage('testing') + config.add_subpackage('typing') + config.add_subpackage('_typing') + config.add_subpackage('_utils') + config.add_data_dir('doc') + config.add_data_files('py.typed') + config.add_data_files('*.pyi') + config.add_subpackage('tests') + config.add_subpackage('_pyinstaller') + config.make_config_py() # installs __config__.py + return config + +if __name__ == '__main__': + print('This is the wrong setup.py file to run') From 1aef35abf73fbdff05f66ab6980ff1617d331eae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Sok=C3=B3=C5=82?= Date: Wed, 6 Sep 2023 11:17:17 +0200 Subject: [PATCH 06/11] MAINT: Adjust typing tests --- numpy/core/defchararray.py | 6 +- numpy/typing/tests/data/reveal/char.pyi | 26 +++---- numpy/typing/tests/data/reveal/chararray.pyi | 76 +++++++++---------- .../tests/data/reveal/lib_function_base.pyi | 4 +- numpy/typing/tests/data/reveal/rec.pyi | 6 +- 5 files changed, 59 insertions(+), 59 deletions(-) diff --git a/numpy/core/defchararray.py b/numpy/core/defchararray.py index 49b274cb868d..b523c0db477c 100644 --- a/numpy/core/defchararray.py +++ b/numpy/core/defchararray.py @@ -2045,14 +2045,14 @@ class adds the following functionality: Examples -------- - >>> charar = np.chararray((3, 3)) + >>> charar = np.char.chararray((3, 3)) >>> charar[:] = 'a' >>> charar chararray([[b'a', b'a', b'a'], [b'a', b'a', b'a'], [b'a', b'a', b'a']], dtype='|S1') - >>> charar = np.chararray(charar.shape, itemsize=5) + >>> charar = np.char.chararray(charar.shape, itemsize=5) >>> charar[:] = 'abc' >>> charar chararray([[b'abc', b'abc', b'abc'], @@ -2246,7 +2246,7 @@ def argsort(self, axis=-1, kind=None, order=None): Examples -------- >>> c = np.array(['a1b c', '1b ca', 'b ca1', 'Ca1b'], 'S5') - >>> c = c.view(np.chararray); c + >>> c = c.view(np.char.chararray); c chararray(['a1b c', '1b ca', 'b ca1', 'Ca1b'], dtype='|S5') >>> c[c.argsort()] diff --git a/numpy/typing/tests/data/reveal/char.pyi b/numpy/typing/tests/data/reveal/char.pyi index e15ed0801a0d..86d4e5af0034 100644 --- a/numpy/typing/tests/data/reveal/char.pyi +++ b/numpy/typing/tests/data/reveal/char.pyi @@ -139,16 +139,16 @@ assert_type(np.char.isupper(AR_S), npt.NDArray[np.bool_]) assert_type(np.char.str_len(AR_U), npt.NDArray[np.int_]) assert_type(np.char.str_len(AR_S), npt.NDArray[np.int_]) -assert_type(np.char.array(AR_U), np.chararray[Any, np.dtype[np.str_]]) -assert_type(np.char.array(AR_S, order="K"), np.chararray[Any, np.dtype[np.bytes_]]) -assert_type(np.char.array("bob", copy=True), np.chararray[Any, np.dtype[np.str_]]) -assert_type(np.char.array(b"bob", itemsize=5), np.chararray[Any, np.dtype[np.bytes_]]) -assert_type(np.char.array(1, unicode=False), np.chararray[Any, np.dtype[np.bytes_]]) -assert_type(np.char.array(1, unicode=True), np.chararray[Any, np.dtype[np.str_]]) - -assert_type(np.char.asarray(AR_U), np.chararray[Any, np.dtype[np.str_]]) -assert_type(np.char.asarray(AR_S, order="K"), np.chararray[Any, np.dtype[np.bytes_]]) -assert_type(np.char.asarray("bob"), np.chararray[Any, np.dtype[np.str_]]) -assert_type(np.char.asarray(b"bob", itemsize=5), np.chararray[Any, np.dtype[np.bytes_]]) -assert_type(np.char.asarray(1, unicode=False), np.chararray[Any, np.dtype[np.bytes_]]) -assert_type(np.char.asarray(1, unicode=True), np.chararray[Any, np.dtype[np.str_]]) +assert_type(np.char.array(AR_U), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(np.char.array(AR_S, order="K"), np.char.chararray[Any, np.dtype[np.bytes_]]) +assert_type(np.char.array("bob", copy=True), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(np.char.array(b"bob", itemsize=5), np.char.chararray[Any, np.dtype[np.bytes_]]) +assert_type(np.char.array(1, unicode=False), np.char.chararray[Any, np.dtype[np.bytes_]]) +assert_type(np.char.array(1, unicode=True), np.char.chararray[Any, np.dtype[np.str_]]) + +assert_type(np.char.asarray(AR_U), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(np.char.asarray(AR_S, order="K"), np.char.chararray[Any, np.dtype[np.bytes_]]) +assert_type(np.char.asarray("bob"), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(np.char.asarray(b"bob", itemsize=5), np.char.chararray[Any, np.dtype[np.bytes_]]) +assert_type(np.char.asarray(1, unicode=False), np.char.chararray[Any, np.dtype[np.bytes_]]) +assert_type(np.char.asarray(1, unicode=True), np.char.chararray[Any, np.dtype[np.str_]]) diff --git a/numpy/typing/tests/data/reveal/chararray.pyi b/numpy/typing/tests/data/reveal/chararray.pyi index 9760eaab541a..2f9075d619c3 100644 --- a/numpy/typing/tests/data/reveal/chararray.pyi +++ b/numpy/typing/tests/data/reveal/chararray.pyi @@ -30,46 +30,46 @@ assert_type(AR_S > AR_S, npt.NDArray[np.bool_]) assert_type(AR_U < AR_U, npt.NDArray[np.bool_]) assert_type(AR_S < AR_S, npt.NDArray[np.bool_]) -assert_type(AR_U * 5, np.chararray[Any, np.dtype[np.str_]]) -assert_type(AR_S * [5], np.chararray[Any, np.dtype[np.bytes_]]) +assert_type(AR_U * 5, np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(AR_S * [5], np.char.chararray[Any, np.dtype[np.bytes_]]) -assert_type(AR_U % "test", np.chararray[Any, np.dtype[np.str_]]) -assert_type(AR_S % b"test", np.chararray[Any, np.dtype[np.bytes_]]) +assert_type(AR_U % "test", np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(AR_S % b"test", np.char.chararray[Any, np.dtype[np.bytes_]]) -assert_type(AR_U.capitalize(), np.chararray[Any, np.dtype[np.str_]]) -assert_type(AR_S.capitalize(), np.chararray[Any, np.dtype[np.bytes_]]) +assert_type(AR_U.capitalize(), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(AR_S.capitalize(), np.char.chararray[Any, np.dtype[np.bytes_]]) -assert_type(AR_U.center(5), np.chararray[Any, np.dtype[np.str_]]) -assert_type(AR_S.center([2, 3, 4], b"a"), np.chararray[Any, np.dtype[np.bytes_]]) +assert_type(AR_U.center(5), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(AR_S.center([2, 3, 4], b"a"), np.char.chararray[Any, np.dtype[np.bytes_]]) -assert_type(AR_U.encode(), np.chararray[Any, np.dtype[np.bytes_]]) -assert_type(AR_S.decode(), np.chararray[Any, np.dtype[np.str_]]) +assert_type(AR_U.encode(), np.char.chararray[Any, np.dtype[np.bytes_]]) +assert_type(AR_S.decode(), np.char.chararray[Any, np.dtype[np.str_]]) -assert_type(AR_U.expandtabs(), np.chararray[Any, np.dtype[np.str_]]) -assert_type(AR_S.expandtabs(tabsize=4), np.chararray[Any, np.dtype[np.bytes_]]) +assert_type(AR_U.expandtabs(), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(AR_S.expandtabs(tabsize=4), np.char.chararray[Any, np.dtype[np.bytes_]]) -assert_type(AR_U.join("_"), np.chararray[Any, np.dtype[np.str_]]) -assert_type(AR_S.join([b"_", b""]), np.chararray[Any, np.dtype[np.bytes_]]) +assert_type(AR_U.join("_"), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(AR_S.join([b"_", b""]), np.char.chararray[Any, np.dtype[np.bytes_]]) -assert_type(AR_U.ljust(5), np.chararray[Any, np.dtype[np.str_]]) -assert_type(AR_S.ljust([4, 3, 1], fillchar=[b"a", b"b", b"c"]), np.chararray[Any, np.dtype[np.bytes_]]) -assert_type(AR_U.rjust(5), np.chararray[Any, np.dtype[np.str_]]) -assert_type(AR_S.rjust([4, 3, 1], fillchar=[b"a", b"b", b"c"]), np.chararray[Any, np.dtype[np.bytes_]]) +assert_type(AR_U.ljust(5), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(AR_S.ljust([4, 3, 1], fillchar=[b"a", b"b", b"c"]), np.char.chararray[Any, np.dtype[np.bytes_]]) +assert_type(AR_U.rjust(5), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(AR_S.rjust([4, 3, 1], fillchar=[b"a", b"b", b"c"]), np.char.chararray[Any, np.dtype[np.bytes_]]) -assert_type(AR_U.lstrip(), np.chararray[Any, np.dtype[np.str_]]) -assert_type(AR_S.lstrip(chars=b"_"), np.chararray[Any, np.dtype[np.bytes_]]) -assert_type(AR_U.rstrip(), np.chararray[Any, np.dtype[np.str_]]) -assert_type(AR_S.rstrip(chars=b"_"), np.chararray[Any, np.dtype[np.bytes_]]) -assert_type(AR_U.strip(), np.chararray[Any, np.dtype[np.str_]]) -assert_type(AR_S.strip(chars=b"_"), np.chararray[Any, np.dtype[np.bytes_]]) +assert_type(AR_U.lstrip(), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(AR_S.lstrip(chars=b"_"), np.char.chararray[Any, np.dtype[np.bytes_]]) +assert_type(AR_U.rstrip(), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(AR_S.rstrip(chars=b"_"), np.char.chararray[Any, np.dtype[np.bytes_]]) +assert_type(AR_U.strip(), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(AR_S.strip(chars=b"_"), np.char.chararray[Any, np.dtype[np.bytes_]]) -assert_type(AR_U.partition("\n"), np.chararray[Any, np.dtype[np.str_]]) -assert_type(AR_S.partition([b"a", b"b", b"c"]), np.chararray[Any, np.dtype[np.bytes_]]) -assert_type(AR_U.rpartition("\n"), np.chararray[Any, np.dtype[np.str_]]) -assert_type(AR_S.rpartition([b"a", b"b", b"c"]), np.chararray[Any, np.dtype[np.bytes_]]) +assert_type(AR_U.partition("\n"), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(AR_S.partition([b"a", b"b", b"c"]), np.char.chararray[Any, np.dtype[np.bytes_]]) +assert_type(AR_U.rpartition("\n"), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(AR_S.rpartition([b"a", b"b", b"c"]), np.char.chararray[Any, np.dtype[np.bytes_]]) -assert_type(AR_U.replace("_", "-"), np.chararray[Any, np.dtype[np.str_]]) -assert_type(AR_S.replace([b"_", b""], [b"a", b"b"]), np.chararray[Any, np.dtype[np.bytes_]]) +assert_type(AR_U.replace("_", "-"), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(AR_S.replace([b"_", b""], [b"a", b"b"]), np.char.chararray[Any, np.dtype[np.bytes_]]) assert_type(AR_U.split("_"), npt.NDArray[np.object_]) assert_type(AR_S.split(maxsplit=[1, 2, 3]), npt.NDArray[np.object_]) @@ -79,17 +79,17 @@ assert_type(AR_S.rsplit(maxsplit=[1, 2, 3]), npt.NDArray[np.object_]) assert_type(AR_U.splitlines(), npt.NDArray[np.object_]) assert_type(AR_S.splitlines(keepends=[True, True, False]), npt.NDArray[np.object_]) -assert_type(AR_U.swapcase(), np.chararray[Any, np.dtype[np.str_]]) -assert_type(AR_S.swapcase(), np.chararray[Any, np.dtype[np.bytes_]]) +assert_type(AR_U.swapcase(), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(AR_S.swapcase(), np.char.chararray[Any, np.dtype[np.bytes_]]) -assert_type(AR_U.title(), np.chararray[Any, np.dtype[np.str_]]) -assert_type(AR_S.title(), np.chararray[Any, np.dtype[np.bytes_]]) +assert_type(AR_U.title(), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(AR_S.title(), np.char.chararray[Any, np.dtype[np.bytes_]]) -assert_type(AR_U.upper(), np.chararray[Any, np.dtype[np.str_]]) -assert_type(AR_S.upper(), np.chararray[Any, np.dtype[np.bytes_]]) +assert_type(AR_U.upper(), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(AR_S.upper(), np.char.chararray[Any, np.dtype[np.bytes_]]) -assert_type(AR_U.zfill(5), np.chararray[Any, np.dtype[np.str_]]) -assert_type(AR_S.zfill([2, 3, 4]), np.chararray[Any, np.dtype[np.bytes_]]) +assert_type(AR_U.zfill(5), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(AR_S.zfill([2, 3, 4]), np.char.chararray[Any, np.dtype[np.bytes_]]) assert_type(AR_U.count("a", start=[1, 2, 3]), npt.NDArray[np.int_]) assert_type(AR_S.count([b"a", b"b", b"c"], end=9), npt.NDArray[np.int_]) diff --git a/numpy/typing/tests/data/reveal/lib_function_base.pyi b/numpy/typing/tests/data/reveal/lib_function_base.pyi index 80a9afd45aec..6666c2407a1f 100644 --- a/numpy/typing/tests/data/reveal/lib_function_base.pyi +++ b/numpy/typing/tests/data/reveal/lib_function_base.pyi @@ -73,8 +73,8 @@ assert_type(np.select([AR_f8], [AR_f8]), npt.NDArray[Any]) assert_type(np.copy(AR_LIKE_f8), npt.NDArray[Any]) assert_type(np.copy(AR_U), npt.NDArray[np.str_]) assert_type(np.copy(CHAR_AR_U), np.ndarray[Any, Any]) -assert_type(np.copy(CHAR_AR_U, "K", subok=True), np.chararray[Any, np.dtype[np.str_]]) -assert_type(np.copy(CHAR_AR_U, subok=True), np.chararray[Any, np.dtype[np.str_]]) +assert_type(np.copy(CHAR_AR_U, "K", subok=True), np.char.chararray[Any, np.dtype[np.str_]]) +assert_type(np.copy(CHAR_AR_U, subok=True), np.char.chararray[Any, np.dtype[np.str_]]) assert_type(np.gradient(AR_f8, axis=None), Any) assert_type(np.gradient(AR_LIKE_f8, edge_order=2), Any) diff --git a/numpy/typing/tests/data/reveal/rec.pyi b/numpy/typing/tests/data/reveal/rec.pyi index 045039968294..c137386672b1 100644 --- a/numpy/typing/tests/data/reveal/rec.pyi +++ b/numpy/typing/tests/data/reveal/rec.pyi @@ -59,7 +59,7 @@ assert_type( np.rec.recarray[Any, np.dtype[Any]], ) -assert_type(np.rec.fromarrays(AR_LIST), np.recarray[Any, np.dtype[Any]]) +assert_type(np.rec.fromarrays(AR_LIST), np.rec.recarray[Any, np.dtype[Any]]) assert_type( np.rec.fromarrays(AR_LIST, dtype=np.int64), np.rec.recarray[Any, np.dtype[Any]], @@ -75,7 +75,7 @@ assert_type( assert_type( np.rec.fromrecords((1, 1.5)), - np.recarray[Any, np.dtype[np.record]] + np.rec.recarray[Any, np.dtype[np.record]] ) assert_type( @@ -126,7 +126,7 @@ assert_type( np.rec.recarray[Any, np.dtype[np.record]], ) -assert_type(np.rec.array(AR_i8), np.recarray[Any, np.dtype[np.int64]]) +assert_type(np.rec.array(AR_i8), np.rec.recarray[Any, np.dtype[np.int64]]) assert_type( np.rec.array([(1, 1.5)], dtype=[("i8", np.int64), ("f8", np.float64)]), From 5752d92ad47c955da28dbd7a9d2812d4bc7dd281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Sok=C3=B3=C5=82?= <8431159+mtsokol@users.noreply.github.com> Date: Wed, 6 Sep 2023 12:21:42 +0200 Subject: [PATCH 07/11] Update numpy/char/__init__.pyi Co-authored-by: Bas van Beek <43369155+BvB93@users.noreply.github.com> --- numpy/char/__init__.pyi | 1 - 1 file changed, 1 deletion(-) diff --git a/numpy/char/__init__.pyi b/numpy/char/__init__.pyi index 4d475bf31b71..f5612532b3d1 100644 --- a/numpy/char/__init__.pyi +++ b/numpy/char/__init__.pyi @@ -55,4 +55,3 @@ from numpy.core.defchararray import ( ) __all__: list[str] -__path__: list[str] From cee509746b55458b5e879a607b3e2501ff71ea2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Sok=C3=B3=C5=82?= Date: Tue, 12 Sep 2023 11:09:36 +0200 Subject: [PATCH 08/11] Restore np.recarray and deprecate np.chararray --- .../upcoming_changes/24587.python_removal.rst | 5 +- doc/source/glossary.rst | 2 +- doc/source/reference/arrays.classes.rst | 2 +- doc/source/user/basics.io.genfromtxt.rst | 2 +- doc/source/user/basics.rec.rst | 10 ++-- numpy/__init__.py | 10 +++- numpy/__init__.pyi | 20 +++---- numpy/_expired_attrs_2_0.py | 2 - numpy/core/__init__.py | 4 +- numpy/core/_add_newdocs.py | 8 +-- numpy/core/records.py | 24 ++++----- numpy/core/records.pyi | 10 +++- numpy/core/tests/test_arraymethod.py | 2 +- numpy/core/tests/test_deprecations.py | 1 + numpy/core/tests/test_dtype.py | 2 +- numpy/core/tests/test_records.py | 52 +++++++++---------- numpy/core/tests/test_regression.py | 6 +-- numpy/lib/_npyio_impl.py | 4 +- numpy/lib/recfunctions.py | 10 ++-- numpy/lib/tests/test_io.py | 12 ++--- numpy/lib/tests/test_recfunctions.py | 6 +-- numpy/ma/core.py | 3 +- numpy/ma/mrecords.py | 2 +- numpy/ma/tests/test_core.py | 8 +-- numpy/random/tests/test_generator_mt19937.py | 2 +- numpy/random/tests/test_random.py | 2 +- numpy/random/tests/test_randomstate.py | 2 +- numpy/typing/tests/data/reveal/rec.pyi | 44 ++++++++-------- 28 files changed, 132 insertions(+), 125 deletions(-) diff --git a/doc/release/upcoming_changes/24587.python_removal.rst b/doc/release/upcoming_changes/24587.python_removal.rst index 4e19fc9a9f0a..86197e6b6c37 100644 --- a/doc/release/upcoming_changes/24587.python_removal.rst +++ b/doc/release/upcoming_changes/24587.python_removal.rst @@ -1,11 +1,8 @@ * ``np.compare_chararrays`` has been removed from the main namespace. Use ``np.char.compare_chararrays`` instead. -* ``np.chararray`` has been removed from the main namespace. +* ``np.chararray`` has been deprecated and it will be removed in the future. Use ``np.char.chararray`` instead. * ``np.format_parser`` has been removed from the main namespace. Use ``np.rec.format_parser`` instead. - -* ``np.recarray`` has been removed from the main namespace. - Use ``np.rec.recarray`` instead. diff --git a/doc/source/glossary.rst b/doc/source/glossary.rst index 98aebcac28ab..ae2ab6ea4247 100644 --- a/doc/source/glossary.rst +++ b/doc/source/glossary.rst @@ -442,7 +442,7 @@ Glossary record array A :term:`structured array` with allowing access in an attribute style (``a.field``) in addition to ``a['field']``. For details, see - :doc:`numpy.rec.recarray. ` + :doc:`numpy.recarray. ` row-major diff --git a/doc/source/reference/arrays.classes.rst b/doc/source/reference/arrays.classes.rst index 26cf1bd02445..ae2926be8b9c 100644 --- a/doc/source/reference/arrays.classes.rst +++ b/doc/source/reference/arrays.classes.rst @@ -526,7 +526,7 @@ scalar data type object :class:`record`. .. autosummary:: :toctree: generated/ - rec.recarray + recarray record .. note:: diff --git a/doc/source/user/basics.io.genfromtxt.rst b/doc/source/user/basics.io.genfromtxt.rst index 5f6657bfbbc7..1f44bea22582 100644 --- a/doc/source/user/basics.io.genfromtxt.rst +++ b/doc/source/user/basics.io.genfromtxt.rst @@ -323,7 +323,7 @@ Validating names ---------------- NumPy arrays with a structured dtype can also be viewed as -:class:`~numpy.rec.recarray`, where a field can be accessed as if it were an +:class:`~numpy.recarray`, where a field can be accessed as if it were an attribute. For that reason, we may need to make sure that the field name doesn't contain any space or invalid character, or that it does not correspond to the name of a standard attribute (like ``size`` or diff --git a/doc/source/user/basics.rec.rst b/doc/source/user/basics.rec.rst index 69ad4a46025a..3e23339a54f7 100644 --- a/doc/source/user/basics.rec.rst +++ b/doc/source/user/basics.rec.rst @@ -630,7 +630,7 @@ Record Arrays ============= As an optional convenience numpy provides an ndarray subclass, -:class:`numpy.rec.recarray` that allows access to fields of structured arrays +:class:`numpy.recarray` that allows access to fields of structured arrays by attribute instead of only by index. Record arrays use a special datatype, :class:`numpy.record`, that allows field access by attribute on the structured scalars obtained from the array. @@ -673,13 +673,13 @@ appropriate `view `_:: >>> arr = np.array([(1, 2., 'Hello'), (2, 3., "World")], ... dtype=[('foo', 'i4'),('bar', 'f4'), ('baz', 'a10')]) >>> recordarr = arr.view(dtype=np.dtype((np.record, arr.dtype)), - ... type=np.rec.recarray) + ... type=np.recarray) -For convenience, viewing an ndarray as type :class:`numpy.rec.recarray` will +For convenience, viewing an ndarray as type :class:`numpy.recarray` will automatically convert to :class:`numpy.record` datatype, so the dtype can be left out of the view:: - >>> recordarr = arr.view(np.rec.recarray) + >>> recordarr = arr.view(np.recarray) >>> recordarr.dtype dtype((numpy.record, [('foo', '>> type(recordarr.foo) >>> type(recordarr.bar) - + Note that if a field has the same name as an ndarray attribute, the ndarray attribute takes precedence. Such fields will be inaccessible by attribute but diff --git a/numpy/__init__.py b/numpy/__init__.py index 596b0256da9f..3447a0f65496 100644 --- a/numpy/__init__.py +++ b/numpy/__init__.py @@ -120,7 +120,7 @@ from . import core from .core import ( - _no_nep50_warning, memmap, iinfo, finfo, + _no_nep50_warning, memmap, iinfo, finfo, recarray, False_, ScalarType, True_, abs, absolute, add, all, allclose, alltrue, amax, amin, any, arange, arccos, arccosh, arcsin, arcsinh, arctan, arctan2, arctanh, argmax, argmin, argpartition, argsort, argwhere, @@ -390,6 +390,14 @@ def __getattr__(attr): f"{__expired_attributes__[attr]}" ) + if attr == "chararray": + warnings.warn( + "`np.chararray` is deprecated and will be removed from " + "the main namespace in the future. Use `np.char.chararray` " + "instead.", DeprecationWarning, stacklevel=2) + import numpy.char as char + return char.chararray + raise AttributeError("module {!r} has no attribute " "{!r}".format(__name__, attr)) diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi index 463b4f0e2b54..19a540f8a0e5 100644 --- a/numpy/__init__.pyi +++ b/numpy/__init__.pyi @@ -211,9 +211,14 @@ from numpy import ( char as char, ) -from numpy.core import defchararray, records -char = defchararray -rec = records +from numpy.core.records import ( + record as record, + recarray as recarray, +) + +from numpy.core.defchararray import ( + chararray as chararray, +) from numpy.core.function_base import ( linspace as linspace, @@ -3390,15 +3395,6 @@ class iinfo(Generic[_IntType]): @overload def __new__(cls, dtype: str) -> iinfo[Any]: ... -class record(void): - def __getattribute__(self, attr: str) -> Any: ... - def __setattr__(self, attr: str, val: ArrayLike) -> None: ... - def pprint(self) -> str: ... - @overload - def __getitem__(self, key: str | SupportsIndex) -> Any: ... - @overload - def __getitem__(self, key: list[str]) -> record: ... - _NDIterFlagsKind = L[ "buffered", "c_index", diff --git a/numpy/_expired_attrs_2_0.py b/numpy/_expired_attrs_2_0.py index 019d01a90145..bf9456c00c89 100644 --- a/numpy/_expired_attrs_2_0.py +++ b/numpy/_expired_attrs_2_0.py @@ -71,7 +71,5 @@ "byte_bounds": "Now it's available under `np.lib.array_utils.byte_bounds`", "compare_chararrays": "It's still available as `np.char.compare_chararrays`.", - "chararray": "It's still available as `np.char.chararray`.", "format_parser": "It's still available as `np.rec.format_parser`.", - "recarray": "It's still available as `np.rec.recarray`.", } diff --git a/numpy/core/__init__.py b/numpy/core/__init__.py index 1fc724b73f59..a0946d89eaee 100644 --- a/numpy/core/__init__.py +++ b/numpy/core/__init__.py @@ -76,7 +76,7 @@ from .numeric import * from . import fromnumeric from .fromnumeric import * -from .records import record +from .records import record, recarray # Note: module name memmap is overwritten by a class with same name from .memmap import * from . import function_base @@ -102,7 +102,7 @@ from . import _dtype from . import _methods -__all__ = ['memmap', 'sctypeDict', 'record', 'abs'] +__all__ = ['memmap', 'sctypeDict', 'record', 'recarray', 'abs'] __all__ += numeric.__all__ __all__ += function_base.__all__ __all__ += getlimits.__all__ diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py index d5cffaa31f5e..67dcbaa767bf 100644 --- a/numpy/core/_add_newdocs.py +++ b/numpy/core/_add_newdocs.py @@ -978,9 +978,9 @@ Contrary to `asanyarray`, ndarray subclasses are not passed through: - >>> issubclass(np.rec.recarray, np.ndarray) + >>> issubclass(np.recarray, np.ndarray) True - >>> a = np.array([(1., 2), (3., 4)], dtype='f4,i4').view(np.rec.recarray) + >>> a = np.array([(1., 2), (3., 4)], dtype='f4,i4').view(np.recarray) >>> np.asarray(a) is a False >>> np.asanyarray(a) is a @@ -1044,7 +1044,7 @@ Instances of `ndarray` subclasses are passed through as-is: - >>> a = np.array([(1., 2), (3., 4)], dtype='f4,i4').view(np.rec.recarray) + >>> a = np.array([(1., 2), (3., 4)], dtype='f4,i4').view(np.recarray) >>> np.asanyarray(a) is a True @@ -4645,7 +4645,7 @@ Using a view to convert an array to a recarray: - >>> z = x.view(np.rec.recarray) + >>> z = x.view(np.recarray) >>> z.a array([1, 3], dtype=int8) diff --git a/numpy/core/records.py b/numpy/core/records.py index 83dcb12d9598..01637c000bb8 100644 --- a/numpy/core/records.py +++ b/numpy/core/records.py @@ -307,7 +307,7 @@ def pprint(self): # the fields (and any subfields) -@set_module("numpy.rec") +@set_module("numpy") class recarray(ndarray): """Construct an ndarray that allows field access using attributes. @@ -378,7 +378,7 @@ class recarray(ndarray): use one of the following methods: 1. Create a standard ndarray and convert it to a record array, - using ``arr.view(np.rec.recarray)`` + using ``arr.view(np.recarray)`` 2. Use the `buf` keyword. 3. Use `np.rec.fromrecords`. @@ -395,7 +395,7 @@ class recarray(ndarray): View the array as a record array: - >>> x = x.view(np.rec.recarray) + >>> x = x.view(np.recarray) >>> x.x array([1., 3.]) @@ -405,7 +405,7 @@ class recarray(ndarray): Create a new, empty record array: - >>> np.rec.recarray((2,), + >>> np.recarray((2,), ... dtype=[('x', int), ('y', float), ('z', int)]) #doctest: +SKIP rec.array([(-1073741821, 1.2249118382103472e-301, 24547520), (3471280, 1.2134086255804012e-316, 0)], @@ -538,7 +538,7 @@ def __repr__(self): # This should only happen if the user is playing # strange games with dtypes. prefix = "array(" - fmt = 'array(%s,%sdtype=%s).view(numpy.rec.recarray)' + fmt = 'array(%s,%sdtype=%s).view(numpy.recarray)' # get data/shape string. logic taken from numeric.array_repr if self.size > 0 or self.shape == (0,): @@ -605,7 +605,7 @@ def fromarrays(arrayList, dtype=None, shape=None, formats=None, Returns ------- - np.rec.recarray + np.recarray Record array consisting of given arrayList columns. Examples @@ -703,7 +703,7 @@ def fromrecords(recList, dtype=None, shape=None, formats=None, names=None, Returns ------- - np.rec.recarray + np.recarray record array consisting of given recList rows. Examples @@ -789,7 +789,7 @@ def fromstring(datastring, dtype=None, shape=None, offset=0, formats=None, Returns ------- - np.rec.recarray + np.recarray Record array view into the data in datastring. This will be readonly if `datastring` is readonly. @@ -871,7 +871,7 @@ def fromfile(fd, dtype=None, shape=None, offset=0, formats=None, Returns ------- - np.rec.recarray + np.recarray record array consisting of data enclosed in file. Examples @@ -983,16 +983,16 @@ def array(obj, dtype=None, shape=None, offset=0, strides=None, formats=None, Returns ------- - np.rec.recarray + np.recarray Record array created from the specified object. Notes ----- - If `obj` is ``None``, then call the `~numpy.rec.recarray` constructor. If + If `obj` is ``None``, then call the `~numpy.recarray` constructor. If `obj` is a string, then call the `fromstring` constructor. If `obj` is a list or a tuple, then if the first object is an `~numpy.ndarray`, call `fromarrays`, otherwise call `fromrecords`. If `obj` is a - `~numpy.rec.recarray`, then make a copy of the data in the recarray + `~numpy.recarray`, then make a copy of the data in the recarray (if ``copy=True``) and use the new formats, names, and titles. If `obj` is a file, then call `fromfile`. Finally, if obj is an `ndarray`, then return ``obj.view(recarray)``, making a copy of the data if ``copy=True``. diff --git a/numpy/core/records.pyi b/numpy/core/records.pyi index 05a8da1305b2..6424f100f8c5 100644 --- a/numpy/core/records.pyi +++ b/numpy/core/records.pyi @@ -10,7 +10,6 @@ from typing import ( ) from numpy import ( - record as record, ndarray, dtype, generic, @@ -41,6 +40,15 @@ class _SupportsReadInto(Protocol): def tell(self, /) -> int: ... def readinto(self, buffer: memoryview, /) -> int: ... +class record(void): + def __getattribute__(self, attr: str) -> Any: ... + def __setattr__(self, attr: str, val: ArrayLike) -> None: ... + def pprint(self) -> str: ... + @overload + def __getitem__(self, key: str | SupportsIndex) -> Any: ... + @overload + def __getitem__(self, key: list[str]) -> record: ... + class recarray(ndarray[_ShapeType, _DType_co]): # NOTE: While not strictly mandatory, we're demanding here that arguments # for the `format_parser`- and `dtype`-based dtype constructors are diff --git a/numpy/core/tests/test_arraymethod.py b/numpy/core/tests/test_arraymethod.py index 1e2319fc6f94..b98d712800b7 100644 --- a/numpy/core/tests/test_arraymethod.py +++ b/numpy/core/tests/test_arraymethod.py @@ -66,7 +66,7 @@ def test_invalid_arguments(self, args, error): @pytest.mark.parametrize( "cls", [ - np.ndarray, np.rec.recarray, np.char.chararray, np.matrix, np.memmap + np.ndarray, np.recarray, np.char.chararray, np.matrix, np.memmap ] ) class TestClassGetItem: diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py index a82d91ebf29b..3a366e6f5371 100644 --- a/numpy/core/tests/test_deprecations.py +++ b/numpy/core/tests/test_deprecations.py @@ -771,3 +771,4 @@ def test_lib_functions_deprecation_call(self): self.assert_deprecated(lambda: in1d([1], [1])) self.assert_deprecated(lambda: row_stack([[]])) self.assert_deprecated(lambda: trapz([1], [1])) + self.assert_deprecated(lambda: np.chararray) diff --git a/numpy/core/tests/test_dtype.py b/numpy/core/tests/test_dtype.py index a50f58581499..fa85d0358c8a 100644 --- a/numpy/core/tests/test_dtype.py +++ b/numpy/core/tests/test_dtype.py @@ -569,7 +569,7 @@ def test_fieldless_views(self): def test_nonstructured_with_object(self): # See gh-23277, the dtype here thinks it contain objects, if the # assert about that fails, the test becomes meaningless (which is OK) - arr = np.rec.recarray((0,), dtype="O") + arr = np.recarray((0,), dtype="O") assert arr.dtype.names is None # no fields assert arr.dtype.hasobject # but claims to contain objects del arr # the deletion failed previously. diff --git a/numpy/core/tests/test_records.py b/numpy/core/tests/test_records.py index 76993c8972e5..e7823503e88c 100644 --- a/numpy/core/tests/test_records.py +++ b/numpy/core/tests/test_records.py @@ -146,7 +146,7 @@ def test_recarray_from_repr(self): a = np.array([(1,'ABC'), (2, "DEF")], dtype=[('foo', int), ('bar', 'S4')]) recordarr = np.rec.array(a) - recarr = a.view(np.rec.recarray) + recarr = a.view(np.recarray) recordview = a.view(np.dtype((np.record, a.dtype))) recordarr_r = eval("np." + repr(recordarr), {'np': np}) @@ -154,11 +154,11 @@ def test_recarray_from_repr(self): # Prints the type `numpy.record` as part of the dtype: recordview_r = eval("np." + repr(recordview), {'np': np, 'numpy': np}) - assert_equal(type(recordarr_r), np.rec.recarray) + assert_equal(type(recordarr_r), np.recarray) assert_equal(recordarr_r.dtype.type, np.record) assert_equal(recordarr, recordarr_r) - assert_equal(type(recarr_r), np.rec.recarray) + assert_equal(type(recarr_r), np.recarray) assert_equal(recarr_r.dtype.type, np.record) assert_equal(recarr, recarr_r) @@ -173,30 +173,30 @@ def test_recarray_views(self): #check that np.rec.array gives right dtypes assert_equal(np.rec.array(a).dtype.type, np.record) - assert_equal(type(np.rec.array(a)), np.rec.recarray) + assert_equal(type(np.rec.array(a)), np.recarray) assert_equal(np.rec.array(b).dtype.type, np.int64) - assert_equal(type(np.rec.array(b)), np.rec.recarray) + assert_equal(type(np.rec.array(b)), np.recarray) #check that viewing as recarray does the same - assert_equal(a.view(np.rec.recarray).dtype.type, np.record) - assert_equal(type(a.view(np.rec.recarray)), np.rec.recarray) - assert_equal(b.view(np.rec.recarray).dtype.type, np.int64) - assert_equal(type(b.view(np.rec.recarray)), np.rec.recarray) + assert_equal(a.view(np.recarray).dtype.type, np.record) + assert_equal(type(a.view(np.recarray)), np.recarray) + assert_equal(b.view(np.recarray).dtype.type, np.int64) + assert_equal(type(b.view(np.recarray)), np.recarray) - #check that view to non-structured dtype preserves type=np.rec.recarray + #check that view to non-structured dtype preserves type=np.recarray r = np.rec.array(np.ones(4, dtype="f4,i4")) rv = r.view('f8').view('f4,i4') - assert_equal(type(rv), np.rec.recarray) + assert_equal(type(rv), np.recarray) assert_equal(rv.dtype.type, np.record) - #check that getitem also preserves np.rec.recarray and np.record + #check that getitem also preserves np.recarray and np.record r = np.rec.array(np.ones(4, dtype=[('a', 'i4'), ('b', 'i4'), ('c', 'i4,i4')])) assert_equal(r['c'].dtype.type, np.record) - assert_equal(type(r['c']), np.rec.recarray) + assert_equal(type(r['c']), np.recarray) #and that it preserves subclasses (gh-6949) - class C(np.rec.recarray): + class C(np.recarray): pass c = r.view(C) @@ -278,7 +278,7 @@ def test_recarray_stringtypes(self): # Issue #3993 a = np.array([('abc ', 1), ('abc', 2)], dtype=[('foo', 'S4'), ('bar', int)]) - a = a.view(np.rec.recarray) + a = a.view(np.recarray) assert_equal(a.foo[0] == a.foo[1], False) def test_recarray_returntypes(self): @@ -290,10 +290,10 @@ def test_recarray_returntypes(self): ('baz', int), ('qux', qux_fields)]) assert_equal(type(a.foo), np.ndarray) assert_equal(type(a['foo']), np.ndarray) - assert_equal(type(a.bar), np.rec.recarray) - assert_equal(type(a['bar']), np.rec.recarray) + assert_equal(type(a.bar), np.recarray) + assert_equal(type(a['bar']), np.recarray) assert_equal(a.bar.dtype.type, np.record) - assert_equal(type(a['qux']), np.rec.recarray) + assert_equal(type(a['qux']), np.recarray) assert_equal(a.qux.dtype.type, np.record) assert_equal(dict(a.qux.dtype.fields), qux_fields) assert_equal(type(a.baz), np.ndarray) @@ -442,18 +442,18 @@ def test_pickle_void(self): def test_objview_record(self): # https://github.com/numpy/numpy/issues/2599 dt = np.dtype([('foo', 'i8'), ('bar', 'O')]) - r = np.zeros((1, 3), dtype=dt).view(np.rec.recarray) + r = np.zeros((1, 3), dtype=dt).view(np.recarray) r.foo = np.array([1, 2, 3]) # TypeError? # https://github.com/numpy/numpy/issues/3256 - ra = np.rec.recarray( + ra = np.recarray( (2,), dtype=[('x', object), ('y', float), ('z', int)] ) ra[['x','y']] # TypeError? def test_record_scalar_setitem(self): # https://github.com/numpy/numpy/issues/3561 - rec = np.rec.recarray(1, dtype=[('x', float, 5)]) + rec = np.recarray(1, dtype=[('x', float, 5)]) rec[0].x = 1 assert_equal(rec[0].x, np.ones(5)) @@ -472,7 +472,7 @@ def test_fromarrays_nested_structured_arrays(self): @pytest.mark.parametrize('nfields', [0, 1, 2]) def test_assign_dtype_attribute(self, nfields): dt = np.dtype([('a', np.uint8), ('b', np.uint8), ('c', np.uint8)][:nfields]) - data = np.zeros(3, dt).view(np.rec.recarray) + data = np.zeros(3, dt).view(np.recarray) # the original and resulting dtypes differ on whether they are records assert data.dtype.type == np.record @@ -488,9 +488,9 @@ def test_nested_fields_are_records(self, nfields): dt = np.dtype([('a', np.uint8), ('b', np.uint8), ('c', np.uint8)][:nfields]) dt_outer = np.dtype([('inner', dt)]) - data = np.zeros(3, dt_outer).view(np.rec.recarray) - assert isinstance(data, np.rec.recarray) - assert isinstance(data['inner'], np.rec.recarray) + data = np.zeros(3, dt_outer).view(np.recarray) + assert isinstance(data, np.recarray) + assert isinstance(data['inner'], np.recarray) data0 = data[0] assert isinstance(data0, np.record) @@ -505,7 +505,7 @@ def test_nested_dtype_padding(self): dt_outer = np.dtype([('inner', dt_padded_end)]) - data = np.zeros(3, dt_outer).view(np.rec.recarray) + data = np.zeros(3, dt_outer).view(np.recarray) assert_equal(data['inner'].dtype, dt_padded_end) data0 = data[0] diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py index 346a59407537..1e588f6ffc79 100644 --- a/numpy/core/tests/test_regression.py +++ b/numpy/core/tests/test_regression.py @@ -179,7 +179,7 @@ def test_endian_recarray(self): ('head', '>u4'), ('data', '>u4', 2), ]) - buf = np.rec.recarray(1, dtype=dt) + buf = np.recarray(1, dtype=dt) buf[0]['head'] = 1 buf[0]['data'][:] = [1, 1] @@ -1169,7 +1169,7 @@ def test_recarray_tolist(self): # Comparisons fail for NaN, so we can't use random memory # for the test. buf = np.zeros(40, dtype=np.int8) - a = np.rec.recarray(2, formats="i4,f8,f8", names="id,x,y", buf=buf) + a = np.recarray(2, formats="i4,f8,f8", names="id,x,y", buf=buf) b = a.tolist() assert_( a[0].tolist() == b[0]) assert_( a[1].tolist() == b[1]) @@ -2080,7 +2080,7 @@ def test_searchsorted_wrong_dtype(self): assert_raises(TypeError, np.searchsorted, a, 1.2) # Ticket #2066, similar problem: dtype = np.rec.format_parser(['i4', 'i4'], [], []) - a = np.rec.recarray((2,), dtype) + a = np.recarray((2,), dtype) a[...] = [(1, 2), (3, 4)] assert_raises(TypeError, np.searchsorted, a, 1) diff --git a/numpy/lib/_npyio_impl.py b/numpy/lib/_npyio_impl.py index c2f05c9efa90..87a08bec9138 100644 --- a/numpy/lib/_npyio_impl.py +++ b/numpy/lib/_npyio_impl.py @@ -2500,7 +2500,7 @@ def recfromtxt(fname, **kwargs): from numpy.ma.mrecords import MaskedRecords output = output.view(MaskedRecords) else: - output = output.view(np.rec.recarray) + output = output.view(np.recarray) return output @@ -2551,5 +2551,5 @@ def recfromcsv(fname, **kwargs): from numpy.ma.mrecords import MaskedRecords output = output.view(MaskedRecords) else: - output = output.view(np.rec.recarray) + output = output.view(np.recarray) return output diff --git a/numpy/lib/recfunctions.py b/numpy/lib/recfunctions.py index 9b924473bc8a..f22f4e9ccd3f 100644 --- a/numpy/lib/recfunctions.py +++ b/numpy/lib/recfunctions.py @@ -596,7 +596,7 @@ def _rec_drop_fields_dispatcher(base, drop_names): @array_function_dispatch(_rec_drop_fields_dispatcher) def rec_drop_fields(base, drop_names): """ - Returns a new numpy.rec.recarray with fields in `drop_names` dropped. + Returns a new numpy.recarray with fields in `drop_names` dropped. """ return drop_fields(base, drop_names, usemask=False, asrecarray=True) @@ -756,7 +756,7 @@ def rec_append_fields(base, names, data, dtypes=None): Returns ------- - appended_array : np.rec.recarray + appended_array : np.recarray """ return append_fields(base, names, data=data, dtypes=dtypes, asrecarray=True, usemask=False) @@ -958,7 +958,7 @@ def structured_to_unstructured(arr, dtype=None, copy=False, casting='unsafe'): If true, always return a copy. If false, a view is returned if possible, such as when the `dtype` and strides of the fields are suitable and the array subtype is one of `numpy.ndarray`, - `numpy.rec.recarray` or `numpy.memmap`. + `numpy.recarray` or `numpy.memmap`. .. versionchanged:: 1.25.0 A view can now be returned if the fields are separated by a @@ -1026,7 +1026,7 @@ def structured_to_unstructured(arr, dtype=None, copy=False, casting='unsafe'): # we only allow a few types to be unstructured by manipulating the # strides, because we know it won't work with, for example, np.matrix nor # np.ma.MaskedArray. - can_view = type(arr) in (np.ndarray, np.rec.recarray, np.memmap) + can_view = type(arr) in (np.ndarray, np.recarray, np.memmap) if (not copy) and can_view and all(dt.base == out_dtype for dt in dts): # all elements have the right dtype already; if they have a common # stride, we can just return a view @@ -1663,7 +1663,7 @@ def rec_join(key, r1, r2, jointype='inner', r1postfix='1', r2postfix='2', defaults=None): """ Join arrays `r1` and `r2` on keys. - Alternative to join_by, that always returns a np.rec.recarray. + Alternative to join_by, that always returns a np.recarray. See Also -------- diff --git a/numpy/lib/tests/test_io.py b/numpy/lib/tests/test_io.py index c6ca81b07e72..36505b34a515 100644 --- a/numpy/lib/tests/test_io.py +++ b/numpy/lib/tests/test_io.py @@ -2302,7 +2302,7 @@ def test_recfromtxt(self): test = recfromtxt(data, **kwargs) control = np.array([(0, 1), (2, 3)], dtype=[('A', int), ('B', int)]) - assert_(isinstance(test, np.rec.recarray)) + assert_(isinstance(test, np.recarray)) assert_equal(test, control) # data = TextIO('A,B\n0,1\n2,N/A') @@ -2322,7 +2322,7 @@ def test_recfromcsv(self): test = recfromcsv(data, dtype=None, **kwargs) control = np.array([(0, 1), (2, 3)], dtype=[('A', int), ('B', int)]) - assert_(isinstance(test, np.rec.recarray)) + assert_(isinstance(test, np.recarray)) assert_equal(test, control) # data = TextIO('A,B\n0,1\n2,N/A') @@ -2338,7 +2338,7 @@ def test_recfromcsv(self): test = recfromcsv(data, missing_values='N/A',) control = np.array([(0, 1), (2, 3)], dtype=[('a', int), ('b', int)]) - assert_(isinstance(test, np.rec.recarray)) + assert_(isinstance(test, np.recarray)) assert_equal(test, control) # data = TextIO('A,B\n0,1\n2,3') @@ -2346,7 +2346,7 @@ def test_recfromcsv(self): test = recfromcsv(data, missing_values='N/A', dtype=dtype) control = np.array([(0, 1), (2, 3)], dtype=dtype) - assert_(isinstance(test, np.rec.recarray)) + assert_(isinstance(test, np.recarray)) assert_equal(test, control) #gh-10394 @@ -2626,7 +2626,7 @@ def test_recfromtxt(self, filename_type): test = recfromtxt(path, **kwargs) control = np.array([(0, 1), (2, 3)], dtype=[('A', int), ('B', int)]) - assert_(isinstance(test, np.rec.recarray)) + assert_(isinstance(test, np.recarray)) assert_equal(test, control) @pytest.mark.parametrize("filename_type", [Path, str]) @@ -2643,7 +2643,7 @@ def test_recfromcsv(self, filename_type): test = recfromcsv(path, dtype=None, **kwargs) control = np.array([(0, 1), (2, 3)], dtype=[('A', int), ('B', int)]) - assert_(isinstance(test, np.rec.recarray)) + assert_(isinstance(test, np.recarray)) assert_equal(test, control) diff --git a/numpy/lib/tests/test_recfunctions.py b/numpy/lib/tests/test_recfunctions.py index 3c84a2abd633..98860dfdab77 100644 --- a/numpy/lib/tests/test_recfunctions.py +++ b/numpy/lib/tests/test_recfunctions.py @@ -350,13 +350,13 @@ def inspect(dt, dtype=None): dd_expected = structured_to_unstructured(d_plain, copy=True) # recarray - d = d_plain.view(np.rec.recarray) + d = d_plain.view(np.recarray) dd = structured_to_unstructured(d, copy=False) ddd = structured_to_unstructured(d, copy=True) assert_(np.shares_memory(d, dd)) - assert_(type(dd) is np.rec.recarray) - assert_(type(ddd) is np.rec.recarray) + assert_(type(dd) is np.recarray) + assert_(type(ddd) is np.recarray) assert_equal(dd, dd_expected) assert_equal(ddd, dd_expected) diff --git a/numpy/ma/core.py b/numpy/ma/core.py index f5bbd85af8f5..57728c3220ce 100644 --- a/numpy/ma/core.py +++ b/numpy/ma/core.py @@ -3818,8 +3818,7 @@ def filled(self, fill_value=None): Subclassing is preserved. This means that if, e.g., the data part of the masked array is a recarray, `filled` returns a recarray: - >>> from numpy import rec - >>> x = np.array([(-1, 2), (-3, 4)], dtype='i8,i8').view(rec.recarray) + >>> x = np.array([(-1, 2), (-3, 4)], dtype='i8,i8').view(np.recarray) >>> m = np.ma.array(x, mask=[(True, False), (False, True)]) >>> m.filled() rec.array([(999999, 2), ( -3, 999999)], diff --git a/numpy/ma/mrecords.py b/numpy/ma/mrecords.py index c554f6ba68ca..82b2ff79c6b4 100644 --- a/numpy/ma/mrecords.py +++ b/numpy/ma/mrecords.py @@ -1,6 +1,6 @@ """:mod:`numpy.ma..mrecords` -Defines the equivalent of :class:`numpy.rec.recarrays` for masked arrays, +Defines the equivalent of :class:`numpy.recarrays` for masked arrays, where fields can be accessed as attributes. Note that :class:`numpy.ma.MaskedArray` already supports structured datatypes and the masking of individual fields. diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py index 7a6d17fb314c..a4f8deb93ab5 100644 --- a/numpy/ma/tests/test_core.py +++ b/numpy/ma/tests/test_core.py @@ -645,13 +645,13 @@ def test_pickling(self): def test_pickling_subbaseclass(self): # Test pickling w/ a subclass of ndarray x = np.array([(1.0, 2), (3.0, 4)], - dtype=[('x', float), ('y', int)]).view(np.rec.recarray) + dtype=[('x', float), ('y', int)]).view(np.recarray) a = masked_array(x, mask=[(True, False), (False, True)]) for proto in range(2, pickle.HIGHEST_PROTOCOL + 1): a_pickled = pickle.loads(pickle.dumps(a, protocol=proto)) assert_equal(a_pickled._mask, a._mask) assert_equal(a_pickled, a) - assert_(isinstance(a_pickled._data, np.rec.recarray)) + assert_(isinstance(a_pickled._data, np.recarray)) def test_pickling_maskedconstant(self): # Test pickling MaskedConstant @@ -5220,9 +5220,9 @@ def test_view_to_subdtype(self): def test_view_to_dtype_and_type(self): (data, a, controlmask) = self.data - test = a.view((float, 2), np.rec.recarray) + test = a.view((float, 2), np.recarray) assert_equal(test, data) - assert_(isinstance(test, np.rec.recarray)) + assert_(isinstance(test, np.recarray)) assert_(not isinstance(test, MaskedArray)) diff --git a/numpy/random/tests/test_generator_mt19937.py b/numpy/random/tests/test_generator_mt19937.py index 912a3c849f82..21345b0d6c72 100644 --- a/numpy/random/tests/test_generator_mt19937.py +++ b/numpy/random/tests/test_generator_mt19937.py @@ -953,7 +953,7 @@ def test_shuffle(self): # gh-11442 lambda x: (np.asarray([(i, i) for i in x], [("a", int), ("b", int)]) - .view(np.rec.recarray)), + .view(np.recarray)), # gh-4270 lambda x: np.asarray([(i, i) for i in x], [("a", object, (1,)), diff --git a/numpy/random/tests/test_random.py b/numpy/random/tests/test_random.py index c0562f6960d2..e64ace711953 100644 --- a/numpy/random/tests/test_random.py +++ b/numpy/random/tests/test_random.py @@ -487,7 +487,7 @@ def test_shuffle(self): # gh-11442 lambda x: (np.asarray([(i, i) for i in x], [("a", int), ("b", int)]) - .view(np.rec.recarray)), + .view(np.recarray)), # gh-4270 lambda x: np.asarray([(i, i) for i in x], [("a", object), ("b", np.int32)])]: diff --git a/numpy/random/tests/test_randomstate.py b/numpy/random/tests/test_randomstate.py index b4f28ade1217..524ac7b7c5e0 100644 --- a/numpy/random/tests/test_randomstate.py +++ b/numpy/random/tests/test_randomstate.py @@ -689,7 +689,7 @@ def test_shuffle(self): # gh-11442 lambda x: (np.asarray([(i, i) for i in x], [("a", int), ("b", int)]) - .view(np.rec.recarray)), + .view(np.recarray)), # gh-4270 lambda x: np.asarray([(i, i) for i in x], [("a", object, (1,)), diff --git a/numpy/typing/tests/data/reveal/rec.pyi b/numpy/typing/tests/data/reveal/rec.pyi index c137386672b1..1c1558bf3462 100644 --- a/numpy/typing/tests/data/reveal/rec.pyi +++ b/numpy/typing/tests/data/reveal/rec.pyi @@ -11,7 +11,7 @@ else: from typing_extensions import assert_type AR_i8: npt.NDArray[np.int64] -REC_AR_V: np.rec.recarray[Any, np.dtype[np.record]] +REC_AR_V: np.recarray[Any, np.dtype[np.record]] AR_LIST: list[npt.NDArray[np.int64]] record: np.record @@ -41,28 +41,28 @@ assert_type(REC_AR_V.field_a, Any) assert_type(REC_AR_V.__array_finalize__(object()), None) assert_type( - np.rec.recarray( + np.recarray( shape=(10, 5), formats=[np.float64, np.int64, np.bool_], order="K", byteorder="|", ), - np.rec.recarray[Any, np.dtype[np.record]], + np.recarray[Any, np.dtype[np.record]], ) assert_type( - np.rec.recarray( + np.recarray( shape=(10, 5), dtype=[("f8", np.float64), ("i8", np.int64)], strides=(5, 5), ), - np.rec.recarray[Any, np.dtype[Any]], + np.recarray[Any, np.dtype[Any]], ) -assert_type(np.rec.fromarrays(AR_LIST), np.rec.recarray[Any, np.dtype[Any]]) +assert_type(np.rec.fromarrays(AR_LIST), np.recarray[Any, np.dtype[Any]]) assert_type( np.rec.fromarrays(AR_LIST, dtype=np.int64), - np.rec.recarray[Any, np.dtype[Any]], + np.recarray[Any, np.dtype[Any]], ) assert_type( np.rec.fromarrays( @@ -70,12 +70,12 @@ assert_type( formats=[np.int64, np.float64], names=["i8", "f8"] ), - np.rec.recarray[Any, np.dtype[np.record]], + np.recarray[Any, np.dtype[np.record]], ) assert_type( np.rec.fromrecords((1, 1.5)), - np.rec.recarray[Any, np.dtype[np.record]] + np.recarray[Any, np.dtype[np.record]] ) assert_type( @@ -83,7 +83,7 @@ assert_type( [(1, 1.5)], dtype=[("i8", np.int64), ("f8", np.float64)], ), - np.rec.recarray[Any, np.dtype[np.record]], + np.recarray[Any, np.dtype[np.record]], ) assert_type( @@ -92,7 +92,7 @@ assert_type( formats=[np.int64, np.float64], names=["i8", "f8"] ), - np.rec.recarray[Any, np.dtype[np.record]], + np.recarray[Any, np.dtype[np.record]], ) assert_type( @@ -100,7 +100,7 @@ assert_type( b"(1, 1.5)", dtype=[("i8", np.int64), ("f8", np.float64)], ), - np.rec.recarray[Any, np.dtype[np.record]], + np.recarray[Any, np.dtype[np.record]], ) assert_type( @@ -109,13 +109,13 @@ assert_type( formats=[np.int64, np.float64], names=["i8", "f8"] ), - np.rec.recarray[Any, np.dtype[np.record]], + np.recarray[Any, np.dtype[np.record]], ) assert_type(np.rec.fromfile( "test_file.txt", dtype=[("i8", np.int64), ("f8", np.float64)], -), np.rec.recarray[Any, np.dtype[Any]]) +), np.recarray[Any, np.dtype[Any]]) assert_type( np.rec.fromfile( @@ -123,14 +123,14 @@ assert_type( formats=[np.int64, np.float64], names=["i8", "f8"] ), - np.rec.recarray[Any, np.dtype[np.record]], + np.recarray[Any, np.dtype[np.record]], ) -assert_type(np.rec.array(AR_i8), np.rec.recarray[Any, np.dtype[np.int64]]) +assert_type(np.rec.array(AR_i8), np.recarray[Any, np.dtype[np.int64]]) assert_type( np.rec.array([(1, 1.5)], dtype=[("i8", np.int64), ("f8", np.float64)]), - np.rec.recarray[Any, np.dtype[Any]], + np.recarray[Any, np.dtype[Any]], ) assert_type( @@ -139,7 +139,7 @@ assert_type( formats=[np.int64, np.float64], names=["i8", "f8"] ), - np.rec.recarray[Any, np.dtype[np.record]], + np.recarray[Any, np.dtype[np.record]], ) assert_type( @@ -148,7 +148,7 @@ assert_type( dtype=np.float64, shape=(10, 3), ), - np.rec.recarray[Any, np.dtype[Any]], + np.recarray[Any, np.dtype[Any]], ) assert_type( @@ -158,15 +158,15 @@ assert_type( names=["i8", "f8"], shape=(10, 3), ), - np.rec.recarray[Any, np.dtype[np.record]], + np.recarray[Any, np.dtype[np.record]], ) assert_type( np.rec.array(file_obj, dtype=np.float64), - np.rec.recarray[Any, np.dtype[Any]], + np.recarray[Any, np.dtype[Any]], ) assert_type( np.rec.array(file_obj, formats=[np.int64, np.float64], names=["i8", "f8"]), - np.rec.recarray[Any, np.dtype[np.record]], + np.recarray[Any, np.dtype[np.record]], ) From eb6a10a2294defc48a93fad1f57d73628e04db2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Sok=C3=B3=C5=82?= Date: Wed, 13 Sep 2023 12:59:43 +0200 Subject: [PATCH 09/11] Apply review comments --- .../upcoming_changes/24587.python_removal.rst | 5 +-- numpy/__init__.py | 4 +-- numpy/setup.py | 35 ------------------- 3 files changed, 5 insertions(+), 39 deletions(-) delete mode 100644 numpy/setup.py diff --git a/doc/release/upcoming_changes/24587.python_removal.rst b/doc/release/upcoming_changes/24587.python_removal.rst index 86197e6b6c37..801e7fb3a100 100644 --- a/doc/release/upcoming_changes/24587.python_removal.rst +++ b/doc/release/upcoming_changes/24587.python_removal.rst @@ -1,8 +1,9 @@ * ``np.compare_chararrays`` has been removed from the main namespace. Use ``np.char.compare_chararrays`` instead. -* ``np.chararray`` has been deprecated and it will be removed in the future. - Use ``np.char.chararray`` instead. +* The ``charrarray`` in the main namespace has been deprecated. It can be imported + without a deprecation warning from ``np.char.chararray`` for now, + but we are planning to fully deprecate and remove ``chararray`` in the future. * ``np.format_parser`` has been removed from the main namespace. Use ``np.rec.format_parser`` instead. diff --git a/numpy/__init__.py b/numpy/__init__.py index 3447a0f65496..1128e5ee525b 100644 --- a/numpy/__init__.py +++ b/numpy/__init__.py @@ -393,8 +393,8 @@ def __getattr__(attr): if attr == "chararray": warnings.warn( "`np.chararray` is deprecated and will be removed from " - "the main namespace in the future. Use `np.char.chararray` " - "instead.", DeprecationWarning, stacklevel=2) + "the main namespace in the future. Use an array with a string " + "or bytes dtype instead.", DeprecationWarning, stacklevel=2) import numpy.char as char return char.chararray diff --git a/numpy/setup.py b/numpy/setup.py deleted file mode 100644 index d3c0d3464c0e..000000000000 --- a/numpy/setup.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python3 - -def configuration(parent_package='',top_path=None): - from numpy.distutils.misc_util import Configuration - config = Configuration('numpy', parent_package, top_path) - - config.add_subpackage('array_api') - config.add_subpackage('compat') - config.add_subpackage('core') - config.add_subpackage('distutils') - config.add_subpackage('doc') - config.add_subpackage('f2py') - config.add_subpackage('fft') - config.add_subpackage('lib') - config.add_subpackage('linalg') - config.add_subpackage('ma') - config.add_subpackage('matrixlib') - config.add_subpackage('polynomial') - config.add_subpackage('random') - config.add_subpackage('rec') - config.add_subpackage('char') - config.add_subpackage('testing') - config.add_subpackage('typing') - config.add_subpackage('_typing') - config.add_subpackage('_utils') - config.add_data_dir('doc') - config.add_data_files('py.typed') - config.add_data_files('*.pyi') - config.add_subpackage('tests') - config.add_subpackage('_pyinstaller') - config.make_config_py() # installs __config__.py - return config - -if __name__ == '__main__': - print('This is the wrong setup.py file to run') From 5312b6ed486a503e1917065197d5c6401e501400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Sok=C3=B3=C5=82?= Date: Sun, 17 Sep 2023 20:02:44 +0200 Subject: [PATCH 10/11] Apply review comments --- numpy/core/records.py | 2 +- numpy/lib/_shape_base_impl.py | 4 +++- numpy/tests/test_public_api.py | 9 +++------ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/numpy/core/records.py b/numpy/core/records.py index 01637c000bb8..525fc4897afd 100644 --- a/numpy/core/records.py +++ b/numpy/core/records.py @@ -307,7 +307,7 @@ def pprint(self): # the fields (and any subfields) -@set_module("numpy") +@set_module("numpy.rec") class recarray(ndarray): """Construct an ndarray that allows field access using attributes. diff --git a/numpy/lib/_shape_base_impl.py b/numpy/lib/_shape_base_impl.py index 817278edc4a0..076dd67604a6 100644 --- a/numpy/lib/_shape_base_impl.py +++ b/numpy/lib/_shape_base_impl.py @@ -8,6 +8,7 @@ from numpy.core import overrides from numpy.core import vstack, atleast_3d from numpy.core.numeric import normalize_axis_tuple +from numpy.core.overrides import set_module from numpy.core.shape_base import _arrays_for_stack_dispatcher from numpy.lib._index_tricks_impl import ndindex from numpy.matrixlib.defmatrix import matrix # this raises all the right alarm bells @@ -604,7 +605,8 @@ def expand_dims(a, axis): return a.reshape(shape) -# TODO: Remove once deprecation period passes +# NOTE: Remove once deprecation period passes +@set_module("numpy") def row_stack(tup, *, dtype=None, casting="same_kind"): # Deprecated in NumPy 2.0, 2023-08-18 warnings.warn( diff --git a/numpy/tests/test_public_api.py b/numpy/tests/test_public_api.py index 2f302cc8e5b9..6078037aa132 100644 --- a/numpy/tests/test_public_api.py +++ b/numpy/tests/test_public_api.py @@ -31,14 +31,11 @@ def check_dir(module, module_name=None): def test_numpy_namespace(): - # None of these objects are publicly documented to be part of the main - # NumPy namespace (some are useful though, others need to be cleaned up) - undocumented = { + # We override dir to not show these members + allowlist = { + 'recarray': 'numpy.rec.recarray', 'show_config': 'numpy.__config__.show', - 'row_stack': 'numpy.lib._shape_base_impl.row_stack' } - # We override dir to not show these members - allowlist = undocumented bad_results = check_dir(np) # pytest gives better error messages with the builtin assert than with # assert_equal From 2752b0472ea79b2cd7ba6b958b34c09c59d0b8cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Sok=C3=B3=C5=82?= Date: Sun, 17 Sep 2023 20:16:15 +0200 Subject: [PATCH 11/11] Fix rst doc --- doc/source/user/basics.rec.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/user/basics.rec.rst b/doc/source/user/basics.rec.rst index 3e23339a54f7..efe2c8cc982d 100644 --- a/doc/source/user/basics.rec.rst +++ b/doc/source/user/basics.rec.rst @@ -697,7 +697,7 @@ array if the field has a structured type but as a plain ndarray otherwise. :: >>> type(recordarr.foo) >>> type(recordarr.bar) - + Note that if a field has the same name as an ndarray attribute, the ndarray attribute takes precedence. Such fields will be inaccessible by attribute but