forked from pool/python-pandas
		
	Compare commits
	
		
			21 Commits
		
	
	
		
	
	| Author | SHA256 | Date | |
|---|---|---|---|
| 93ae2a2ae1 | |||
| 1f436a5c27 | |||
| 1ff82036d2 | |||
| 2d224fe122 | |||
| 31ec40e067 | |||
| fd609b4228 | |||
| 2f1646e94b | |||
| 70eb931282 | |||
| da91e54acb | |||
| 2798c7a559 | |||
| fa780a9d09 | |||
| b2102469f7 | |||
| 4aba75120f | |||
| 1ba1eb643a | |||
| 2daa1866d4 | |||
| 0f67c70d37 | |||
| c95de0adff | |||
| 65565ef45c | |||
| 1913e4ed18 | |||
| c7c075db10 | |||
| b9debc1c19 | 
| @@ -2,4 +2,5 @@ | |||||||
|   <package>test-py310</package> |   <package>test-py310</package> | ||||||
|   <package>test-py311</package> |   <package>test-py311</package> | ||||||
|   <package>test-py312</package> |   <package>test-py312</package> | ||||||
|  |   <package>test-py313</package> | ||||||
| </multibuild> | </multibuild> | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								_service
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								_service
									
									
									
									
									
								
							| @@ -1,16 +1,16 @@ | |||||||
