From 62cc9a831a3a4a63788c37f1df49dcaee4992d48 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Wed, 15 Aug 2018 18:58:15 -0700 Subject: [PATCH 1/3] Fix and test scalar extension dtype op corner case --- pandas/core/ops.py | 4 ++-- pandas/tests/arithmetic/test_object.py | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/pandas/core/ops.py b/pandas/core/ops.py index 10418ccbb1f64..4b53cf92e1b66 100644 --- a/pandas/core/ops.py +++ b/pandas/core/ops.py @@ -1228,8 +1228,8 @@ def wrapper(left, right): "{op}".format(typ=type(left).__name__, op=str_rep)) elif (is_extension_array_dtype(left) or - is_extension_array_dtype(right)): - # TODO: should this include `not is_scalar(right)`? + (is_extension_array_dtype(right) and not is_scalar(right))): + # disallow scalar to exclude e.g. "category", "Int64" return dispatch_to_extension_op(op, left, right) elif is_datetime64_dtype(left) or is_datetime64tz_dtype(left): diff --git a/pandas/tests/arithmetic/test_object.py b/pandas/tests/arithmetic/test_object.py index c02c3becbd556..c9b7b364caf20 100644 --- a/pandas/tests/arithmetic/test_object.py +++ b/pandas/tests/arithmetic/test_object.py @@ -73,6 +73,25 @@ def test_more_na_comparisons(self, dtype): class TestArithmetic(object): + def test_add_extension_scalar(self, box): + # Check that scalars satisfying is_extension_array_dtype(obj) + # do not incorrectly try to dispatch to an ExtensionArray operation + + arr = pd.Series(['a', 'b', 'c']) + arr = tm.box_expected(arr, box) + + expected = pd.Series(['acategory', 'bcategory', 'ccategory']) + expected = tm.box_expected(expected, box) + + result = arr + "category" + tm.assert_equal(result, expected) + + expected = pd.Series(['aInt64', 'bInt64', 'cInt64']) + expected = tm.box_expected(expected, box) + + result = arr + "Int64" + tm.assert_equal(result, expected) + @pytest.mark.parametrize('box', [ pytest.param(pd.Index, marks=pytest.mark.xfail(reason="Does not mask nulls", From 2bd3314bac4521eafbe2b088294ca929b9d710f6 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Wed, 15 Aug 2018 19:03:35 -0700 Subject: [PATCH 2/3] parametrize test --- pandas/tests/arithmetic/test_object.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/pandas/tests/arithmetic/test_object.py b/pandas/tests/arithmetic/test_object.py index c9b7b364caf20..8ebb0a30332df 100644 --- a/pandas/tests/arithmetic/test_object.py +++ b/pandas/tests/arithmetic/test_object.py @@ -73,23 +73,19 @@ def test_more_na_comparisons(self, dtype): class TestArithmetic(object): - def test_add_extension_scalar(self, box): + @pytest.mark.parametrize("op", [operator.add, ops.radd]) + @pytest.mark.parametrize("other", ["category", "Int64"]) + def test_add_extension_scalar(self, other, box, op): # Check that scalars satisfying is_extension_array_dtype(obj) # do not incorrectly try to dispatch to an ExtensionArray operation arr = pd.Series(['a', 'b', 'c']) - arr = tm.box_expected(arr, box) - - expected = pd.Series(['acategory', 'bcategory', 'ccategory']) - expected = tm.box_expected(expected, box) + expected = pd.Series([op(x, other) for x in arr]) - result = arr + "category" - tm.assert_equal(result, expected) - - expected = pd.Series(['aInt64', 'bInt64', 'cInt64']) + arr = tm.box_expected(arr, box) expected = tm.box_expected(expected, box) - result = arr + "Int64" + result = op(arr, other) tm.assert_equal(result, expected) @pytest.mark.parametrize('box', [ From a1e20429bcfe98bf7a628d11969fe05a8eca0676 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Wed, 15 Aug 2018 19:04:23 -0700 Subject: [PATCH 3/3] Add GH references --- pandas/core/ops.py | 2 +- pandas/tests/arithmetic/test_object.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/core/ops.py b/pandas/core/ops.py index 4b53cf92e1b66..ddd82de2da5fc 100644 --- a/pandas/core/ops.py +++ b/pandas/core/ops.py @@ -1229,7 +1229,7 @@ def wrapper(left, right): elif (is_extension_array_dtype(left) or (is_extension_array_dtype(right) and not is_scalar(right))): - # disallow scalar to exclude e.g. "category", "Int64" + # GH#22378 disallow scalar to exclude e.g. "category", "Int64" return dispatch_to_extension_op(op, left, right) elif is_datetime64_dtype(left) or is_datetime64tz_dtype(left): diff --git a/pandas/tests/arithmetic/test_object.py b/pandas/tests/arithmetic/test_object.py index 8ebb0a30332df..2c1cc83c09f88 100644 --- a/pandas/tests/arithmetic/test_object.py +++ b/pandas/tests/arithmetic/test_object.py @@ -76,6 +76,7 @@ class TestArithmetic(object): @pytest.mark.parametrize("op", [operator.add, ops.radd]) @pytest.mark.parametrize("other", ["category", "Int64"]) def test_add_extension_scalar(self, other, box, op): + # GH#22378 # Check that scalars satisfying is_extension_array_dtype(obj) # do not incorrectly try to dispatch to an ExtensionArray operation