Skip to content

Commit

Permalink
CLN: callable to Series.iloc returning a tuple (pandas-dev#58626)
Browse files Browse the repository at this point in the history
* CLN: callable to Series.iloc returning a tuple

* undo other change

* concat string

* Update doc/source/whatsnew/v3.0.0.rst

Co-authored-by: William Ayd <william.ayd@icloud.com>

---------

Co-authored-by: William Ayd <william.ayd@icloud.com>
  • Loading branch information
mroeschke and WillAyd authored May 8, 2024
1 parent d642a87 commit 231d652
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 14 deletions.
1 change: 1 addition & 0 deletions doc/source/whatsnew/v3.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ Removal of prior version deprecations/changes
- All arguments except ``name`` in :meth:`Index.rename` are now keyword only (:issue:`56493`)
- All arguments except the first ``path``-like argument in IO writers are now keyword only (:issue:`54229`)
- Changed behavior of :meth:`Series.__getitem__` and :meth:`Series.__setitem__` to always treat integer keys as labels, never as positional, consistent with :class:`DataFrame` behavior (:issue:`50617`)
- Disallow a callable argument to :meth:`Series.iloc` to return a ``tuple`` (:issue:`53769`)
- Disallow allowing logical operations (``||``, ``&``, ``^``) between pandas objects and dtype-less sequences (e.g. ``list``, ``tuple``); wrap the objects in :class:`Series`, :class:`Index`, or ``np.array`` first instead (:issue:`52264`)
- Disallow automatic casting to object in :class:`Series` logical operations (``&``, ``^``, ``||``) between series with mismatched indexes and dtypes other than ``object`` or ``bool`` (:issue:`52538`)
- Disallow calling :meth:`Series.replace` or :meth:`DataFrame.replace` without a ``value`` and with non-dict-like ``to_replace`` (:issue:`33302`)
Expand Down
15 changes: 6 additions & 9 deletions pandas/core/indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def iloc(self) -> _iLocIndexer:
"""
Purely integer-location based indexing for selection by position.
.. deprecated:: 2.2.0
.. versionchanged:: 3.0
Returning a tuple from a callable is deprecated.
Expand Down Expand Up @@ -905,7 +905,7 @@ def __setitem__(self, key, value) -> None:
key = tuple(com.apply_if_callable(x, self.obj) for x in key)
else:
maybe_callable = com.apply_if_callable(key, self.obj)
key = self._check_deprecated_callable_usage(key, maybe_callable)
key = self._raise_callable_usage(key, maybe_callable)
indexer = self._get_setitem_indexer(key)
self._has_valid_setitem_indexer(key)

Expand Down Expand Up @@ -1164,14 +1164,11 @@ def _contains_slice(x: object) -> bool:
def _convert_to_indexer(self, key, axis: AxisInt):
raise AbstractMethodError(self)

def _check_deprecated_callable_usage(self, key: Any, maybe_callable: T) -> T:
def _raise_callable_usage(self, key: Any, maybe_callable: T) -> T:
# GH53533
if self.name == "iloc" and callable(key) and isinstance(maybe_callable, tuple):
warnings.warn(
"Returning a tuple from a callable with iloc "
"is deprecated and will be removed in a future version",
FutureWarning,
stacklevel=find_stack_level(),
raise ValueError(
"Returning a tuple from a callable with iloc is not allowed.",
)
return maybe_callable

Expand All @@ -1189,7 +1186,7 @@ def __getitem__(self, key):
axis = self.axis or 0

maybe_callable = com.apply_if_callable(key, self.obj)
maybe_callable = self._check_deprecated_callable_usage(key, maybe_callable)
maybe_callable = self._raise_callable_usage(key, maybe_callable)
return self._getitem_axis(maybe_callable, axis=axis)

def _is_scalar_access(self, key: tuple):
Expand Down
10 changes: 5 additions & 5 deletions pandas/tests/frame/indexing/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1019,13 +1019,13 @@ def test_single_element_ix_dont_upcast(self, float_frame):
result = df.loc[[0], "b"]
tm.assert_series_equal(result, expected)

def test_iloc_callable_tuple_return_value(self):
# GH53769
def test_iloc_callable_tuple_return_value_raises(self):
# GH53769: Enforced pandas 3.0
df = DataFrame(np.arange(40).reshape(10, 4), index=range(0, 20, 2))
msg = "callable with iloc"
with tm.assert_produces_warning(FutureWarning, match=msg):
msg = "Returning a tuple from"
with pytest.raises(ValueError, match=msg):
df.iloc[lambda _: (0,)]
with tm.assert_produces_warning(FutureWarning, match=msg):
with pytest.raises(ValueError, match=msg):
df.iloc[lambda _: (0,)] = 1

def test_iloc_row(self):
Expand Down

0 comments on commit 231d652

Please sign in to comment.