| <services> | <services> | ||||||
|   <service name="tar_scm" mode="disabled"> |   <service name="tar_scm" mode="manual"> | ||||||
|     <param name="url">https://github.com/pandas-dev/pandas.git</param> |     <param name="url">https://github.com/pandas-dev/pandas.git</param> | ||||||
|     <param name="scm">git</param> |     <param name="scm">git</param> | ||||||
|     <param name="revision">v2.2.2</param> |     <param name="revision">v2.3.2</param> | ||||||
|     <param name="versionformat">@PARENT_TAG@</param> |     <param name="versionformat">@PARENT_TAG@</param> | ||||||
|     <param name="versionrewrite-pattern">v(.*)</param> |     <param name="versionrewrite-pattern">v(.*)</param> | ||||||
|     <param name="filename">pandas</param> |     <param name="filename">pandas</param> | ||||||
|     <param name="package-meta">yes</param> |     <param name="package-meta">yes</param> | ||||||
|   </service> |   </service> | ||||||
|   <service name="recompress" mode="disabled"> |   <service name="recompress" mode="manual"> | ||||||
|     <param name="file">*.tar</param> |     <param name="file">*.tar</param> | ||||||
|     <param name="compression">gz</param> |     <param name="compression">gz</param> | ||||||
|   </service> |   </service> | ||||||
|   <service name="set_version" mode="disabled" /> |   <service name="set_version" mode="manual" /> | ||||||
| </services> | </services> | ||||||
|   | |||||||
| @@ -1,3 +0,0 @@ | |||||||
| version https://git-lfs.github.com/spec/v1 |  | ||||||
| oid sha256:8f044538e419c7d5c03434c96b1439cbd88701dcd02d6a79b08947fbb656c2f4 |  | ||||||
| size 50782448 |  | ||||||
							
								
								
									
										3
									
								
								pandas-2.3.2.tar.gz
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								pandas-2.3.2.tar.gz
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:cd1680a92a849ea183199f53098f0a9cc0083a2893ef31c597defdd4a10bd7d8 | ||||||
|  | size 406331098 | ||||||
| @@ -1,40 +0,0 @@ | |||||||
| From 1828b62ee913da44ec4402642ef7baaafeb65677 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com> |  | ||||||
| Date: Mon, 15 Apr 2024 09:47:31 -1000 |  | ||||||
| Subject: [PATCH] Backport PR #58268: CI/TST: Unxfail |  | ||||||
|  test_slice_locs_negative_step Pyarrow test |  | ||||||
|  |  | ||||||
| --- |  | ||||||
|  pandas/tests/indexes/object/test_indexing.py | 12 +----------- |  | ||||||
|  1 file changed, 1 insertion(+), 11 deletions(-) |  | ||||||
|  |  | ||||||
| diff --git a/pandas/tests/indexes/object/test_indexing.py b/pandas/tests/indexes/object/test_indexing.py |  | ||||||
| index 443cacf94d239..ebf9dac715f8d 100644 |  | ||||||
| --- a/pandas/tests/indexes/object/test_indexing.py |  | ||||||
| +++ b/pandas/tests/indexes/object/test_indexing.py |  | ||||||
| @@ -7,7 +7,6 @@ |  | ||||||
|      NA, |  | ||||||
|      is_matching_na, |  | ||||||
|  ) |  | ||||||
| -from pandas.compat import pa_version_under16p0 |  | ||||||
|  import pandas.util._test_decorators as td |  | ||||||
|   |  | ||||||
|  import pandas as pd |  | ||||||
| @@ -201,16 +200,7 @@ class TestSliceLocs: |  | ||||||
|              (pd.IndexSlice["m":"m":-1], ""),  # type: ignore[misc] |  | ||||||
|          ], |  | ||||||
|      ) |  | ||||||
| -    def test_slice_locs_negative_step(self, in_slice, expected, dtype, request): |  | ||||||
| -        if ( |  | ||||||
| -            not pa_version_under16p0 |  | ||||||
| -            and dtype == "string[pyarrow_numpy]" |  | ||||||
| -            and in_slice == slice("a", "a", -1) |  | ||||||
| -        ): |  | ||||||
| -            request.applymarker( |  | ||||||
| -                pytest.mark.xfail(reason="https://github.com/apache/arrow/issues/40642") |  | ||||||
| -            ) |  | ||||||
| - |  | ||||||
| +    def test_slice_locs_negative_step(self, in_slice, expected, dtype): |  | ||||||
|          index = Index(list("bcdxy"), dtype=dtype) |  | ||||||
|   |  | ||||||
|          s_start, s_stop = index.slice_locs(in_slice.start, in_slice.stop, in_slice.step) |  | ||||||
| @@ -1,71 +0,0 @@ | |||||||
| From 0cab756077f5291f8d6a7fcfacaf374f62b866a0 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Elliott Sales de Andrade <quantum.analyst@gmail.com> |  | ||||||
| Date: Mon, 29 Apr 2024 23:11:21 -0400 |  | ||||||
| Subject: [PATCH 1/2] Remove deprecated plot_date calls |  | ||||||
|  |  | ||||||
| These were deprecated in Matplotlib 3.9. |  | ||||||
| --- |  | ||||||
|  pandas/tests/plotting/test_datetimelike.py | 10 ++++------ |  | ||||||
|  1 file changed, 4 insertions(+), 6 deletions(-) |  | ||||||
|  |  | ||||||
| diff --git a/pandas/tests/plotting/test_datetimelike.py b/pandas/tests/plotting/test_datetimelike.py |  | ||||||
| index 6b709522bab70..b91bde41bf4c4 100644 |  | ||||||
| --- a/pandas/tests/plotting/test_datetimelike.py |  | ||||||
| +++ b/pandas/tests/plotting/test_datetimelike.py |  | ||||||
| @@ -1432,13 +1432,11 @@ def test_mpl_nopandas(self): |  | ||||||
|          values1 = np.arange(10.0, 11.0, 0.5) |  | ||||||
|          values2 = np.arange(11.0, 12.0, 0.5) |  | ||||||
|   |  | ||||||
| -        kw = {"fmt": "-", "lw": 4} |  | ||||||
| - |  | ||||||
|          _, ax = mpl.pyplot.subplots() |  | ||||||
| -        ax.plot_date([x.toordinal() for x in dates], values1, **kw) |  | ||||||
| -        ax.plot_date([x.toordinal() for x in dates], values2, **kw) |  | ||||||
| - |  | ||||||
| -        line1, line2 = ax.get_lines() |  | ||||||
| +        line1, line2, = ax.plot( |  | ||||||
| +            [x.toordinal() for x in dates], values1, "-", |  | ||||||
| +            [x.toordinal() for x in dates], values2, "-", |  | ||||||
| +            linewidth=4) |  | ||||||
|   |  | ||||||
|          exp = np.array([x.toordinal() for x in dates], dtype=np.float64) |  | ||||||
|          tm.assert_numpy_array_equal(line1.get_xydata()[:, 0], exp) |  | ||||||
|  |  | ||||||
| From 6d6574c4e71e3bab91503f85c8aa80c927785865 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: "pre-commit-ci[bot]" |  | ||||||
|  <66853113+pre-commit-ci[bot]@users.noreply.github.com> |  | ||||||
| Date: Tue, 30 Apr 2024 16:47:26 +0000 |  | ||||||
| Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks |  | ||||||
|  |  | ||||||
| for more information, see https://pre-commit.ci |  | ||||||
| --- |  | ||||||
|  pandas/tests/plotting/test_datetimelike.py | 16 ++++++++++++---- |  | ||||||
|  1 file changed, 12 insertions(+), 4 deletions(-) |  | ||||||
|  |  | ||||||
| diff --git a/pandas/tests/plotting/test_datetimelike.py b/pandas/tests/plotting/test_datetimelike.py |  | ||||||
| index b91bde41bf4c4..4b4eeada58366 100644 |  | ||||||
| --- a/pandas/tests/plotting/test_datetimelike.py |  | ||||||
| +++ b/pandas/tests/plotting/test_datetimelike.py |  | ||||||
| @@ -1433,10 +1433,18 @@ def test_mpl_nopandas(self): |  | ||||||
|          values2 = np.arange(11.0, 12.0, 0.5) |  | ||||||
|   |  | ||||||
|          _, ax = mpl.pyplot.subplots() |  | ||||||
| -        line1, line2, = ax.plot( |  | ||||||
| -            [x.toordinal() for x in dates], values1, "-", |  | ||||||
| -            [x.toordinal() for x in dates], values2, "-", |  | ||||||
| -            linewidth=4) |  | ||||||
| +        ( |  | ||||||
| +            line1, |  | ||||||
| +            line2, |  | ||||||
| +        ) = ax.plot( |  | ||||||
| +            [x.toordinal() for x in dates], |  | ||||||
| +            values1, |  | ||||||
| +            "-", |  | ||||||
| +            [x.toordinal() for x in dates], |  | ||||||
| +            values2, |  | ||||||
| +            "-", |  | ||||||
| +            linewidth=4, |  | ||||||
| +        ) |  | ||||||
|   |  | ||||||
|          exp = np.array([x.toordinal() for x in dates], dtype=np.float64) |  | ||||||
|          tm.assert_numpy_array_equal(line1.get_xydata()[:, 0], exp) |  | ||||||
| @@ -1,29 +0,0 @@ | |||||||
| From d4e803caf7aabd464f6fb1d43ef39903911a3cec Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com> |  | ||||||
| Date: Wed, 3 Jul 2024 06:45:24 -1000 |  | ||||||
| Subject: [PATCH] Backport PR #59168: TST: Address UserWarning in matplotlib |  | ||||||
|  test |  | ||||||
|  |  | ||||||
| --- |  | ||||||
|  pandas/plotting/_matplotlib/core.py | 8 +++++++- |  | ||||||
|  1 file changed, 7 insertions(+), 1 deletion(-) |  | ||||||
|  |  | ||||||
| diff --git a/pandas/plotting/_matplotlib/core.py b/pandas/plotting/_matplotlib/core.py |  | ||||||
| index 2979903edf360..52382d9f7d572 100644 |  | ||||||
| --- a/pandas/plotting/_matplotlib/core.py |  | ||||||
| +++ b/pandas/plotting/_matplotlib/core.py |  | ||||||
| @@ -893,7 +893,13 @@ def _make_legend(self) -> None: |  | ||||||
|          elif self.subplots and self.legend: |  | ||||||
|              for ax in self.axes: |  | ||||||
|                  if ax.get_visible(): |  | ||||||
| -                    ax.legend(loc="best") |  | ||||||
| +                    with warnings.catch_warnings(): |  | ||||||
| +                        warnings.filterwarnings( |  | ||||||
| +                            "ignore", |  | ||||||
| +                            "No artists with labels found to put in legend.", |  | ||||||
| +                            UserWarning, |  | ||||||
| +                        ) |  | ||||||
| +                        ax.legend(loc="best") |  | ||||||
|   |  | ||||||
|      @final |  | ||||||
|      @staticmethod |  | ||||||
| @@ -1,174 +0,0 @@ | |||||||
| diff --git a/pandas/_testing/__init__.py b/pandas/_testing/__init__.py |  | ||||||
| index 361998db8e..87d419e2db 100644 |  | ||||||
| --- a/pandas/_testing/__init__.py |  | ||||||
| +++ b/pandas/_testing/__init__.py |  | ||||||
| @@ -111,6 +111,7 @@ ALL_FLOAT_DTYPES: list[Dtype] = [*FLOAT_NUMPY_DTYPES, *FLOAT_EA_DTYPES] |  | ||||||
|   |  | ||||||
|  COMPLEX_DTYPES: list[Dtype] = [complex, "complex64", "complex128"] |  | ||||||
|  STRING_DTYPES: list[Dtype] = [str, "str", "U"] |  | ||||||
| +COMPLEX_FLOAT_DTYPES: list[Dtype] = [*COMPLEX_DTYPES, *FLOAT_NUMPY_DTYPES] |  | ||||||
|   |  | ||||||
|  DATETIME64_DTYPES: list[Dtype] = ["datetime64[ns]", "M8[ns]"] |  | ||||||
|  TIMEDELTA64_DTYPES: list[Dtype] = ["timedelta64[ns]", "m8[ns]"] |  | ||||||
| diff --git a/pandas/conftest.py b/pandas/conftest.py |  | ||||||
| index 7c35dfdde9..10134c90f8 100644 |  | ||||||
| --- a/pandas/conftest.py |  | ||||||
| +++ b/pandas/conftest.py |  | ||||||
| @@ -1403,6 +1403,21 @@ def complex_dtype(request): |  | ||||||
|      return request.param |  | ||||||
|   |  | ||||||
|   |  | ||||||
| +@pytest.fixture(params=tm.COMPLEX_FLOAT_DTYPES) |  | ||||||
| +def complex_or_float_dtype(request): |  | ||||||
| +    """ |  | ||||||
| +    Parameterized fixture for complex and numpy float dtypes. |  | ||||||
| + |  | ||||||
| +    * complex |  | ||||||
| +    * 'complex64' |  | ||||||
| +    * 'complex128' |  | ||||||
| +    * float |  | ||||||
| +    * 'float32' |  | ||||||
| +    * 'float64' |  | ||||||
| +    """ |  | ||||||
| +    return request.param |  | ||||||
| + |  | ||||||
| + |  | ||||||
|  @pytest.fixture(params=tm.SIGNED_INT_NUMPY_DTYPES) |  | ||||||
|  def any_signed_int_numpy_dtype(request): |  | ||||||
|      """ |  | ||||||
| diff --git a/pandas/core/computation/expr.py b/pandas/core/computation/expr.py |  | ||||||
| index b5861fbaeb..d642c37cea 100644 |  | ||||||
| --- a/pandas/core/computation/expr.py |  | ||||||
| +++ b/pandas/core/computation/expr.py |  | ||||||
| @@ -31,7 +31,6 @@ from pandas.core.computation.ops import ( |  | ||||||
|      UNARY_OPS_SYMS, |  | ||||||
|      BinOp, |  | ||||||
|      Constant, |  | ||||||
| -    Div, |  | ||||||
|      FuncNode, |  | ||||||
|      Op, |  | ||||||
|      Term, |  | ||||||
| @@ -370,7 +369,7 @@ class BaseExprVisitor(ast.NodeVisitor): |  | ||||||
|          "Add", |  | ||||||
|          "Sub", |  | ||||||
|          "Mult", |  | ||||||
| -        None, |  | ||||||
| +        "Div", |  | ||||||
|          "Pow", |  | ||||||
|          "FloorDiv", |  | ||||||
|          "Mod", |  | ||||||
| @@ -533,9 +532,6 @@ class BaseExprVisitor(ast.NodeVisitor): |  | ||||||
|          left, right = self._maybe_downcast_constants(left, right) |  | ||||||
|          return self._maybe_evaluate_binop(op, op_class, left, right) |  | ||||||
|   |  | ||||||
| -    def visit_Div(self, node, **kwargs): |  | ||||||
| -        return lambda lhs, rhs: Div(lhs, rhs) |  | ||||||
| - |  | ||||||
|      def visit_UnaryOp(self, node, **kwargs): |  | ||||||
|          op = self.visit(node.op) |  | ||||||
|          operand = self.visit(node.operand) |  | ||||||
| diff --git a/pandas/core/computation/ops.py b/pandas/core/computation/ops.py |  | ||||||
| index 95ac20ba39..ea8b1c0457 100644 |  | ||||||
| --- a/pandas/core/computation/ops.py |  | ||||||
| +++ b/pandas/core/computation/ops.py |  | ||||||
| @@ -332,31 +332,6 @@ for d in (_cmp_ops_dict, _bool_ops_dict, _arith_ops_dict): |  | ||||||
|      _binary_ops_dict.update(d) |  | ||||||
|   |  | ||||||
|   |  | ||||||
| -def _cast_inplace(terms, acceptable_dtypes, dtype) -> None: |  | ||||||
| -    """ |  | ||||||
| -    Cast an expression inplace. |  | ||||||
| - |  | ||||||
| -    Parameters |  | ||||||
| -    ---------- |  | ||||||
| -    terms : Op |  | ||||||
| -        The expression that should cast. |  | ||||||
| -    acceptable_dtypes : list of acceptable numpy.dtype |  | ||||||
| -        Will not cast if term's dtype in this list. |  | ||||||
| -    dtype : str or numpy.dtype |  | ||||||
| -        The dtype to cast to. |  | ||||||
| -    """ |  | ||||||
| -    dt = np.dtype(dtype) |  | ||||||
| -    for term in terms: |  | ||||||
| -        if term.type in acceptable_dtypes: |  | ||||||
| -            continue |  | ||||||
| - |  | ||||||
| -        try: |  | ||||||
| -            new_value = term.value.astype(dt) |  | ||||||
| -        except AttributeError: |  | ||||||
| -            new_value = dt.type(term.value) |  | ||||||
| -        term.update(new_value) |  | ||||||
| - |  | ||||||
| - |  | ||||||
|  def is_term(obj) -> bool: |  | ||||||
|      return isinstance(obj, Term) |  | ||||||
|   |  | ||||||
| @@ -516,31 +491,6 @@ class BinOp(Op): |  | ||||||
|  def isnumeric(dtype) -> bool: |  | ||||||
|      return issubclass(np.dtype(dtype).type, np.number) |  | ||||||
|   |  | ||||||
| - |  | ||||||
| -class Div(BinOp): |  | ||||||
| -    """ |  | ||||||
| -    Div operator to special case casting. |  | ||||||
| - |  | ||||||
| -    Parameters |  | ||||||
| -    ---------- |  | ||||||
| -    lhs, rhs : Term or Op |  | ||||||
| -        The Terms or Ops in the ``/`` expression. |  | ||||||
| -    """ |  | ||||||
| - |  | ||||||
| -    def __init__(self, lhs, rhs) -> None: |  | ||||||
| -        super().__init__("/", lhs, rhs) |  | ||||||
| - |  | ||||||
| -        if not isnumeric(lhs.return_type) or not isnumeric(rhs.return_type): |  | ||||||
| -            raise TypeError( |  | ||||||
| -                f"unsupported operand type(s) for {self.op}: " |  | ||||||
| -                f"'{lhs.return_type}' and '{rhs.return_type}'" |  | ||||||
| -            ) |  | ||||||
| - |  | ||||||
| -        # do not upcast float32s to float64 un-necessarily |  | ||||||
| -        acceptable_dtypes = [np.float32, np.float64] |  | ||||||
| -        _cast_inplace(com.flatten(self), acceptable_dtypes, np.float64) |  | ||||||
| - |  | ||||||
| - |  | ||||||
|  UNARY_OPS_SYMS = ("+", "-", "~", "not") |  | ||||||
|  _unary_ops_funcs = (operator.pos, operator.neg, operator.invert, operator.invert) |  | ||||||
|  _unary_ops_dict = dict(zip(UNARY_OPS_SYMS, _unary_ops_funcs)) |  | ||||||
| diff --git a/pandas/tests/computation/test_eval.py b/pandas/tests/computation/test_eval.py |  | ||||||
| index 17630f14b0..e8fad6b8cb 100644 |  | ||||||
| --- a/pandas/tests/computation/test_eval.py |  | ||||||
| +++ b/pandas/tests/computation/test_eval.py |  | ||||||
| @@ -747,16 +747,26 @@ class TestTypeCasting: |  | ||||||
|      @pytest.mark.parametrize("op", ["+", "-", "*", "**", "/"]) |  | ||||||
|      # maybe someday... numexpr has too many upcasting rules now |  | ||||||
|      # chain(*(np.core.sctypes[x] for x in ['uint', 'int', 'float'])) |  | ||||||
| -    @pytest.mark.parametrize("dt", [np.float32, np.float64]) |  | ||||||
|      @pytest.mark.parametrize("left_right", [("df", "3"), ("3", "df")]) |  | ||||||
| -    def test_binop_typecasting(self, engine, parser, op, dt, left_right): |  | ||||||
| -        df = DataFrame(np.random.default_rng(2).standard_normal((5, 3)), dtype=dt) |  | ||||||
| +    def test_binop_typecasting( |  | ||||||
| +        self, engine, parser, op, complex_or_float_dtype, left_right, request |  | ||||||
| +    ): |  | ||||||
| +        # GH#21374 |  | ||||||
| +        dtype = complex_or_float_dtype |  | ||||||
| +        df = DataFrame(np.random.default_rng(2).standard_normal((5, 3)), dtype=dtype) |  | ||||||
|          left, right = left_right |  | ||||||
|          s = f"{left} {op} {right}" |  | ||||||
|          res = pd.eval(s, engine=engine, parser=parser) |  | ||||||
| -        assert df.values.dtype == dt |  | ||||||
| -        assert res.values.dtype == dt |  | ||||||
| -        tm.assert_frame_equal(res, eval(s)) |  | ||||||
| +        if dtype == "complex64" and engine == "numexpr": |  | ||||||
| +            mark = pytest.mark.xfail( |  | ||||||
| +                reason="numexpr issue with complex that are upcast " |  | ||||||
| +                "to complex 128 " |  | ||||||
| +                "https://github.com/pydata/numexpr/issues/492" |  | ||||||
| +            ) |  | ||||||
| +            request.applymarker(mark) |  | ||||||
| +        assert df.values.dtype == dtype |  | ||||||
| +        assert res.values.dtype == dtype |  | ||||||
| +        tm.assert_frame_equal(res, eval(s), check_exact=False) |  | ||||||
|   |  | ||||||
|   |  | ||||||
|  # ------------------------------------- |  | ||||||
							
								
								
									
										316
									
								
								pandas-pr61132-dropna.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										316
									
								
								pandas-pr61132-dropna.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,316 @@ | |||||||
|  | From 1e899afbd9ca20f4ce9d6f93e1f62c072be0ed23 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Gen Sato <52241300+halogen22@users.noreply.github.com> | ||||||
|  | Date: Tue, 18 Mar 2025 01:33:40 +0900 | ||||||
|  | Subject: [PATCH] BUG: .mode(dropna=False) doesn't work with nullable integers | ||||||
|  |  (#61132) | ||||||
|  |  | ||||||
|  | * Fix dropna bug when mode | ||||||
|  |  | ||||||
|  | * Fix test cases | ||||||
|  |  | ||||||
|  | * Fix data type incompatible | ||||||
|  | --- | ||||||
|  |  doc/source/whatsnew/v3.0.0.rst            |  1 + | ||||||
|  |  pandas/_libs/hashtable_func_helper.pxi.in |  2 +- | ||||||
|  |  pandas/core/algorithms.py                 | 12 +++--- | ||||||
|  |  pandas/core/arrays/base.py                |  5 ++- | ||||||
|  |  pandas/core/arrays/categorical.py         |  2 +- | ||||||
|  |  pandas/core/arrays/datetimelike.py        |  2 +- | ||||||
|  |  pandas/core/arrays/masked.py              |  8 +--- | ||||||
|  |  pandas/core/series.py                     |  2 +- | ||||||
|  |  pandas/tests/series/test_reductions.py    | 23 +++++++++++ | ||||||
|  |  pandas/tests/test_algos.py                | 47 +++++++++++++++-------- | ||||||
|  |  10 files changed, 71 insertions(+), 33 deletions(-) | ||||||
|  |  | ||||||
|  | Index: pandas-2.3.1/pandas/_libs/hashtable_func_helper.pxi.in | ||||||
|  | =================================================================== | ||||||
|  | --- pandas-2.3.1.orig/pandas/_libs/hashtable_func_helper.pxi.in | ||||||
|  | +++ pandas-2.3.1/pandas/_libs/hashtable_func_helper.pxi.in | ||||||
|  | @@ -443,7 +443,7 @@ def mode(ndarray[htfunc_t] values, bint | ||||||
|  |   | ||||||
|  |      if na_counter > 0: | ||||||
|  |          res_mask = np.zeros(j+1, dtype=np.bool_) | ||||||
|  | -        res_mask[j] = True | ||||||
|  | +        res_mask[j] = (na_counter == max_count) | ||||||
|  |      return modes[:j + 1], res_mask | ||||||
|  |   | ||||||
|  |   | ||||||
|  | Index: pandas-2.3.1/pandas/core/algorithms.py | ||||||
|  | =================================================================== | ||||||
|  | --- pandas-2.3.1.orig/pandas/core/algorithms.py | ||||||
|  | +++ pandas-2.3.1/pandas/core/algorithms.py | ||||||
|  | @@ -1022,7 +1022,7 @@ def duplicated( | ||||||
|  |   | ||||||
|  |  def mode( | ||||||
|  |      values: ArrayLike, dropna: bool = True, mask: npt.NDArray[np.bool_] | None = None | ||||||
|  | -) -> ArrayLike: | ||||||
|  | +) -> tuple[np.ndarray, npt.NDArray[np.bool_]] | ExtensionArray: | ||||||
|  |      """ | ||||||
|  |      Returns the mode(s) of an array. | ||||||
|  |   | ||||||
|  | @@ -1035,7 +1035,7 @@ def mode( | ||||||
|  |   | ||||||
|  |      Returns | ||||||
|  |      ------- | ||||||
|  | -    np.ndarray or ExtensionArray | ||||||
|  | +    Union[Tuple[np.ndarray, npt.NDArray[np.bool_]], ExtensionArray] | ||||||
|  |      """ | ||||||
|  |      values = _ensure_arraylike(values, func_name="mode") | ||||||
|  |      original = values | ||||||
|  | @@ -1049,8 +1049,10 @@ def mode( | ||||||
|  |      values = _ensure_data(values) | ||||||
|  |   | ||||||
|  |      npresult, res_mask = htable.mode(values, dropna=dropna, mask=mask) | ||||||
|  | -    if res_mask is not None: | ||||||
|  | -        return npresult, res_mask  # type: ignore[return-value] | ||||||
|  | +    if res_mask is None: | ||||||
|  | +        res_mask = np.zeros(npresult.shape, dtype=np.bool_) | ||||||
|  | +    else: | ||||||
|  | +        return npresult, res_mask | ||||||
|  |   | ||||||
|  |      try: | ||||||
|  |          npresult = safe_sort(npresult) | ||||||
|  | @@ -1061,7 +1063,7 @@ def mode( | ||||||
|  |          ) | ||||||
|  |   | ||||||
|  |      result = _reconstruct_data(npresult, original.dtype, original) | ||||||
|  | -    return result | ||||||
|  | +    return result, res_mask | ||||||
|  |   | ||||||
|  |   | ||||||
|  |  def rank( | ||||||
|  | Index: pandas-2.3.1/pandas/core/arrays/base.py | ||||||
|  | =================================================================== | ||||||
|  | --- pandas-2.3.1.orig/pandas/core/arrays/base.py | ||||||
|  | +++ pandas-2.3.1/pandas/core/arrays/base.py | ||||||
|  | @@ -2270,8 +2270,9 @@ class ExtensionArray: | ||||||
|  |              Sorted, if possible. | ||||||
|  |          """ | ||||||
|  |          # error: Incompatible return value type (got "Union[ExtensionArray, | ||||||
|  | -        # ndarray[Any, Any]]", expected "Self") | ||||||
|  | -        return mode(self, dropna=dropna)  # type: ignore[return-value] | ||||||
|  | +        # Tuple[np.ndarray, npt.NDArray[np.bool_]]", expected "Self") | ||||||
|  | +        result, _ = mode(self, dropna=dropna) | ||||||
|  | +        return result  # type: ignore[return-value] | ||||||
|  |   | ||||||
|  |      def __array_ufunc__(self, ufunc: np.ufunc, method: str, *inputs, **kwargs): | ||||||
|  |          if any( | ||||||
|  | Index: pandas-2.3.1/pandas/core/arrays/categorical.py | ||||||
|  | =================================================================== | ||||||
|  | --- pandas-2.3.1.orig/pandas/core/arrays/categorical.py | ||||||
|  | +++ pandas-2.3.1/pandas/core/arrays/categorical.py | ||||||
|  | @@ -2459,7 +2459,7 @@ class Categorical(NDArrayBackedExtension | ||||||
|  |          if dropna: | ||||||
|  |              mask = self.isna() | ||||||
|  |   | ||||||
|  | -        res_codes = algorithms.mode(codes, mask=mask) | ||||||
|  | +        res_codes, _ = algorithms.mode(codes, mask=mask) | ||||||
|  |          res_codes = cast(np.ndarray, res_codes) | ||||||
|  |          assert res_codes.dtype == codes.dtype | ||||||
|  |          res = self._from_backing_data(res_codes) | ||||||
|  | Index: pandas-2.3.1/pandas/core/arrays/datetimelike.py | ||||||
|  | =================================================================== | ||||||
|  | --- pandas-2.3.1.orig/pandas/core/arrays/datetimelike.py | ||||||
|  | +++ pandas-2.3.1/pandas/core/arrays/datetimelike.py | ||||||
|  | @@ -1669,7 +1669,7 @@ class DatetimeLikeArrayMixin(  # type: i | ||||||
|  |          if dropna: | ||||||
|  |              mask = self.isna() | ||||||
|  |   | ||||||
|  | -        i8modes = algorithms.mode(self.view("i8"), mask=mask) | ||||||
|  | +        i8modes, _ = algorithms.mode(self.view("i8"), mask=mask) | ||||||
|  |          npmodes = i8modes.view(self._ndarray.dtype) | ||||||
|  |          npmodes = cast(np.ndarray, npmodes) | ||||||
|  |          return self._from_backing_data(npmodes) | ||||||
|  | Index: pandas-2.3.1/pandas/core/arrays/masked.py | ||||||
|  | =================================================================== | ||||||
|  | --- pandas-2.3.1.orig/pandas/core/arrays/masked.py | ||||||
|  | +++ pandas-2.3.1/pandas/core/arrays/masked.py | ||||||
|  | @@ -1124,12 +1124,8 @@ class BaseMaskedArray(OpsMixin, Extensio | ||||||
|  |          return Series(arr, index=index, name="count", copy=False) | ||||||
|  |   | ||||||
|  |      def _mode(self, dropna: bool = True) -> Self: | ||||||
|  | -        if dropna: | ||||||
|  | -            result = mode(self._data, dropna=dropna, mask=self._mask) | ||||||
|  | -            res_mask = np.zeros(result.shape, dtype=np.bool_) | ||||||
|  | -        else: | ||||||
|  | -            result, res_mask = mode(self._data, dropna=dropna, mask=self._mask) | ||||||
|  | -        result = type(self)(result, res_mask)  # type: ignore[arg-type] | ||||||
|  | +        result, res_mask = mode(self._data, dropna=dropna, mask=self._mask) | ||||||
|  | +        result = type(self)(result, res_mask) | ||||||
|  |          return result[result.argsort()] | ||||||
|  |   | ||||||
|  |      @doc(ExtensionArray.equals) | ||||||
|  | Index: pandas-2.3.1/pandas/core/series.py | ||||||
|  | =================================================================== | ||||||
|  | --- pandas-2.3.1.orig/pandas/core/series.py | ||||||
|  | +++ pandas-2.3.1/pandas/core/series.py | ||||||
|  | @@ -2337,7 +2337,7 @@ class Series(base.IndexOpsMixin, NDFrame | ||||||
|  |          # TODO: Add option for bins like value_counts() | ||||||
|  |          values = self._values | ||||||
|  |          if isinstance(values, np.ndarray): | ||||||
|  | -            res_values = algorithms.mode(values, dropna=dropna) | ||||||
|  | +            res_values, _ = algorithms.mode(values, dropna=dropna) | ||||||
|  |          else: | ||||||
|  |              res_values = values._mode(dropna=dropna) | ||||||
|  |   | ||||||
|  | Index: pandas-2.3.1/pandas/tests/series/test_reductions.py | ||||||
|  | =================================================================== | ||||||
|  | --- pandas-2.3.1.orig/pandas/tests/series/test_reductions.py | ||||||
|  | +++ pandas-2.3.1/pandas/tests/series/test_reductions.py | ||||||
|  | @@ -51,6 +51,29 @@ def test_mode_nullable_dtype(any_numeric | ||||||
|  |      tm.assert_series_equal(result, expected) | ||||||
|  |   | ||||||
|  |   | ||||||
|  | +def test_mode_nullable_dtype_edge_case(any_numeric_ea_dtype): | ||||||
|  | +    # GH##58926 | ||||||
|  | +    ser = Series([1, 2, 3, 1], dtype=any_numeric_ea_dtype) | ||||||
|  | +    result = ser.mode(dropna=False) | ||||||
|  | +    expected = Series([1], dtype=any_numeric_ea_dtype) | ||||||
|  | +    tm.assert_series_equal(result, expected) | ||||||
|  | + | ||||||
|  | +    ser2 = Series([1, 1, 2, 3, pd.NA], dtype=any_numeric_ea_dtype) | ||||||
|  | +    result = ser2.mode(dropna=False) | ||||||
|  | +    expected = Series([1], dtype=any_numeric_ea_dtype) | ||||||
|  | +    tm.assert_series_equal(result, expected) | ||||||
|  | + | ||||||
|  | +    ser3 = Series([1, pd.NA, pd.NA], dtype=any_numeric_ea_dtype) | ||||||
|  | +    result = ser3.mode(dropna=False) | ||||||
|  | +    expected = Series([pd.NA], dtype=any_numeric_ea_dtype) | ||||||
|  | +    tm.assert_series_equal(result, expected) | ||||||
|  | + | ||||||
|  | +    ser4 = Series([1, 1, pd.NA, pd.NA], dtype=any_numeric_ea_dtype) | ||||||
|  | +    result = ser4.mode(dropna=False) | ||||||
|  | +    expected = Series([1, pd.NA], dtype=any_numeric_ea_dtype) | ||||||
|  | +    tm.assert_series_equal(result, expected) | ||||||
|  | + | ||||||
|  | + | ||||||
|  |  def test_mode_infer_string(): | ||||||
|  |      # GH#56183 | ||||||
|  |      pytest.importorskip("pyarrow") | ||||||
|  | Index: pandas-2.3.1/pandas/tests/test_algos.py | ||||||
|  | =================================================================== | ||||||
|  | --- pandas-2.3.1.orig/pandas/tests/test_algos.py | ||||||
|  | +++ pandas-2.3.1/pandas/tests/test_algos.py | ||||||
|  | @@ -1855,7 +1855,8 @@ class TestRank: | ||||||
|  |  class TestMode: | ||||||
|  |      def test_no_mode(self): | ||||||
|  |          exp = Series([], dtype=np.float64, index=Index([], dtype=int)) | ||||||
|  | -        tm.assert_numpy_array_equal(algos.mode(np.array([])), exp.values) | ||||||
|  | +        result, _ = algos.mode(np.array([])) | ||||||
|  | +        tm.assert_numpy_array_equal(result, exp.values) | ||||||
|  |   | ||||||
|  |      @pytest.mark.parametrize("dt", np.typecodes["AllInteger"] + np.typecodes["Float"]) | ||||||
|  |      def test_mode_single(self, dt): | ||||||
|  | @@ -1868,20 +1869,24 @@ class TestMode: | ||||||
|  |   | ||||||
|  |          ser = Series(data_single, dtype=dt) | ||||||
|  |          exp = Series(exp_single, dtype=dt) | ||||||
|  | -        tm.assert_numpy_array_equal(algos.mode(ser.values), exp.values) | ||||||
|  | +        result, _ = algos.mode(ser.values) | ||||||
|  | +        tm.assert_numpy_array_equal(result, exp.values) | ||||||
|  |          tm.assert_series_equal(ser.mode(), exp) | ||||||
|  |   | ||||||
|  |          ser = Series(data_multi, dtype=dt) | ||||||
|  |          exp = Series(exp_multi, dtype=dt) | ||||||
|  | -        tm.assert_numpy_array_equal(algos.mode(ser.values), exp.values) | ||||||
|  | +        result, _ = algos.mode(ser.values) | ||||||
|  | +        tm.assert_numpy_array_equal(result, exp.values) | ||||||
|  |          tm.assert_series_equal(ser.mode(), exp) | ||||||
|  |   | ||||||
|  |      def test_mode_obj_int(self): | ||||||
|  |          exp = Series([1], dtype=int) | ||||||
|  | -        tm.assert_numpy_array_equal(algos.mode(exp.values), exp.values) | ||||||
|  | +        result, _ = algos.mode(exp.values) | ||||||
|  | +        tm.assert_numpy_array_equal(result, exp.values) | ||||||
|  |   | ||||||
|  |          exp = Series(["a", "b", "c"], dtype=object) | ||||||
|  | -        tm.assert_numpy_array_equal(algos.mode(exp.values), exp.values) | ||||||
|  | +        result, _ = algos.mode(exp.values) | ||||||
|  | +        tm.assert_numpy_array_equal(result, exp.values) | ||||||
|  |   | ||||||
|  |      @pytest.mark.parametrize("dt", np.typecodes["AllInteger"] + np.typecodes["Float"]) | ||||||
|  |      def test_number_mode(self, dt): | ||||||
|  | @@ -1893,12 +1898,14 @@ class TestMode: | ||||||
|  |   | ||||||
|  |          ser = Series(data_single, dtype=dt) | ||||||
|  |          exp = Series(exp_single, dtype=dt) | ||||||
|  | -        tm.assert_numpy_array_equal(algos.mode(ser.values), exp.values) | ||||||
|  | +        result, _ = algos.mode(ser.values) | ||||||
|  | +        tm.assert_numpy_array_equal(result, exp.values) | ||||||
|  |          tm.assert_series_equal(ser.mode(), exp) | ||||||
|  |   | ||||||
|  |          ser = Series(data_multi, dtype=dt) | ||||||
|  |          exp = Series(exp_multi, dtype=dt) | ||||||
|  | -        tm.assert_numpy_array_equal(algos.mode(ser.values), exp.values) | ||||||
|  | +        result, _ = algos.mode(ser.values) | ||||||
|  | +        tm.assert_numpy_array_equal(result, exp.values) | ||||||
|  |          tm.assert_series_equal(ser.mode(), exp) | ||||||
|  |   | ||||||
|  |      def test_strobj_mode(self): | ||||||
|  | @@ -1907,7 +1914,8 @@ class TestMode: | ||||||
|  |   | ||||||
|  |          ser = Series(data, dtype="c") | ||||||
|  |          exp = Series(exp, dtype="c") | ||||||
|  | -        tm.assert_numpy_array_equal(algos.mode(ser.values), exp.values) | ||||||
|  | +        result, _ = algos.mode(ser.values) | ||||||
|  | +        tm.assert_numpy_array_equal(result, exp.values) | ||||||
|  |          tm.assert_series_equal(ser.mode(), exp) | ||||||
|  |   | ||||||
|  |      @pytest.mark.parametrize("dt", [str, object]) | ||||||
|  | @@ -1920,7 +1928,8 @@ class TestMode: | ||||||
|  |          if using_infer_string and dt is str: | ||||||
|  |              tm.assert_extension_array_equal(algos.mode(ser.values), exp.values) | ||||||
|  |          else: | ||||||
|  | -            tm.assert_numpy_array_equal(algos.mode(ser.values), exp.values) | ||||||
|  | +            result, _ = algos.mode(ser.values) | ||||||
|  | +            tm.assert_numpy_array_equal(result, exp.values) | ||||||
|  |          tm.assert_series_equal(ser.mode(), exp) | ||||||
|  |   | ||||||
|  |      def test_datelike_mode(self): | ||||||
|  | @@ -1954,18 +1963,21 @@ class TestMode: | ||||||
|  |      def test_mixed_dtype(self): | ||||||
|  |          exp = Series(["foo"], dtype=object) | ||||||
|  |          ser = Series([1, "foo", "foo"]) | ||||||
|  | -        tm.assert_numpy_array_equal(algos.mode(ser.values), exp.values) | ||||||
|  | +        result, _ = algos.mode(ser.values) | ||||||
|  | +        tm.assert_numpy_array_equal(result, exp.values) | ||||||
|  |          tm.assert_series_equal(ser.mode(), exp) | ||||||
|  |   | ||||||
|  |      def test_uint64_overflow(self): | ||||||
|  |          exp = Series([2**63], dtype=np.uint64) | ||||||
|  |          ser = Series([1, 2**63, 2**63], dtype=np.uint64) | ||||||
|  | -        tm.assert_numpy_array_equal(algos.mode(ser.values), exp.values) | ||||||
|  | +        result, _ = algos.mode(ser.values) | ||||||
|  | +        tm.assert_numpy_array_equal(result, exp.values) | ||||||
|  |          tm.assert_series_equal(ser.mode(), exp) | ||||||
|  |   | ||||||
|  |          exp = Series([1, 2**63], dtype=np.uint64) | ||||||
|  |          ser = Series([1, 2**63], dtype=np.uint64) | ||||||
|  | -        tm.assert_numpy_array_equal(algos.mode(ser.values), exp.values) | ||||||
|  | +        result, _ = algos.mode(ser.values) | ||||||
|  | +        tm.assert_numpy_array_equal(result, exp.values) | ||||||
|  |          tm.assert_series_equal(ser.mode(), exp) | ||||||
|  |   | ||||||
|  |      def test_categorical(self): | ||||||
|  | @@ -1987,15 +1999,18 @@ class TestMode: | ||||||
|  |      def test_index(self): | ||||||
|  |          idx = Index([1, 2, 3]) | ||||||
|  |          exp = Series([1, 2, 3], dtype=np.int64) | ||||||
|  | -        tm.assert_numpy_array_equal(algos.mode(idx), exp.values) | ||||||
|  | +        result, _ = algos.mode(idx) | ||||||
|  | +        tm.assert_numpy_array_equal(result, exp.values) | ||||||
|  |   | ||||||
|  |          idx = Index([1, "a", "a"]) | ||||||
|  |          exp = Series(["a"], dtype=object) | ||||||
|  | -        tm.assert_numpy_array_equal(algos.mode(idx), exp.values) | ||||||
|  | +        result, _ = algos.mode(idx) | ||||||
|  | +        tm.assert_numpy_array_equal(result, exp.values) | ||||||
|  |   | ||||||
|  |          idx = Index([1, 1, 2, 3, 3]) | ||||||
|  |          exp = Series([1, 3], dtype=np.int64) | ||||||
|  | -        tm.assert_numpy_array_equal(algos.mode(idx), exp.values) | ||||||
|  | +        result, _ = algos.mode(idx) | ||||||
|  | +        tm.assert_numpy_array_equal(result, exp.values) | ||||||
|  |   | ||||||
|  |          idx = Index( | ||||||
|  |              ["1 day", "1 day", "-1 day", "-1 day 2 min", "2 min", "2 min"], | ||||||
| @@ -1,3 +1,181 @@ | |||||||
|  | ------------------------------------------------------------------- | ||||||
|  | Sun Sep 14 21:48:11 UTC 2025 - Dirk Müller <dmueller@suse.com> | ||||||
|  |  | ||||||
|  | - update to 2.3.2: | ||||||
|  |   * Fix to_json() with orient="table" to correctly use the | ||||||
|  |     “string” type in the JSON Table Schema for StringDtype columns | ||||||
|  |   * Boolean operations (|, &, ^) with bool-dtype objects on the | ||||||
|  |     left and StringDtype objects on the right now cast the string | ||||||
|  |     to bool, with a deprecation warning | ||||||
|  |   * Fixed match(), fullmatch() and contains() string methods with | ||||||
|  |     compiled regex for the Arrow-backed string dtype | ||||||
|  |   * Bug in Series.replace() and DataFrame.replace() inconsistently | ||||||
|  |     replacing matching values when missing values are present | ||||||
|  |     for string dtypes | ||||||
|  |  | ||||||
|  | ------------------------------------------------------------------- | ||||||
|  | Fri Jul 11 19:29:45 UTC 2025 - Ben Greiner <code@bnavigator.de> | ||||||
|  |  | ||||||
|  | - Update to 2.3.1 | ||||||
|  |   * This release includes some improvements and fixes to the future | ||||||
|  |     string data type (preview feature for the upcoming pandas 3.0) | ||||||
|  |   ## Improvements and fixes for the StringDtype | ||||||
|  |   * Comparisons between different string dtypes | ||||||
|  |   * Index set operations ignore empty RangeIndex and object dtype | ||||||
|  |     Index | ||||||
|  |   ## Bug fixes | ||||||
|  |   * Bug in DataFrameGroupBy.min(), DataFrameGroupBy.max(), | ||||||
|  |     Resampler.min(), Resampler.max() where all NA values of string | ||||||
|  |     dtype would return float instead of string dtype (GH 60810) | ||||||
|  |   * Bug in DataFrame.join() incorrectly downcasting object-dtype | ||||||
|  |     indexes (GH 61771) | ||||||
|  |   * Bug in DataFrame.sum() with axis=1, DataFrameGroupBy.sum() or | ||||||
|  |     SeriesGroupBy.sum() with skipna=True, and Resampler.sum() with | ||||||
|  |     all NA values of StringDtype resulted in 0 instead of the empty | ||||||
|  |     string "" (GH 60229) | ||||||
|  |   * Fixed bug in DataFrame.explode() and Series.explode() where | ||||||
|  |     methods would fail with dtype="str" (GH 61623) | ||||||
|  |   * Fixed bug in unpickling objects pickled in pandas versions | ||||||
|  |     pre-2.3.0 that used StringDtype (GH 61763) | ||||||
|  | - Release 2.3.0 | ||||||
|  |   ## Enhancements | ||||||
|  |   * The semantics for the copy keyword in __array__ methods (i.e. | ||||||
|  |     called when using np.array() or np.asarray() on pandas objects) | ||||||
|  |     has been updated to work correctly with NumPy >= 2 (GH 57739) | ||||||
|  |   * Series.str.decode() result now has StringDtype when | ||||||
|  |     future.infer_string is True (GH 60709) | ||||||
|  |   * to_hdf() and to_hdf() now round-trip with StringDtype (GH | ||||||
|  |     60663) | ||||||
|  |   * Improved repr of NumpyExtensionArray to account for NEP51 (GH | ||||||
|  |     61085) | ||||||
|  |   * The Series.str.decode() has gained the argument dtype to | ||||||
|  |     control the dtype of the result (GH 60940) | ||||||
|  |   * The cumsum(), cummin(), and cummax() reductions are now | ||||||
|  |     implemented for StringDtype columns (GH 60633) | ||||||
|  |   * The sum() reduction is now implemented for StringDtype columns | ||||||
|  |     (GH 59853) | ||||||
|  |   ## Deprecations | ||||||
|  |   * Deprecated allowing non-bool values for na in str.contains(), | ||||||
|  |     str.startswith(), and str.endswith() for dtypes that do not | ||||||
|  |     already disallow these (GH 59615) | ||||||
|  |   * Deprecated the "pyarrow_numpy" storage option for StringDtype | ||||||
|  |     (GH 60152) | ||||||
|  |   * The deprecation of setting the argument include_groups to True | ||||||
|  |     in DataFrameGroupBy.apply() has been promoted from a | ||||||
|  |     DeprecationWarning to FutureWarning; only False will be allowed | ||||||
|  |     (GH 7155) | ||||||
|  |   ## Bug fixes | ||||||
|  |   ### Numeric | ||||||
|  |   * Bug in Series.mode() and DataFrame.mode() with dropna=False | ||||||
|  |     where not all dtypes would sort in the presence of NA values | ||||||
|  |     (GH 60702) | ||||||
|  |   * Bug in Series.round() where a TypeError would always raise with | ||||||
|  |     object dtype (GH 61206) | ||||||
|  |   ### Strings | ||||||
|  |   * Bug in Series.__pos__() and DataFrame.__pos__() where an | ||||||
|  |     Exception was not raised for StringDtype with storage="pyarrow" | ||||||
|  |     (GH 60710) | ||||||
|  |   * Bug in Series.rank() for StringDtype with storage="pyarrow" | ||||||
|  |     that incorrectly returned integer results with method="average" | ||||||
|  |     and raised an error if it would truncate results (GH 59768) | ||||||
|  |   * Bug in Series.replace() with StringDtype when replacing with a | ||||||
|  |     non-string value was not upcasting to object dtype (GH 60282) | ||||||
|  |   * Bug in Series.str.center() with StringDtype with | ||||||
|  |     storage="pyarrow" not matching the python behavior in corner | ||||||
|  |     cases with an odd number of fill characters (GH 54792) | ||||||
|  |   * Bug in Series.str.replace() when n < 0 for StringDtype with | ||||||
|  |     storage="pyarrow" (GH 59628) | ||||||
|  |   * Bug in Series.str.slice() with negative step with ArrowDtype | ||||||
|  |     and StringDtype with storage="pyarrow" giving incorrect results | ||||||
|  |     (GH 59710) | ||||||
|  |   ### Indexing | ||||||
|  |     Bug in Index.get_indexer() round-tripping through string dtype | ||||||
|  |     when infer_string is enabled (GH 55834) | ||||||
|  |   ### I/O | ||||||
|  |   * Bug in DataFrame.to_excel() which stored decimals as strings | ||||||
|  |     instead of numbers (GH 49598) | ||||||
|  |   ### Other | ||||||
|  |   * Fixed usage of inspect when the optional dependencies pyarrow | ||||||
|  |     or jinja2 are not installed (GH 60196) | ||||||
|  | - Drop patches: | ||||||
|  |   * timedelta.patch | ||||||
|  |   * pandas-pr60545-arrow-exception.patch | ||||||
|  |   * pandas-pr60584-60586-mpl-vert.patch | ||||||
|  | - Refresh dropna.patch to pandas-pr61132-dropna.patch | ||||||
|  |   * gh#pandas-dev/pandas#61132 | ||||||
|  |  | ||||||
|  | ------------------------------------------------------------------- | ||||||
|  | Thu Mar 20 11:36:22 UTC 2025 - Markéta Machová <mmachova@suse.com> | ||||||
|  |  | ||||||
|  | - Add dropna.patch and timedelta.patch to fix tests with Numpy 2.2 | ||||||
|  |  | ||||||
|  | ------------------------------------------------------------------- | ||||||
|  | Thu Feb 20 11:23:33 UTC 2025 - Ben Greiner <code@bnavigator.de> | ||||||
|  |  | ||||||
|  | - Support pyarrow 19 | ||||||
|  |   * Add pandas-pr60545-arrow-exception.patch | ||||||
|  |     gh#pandas-dev/pandas#60545 | ||||||
|  |   * Skip TestParquetPyArrow.test_roundtrip_decimal: Would require | ||||||
|  |     gh#pandas-dev/pandas#60755 and all other backports of the new | ||||||
|  |     string type system. | ||||||
|  |  | ||||||
|  | ------------------------------------------------------------------- | ||||||
|  | Fri Feb  7 18:40:46 UTC 2025 - Ben Greiner <code@bnavigator.de> | ||||||
|  |  | ||||||
|  | - Add pandas-pr60584-60586-mpl-vert.patch | ||||||
|  |   * Fixes matplotlib deprecation errors in the test suite | ||||||
|  |   * gh#pandas-dev/pandas#60584 | ||||||
|  |   * backported in gh#pandas-dev/pandas#60586 | ||||||
|  |  | ||||||
|  | ------------------------------------------------------------------- | ||||||
|  | Fri Dec 13 06:51:11 UTC 2024 - Steve Kowalik <steven.kowalik@suse.com> | ||||||
|  |  | ||||||
|  | - Change skipped tests to also support Python 3.13. | ||||||
|  |  | ||||||
|  | ------------------------------------------------------------------- | ||||||
|  | Wed Nov 27 12:26:36 UTC 2024 - Markéta Machová <mmachova@suse.com> | ||||||
|  |  | ||||||
|  | - Drop tests-nomkl.patch and tests-wasm.patch, not needed anymore | ||||||
|  | - Skip a test failing with new xarray | ||||||
|  |  | ||||||
|  | ------------------------------------------------------------------ | ||||||
|  | Fri Oct 25 05:19:49 UTC 2024 - Steve Kowalik <steven.kowalik@suse.com> | ||||||
|  |  | ||||||
|  | - Skip two tests that fail with Numpy 2.1. | ||||||
|  |  | ||||||
|  | ------------------------------------------------------------------- | ||||||
|  | Fri Oct 11 04:40:52 UTC 2024 - Steve Kowalik <steven.kowalik@suse.com> | ||||||
|  |  | ||||||
|  | - Prepare for Python 3.13, by skipping it if we aren't building for it. | ||||||
|  |  | ||||||
|  | ------------------------------------------------------------------- | ||||||
|  | Tue Oct  1 12:35:22 UTC 2024 - John Paul Adrian Glaubitz <adrian.glaubitz@suse.com> | ||||||
|  |  | ||||||
|  | - Update to 2.2.3 | ||||||
|  |   * Bug in eval() on complex including division / | ||||||
|  |     discards imaginary part. (GH 21374) | ||||||
|  |   * Minor fixes for numpy 2.1 compatibility. (GH 59444) | ||||||
|  |   * Missing licenses for 3rd party dependencies were | ||||||
|  |     added back into the wheels. (GH 58632) | ||||||
|  | - Drop pandas-pr58269-pyarrow16xpass.patch, merged upstream | ||||||
|  | - Drop pandas-pr58484-matplotlib.patch, merged upstream | ||||||
|  | - Drop pandas-pr59175-matplotlib.patch, merged upstream | ||||||
|  | - Drop pandas-pr59353-np2eval.patch, merged upstream | ||||||
|  | - Drop tests-npdev.patch, merged upstream | ||||||
|  | - Drop tests-timedelta.patch, merged upstream | ||||||
|  | - Refresh tests-nomkl.patch | ||||||
|  | - Renumber remaining patches | ||||||
|  |  | ||||||
|  | ------------------------------------------------------------------- | ||||||
|  | Mon Sep 16 19:39:38 UTC 2024 - Markéta Machová <mmachova@suse.com> | ||||||
|  |  | ||||||
|  | - Add bunch of patches to fix the testsuite with NumPy 2.1 | ||||||
|  |   * tests-wasm.patch | ||||||
|  |   * tests-nomkl.patch | ||||||
|  |   * tests-timedelta.patch | ||||||
|  |   * tests-npdev.patch | ||||||
|  | - Skip one test failing with new timezone, the patch would be too big | ||||||
|  |  | ||||||
| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ||||||
| Sun Sep  8 10:02:47 UTC 2024 - Ben Greiner <code@bnavigator.de> | Sun Sep  8 10:02:47 UTC 2024 - Ben Greiner <code@bnavigator.de> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| # | # | ||||||
| # spec file for package python-pandas | # spec file for package python-pandas | ||||||
| # | # | ||||||
| # Copyright (c) 2024 SUSE LLC | # Copyright (c) 2025 SUSE LLC and contributors | ||||||
| # | # | ||||||
| # All modifications and additions to the file contributed by third parties | # All modifications and additions to the file contributed by third parties | ||||||
| # remain the property of their copyright owners, unless otherwise agreed | # remain the property of their copyright owners, unless otherwise agreed | ||||||
| @@ -34,7 +34,13 @@ | |||||||
| %if "%{flavor}" != "test-py312" | %if "%{flavor}" != "test-py312" | ||||||
| %define skip_python312 1 | %define skip_python312 1 | ||||||
| %endif | %endif | ||||||
| # Skip empty buildsets, last one is for sle15_python_module_pythons | %if "%{flavor}" != "test-py313" | ||||||
|  | %define skip_python313 1 | ||||||
|  | %endif | ||||||
|  | %if "%{flavor}" != "test-py314" | ||||||
|  | %define skip_python314 1 | ||||||
|  | %endif | ||||||
|  | # Skip empty buildsets on tumbleweed or flavors other than python311 on leap with sle15_python_module_pythons | ||||||
| %if "%{shrink:%{pythons}}" == "" || ("%pythons" == "python311" && 0%{?skip_python311}) | %if "%{shrink:%{pythons}}" == "" || ("%pythons" == "python311" && 0%{?skip_python311}) | ||||||
| ExclusiveArch:  donotbuild | ExclusiveArch:  donotbuild | ||||||
| %define python_module() %flavor-not-enabled-in-buildset-for-suse-%{?suse_version} | %define python_module() %flavor-not-enabled-in-buildset-for-suse-%{?suse_version} | ||||||
| @@ -55,13 +61,13 @@ ExclusiveArch:  donotbuild | |||||||
| # depend/not depend on python-pyarrow and apache-arrow [bsc#1218592] | # depend/not depend on python-pyarrow and apache-arrow [bsc#1218592] | ||||||
| %bcond_without pyarrow | %bcond_without pyarrow | ||||||
|  |  | ||||||
| %if %{suse_version} <= 1500 | %if 0%{?suse_version} && %{suse_version} <= 1500 | ||||||
| # requires __has_builtin with keywords | # requires __has_builtin with keywords | ||||||
| %define gccver 13 | %define gccver 14 | ||||||
| %endif | %endif | ||||||
| Name:           python-pandas%{psuffix} | Name:           python-pandas%{psuffix} | ||||||
| # Set version through _service | # Set version through _service | ||||||
| Version:        2.2.2 | Version:        2.3.2 | ||||||
| Release:        0 | Release:        0 | ||||||
| Summary:        Python data structures for data analysis, time series, and statistics | Summary:        Python data structures for data analysis, time series, and statistics | ||||||
| License:        BSD-3-Clause | License:        BSD-3-Clause | ||||||
| @@ -69,26 +75,20 @@ URL:            https://pandas.pydata.org/ | |||||||
| # SourceRepository: https://github.com/pandas-dev/pandas | # SourceRepository: https://github.com/pandas-dev/pandas | ||||||
| # Must be created by cloning through `osc service runall`: gh#pandas-dev/pandas#54903, gh#pandas-dev/pandas#54907 | # Must be created by cloning through `osc service runall`: gh#pandas-dev/pandas#54903, gh#pandas-dev/pandas#54907 | ||||||
| Source0:        pandas-%{version}.tar.gz | Source0:        pandas-%{version}.tar.gz | ||||||
| # PATCH-FIX-UPSTREAM pandas-pr58269-pyarrow16xpass.patch -- gh#pandas-dev/pandas#58269 | # PATCH-FIX-UPSTREAM pandas-pr61132-dropna.patch gh#pandas-dev/pandas#61132 BUG: .mode(dropna=False) doesn't work with nullable integers | ||||||
| Patch0:         pandas-pr58269-pyarrow16xpass.patch | Patch1:         pandas-pr61132-dropna.patch | ||||||
| # PATCH-FIX-UPSTREAM pandas-pr58484-matplotlib.patch -- gh#pandas-dev/pandas#58484 mcepl@suse.com, make pandas compatible with the modern matplotlib |  | ||||||
| Patch2:         pandas-pr58484-matplotlib.patch |  | ||||||
| # PATCH-FIX-UPSTREAM pandas-pr59175-matplotlib.patch -- gh#pandas-dev/pandas#59175 |  | ||||||
| Patch3:         https://github.com/pandas-dev/pandas/pull/59175.patch#/pandas-pr59175-matplotlib.patch |  | ||||||
| # PATCH-FIX-UPSTREAM pandas-pr59353-np2eval.patch -- gh#pandas-dev/pandas#59144 backported to 2.2, no new tests, see gh#pandas-dev/pandas#58548, gh#pandas-dev/pandas#59353 |  | ||||||
| Patch4:         pandas-pr59353-np2eval.patch |  | ||||||
| %if !%{with test} | %if !%{with test} | ||||||
| BuildRequires:  %{python_module Cython >= 3.0.5} | BuildRequires:  %{python_module Cython >= 3.0.5} | ||||||
| BuildRequires:  %{python_module devel >= 3.9} | BuildRequires:  %{python_module devel >= 3.9} | ||||||
| BuildRequires:  %{python_module meson-python >= 0.13.1} | BuildRequires:  %{python_module meson-python >= 0.13.1} | ||||||
| BuildRequires:  %{python_module numpy-devel >= 1.26} | BuildRequires:  %{python_module numpy-devel >= 1.22.4} | ||||||
| BuildRequires:  %{python_module pip} | BuildRequires:  %{python_module pip} | ||||||
| BuildRequires:  %{python_module versioneer-toml} | BuildRequires:  %{python_module versioneer-toml} | ||||||
| BuildRequires:  %{python_module wheel} | BuildRequires:  %{python_module wheel} | ||||||
| BuildRequires:  fdupes | BuildRequires:  fdupes | ||||||
| BuildRequires:  gcc%{?gccver}-c++ | BuildRequires:  gcc%{?gccver}-c++ | ||||||
| BuildRequires:  git-core | BuildRequires:  git-core | ||||||
| BuildRequires:  meson >= 1.2.1 | BuildRequires:  (meson >= 1.2.1 with meson < 2) | ||||||
| %endif | %endif | ||||||
| BuildRequires:  python-rpm-macros | BuildRequires:  python-rpm-macros | ||||||
| Requires:       python-python-dateutil >= 2.8.2 | Requires:       python-python-dateutil >= 2.8.2 | ||||||
| @@ -102,7 +102,7 @@ Requires:       python-numpy >= 1.22.4 | |||||||
| %if 0%{python_version_nodots} == 311 | %if 0%{python_version_nodots} == 311 | ||||||
| Requires:       python-numpy >= 1.23.2 | Requires:       python-numpy >= 1.23.2 | ||||||
| %else | %else | ||||||
| Requires:       python-numpy >= 1.26 | Requires:       python-numpy >= 1.26.0 | ||||||
| %endif | %endif | ||||||
| %endif | %endif | ||||||
| # SECTION extras | # SECTION extras | ||||||
| @@ -209,7 +209,7 @@ provide speed improvements, especially when working with large data sets. | |||||||
| %package computation | %package computation | ||||||
| Summary:        The python pandas[computation] extra | Summary:        The python pandas[computation] extra | ||||||
| Requires:       python-pandas = %{version} | Requires:       python-pandas = %{version} | ||||||
| Requires:       python-scipy >= 1.10.0 | Requires:       python-scipy >= 1.12.0 | ||||||
| Requires:       python-xarray >= 2022.12.0 | Requires:       python-xarray >= 2022.12.0 | ||||||
| BuildArch:      noarch | BuildArch:      noarch | ||||||
|  |  | ||||||
| @@ -218,7 +218,7 @@ This package provides the [computation] extra for python-pandas | |||||||
|  |  | ||||||
| %package fss | %package fss | ||||||
| Summary:        The python pandas[fss] extra | Summary:        The python pandas[fss] extra | ||||||
| Requires:       python-fsspec >= 2022.11 | Requires:       python-fsspec >= 2023.12.2 | ||||||
| Requires:       python-pandas = %{version} | Requires:       python-pandas = %{version} | ||||||
| BuildArch:      noarch | BuildArch:      noarch | ||||||
|  |  | ||||||
| @@ -410,7 +410,7 @@ Requires:       python-beautifulsoup4 >= 4.11.2 | |||||||
| Requires:       python-blosc | Requires:       python-blosc | ||||||
| %{?with_calamine:Requires:       python-calamine >= 0.1.7} | %{?with_calamine:Requires:       python-calamine >= 0.1.7} | ||||||
| %{?with_pyarrow:Requires:   python-fastparquet >= 2022.12} | %{?with_pyarrow:Requires:   python-fastparquet >= 2022.12} | ||||||
| Requires:       python-fsspec >= 2022.11 | Requires:       python-fsspec >= 2023.12.2 | ||||||
| Requires:       python-gcsfs >= 2022.11 | Requires:       python-gcsfs >= 2022.11 | ||||||
| Requires:       python-html5lib >= 1.1 | Requires:       python-html5lib >= 1.1 | ||||||
| Requires:       python-hypothesis >= 6.46.1 | Requires:       python-hypothesis >= 6.46.1 | ||||||
| @@ -426,7 +426,7 @@ Requires:       python-psycopg2 >= 2.9.6 | |||||||
| Requires:       python-pyreadstat >= 1.2.0 | Requires:       python-pyreadstat >= 1.2.0 | ||||||
| Requires:       python-pytest >= 7.3.2 | Requires:       python-pytest >= 7.3.2 | ||||||
| Requires:       python-pytest-xdist >= 2.2.0 | Requires:       python-pytest-xdist >= 2.2.0 | ||||||
| Requires:       python-scipy >= 1.10.0 | Requires:       python-scipy >= 1.12.0 | ||||||
| Requires:       python-tables >= 3.8.0 | Requires:       python-tables >= 3.8.0 | ||||||
| Requires:       python-tabulate >= 0.9 | Requires:       python-tabulate >= 0.9 | ||||||
| Requires:       python-xarray >= 2022.12 | Requires:       python-xarray >= 2022.12 | ||||||
| @@ -514,13 +514,16 @@ SKIP_TESTS+=" or test_psycopg2_schema_support" | |||||||
| SKIP_TESTS+=" or test_self_join_date_columns" | SKIP_TESTS+=" or test_self_join_date_columns" | ||||||
| # expects a dirty git revision from git repo | # expects a dirty git revision from git repo | ||||||
| SKIP_TESTS+=" or test_git_version" | SKIP_TESTS+=" or test_git_version" | ||||||
| %if "%{flavor}" == "test-py312" |  | ||||||
| # https://github.com/pandas-dev/pandas/pull/57391, proposed change is not necessarily the right one | # https://github.com/pandas-dev/pandas/pull/57391, proposed change is not necessarily the right one | ||||||
|  | %if "%{flavor}" == "test-py312" || "%{flavor}" == "test-py313" | ||||||
| SKIP_TESTS+=" or (test_scalar_unary and numexpr-pandas)" | SKIP_TESTS+=" or (test_scalar_unary and numexpr-pandas)" | ||||||
| %endif | %endif | ||||||
| # Numpy2: unexpected 'np.str_(...)' in error message | # https://github.com/pandas-dev/pandas/pull/55901, not gonna merge this huge patch to fix one test failing with new timezone, will be included in 3.0 | ||||||
| SKIP_TESTS+=" or test_group_subplot_invalid_column_name" | SKIP_TESTS+=" or test_array_inference[data7-expected7]" | ||||||
|  | # too new xarray, gh#pandas-dev/pandas#60109 backport too much | ||||||
|  | SKIP_TESTS+=" or (TestDataFrameToXArray and test_to_xarray_index_types)" | ||||||
|  | # xpass strict: our xarray seems to handle this fine | ||||||
|  | SKIP_TESTS+=" or (TestSeriesToXArray and test_to_xarray_index_types)" | ||||||
| %ifarch %{ix86} %{arm32} | %ifarch %{ix86} %{arm32} | ||||||
| # https://github.com/pandas-dev/pandas/issues/31856 | # https://github.com/pandas-dev/pandas/issues/31856 | ||||||
| SKIP_TESTS+=" or test_maybe_promote_int_with_int" | SKIP_TESTS+=" or test_maybe_promote_int_with_int" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user