From f0718fa9f910c46a4417777bf3911d376886917c Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Fri, 23 Aug 2019 14:07:40 -0500 Subject: [PATCH 1/3] BUG: Fixed PandasArray.__setitem__ with str Closes https://github.com/pandas-dev/pandas/issues/28118 --- doc/source/whatsnew/v1.0.0.rst | 2 +- pandas/core/arrays/numpy_.py | 9 ++++++++- pandas/tests/arrays/test_numpy.py | 8 ++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v1.0.0.rst b/doc/source/whatsnew/v1.0.0.rst index 4decc99087a9e..f2fd600bfe407 100644 --- a/doc/source/whatsnew/v1.0.0.rst +++ b/doc/source/whatsnew/v1.0.0.rst @@ -198,7 +198,7 @@ Build Changes ExtensionArray ^^^^^^^^^^^^^^ -- +- Bug in :class:`arrays.PandasArray` when setting a scalar string (:issue:`28118`) - diff --git a/pandas/core/arrays/numpy_.py b/pandas/core/arrays/numpy_.py index 4e2e37d88eb9a..174bd7c104d02 100644 --- a/pandas/core/arrays/numpy_.py +++ b/pandas/core/arrays/numpy_.py @@ -8,6 +8,7 @@ from pandas.util._decorators import Appender from pandas.util._validators import validate_fillna_kwargs +from pandas.core.dtypes.common import is_object_dtype from pandas.core.dtypes.dtypes import ExtensionDtype from pandas.core.dtypes.generic import ABCIndexClass, ABCSeries from pandas.core.dtypes.inference import is_array_like, is_list_like @@ -236,7 +237,13 @@ def __setitem__(self, key, value): value = np.asarray(value) values = self._ndarray - t = np.result_type(value, values) + if isinstance(value, str): + if is_object_dtype(self.dtype._dtype): + t = np.dtype(object) + else: + t = self.dtype._dtype + else: + t = np.result_type(value, values) if t != self._ndarray.dtype: values = values.astype(t, casting="safe") values[key] = value diff --git a/pandas/tests/arrays/test_numpy.py b/pandas/tests/arrays/test_numpy.py index c4c1696ede6e6..909a12bfb3095 100644 --- a/pandas/tests/arrays/test_numpy.py +++ b/pandas/tests/arrays/test_numpy.py @@ -211,3 +211,11 @@ def test_basic_binop(): result = x + x expected = PandasArray(np.array([2, 4, 6])) tm.assert_extension_array_equal(result, expected) + + +@pytest.mark.parametrize("dtype", [None, object]) +def test_setitem_object_typecode(dtype): + arr = PandasArray(np.array(["a", "b", "c"], dtype=dtype)) + arr[0] = "t" + expected = PandasArray(np.array(["t", "b", "c"], dtype=dtype)) + tm.assert_extension_array_equal(arr, expected) From 75c2c588ae13402f068019c75d4dd3d9621cb978 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Mon, 9 Sep 2019 15:32:49 -0500 Subject: [PATCH 2/3] no casting --- pandas/core/arrays/numpy_.py | 18 ++---------------- pandas/tests/arrays/test_numpy.py | 7 +++++++ 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/pandas/core/arrays/numpy_.py b/pandas/core/arrays/numpy_.py index 174bd7c104d02..32da0199e28f8 100644 --- a/pandas/core/arrays/numpy_.py +++ b/pandas/core/arrays/numpy_.py @@ -8,7 +8,6 @@ from pandas.util._decorators import Appender from pandas.util._validators import validate_fillna_kwargs -from pandas.core.dtypes.common import is_object_dtype from pandas.core.dtypes.dtypes import ExtensionDtype from pandas.core.dtypes.generic import ABCIndexClass, ABCSeries from pandas.core.dtypes.inference import is_array_like, is_list_like @@ -236,21 +235,8 @@ def __setitem__(self, key, value): if not lib.is_scalar(value): value = np.asarray(value) - values = self._ndarray - if isinstance(value, str): - if is_object_dtype(self.dtype._dtype): - t = np.dtype(object) - else: - t = self.dtype._dtype - else: - t = np.result_type(value, values) - if t != self._ndarray.dtype: - values = values.astype(t, casting="safe") - values[key] = value - self._dtype = PandasDtype(t) - self._ndarray = values - else: - self._ndarray[key] = value + value = np.asarray(value, dtype=self._ndarray.dtype) + self._ndarray[key] = value def __len__(self) -> int: return len(self._ndarray) diff --git a/pandas/tests/arrays/test_numpy.py b/pandas/tests/arrays/test_numpy.py index 909a12bfb3095..7a150c35fea09 100644 --- a/pandas/tests/arrays/test_numpy.py +++ b/pandas/tests/arrays/test_numpy.py @@ -219,3 +219,10 @@ def test_setitem_object_typecode(dtype): arr[0] = "t" expected = PandasArray(np.array(["t", "b", "c"], dtype=dtype)) tm.assert_extension_array_equal(arr, expected) + + +def test_setitem_no_coercion(): + # https://github.com/pandas-dev/pandas/issues/28150 + arr = PandasArray(np.array([1, 2, 3])) + with pytest.raises(ValueError, match="int"): + arr[0] = "a" From 18288907baeb52363043d40ac5f201ce6529d027 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Tue, 10 Sep 2019 16:37:27 -0500 Subject: [PATCH 3/3] whatsnews --- doc/source/whatsnew/v1.0.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.0.0.rst b/doc/source/whatsnew/v1.0.0.rst index ddb4a49ce5129..3baffaf9bd168 100644 --- a/doc/source/whatsnew/v1.0.0.rst +++ b/doc/source/whatsnew/v1.0.0.rst @@ -223,7 +223,7 @@ Build Changes ExtensionArray ^^^^^^^^^^^^^^ -- Bug in :class:`arrays.PandasArray` when setting a scalar string (:issue:`28118`) +- Bug in :class:`arrays.PandasArray` when setting a scalar string (:issue:`28118`, :issue:`28150`). -