From 9f966756dabadd8c2fbe002761f11c4a5c950a81 Mon Sep 17 00:00:00 2001 From: Siddhesh Bangar Date: Mon, 20 May 2024 00:39:03 +0100 Subject: [PATCH 1/8] Fix:#58748 --- pandas/core/computation/ops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/computation/ops.py b/pandas/core/computation/ops.py index b7a1cb173f659..4a04a2afdbaaf 100644 --- a/pandas/core/computation/ops.py +++ b/pandas/core/computation/ops.py @@ -509,7 +509,7 @@ def _disallow_scalar_only_bool_ops(self) -> None: def isnumeric(dtype) -> bool: - return issubclass(np.dtype(dtype).type, np.number) + return getattr(dtype, '_is_numeric', False) or issubclass(np.dtype(dtype).type, np.number) class Div(BinOp): From 577b337f171f6cd2f3562a99842374c05caf70f1 Mon Sep 17 00:00:00 2001 From: Siddhesh Bangar Date: Tue, 21 May 2024 02:01:04 +0100 Subject: [PATCH 2/8] Updated #58748 and Added Test --- pandas/core/computation/ops.py | 4 +++- pandas/tests/extension/test_datetime.py | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/pandas/core/computation/ops.py b/pandas/core/computation/ops.py index 4a04a2afdbaaf..61f9d4eff1e54 100644 --- a/pandas/core/computation/ops.py +++ b/pandas/core/computation/ops.py @@ -509,7 +509,9 @@ def _disallow_scalar_only_bool_ops(self) -> None: def isnumeric(dtype) -> bool: - return getattr(dtype, '_is_numeric', False) or issubclass(np.dtype(dtype).type, np.number) + return getattr(dtype, "_is_numeric", False) or issubclass( + np.dtype(dtype).type, np.number + ) class Div(BinOp): diff --git a/pandas/tests/extension/test_datetime.py b/pandas/tests/extension/test_datetime.py index a42fa6088d9c8..9e92ccddd1aec 100644 --- a/pandas/tests/extension/test_datetime.py +++ b/pandas/tests/extension/test_datetime.py @@ -88,6 +88,13 @@ def cmp(a, b): return cmp +@pytest.fixture +def isnumeric(dtype): + return getattr(dtype, "is_numeric", False) or issubclass( + np.dtype(dtype).type, np.number + ) + + # ---------------------------------------------------------------------------- class TestDatetimeArray(base.ExtensionTests): def _get_expected_exception(self, op_name, obj, other): From 78ea9e670560a5deec10bf21bc912a5b65a400cb Mon Sep 17 00:00:00 2001 From: Siddhesh Bangar Date: Wed, 22 May 2024 15:00:04 +0100 Subject: [PATCH 3/8] Fix Imports and Added Test --- pandas/core/computation/ops.py | 11 ++++------- pandas/tests/extension/test_datetime.py | 7 ------- pandas/tests/frame/test_query_eval.py | 7 +++++++ 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/pandas/core/computation/ops.py b/pandas/core/computation/ops.py index 61f9d4eff1e54..d69765e91f467 100644 --- a/pandas/core/computation/ops.py +++ b/pandas/core/computation/ops.py @@ -19,6 +19,7 @@ from pandas.core.dtypes.common import ( is_list_like, + is_numeric_dtype, is_scalar, ) @@ -508,12 +509,6 @@ def _disallow_scalar_only_bool_ops(self) -> None: raise NotImplementedError("cannot evaluate scalar only bool ops") -def isnumeric(dtype) -> bool: - return getattr(dtype, "_is_numeric", False) or issubclass( - np.dtype(dtype).type, np.number - ) - - class Div(BinOp): """ Div operator to special case casting. @@ -527,7 +522,9 @@ class Div(BinOp): def __init__(self, lhs, rhs) -> None: super().__init__("/", lhs, rhs) - if not isnumeric(lhs.return_type) or not isnumeric(rhs.return_type): + if not is_numeric_dtype(lhs.return_type) or not is_numeric_dtype( + rhs.return_type + ): raise TypeError( f"unsupported operand type(s) for {self.op}: " f"'{lhs.return_type}' and '{rhs.return_type}'" diff --git a/pandas/tests/extension/test_datetime.py b/pandas/tests/extension/test_datetime.py index 9e92ccddd1aec..a42fa6088d9c8 100644 --- a/pandas/tests/extension/test_datetime.py +++ b/pandas/tests/extension/test_datetime.py @@ -88,13 +88,6 @@ def cmp(a, b): return cmp -@pytest.fixture -def isnumeric(dtype): - return getattr(dtype, "is_numeric", False) or issubclass( - np.dtype(dtype).type, np.number - ) - - # ---------------------------------------------------------------------------- class TestDatetimeArray(base.ExtensionTests): def _get_expected_exception(self, op_name, obj, other): diff --git a/pandas/tests/frame/test_query_eval.py b/pandas/tests/frame/test_query_eval.py index 643d342b052a4..b24e5f2923cb6 100644 --- a/pandas/tests/frame/test_query_eval.py +++ b/pandas/tests/frame/test_query_eval.py @@ -202,6 +202,13 @@ def test_eval_simple(self, engine, parser): expected = df["a"] tm.assert_series_equal(expected, res) + def test_extension_array_eval(): + # GH#58748 + df = DataFrame({"a": pd.array([1, 2, 3]), "b": pd.array([4, 5, 6])}) + result = df.eval("a / b") + expected = Series([0.25, 0.40, 0.50]) + tm.assert_series_equal(result, expected) + class TestDataFrameQueryWithMultiIndex: def test_query_with_named_multiindex(self, parser, engine): From 115a36b1b8a36666ebb0958a3e5d03f6bcebb820 Mon Sep 17 00:00:00 2001 From: Siddhesh Bangar Date: Tue, 28 May 2024 16:31:49 +0100 Subject: [PATCH 4/8] Fix:Tests --- pandas/tests/frame/test_query_eval.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pandas/tests/frame/test_query_eval.py b/pandas/tests/frame/test_query_eval.py index b24e5f2923cb6..d93ef626a1825 100644 --- a/pandas/tests/frame/test_query_eval.py +++ b/pandas/tests/frame/test_query_eval.py @@ -202,10 +202,12 @@ def test_eval_simple(self, engine, parser): expected = df["a"] tm.assert_series_equal(expected, res) - def test_extension_array_eval(): + +class TestDataFrameEvalWithMultiIndex: + def test_extension_array_eval(self, engine, parser): # GH#58748 df = DataFrame({"a": pd.array([1, 2, 3]), "b": pd.array([4, 5, 6])}) - result = df.eval("a / b") + result = df.eval("a / b", engine=engine, parser=parser) expected = Series([0.25, 0.40, 0.50]) tm.assert_series_equal(result, expected) From 962bb394a98526844bb64d6f42cbdd1d600d546b Mon Sep 17 00:00:00 2001 From: Siddhesh Bangar Date: Sat, 8 Jun 2024 13:58:04 +0530 Subject: [PATCH 5/8] Updated:whatsnew v3.0 --- doc/source/whatsnew/v3.0.0.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 2b45c8aa4865f..9fedd7ff4f10c 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -606,6 +606,7 @@ Other - Bug in :meth:`Series.replace` and :meth:`DataFrame.replace` inconsistently replacing matching instances when ``regex=True`` and missing values are present. (:issue:`56599`) - Bug in Dataframe Interchange Protocol implementation was returning incorrect results for data buffers' associated dtype, for string and datetime columns (:issue:`54781`) - Bug in ``Series.list`` methods not preserving the original :class:`Index`. (:issue:`58425`) +- Bug in :func:`eval` including division ``\`` failed with a ``TypeError`` (:issue:`58748`) .. ***DO NOT USE THIS SECTION*** From 2bbe59c073c10838dc016413b336c727ad2d1601 Mon Sep 17 00:00:00 2001 From: Siddhesh Bangar Date: Sat, 8 Jun 2024 14:08:13 +0530 Subject: [PATCH 6/8] Updated: whatsnew v3.0 --- doc/source/whatsnew/v3.0.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 9fedd7ff4f10c..2ff3fbc05e1a4 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -606,7 +606,7 @@ Other - Bug in :meth:`Series.replace` and :meth:`DataFrame.replace` inconsistently replacing matching instances when ``regex=True`` and missing values are present. (:issue:`56599`) - Bug in Dataframe Interchange Protocol implementation was returning incorrect results for data buffers' associated dtype, for string and datetime columns (:issue:`54781`) - Bug in ``Series.list`` methods not preserving the original :class:`Index`. (:issue:`58425`) -- Bug in :func:`eval` including division ``\`` failed with a ``TypeError`` (:issue:`58748`) +- Bug in :func:`eval` including division ``\`` failed with a ``TypeError``. (:issue:`58748`) .. ***DO NOT USE THIS SECTION*** From 92342c7949a60d4b413993138ce7623f71b3dfde Mon Sep 17 00:00:00 2001 From: Siddhesh Bangar Date: Sat, 8 Jun 2024 16:15:47 +0530 Subject: [PATCH 7/8] Updated: Tests --- doc/source/whatsnew/v3.0.0.rst | 2 +- pandas/tests/frame/test_query_eval.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 2ff3fbc05e1a4..236977b96ca24 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -593,6 +593,7 @@ Styler Other ^^^^^ - Bug in :class:`DataFrame` when passing a ``dict`` with a NA scalar and ``columns`` that would always return ``np.nan`` (:issue:`57205`) +- Bug in :func:`eval` including division ``\`` failed with a ``TypeError``. (:issue:`58748`) - Bug in :func:`eval` where the names of the :class:`Series` were not preserved when using ``engine="numexpr"``. (:issue:`10239`) - Bug in :func:`unique` on :class:`Index` not always returning :class:`Index` (:issue:`57043`) - Bug in :meth:`DataFrame.eval` and :meth:`DataFrame.query` which caused an exception when using NumPy attributes via ``@`` notation, e.g., ``df.eval("@np.floor(a)")``. (:issue:`58041`) @@ -606,7 +607,6 @@ Other - Bug in :meth:`Series.replace` and :meth:`DataFrame.replace` inconsistently replacing matching instances when ``regex=True`` and missing values are present. (:issue:`56599`) - Bug in Dataframe Interchange Protocol implementation was returning incorrect results for data buffers' associated dtype, for string and datetime columns (:issue:`54781`) - Bug in ``Series.list`` methods not preserving the original :class:`Index`. (:issue:`58425`) -- Bug in :func:`eval` including division ``\`` failed with a ``TypeError``. (:issue:`58748`) .. ***DO NOT USE THIS SECTION*** diff --git a/pandas/tests/frame/test_query_eval.py b/pandas/tests/frame/test_query_eval.py index d93ef626a1825..ff1bf5632e920 100644 --- a/pandas/tests/frame/test_query_eval.py +++ b/pandas/tests/frame/test_query_eval.py @@ -202,8 +202,6 @@ def test_eval_simple(self, engine, parser): expected = df["a"] tm.assert_series_equal(expected, res) - -class TestDataFrameEvalWithMultiIndex: def test_extension_array_eval(self, engine, parser): # GH#58748 df = DataFrame({"a": pd.array([1, 2, 3]), "b": pd.array([4, 5, 6])}) From f007a0f770ef3225b89dd69061946c46a85af5b0 Mon Sep 17 00:00:00 2001 From: Siddhesh Bangar Date: Sun, 9 Jun 2024 15:50:56 +0530 Subject: [PATCH 8/8] Updated: Whatsnew v3.0 --- doc/source/whatsnew/v3.0.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 236977b96ca24..27ced4cc80b21 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -593,7 +593,7 @@ Styler Other ^^^^^ - Bug in :class:`DataFrame` when passing a ``dict`` with a NA scalar and ``columns`` that would always return ``np.nan`` (:issue:`57205`) -- Bug in :func:`eval` including division ``\`` failed with a ``TypeError``. (:issue:`58748`) +- Bug in :func:`eval` on :class:`ExtensionArray` on including division ``/`` failed with a ``TypeError``. (:issue:`58748`) - Bug in :func:`eval` where the names of the :class:`Series` were not preserved when using ``engine="numexpr"``. (:issue:`10239`) - Bug in :func:`unique` on :class:`Index` not always returning :class:`Index` (:issue:`57043`) - Bug in :meth:`DataFrame.eval` and :meth:`DataFrame.query` which caused an exception when using NumPy attributes via ``@`` notation, e.g., ``df.eval("@np.floor(a)")``. (:issue:`58041`)