diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index a716139c4f48..47f20e5f409d 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -108,11 +108,14 @@ jobs: with: python-version: "3.x" + # We need rtools 4.0 to have 32 bit support on windows + - if: runner.os == 'windows' + uses: r-windows/install-rtools@ca1090c210479e995c03019a22b9798cdf57073a # main + - name: setup rtools for 32-bit run: | echo "PLAT=i686" >> $env:GITHUB_ENV - echo "MSYSTEM=MINGW32" >> $env:GITHUB_ENV - echo "PATH=$env:RTOOLS40_HOME\mingw32\bin;$env:PATH" >> $env:GITHUB_ENV + echo "PATH=c:\rtools40\mingw32\bin;$env:PATH" >> $env:GITHUB_ENV gfortran --version if: ${{ matrix.buildplat[1] == 'win32' }} diff --git a/azure-steps-windows.yml b/azure-steps-windows.yml index 8fe677eab1eb..df64dc39dcb7 100644 --- a/azure-steps-windows.yml +++ b/azure-steps-windows.yml @@ -32,8 +32,9 @@ steps: displayName: 'Install dependencies; some are optional to avoid test skips' - powershell: | - choco install -y rtools - refreshenv + # rtools 42+ does not support 32 bits builds. + choco install --confirm --no-progress --allow-downgrade rtools --version=4.0.0.20220206 + echo "##vso[task.setvariable variable=RTOOLS40_HOME]c:\rtools40" displayName: 'Install rtools' - powershell: | diff --git a/doc/changelog/1.24.4-changelog.rst b/doc/changelog/1.24.4-changelog.rst new file mode 100644 index 000000000000..f86e4b142d64 --- /dev/null +++ b/doc/changelog/1.24.4-changelog.rst @@ -0,0 +1,23 @@ + +Contributors +============ + +A total of 4 people contributed to this release. People with a "+" by their +names contributed a patch for the first time. + +* Bas van Beek +* Charles Harris +* Sebastian Berg +* Hongyang Peng + + +Pull requests merged +==================== + +A total of 6 pull requests were merged for this release. + +* `#23720 `__: MAINT, BLD: Pin rtools to version 4.0 for Windows builds. +* `#23739 `__: BUG: fix the method for checking local files for 1.24.x +* `#23760 `__: MAINT: Copy rtools installation from install-rtools. +* `#23761 `__: BUG: Fix masked array ravel order for A (and somewhat K) +* `#23890 `__: TYP,DOC: Annotate and document the ``metadata`` parameter of... +* `#23994 `__: MAINT: Update rtools installation diff --git a/doc/source/release.rst b/doc/source/release.rst index bc05f00f7b2c..fbc42ee2088e 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -5,6 +5,7 @@ Release notes .. toctree:: :maxdepth: 3 + 1.24.4 1.24.3 1.24.2 1.24.1 diff --git a/doc/source/release/1.24.4-notes.rst b/doc/source/release/1.24.4-notes.rst new file mode 100644 index 000000000000..41cf1aeb9189 --- /dev/null +++ b/doc/source/release/1.24.4-notes.rst @@ -0,0 +1,31 @@ +.. currentmodule:: numpy + +========================== +NumPy 1.24.4 Release Notes +========================== +NumPy 1.24.4 is a maintenance release that fixes bugs and regressions discovered after the +1.24.3 release. The Python versions supported by this release are 3.8-3.11. + +Contributors +============ + +A total of 4 people contributed to this release. People with a "+" by their +names contributed a patch for the first time. + +* Bas van Beek +* Charles Harris +* Sebastian Berg +* Hongyang Peng + + +Pull requests merged +==================== + +A total of 6 pull requests were merged for this release. + +* `#23720 `__: MAINT, BLD: Pin rtools to version 4.0 for Windows builds. +* `#23739 `__: BUG: fix the method for checking local files for 1.24.x +* `#23760 `__: MAINT: Copy rtools installation from install-rtools. +* `#23761 `__: BUG: Fix masked array ravel order for A (and somewhat K) +* `#23890 `__: TYP,DOC: Annotate and document the ``metadata`` parameter of... +* `#23994 `__: MAINT: Update rtools installation + diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi index 853444f23cb2..99a96f96ec1b 100644 --- a/numpy/__init__.pyi +++ b/numpy/__init__.pyi @@ -690,6 +690,7 @@ class dtype(Generic[_DTypeScalar_co]): dtype: type[_DTypeScalar_co], align: bool = ..., copy: bool = ..., + metadata: dict[builtins.str, Any] = ..., ) -> dtype[_DTypeScalar_co]: ... # Overloads for string aliases, Python types, and some assorted # other special cases. Order is sometimes important because of the @@ -701,108 +702,108 @@ class dtype(Generic[_DTypeScalar_co]): # first. # Builtin types @overload - def __new__(cls, dtype: type[bool], align: bool = ..., copy: bool = ...) -> dtype[bool_]: ... + def __new__(cls, dtype: type[bool], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[bool_]: ... @overload - def __new__(cls, dtype: type[int], align: bool = ..., copy: bool = ...) -> dtype[int_]: ... + def __new__(cls, dtype: type[int], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[int_]: ... @overload - def __new__(cls, dtype: None | type[float], align: bool = ..., copy: bool = ...) -> dtype[float_]: ... + def __new__(cls, dtype: None | type[float], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[float_]: ... @overload - def __new__(cls, dtype: type[complex], align: bool = ..., copy: bool = ...) -> dtype[complex_]: ... + def __new__(cls, dtype: type[complex], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[complex_]: ... @overload - def __new__(cls, dtype: type[builtins.str], align: bool = ..., copy: bool = ...) -> dtype[str_]: ... + def __new__(cls, dtype: type[builtins.str], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[str_]: ... @overload - def __new__(cls, dtype: type[bytes], align: bool = ..., copy: bool = ...) -> dtype[bytes_]: ... + def __new__(cls, dtype: type[bytes], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[bytes_]: ... # `unsignedinteger` string-based representations and ctypes @overload - def __new__(cls, dtype: _UInt8Codes | type[ct.c_uint8], align: bool = ..., copy: bool = ...) -> dtype[uint8]: ... + def __new__(cls, dtype: _UInt8Codes | type[ct.c_uint8], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[uint8]: ... @overload - def __new__(cls, dtype: _UInt16Codes | type[ct.c_uint16], align: bool = ..., copy: bool = ...) -> dtype[uint16]: ... + def __new__(cls, dtype: _UInt16Codes | type[ct.c_uint16], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[uint16]: ... @overload - def __new__(cls, dtype: _UInt32Codes | type[ct.c_uint32], align: bool = ..., copy: bool = ...) -> dtype[uint32]: ... + def __new__(cls, dtype: _UInt32Codes | type[ct.c_uint32], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[uint32]: ... @overload - def __new__(cls, dtype: _UInt64Codes | type[ct.c_uint64], align: bool = ..., copy: bool = ...) -> dtype[uint64]: ... + def __new__(cls, dtype: _UInt64Codes | type[ct.c_uint64], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[uint64]: ... @overload - def __new__(cls, dtype: _UByteCodes | type[ct.c_ubyte], align: bool = ..., copy: bool = ...) -> dtype[ubyte]: ... + def __new__(cls, dtype: _UByteCodes | type[ct.c_ubyte], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[ubyte]: ... @overload - def __new__(cls, dtype: _UShortCodes | type[ct.c_ushort], align: bool = ..., copy: bool = ...) -> dtype[ushort]: ... + def __new__(cls, dtype: _UShortCodes | type[ct.c_ushort], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[ushort]: ... @overload - def __new__(cls, dtype: _UIntCCodes | type[ct.c_uint], align: bool = ..., copy: bool = ...) -> dtype[uintc]: ... + def __new__(cls, dtype: _UIntCCodes | type[ct.c_uint], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[uintc]: ... # NOTE: We're assuming here that `uint_ptr_t == size_t`, # an assumption that does not hold in rare cases (same for `ssize_t`) @overload - def __new__(cls, dtype: _UIntPCodes | type[ct.c_void_p] | type[ct.c_size_t], align: bool = ..., copy: bool = ...) -> dtype[uintp]: ... + def __new__(cls, dtype: _UIntPCodes | type[ct.c_void_p] | type[ct.c_size_t], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[uintp]: ... @overload - def __new__(cls, dtype: _UIntCodes | type[ct.c_ulong], align: bool = ..., copy: bool = ...) -> dtype[uint]: ... + def __new__(cls, dtype: _UIntCodes | type[ct.c_ulong], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[uint]: ... @overload - def __new__(cls, dtype: _ULongLongCodes | type[ct.c_ulonglong], align: bool = ..., copy: bool = ...) -> dtype[ulonglong]: ... + def __new__(cls, dtype: _ULongLongCodes | type[ct.c_ulonglong], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[ulonglong]: ... # `signedinteger` string-based representations and ctypes @overload - def __new__(cls, dtype: _Int8Codes | type[ct.c_int8], align: bool = ..., copy: bool = ...) -> dtype[int8]: ... + def __new__(cls, dtype: _Int8Codes | type[ct.c_int8], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[int8]: ... @overload - def __new__(cls, dtype: _Int16Codes | type[ct.c_int16], align: bool = ..., copy: bool = ...) -> dtype[int16]: ... + def __new__(cls, dtype: _Int16Codes | type[ct.c_int16], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[int16]: ... @overload - def __new__(cls, dtype: _Int32Codes | type[ct.c_int32], align: bool = ..., copy: bool = ...) -> dtype[int32]: ... + def __new__(cls, dtype: _Int32Codes | type[ct.c_int32], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[int32]: ... @overload - def __new__(cls, dtype: _Int64Codes | type[ct.c_int64], align: bool = ..., copy: bool = ...) -> dtype[int64]: ... + def __new__(cls, dtype: _Int64Codes | type[ct.c_int64], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[int64]: ... @overload - def __new__(cls, dtype: _ByteCodes | type[ct.c_byte], align: bool = ..., copy: bool = ...) -> dtype[byte]: ... + def __new__(cls, dtype: _ByteCodes | type[ct.c_byte], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[byte]: ... @overload - def __new__(cls, dtype: _ShortCodes | type[ct.c_short], align: bool = ..., copy: bool = ...) -> dtype[short]: ... + def __new__(cls, dtype: _ShortCodes | type[ct.c_short], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[short]: ... @overload - def __new__(cls, dtype: _IntCCodes | type[ct.c_int], align: bool = ..., copy: bool = ...) -> dtype[intc]: ... + def __new__(cls, dtype: _IntCCodes | type[ct.c_int], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[intc]: ... @overload - def __new__(cls, dtype: _IntPCodes | type[ct.c_ssize_t], align: bool = ..., copy: bool = ...) -> dtype[intp]: ... + def __new__(cls, dtype: _IntPCodes | type[ct.c_ssize_t], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[intp]: ... @overload - def __new__(cls, dtype: _IntCodes | type[ct.c_long], align: bool = ..., copy: bool = ...) -> dtype[int_]: ... + def __new__(cls, dtype: _IntCodes | type[ct.c_long], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[int_]: ... @overload - def __new__(cls, dtype: _LongLongCodes | type[ct.c_longlong], align: bool = ..., copy: bool = ...) -> dtype[longlong]: ... + def __new__(cls, dtype: _LongLongCodes | type[ct.c_longlong], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[longlong]: ... # `floating` string-based representations and ctypes @overload - def __new__(cls, dtype: _Float16Codes, align: bool = ..., copy: bool = ...) -> dtype[float16]: ... + def __new__(cls, dtype: _Float16Codes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[float16]: ... @overload - def __new__(cls, dtype: _Float32Codes, align: bool = ..., copy: bool = ...) -> dtype[float32]: ... + def __new__(cls, dtype: _Float32Codes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[float32]: ... @overload - def __new__(cls, dtype: _Float64Codes, align: bool = ..., copy: bool = ...) -> dtype[float64]: ... + def __new__(cls, dtype: _Float64Codes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[float64]: ... @overload - def __new__(cls, dtype: _HalfCodes, align: bool = ..., copy: bool = ...) -> dtype[half]: ... + def __new__(cls, dtype: _HalfCodes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[half]: ... @overload - def __new__(cls, dtype: _SingleCodes | type[ct.c_float], align: bool = ..., copy: bool = ...) -> dtype[single]: ... + def __new__(cls, dtype: _SingleCodes | type[ct.c_float], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[single]: ... @overload - def __new__(cls, dtype: _DoubleCodes | type[ct.c_double], align: bool = ..., copy: bool = ...) -> dtype[double]: ... + def __new__(cls, dtype: _DoubleCodes | type[ct.c_double], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[double]: ... @overload - def __new__(cls, dtype: _LongDoubleCodes | type[ct.c_longdouble], align: bool = ..., copy: bool = ...) -> dtype[longdouble]: ... + def __new__(cls, dtype: _LongDoubleCodes | type[ct.c_longdouble], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[longdouble]: ... # `complexfloating` string-based representations @overload - def __new__(cls, dtype: _Complex64Codes, align: bool = ..., copy: bool = ...) -> dtype[complex64]: ... + def __new__(cls, dtype: _Complex64Codes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[complex64]: ... @overload - def __new__(cls, dtype: _Complex128Codes, align: bool = ..., copy: bool = ...) -> dtype[complex128]: ... + def __new__(cls, dtype: _Complex128Codes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[complex128]: ... @overload - def __new__(cls, dtype: _CSingleCodes, align: bool = ..., copy: bool = ...) -> dtype[csingle]: ... + def __new__(cls, dtype: _CSingleCodes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[csingle]: ... @overload - def __new__(cls, dtype: _CDoubleCodes, align: bool = ..., copy: bool = ...) -> dtype[cdouble]: ... + def __new__(cls, dtype: _CDoubleCodes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[cdouble]: ... @overload - def __new__(cls, dtype: _CLongDoubleCodes, align: bool = ..., copy: bool = ...) -> dtype[clongdouble]: ... + def __new__(cls, dtype: _CLongDoubleCodes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[clongdouble]: ... # Miscellaneous string-based representations and ctypes @overload - def __new__(cls, dtype: _BoolCodes | type[ct.c_bool], align: bool = ..., copy: bool = ...) -> dtype[bool_]: ... + def __new__(cls, dtype: _BoolCodes | type[ct.c_bool], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[bool_]: ... @overload - def __new__(cls, dtype: _TD64Codes, align: bool = ..., copy: bool = ...) -> dtype[timedelta64]: ... + def __new__(cls, dtype: _TD64Codes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[timedelta64]: ... @overload - def __new__(cls, dtype: _DT64Codes, align: bool = ..., copy: bool = ...) -> dtype[datetime64]: ... + def __new__(cls, dtype: _DT64Codes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[datetime64]: ... @overload - def __new__(cls, dtype: _StrCodes, align: bool = ..., copy: bool = ...) -> dtype[str_]: ... + def __new__(cls, dtype: _StrCodes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[str_]: ... @overload - def __new__(cls, dtype: _BytesCodes | type[ct.c_char], align: bool = ..., copy: bool = ...) -> dtype[bytes_]: ... + def __new__(cls, dtype: _BytesCodes | type[ct.c_char], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[bytes_]: ... @overload - def __new__(cls, dtype: _VoidCodes, align: bool = ..., copy: bool = ...) -> dtype[void]: ... + def __new__(cls, dtype: _VoidCodes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[void]: ... @overload - def __new__(cls, dtype: _ObjectCodes | type[ct.py_object], align: bool = ..., copy: bool = ...) -> dtype[object_]: ... + def __new__(cls, dtype: _ObjectCodes | type[ct.py_object[Any]], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[object_]: ... # dtype of a dtype is the same dtype @overload @@ -811,6 +812,7 @@ class dtype(Generic[_DTypeScalar_co]): dtype: dtype[_DTypeScalar_co], align: bool = ..., copy: bool = ..., + metadata: dict[builtins.str, Any] = ..., ) -> dtype[_DTypeScalar_co]: ... @overload def __new__( @@ -818,6 +820,7 @@ class dtype(Generic[_DTypeScalar_co]): dtype: _SupportsDType[dtype[_DTypeScalar_co]], align: bool = ..., copy: bool = ..., + metadata: dict[builtins.str, Any] = ..., ) -> dtype[_DTypeScalar_co]: ... # Handle strings that can't be expressed as literals; i.e. s1, s2, ... @overload @@ -826,6 +829,7 @@ class dtype(Generic[_DTypeScalar_co]): dtype: builtins.str, align: bool = ..., copy: bool = ..., + metadata: dict[builtins.str, Any] = ..., ) -> dtype[Any]: ... # Catchall overload for void-likes @overload @@ -834,6 +838,7 @@ class dtype(Generic[_DTypeScalar_co]): dtype: _VoidDTypeLike, align: bool = ..., copy: bool = ..., + metadata: dict[builtins.str, Any] = ..., ) -> dtype[void]: ... # Catchall overload for object-likes @overload @@ -842,6 +847,7 @@ class dtype(Generic[_DTypeScalar_co]): dtype: type[object], align: bool = ..., copy: bool = ..., + metadata: dict[builtins.str, Any] = ..., ) -> dtype[object_]: ... if sys.version_info >= (3, 9): diff --git a/numpy/compat/py3k.py b/numpy/compat/py3k.py index 3d10bb988c2f..6392421c846c 100644 --- a/numpy/compat/py3k.py +++ b/numpy/compat/py3k.py @@ -49,6 +49,17 @@ def asstr(s): def isfileobj(f): return isinstance(f, (io.FileIO, io.BufferedReader, io.BufferedWriter)) +def _isfileobj(f): + if not isinstance(f, (io.FileIO, io.BufferedReader, io.BufferedWriter)): + return False + try: + # BufferedReader/Writer may raise OSError when + # fetching `fileno()` (e.g. when wrapping BytesIO). + f.fileno() + return True + except OSError: + return False + def open_latin1(filename, mode='r'): return open(filename, mode=mode, encoding='iso-8859-1') diff --git a/numpy/compat/tests/test_compat.py b/numpy/compat/tests/test_compat.py index 2b8acbaa0662..644300329268 100644 --- a/numpy/compat/tests/test_compat.py +++ b/numpy/compat/tests/test_compat.py @@ -1,6 +1,7 @@ from os.path import join +from io import BufferedReader, BytesIO -from numpy.compat import isfileobj +from numpy.compat.py3k import isfileobj, _isfileobj from numpy.testing import assert_ from numpy.testing import tempdir @@ -17,3 +18,18 @@ def test_isfileobj(): with open(filename, 'rb') as f: assert_(isfileobj(f)) + +def test__isfileobj(): + with tempdir(prefix="numpy_test_compat_") as folder: + filename = join(folder, 'a.bin') + + with open(filename, 'wb') as f: + assert_(_isfileobj(f)) + + with open(filename, 'ab') as f: + assert_(_isfileobj(f)) + + with open(filename, 'rb') as f: + assert_(_isfileobj(f)) + + assert_(_isfileobj(BufferedReader(BytesIO())) is False) diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py index d75f9ec64ef5..09f47380f77c 100644 --- a/numpy/core/_add_newdocs.py +++ b/numpy/core/_add_newdocs.py @@ -5867,7 +5867,7 @@ add_newdoc('numpy.core.multiarray', 'dtype', """ - dtype(dtype, align=False, copy=False) + dtype(dtype, align=False, copy=False, [metadata]) Create a data type object. @@ -5887,6 +5887,8 @@ copy : bool, optional Make a new copy of the data-type object. If ``False``, the result may just be a reference to a built-in data-type object. + metadata : dict, optional + An optional dictionary with dtype metadata. See also -------- diff --git a/numpy/lib/format.py b/numpy/lib/format.py index 54fd0b0bc936..9a19966eb6a1 100644 --- a/numpy/lib/format.py +++ b/numpy/lib/format.py @@ -165,8 +165,9 @@ import warnings from numpy.lib.utils import safe_eval from numpy.compat import ( - isfileobj, os_fspath, pickle + os_fspath, pickle ) +from numpy.compat.py3k import _isfileobj __all__ = [] @@ -710,7 +711,7 @@ def write_array(fp, array, version=None, allow_pickle=True, pickle_kwargs=None): pickle_kwargs = {} pickle.dump(array, fp, protocol=3, **pickle_kwargs) elif array.flags.f_contiguous and not array.flags.c_contiguous: - if isfileobj(fp): + if _isfileobj(fp): array.T.tofile(fp) else: for chunk in numpy.nditer( @@ -718,7 +719,7 @@ def write_array(fp, array, version=None, allow_pickle=True, pickle_kwargs=None): buffersize=buffersize, order='F'): fp.write(chunk.tobytes('C')) else: - if isfileobj(fp): + if _isfileobj(fp): array.tofile(fp) else: for chunk in numpy.nditer( @@ -796,7 +797,7 @@ def read_array(fp, allow_pickle=False, pickle_kwargs=None, *, "You may need to pass the encoding= option " "to numpy.load" % (err,)) from err else: - if isfileobj(fp): + if _isfileobj(fp): # We can use the fast fromfile() function. array = numpy.fromfile(fp, dtype=dtype, count=count) else: @@ -888,7 +889,7 @@ def open_memmap(filename, mode='r+', dtype=None, shape=None, numpy.memmap """ - if isfileobj(filename): + if _isfileobj(filename): raise ValueError("Filename must be a string or a path-like object." " Memmap cannot use existing file handles.") diff --git a/numpy/ma/core.py b/numpy/ma/core.py index acf1a04441d6..5fb16d0cba69 100644 --- a/numpy/ma/core.py +++ b/numpy/ma/core.py @@ -4656,7 +4656,7 @@ def ravel(self, order='C'): # TODO: We don't actually support K, so use A instead. We could # try to guess this correct by sorting strides or deprecate. if order in "kKaA": - order = "C" if self._data.flags.fnc else "F" + order = "F" if self._data.flags.fnc else "C" r = ndarray.ravel(self._data, order=order).view(type(self)) r._update_from(self) if self._mask is not nomask: diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py index 6c03e0ba23a1..722b3ded4fbe 100644 --- a/numpy/ma/tests/test_core.py +++ b/numpy/ma/tests/test_core.py @@ -3441,6 +3441,8 @@ def test_ravel_order(self, order, data_order): raveled = x.ravel(order) assert (raveled.filled(0) == 0).all() + # NOTE: Can be wrong if arr order is neither C nor F and `order="K"` + assert_array_equal(arr.ravel(order), x.ravel(order)._data) def test_reshape(self): # Tests reshape diff --git a/numpy/typing/tests/data/reveal/dtype.pyi b/numpy/typing/tests/data/reveal/dtype.pyi index 7a658511a019..ce6b803d6830 100644 --- a/numpy/typing/tests/data/reveal/dtype.pyi +++ b/numpy/typing/tests/data/reveal/dtype.pyi @@ -6,6 +6,7 @@ dtype_V: np.dtype[np.void] dtype_i8: np.dtype[np.int64] reveal_type(np.dtype(np.float64)) # E: dtype[{float64}] +reveal_type(np.dtype(np.float64, metadata={"test": "test"})) # E: dtype[{float64}] reveal_type(np.dtype(np.int64)) # E: dtype[{int64}] # String aliases diff --git a/pavement.py b/pavement.py index a3ff6665c237..43586ebbbfd5 100644 --- a/pavement.py +++ b/pavement.py @@ -38,7 +38,7 @@ #----------------------------------- # Path to the release notes -RELEASE_NOTES = 'doc/source/release/1.24.3-notes.rst' +RELEASE_NOTES = 'doc/source/release/1.24.4-notes.rst' #------------------------------------------------------- diff --git a/tools/wheels/upload_wheels.sh b/tools/wheels/upload_wheels.sh index 6694caf019c5..dd2d44a455b8 100644 --- a/tools/wheels/upload_wheels.sh +++ b/tools/wheels/upload_wheels.sh @@ -38,6 +38,7 @@ upload_wheels() { echo no token set, not uploading else python -m pip install \ + 'urllib3<2.0.0' \ git+https://github.com/Anaconda-Platform/anaconda-client.git@be1e14936a8e947da94d026c990715f0596d7043 # sdists are located under dist folder when built through setup.py if compgen -G "./dist/*.gz"; then