Skip to content

Commit

Permalink
Always return ndarray
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAugspurger committed Oct 3, 2018
1 parent 1921c6f commit 7714e79
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 11 deletions.
24 changes: 18 additions & 6 deletions pandas/core/arrays/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -739,14 +739,22 @@ def _create_method(cls, op, coerce_to_dtype=True):
----------
op : function
An operator that takes arguments op(a, b)
coerce_to_dtype : bool
coerce_to_dtype : bool, default True
boolean indicating whether to attempt to convert
the result to the underlying ExtensionArray dtype
(default True)
the result to the underlying ExtensionArray dtype.
If it's not possible to create a new ExtensionArray with the
values, an ndarray is returned instead.
Returns
-------
A method that can be bound to a method of a class
Callable[[Any, Any], Union[ndarray, ExtensionArray]]
A method that can be bound to a class. When used, the method
receives the two arguments, one of which is the instance of
this class, and should return an ExtensionArray or an ndarray.
Returning an ndarray may be necessary when the result of the
`op` cannot be stored in the ExtensionArray. The dtype of the
ndarray uses NumPy's normal inference rules.
Example
-------
Expand All @@ -757,7 +765,6 @@ def _create_method(cls, op, coerce_to_dtype=True):
in the class definition of MyExtensionArray to create the operator
for addition, that will be based on the operator implementation
of the underlying elements of the ExtensionArray
"""

def _binop(self, other):
Expand All @@ -778,7 +785,12 @@ def convert_values(param):
try:
res = self._from_sequence(res)
except Exception:
res = np.asarray(res, dtype=object)
# https://github.com/pandas-dev/pandas/issues/22850
# We catch all regular exceptions here, and fall back
# to an ndarray.
res = np.asarray(res)
else:
res = np.asarray(res)

return res

Expand Down
8 changes: 5 additions & 3 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -2323,12 +2323,14 @@ def combine(self, other, func, fill_value=None):
pass
elif is_extension_array_dtype(self.values):
# The function can return something of any type, so check
# if the type is compatible with the calling EA
# ExtensionArray._from_sequence can raise anything, so we
# have to catch everything.
# if the type is compatible with the calling EA.
try:
new_values = self._values._from_sequence(new_values)
except Exception:
# https://github.com/pandas-dev/pandas/issues/22850
# pandas has no control over what 3rd-party ExtensionArrays
# do in _values_from_sequence. We still want ops to work
# though, so we catch any regular Exception.
pass

return self._constructor(new_values, index=new_index, name=new_name)
Expand Down
17 changes: 15 additions & 2 deletions pandas/tests/extension/decimal/test_decimal.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,15 @@ def _from_sequence(cls, scalars, dtype=None, copy=False):
raise KeyError("For the test")


class DecimalArrayWithoutCoercion(DecimalArrayWithoutFromSequence):
@classmethod
def _create_arithmetic_method(cls, op):
return cls._create_method(op, coerce_to_dtype=False)


DecimalArrayWithoutCoercion._add_arithmetic_ops()


def test_combine_from_sequence_raises():
# https://github.com/pandas-dev/pandas/issues/22850
ser = pd.Series(DecimalArrayWithoutFromSequence([
Expand All @@ -293,8 +302,12 @@ def test_combine_from_sequence_raises():
tm.assert_series_equal(result, expected)


def test_scalar_ops_from_sequence_raises():
arr = DecimalArrayWithoutFromSequence([
@pytest.mark.parametrize("class_", [DecimalArrayWithoutFromSequence,
DecimalArrayWithoutCoercion])
def test_scalar_ops_from_sequence_raises(class_):
# op(EA, EA) should return an EA, or an ndarray if it's not possible
# to return an EA with the return values.
arr = class_([
decimal.Decimal("1.0"),
decimal.Decimal("2.0")
])
Expand Down

0 comments on commit 7714e79

Please sign in to comment.