diff --git a/.github/workflows/sdist.yml b/.github/workflows/sdist.yml index 2e1ffe6d0d17e..1a06ea31ccbb8 100644 --- a/.github/workflows/sdist.yml +++ b/.github/workflows/sdist.yml @@ -79,9 +79,9 @@ jobs: run: | case "${{matrix.python-version}}" in 3.8) - pip install numpy==1.19.5 ;; + pip install numpy==1.20.3 ;; 3.9) - pip install numpy==1.19.5 ;; + pip install numpy==1.20.3 ;; 3.10) pip install numpy==1.21.2 ;; esac diff --git a/ci/deps/actions-38-minimum_versions.yaml b/ci/deps/actions-38-minimum_versions.yaml index 3ab27830060b2..89ebabbbc7469 100644 --- a/ci/deps/actions-38-minimum_versions.yaml +++ b/ci/deps/actions-38-minimum_versions.yaml @@ -17,7 +17,7 @@ dependencies: # required dependencies - python-dateutil=2.8.1 - - numpy=1.19.5 + - numpy=1.20.3 - pytz=2020.1 # optional dependencies diff --git a/doc/source/getting_started/install.rst b/doc/source/getting_started/install.rst index 5d9bfd97030b5..605a69b26a646 100644 --- a/doc/source/getting_started/install.rst +++ b/doc/source/getting_started/install.rst @@ -235,7 +235,7 @@ Dependencies ================================================================ ========================== Package Minimum supported version ================================================================ ========================== -`NumPy `__ 1.19.5 +`NumPy `__ 1.20.3 `python-dateutil `__ 2.8.1 `pytz `__ 2020.1 ================================================================ ========================== diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 4674f28744f7e..1572fdebe2643 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -416,7 +416,7 @@ If installed, we now require: +-----------------+-----------------+----------+---------+ | Package | Minimum Version | Required | Changed | +=================+=================+==========+=========+ -| numpy | 1.19.5 | X | X | +| numpy | 1.20.3 | X | X | +-----------------+-----------------+----------+---------+ | mypy (dev) | 0.971 | | X | +-----------------+-----------------+----------+---------+ diff --git a/pandas/compat/__init__.py b/pandas/compat/__init__.py index 147134afd70c3..91d05ea66402b 100644 --- a/pandas/compat/__init__.py +++ b/pandas/compat/__init__.py @@ -17,7 +17,7 @@ from pandas._typing import F from pandas.compat.numpy import ( is_numpy_dev, - np_version_under1p20, + np_version_under1p21, ) from pandas.compat.pyarrow import ( pa_version_under1p01, @@ -152,7 +152,7 @@ def get_lzma_file() -> type[lzma.LZMAFile]: __all__ = [ "is_numpy_dev", - "np_version_under1p20", + "np_version_under1p21", "pa_version_under1p01", "pa_version_under2p0", "pa_version_under3p0", diff --git a/pandas/compat/numpy/__init__.py b/pandas/compat/numpy/__init__.py index 803f495b311b9..60ec74553a207 100644 --- a/pandas/compat/numpy/__init__.py +++ b/pandas/compat/numpy/__init__.py @@ -6,12 +6,11 @@ # numpy versioning _np_version = np.__version__ _nlv = Version(_np_version) -np_version_under1p20 = _nlv < Version("1.20") +np_version_under1p21 = _nlv < Version("1.21") np_version_under1p22 = _nlv < Version("1.22") np_version_gte1p22 = _nlv >= Version("1.22") is_numpy_dev = _nlv.dev is not None -_min_numpy_ver = "1.19.5" -is_numpy_min = _nlv == Version(_min_numpy_ver) +_min_numpy_ver = "1.20.3" if is_numpy_dev or not np_version_under1p22: np_percentile_argname = "method" diff --git a/pandas/core/array_algos/putmask.py b/pandas/core/array_algos/putmask.py index 84160344437b5..17622e78d1b12 100644 --- a/pandas/core/array_algos/putmask.py +++ b/pandas/core/array_algos/putmask.py @@ -12,7 +12,7 @@ ArrayLike, npt, ) -from pandas.compat import np_version_under1p20 +from pandas.compat import np_version_under1p21 from pandas.core.dtypes.cast import infer_dtype_from from pandas.core.dtypes.common import is_list_like @@ -66,7 +66,7 @@ def putmask_without_repeat( mask : np.ndarray[bool] new : Any """ - if np_version_under1p20: + if np_version_under1p21: new = setitem_datetimelike_compat(values, mask.sum(), new) if getattr(new, "ndim", 0) >= 1: @@ -78,7 +78,6 @@ def putmask_without_repeat( shape = np.shape(new) # np.shape compat for if setitem_datetimelike_compat # changed arraylike to list e.g. test_where_dt64_2d - if nlocs == shape[-1]: # GH#30567 # If length of ``new`` is less than the length of ``values``, diff --git a/pandas/tests/arrays/floating/test_construction.py b/pandas/tests/arrays/floating/test_construction.py index ebce80cba237d..2dcd54f443029 100644 --- a/pandas/tests/arrays/floating/test_construction.py +++ b/pandas/tests/arrays/floating/test_construction.py @@ -1,8 +1,6 @@ import numpy as np import pytest -from pandas.compat import np_version_under1p20 - import pandas as pd import pandas._testing as tm from pandas.core.arrays import FloatingArray @@ -54,11 +52,6 @@ def test_floating_array_disallows_float16(): def test_floating_array_disallows_Float16_dtype(request): # GH#44715 - if np_version_under1p20: - # https://github.com/numpy/numpy/issues/20512 - mark = pytest.mark.xfail(reason="numpy does not raise on np.dtype('Float16')") - request.node.add_marker(mark) - with pytest.raises(TypeError, match="data type 'Float16' not understood"): pd.array([1.0, 2.0], dtype="Float16") diff --git a/pandas/tests/arrays/sparse/test_arithmetics.py b/pandas/tests/arrays/sparse/test_arithmetics.py index 9593152735ed6..1a32c995f4afa 100644 --- a/pandas/tests/arrays/sparse/test_arithmetics.py +++ b/pandas/tests/arrays/sparse/test_arithmetics.py @@ -3,11 +3,8 @@ import numpy as np import pytest -from pandas.compat import np_version_under1p20 - import pandas as pd import pandas._testing as tm -from pandas.core import ops from pandas.core.arrays.sparse import ( SparseArray, SparseDtype, @@ -121,19 +118,7 @@ def test_float_scalar( self, kind, mix, all_arithmetic_functions, fill_value, scalar, request ): op = all_arithmetic_functions - - if np_version_under1p20: - if op in [operator.floordiv, ops.rfloordiv]: - if op is operator.floordiv and scalar != 0: - pass - elif op is ops.rfloordiv and scalar == 0: - pass - else: - mark = pytest.mark.xfail(raises=AssertionError, reason="GH#38172") - request.node.add_marker(mark) - values = np.array([np.nan, 1, 2, 0, np.nan, 0, 1, 2, 1, np.nan]) - a = SparseArray(values, kind=kind, fill_value=fill_value) self._check_numeric_ops(a, scalar, values, scalar, mix, op) @@ -171,14 +156,6 @@ def test_float_same_index_with_nans( ): # when sp_index are the same op = all_arithmetic_functions - - if ( - np_version_under1p20 - and op is ops.rfloordiv - and not (mix and kind == "block") - ): - mark = pytest.mark.xfail(raises=AssertionError, reason="GH#38172") - request.node.add_marker(mark) values = np.array([np.nan, 1, 2, 0, np.nan, 0, 1, 2, 1, np.nan]) rvalues = np.array([np.nan, 2, 3, 4, np.nan, 0, 1, 3, 2, np.nan]) @@ -353,13 +330,7 @@ def test_bool_array_logical(self, kind, fill_value): def test_mixed_array_float_int(self, kind, mix, all_arithmetic_functions, request): op = all_arithmetic_functions - - if np_version_under1p20 and op in [operator.floordiv, ops.rfloordiv] and mix: - mark = pytest.mark.xfail(raises=AssertionError, reason="GH#38172") - request.node.add_marker(mark) - rdtype = "int64" - values = np.array([np.nan, 1, 2, 0, np.nan, 0, 1, 2, 1, np.nan]) rvalues = np.array([2, 0, 2, 3, 0, 0, 1, 5, 2, 0], dtype=rdtype) diff --git a/pandas/tests/extension/base/casting.py b/pandas/tests/extension/base/casting.py index 4987751f31dac..0eb8123e6bdb8 100644 --- a/pandas/tests/extension/base/casting.py +++ b/pandas/tests/extension/base/casting.py @@ -1,7 +1,7 @@ import numpy as np import pytest -from pandas.compat import np_version_under1p20 +from pandas.compat import np_version_under1p21 import pandas.util._test_decorators as td import pandas as pd @@ -32,8 +32,7 @@ def test_astype_object_frame(self, all_data): assert result._mgr.arrays[0].dtype == np.dtype(object) # earlier numpy raises TypeError on e.g. np.dtype(np.int64) == "Int64" - # instead of returning False - if not np_version_under1p20: + if not np_version_under1p21: # check that we can compare the dtypes comp = result.dtypes == df.dtypes assert not comp.any() diff --git a/pandas/tests/extension/test_sparse.py b/pandas/tests/extension/test_sparse.py index d13f6dab1cc9b..60eef0d8097e4 100644 --- a/pandas/tests/extension/test_sparse.py +++ b/pandas/tests/extension/test_sparse.py @@ -17,7 +17,6 @@ import numpy as np import pytest -from pandas.compat import np_version_under1p20 from pandas.errors import PerformanceWarning from pandas.core.dtypes.common import is_object_dtype @@ -415,12 +414,9 @@ def test_astype_object_frame(self, all_data): result = df.astype(object) assert is_object_dtype(result._mgr.arrays[0].dtype) - # earlier numpy raises TypeError on e.g. np.dtype(np.int64) == "Int64" - # instead of returning False - if not np_version_under1p20: - # check that we can compare the dtypes - comp = result.dtypes == df.dtypes - assert not comp.any() + # check that we can compare the dtypes + comp = result.dtypes == df.dtypes + assert not comp.any() def test_astype_str(self, data): with tm.assert_produces_warning(FutureWarning, match="astype from Sparse"): diff --git a/pandas/tests/frame/indexing/test_where.py b/pandas/tests/frame/indexing/test_where.py index 5b9883f3866e7..aa55a7c91d0e6 100644 --- a/pandas/tests/frame/indexing/test_where.py +++ b/pandas/tests/frame/indexing/test_where.py @@ -4,8 +4,6 @@ import numpy as np import pytest -from pandas.compat import np_version_under1p20 - from pandas.core.dtypes.common import is_scalar import pandas as pd @@ -1006,7 +1004,6 @@ def _check_where_equivalences(df, mask, other, expected): tm.assert_frame_equal(df, expected) -@pytest.mark.xfail(np_version_under1p20, reason="failed on Numpy 1.19.5") def test_where_dt64_2d(): dti = date_range("2016-01-01", periods=6) dta = dti._data.reshape(3, 2) diff --git a/pandas/tests/frame/methods/test_quantile.py b/pandas/tests/frame/methods/test_quantile.py index 798212f957e3c..16b82727fd069 100644 --- a/pandas/tests/frame/methods/test_quantile.py +++ b/pandas/tests/frame/methods/test_quantile.py @@ -1,7 +1,10 @@ import numpy as np import pytest -from pandas.compat.numpy import np_percentile_argname +from pandas.compat.numpy import ( + np_percentile_argname, + np_version_under1p21, +) import pandas as pd from pandas import ( @@ -655,7 +658,7 @@ def compute_quantile(self, obj, qs): result = obj.quantile(qs, numeric_only=False) return result - def test_quantile_ea(self, obj, index): + def test_quantile_ea(self, request, obj, index): # result should be invariant to shuffling indexer = np.arange(len(index), dtype=np.intp) @@ -665,6 +668,11 @@ def test_quantile_ea(self, obj, index): qs = [0.5, 0, 1] result = self.compute_quantile(obj, qs) + if np_version_under1p21 and index.dtype == "timedelta64[ns]": + msg = "failed on Numpy 1.20.3; TypeError: data type 'Int64' not understood" + mark = pytest.mark.xfail(reason=msg, raises=TypeError) + request.node.add_marker(mark) + exp_dtype = index.dtype if index.dtype == "Int64": # match non-nullable casting behavior @@ -700,7 +708,7 @@ def test_quantile_ea_with_na(self, obj, index): # TODO(GH#39763): filtering can be removed after GH#39763 is fixed @pytest.mark.filterwarnings("ignore:Using .astype to convert:FutureWarning") - def test_quantile_ea_all_na(self, obj, index): + def test_quantile_ea_all_na(self, request, obj, index): obj.iloc[:] = index._na_value # TODO(ArrayManager): this casting should be unnecessary after GH#39763 is fixed @@ -715,6 +723,11 @@ def test_quantile_ea_all_na(self, obj, index): qs = [0.5, 0, 1] result = self.compute_quantile(obj, qs) + if np_version_under1p21 and index.dtype == "timedelta64[ns]": + msg = "failed on Numpy 1.20.3; TypeError: data type 'Int64' not understood" + mark = pytest.mark.xfail(reason=msg, raises=TypeError) + request.node.add_marker(mark) + expected = index.take([-1, -1, -1], allow_fill=True, fill_value=index._na_value) expected = Series(expected, index=qs, name="A") if expected.dtype == "Int64": @@ -722,7 +735,7 @@ def test_quantile_ea_all_na(self, obj, index): expected = type(obj)(expected) tm.assert_equal(result, expected) - def test_quantile_ea_scalar(self, obj, index): + def test_quantile_ea_scalar(self, request, obj, index): # scalar qs # result should be invariant to shuffling @@ -733,6 +746,11 @@ def test_quantile_ea_scalar(self, obj, index): qs = 0.5 result = self.compute_quantile(obj, qs) + if np_version_under1p21 and index.dtype == "timedelta64[ns]": + msg = "failed on Numpy 1.20.3; TypeError: data type 'Int64' not understood" + mark = pytest.mark.xfail(reason=msg, raises=TypeError) + request.node.add_marker(mark) + exp_dtype = index.dtype if index.dtype == "Int64": exp_dtype = "Float64" diff --git a/pandas/tests/frame/methods/test_replace.py b/pandas/tests/frame/methods/test_replace.py index f7504e9173bf5..555d24e747f44 100644 --- a/pandas/tests/frame/methods/test_replace.py +++ b/pandas/tests/frame/methods/test_replace.py @@ -6,8 +6,6 @@ import numpy as np import pytest -from pandas.compat import np_version_under1p20 - import pandas as pd from pandas import ( DataFrame, @@ -1316,12 +1314,6 @@ def test_replace_commutative(self, df, to_replace, exp): ) def test_replace_replacer_dtype(self, request, replacer): # GH26632 - if np.isscalar(replacer) and replacer.dtype.itemsize < 8: - request.node.add_marker( - pytest.mark.xfail( - np_version_under1p20, reason="np.putmask doesn't coerce dtype" - ) - ) df = DataFrame(["a"]) result = df.replace({"a": replacer, "b": replacer}) expected = DataFrame([replacer]) diff --git a/pandas/tests/indexing/test_iloc.py b/pandas/tests/indexing/test_iloc.py index 2a116c992231b..fdf741040407f 100644 --- a/pandas/tests/indexing/test_iloc.py +++ b/pandas/tests/indexing/test_iloc.py @@ -10,7 +10,6 @@ import numpy as np import pytest -from pandas.compat.numpy import is_numpy_min from pandas.errors import IndexingError import pandas.util._test_decorators as td @@ -1199,7 +1198,6 @@ def test_iloc_getitem_int_single_ea_block_view(self): arr[2] = arr[-1] assert ser[0] == arr[-1] - @pytest.mark.xfail(is_numpy_min, reason="Column A gets coerced to integer type") def test_iloc_setitem_multicolumn_to_datetime(self, using_array_manager): # GH#20511 diff --git a/pandas/tests/series/test_constructors.py b/pandas/tests/series/test_constructors.py index de9a682acdfd6..fc17f0b942d09 100644 --- a/pandas/tests/series/test_constructors.py +++ b/pandas/tests/series/test_constructors.py @@ -13,7 +13,6 @@ iNaT, lib, ) -from pandas.compat.numpy import np_version_under1p20 import pandas.util._test_decorators as td from pandas.core.dtypes.common import ( @@ -1904,9 +1903,6 @@ def test_constructor_dtype_timedelta_ns_s_astype_int64(self): @pytest.mark.filterwarnings( "ignore:elementwise comparison failed:DeprecationWarning" ) - @pytest.mark.xfail( - np_version_under1p20, reason="np.array([td64nat, float, float]) raises" - ) @pytest.mark.parametrize("func", [Series, DataFrame, Index, pd.array]) def test_constructor_mismatched_null_nullable_dtype( self, func, any_numeric_ea_dtype diff --git a/setup.cfg b/setup.cfg index b191930acf4c5..8f7cfc288ecdb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -31,9 +31,7 @@ project_urls = [options] packages = find: install_requires = - numpy>=1.18.5; platform_machine!='aarch64' and platform_machine!='arm64' and python_version<'3.10' - numpy>=1.19.2; platform_machine=='aarch64' and python_version<'3.10' - numpy>=1.20.0; platform_machine=='arm64' and python_version<'3.10' + numpy>=1.20.3; python_version<'3.10' numpy>=1.21.0; python_version>='3.10' python-dateutil>=2.8.1 pytz>=2020.1