Skip to content

Commit 2b0f190

Browse files
authored
REF: avoid accessing ._engine in Series/DataFrame (#41956)
1 parent c704d04 commit 2b0f190

File tree

4 files changed

+20
-31
lines changed

4 files changed

+20
-31
lines changed

pandas/core/frame.py

+13-19
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,6 @@
158158
from pandas.core.indexers import check_key_length
159159
from pandas.core.indexes import base as ibase
160160
from pandas.core.indexes.api import (
161-
CategoricalIndex,
162161
DatetimeIndex,
163162
Index,
164163
PeriodIndex,
@@ -3557,8 +3556,8 @@ def _get_value(self, index, col, takeable: bool = False) -> Scalar:
35573556
35583557
Notes
35593558
-----
3560-
Assumes that index and columns both have ax._index_as_unique;
3561-
caller is responsible for checking.
3559+
Assumes that both `self.index._index_as_unique` and
3560+
`self.columns._index_as_unique`; Caller is responsible for checking.
35623561
"""
35633562
if takeable:
35643563
series = self._ixs(col, axis=1)
@@ -3567,21 +3566,17 @@ def _get_value(self, index, col, takeable: bool = False) -> Scalar:
35673566
series = self._get_item_cache(col)
35683567
engine = self.index._engine
35693568

3570-
if isinstance(self.index, CategoricalIndex):
3571-
# Trying to use the engine fastpath may give incorrect results
3572-
# if our categories are integers that dont match our codes
3573-
col = self.columns.get_loc(col)
3574-
index = self.index.get_loc(index)
3575-
return self._get_value(index, col, takeable=True)
3569+
if not isinstance(self.index, MultiIndex):
3570+
# CategoricalIndex: Trying to use the engine fastpath may give incorrect
3571+
# results if our categories are integers that dont match our codes
3572+
# IntervalIndex: IntervalTree has no get_loc
3573+
row = self.index.get_loc(index)
3574+
return series._values[row]
35763575

3577-
try:
3578-
loc = engine.get_loc(index)
3579-
return series._values[loc]
3580-
except AttributeError:
3581-
# IntervalTree has no get_loc
3582-
col = self.columns.get_loc(col)
3583-
index = self.index.get_loc(index)
3584-
return self._get_value(index, col, takeable=True)
3576+
# For MultiIndex going through engine effectively restricts us to
3577+
# same-length tuples; see test_get_set_value_no_partial_indexing
3578+
loc = engine.get_loc(index)
3579+
return series._values[loc]
35853580

35863581
def __setitem__(self, key, value):
35873582
key = com.apply_if_callable(key, self)
@@ -3816,8 +3811,7 @@ def _set_value(
38163811
return
38173812

38183813
series = self._get_item_cache(col)
3819-
engine = self.index._engine
3820-
loc = engine.get_loc(index)
3814+
loc = self.index.get_loc(index)
38213815
validate_numeric_casting(series.dtype, value)
38223816

38233817
series._values[loc] = value

pandas/core/indexing.py

+5-10
Original file line numberDiff line numberDiff line change
@@ -916,8 +916,7 @@ def __getitem__(self, key):
916916
key = tuple(list(x) if is_iterator(x) else x for x in key)
917917
key = tuple(com.apply_if_callable(x, self.obj) for x in key)
918918
if self._is_scalar_access(key):
919-
with suppress(KeyError, IndexError):
920-
return self.obj._get_value(*key, takeable=self._takeable)
919+
return self.obj._get_value(*key, takeable=self._takeable)
921920
return self._getitem_tuple(key)
922921
else:
923922
# we by definition only have the 0th axis
@@ -2187,7 +2186,7 @@ class _ScalarAccessIndexer(NDFrameIndexerBase):
21872186
Access scalars quickly.
21882187
"""
21892188

2190-
def _convert_key(self, key, is_setter: bool = False):
2189+
def _convert_key(self, key):
21912190
raise AbstractMethodError(self)
21922191

21932192
def __getitem__(self, key):
@@ -2211,7 +2210,7 @@ def __setitem__(self, key, value):
22112210

22122211
if not isinstance(key, tuple):
22132212
key = _tuplify(self.ndim, key)
2214-
key = list(self._convert_key(key, is_setter=True))
2213+
key = list(self._convert_key(key))
22152214
if len(key) != self.ndim:
22162215
raise ValueError("Not enough indexers for scalar access (setting)!")
22172216

@@ -2222,7 +2221,7 @@ def __setitem__(self, key, value):
22222221
class _AtIndexer(_ScalarAccessIndexer):
22232222
_takeable = False
22242223

2225-
def _convert_key(self, key, is_setter: bool = False):
2224+
def _convert_key(self, key):
22262225
"""
22272226
Require they keys to be the same type as the index. (so we don't
22282227
fallback)
@@ -2233,10 +2232,6 @@ def _convert_key(self, key, is_setter: bool = False):
22332232
if self.ndim == 1 and len(key) > 1:
22342233
key = (key,)
22352234

2236-
# allow arbitrary setting
2237-
if is_setter:
2238-
return list(key)
2239-
22402235
return key
22412236

22422237
@property
@@ -2271,7 +2266,7 @@ def __setitem__(self, key, value):
22712266
class _iAtIndexer(_ScalarAccessIndexer):
22722267
_takeable = True
22732268

2274-
def _convert_key(self, key, is_setter: bool = False):
2269+
def _convert_key(self, key):
22752270
"""
22762271
Require integer args. (and convert to label arguments)
22772272
"""

pandas/tests/indexing/test_iloc.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ def test_iloc_getitem_labelled_frame(self):
596596
assert result == exp
597597

598598
# out-of-bounds exception
599-
msg = "single positional indexer is out-of-bounds"
599+
msg = "index 5 is out of bounds for axis 0 with size 4"
600600
with pytest.raises(IndexError, match=msg):
601601
df.iloc[10, 5]
602602

pandas/tests/indexing/test_indexing.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ def test_string_slice_empty(self):
518518
with pytest.raises(KeyError, match="'2011'"):
519519
df["2011"]
520520

521-
with pytest.raises(KeyError, match="'2011'"):
521+
with pytest.raises(KeyError, match="^0$"):
522522
df.loc["2011", 0]
523523

524524
def test_astype_assignment(self):

0 commit comments

Comments
 (0)