5
5
TYPE_CHECKING ,
6
6
Hashable ,
7
7
Sequence ,
8
+ final ,
8
9
)
9
10
import warnings
10
11
@@ -626,6 +627,7 @@ class _LocationIndexer(NDFrameIndexerBase):
626
627
_valid_types : str
627
628
axis = None
628
629
630
+ @final
629
631
def __call__ (self , axis = None ):
630
632
# we need to return a copy of ourselves
631
633
new_self = type (self )(self .name , self .obj )
@@ -640,14 +642,15 @@ def _get_setitem_indexer(self, key):
640
642
Convert a potentially-label-based key into a positional indexer.
641
643
"""
642
644
if self .name == "loc" :
645
+ # always holds here bc iloc overrides _get_setitem_indexer
643
646
self ._ensure_listlike_indexer (key )
644
647
645
648
if isinstance (key , tuple ):
646
649
for x in key :
647
650
check_deprecated_indexers (x )
648
651
649
652
if self .axis is not None :
650
- return self ._convert_tuple (key )
653
+ key = self ._tupleize_axis_indexer (key )
651
654
652
655
ax = self .obj ._get_axis (0 )
653
656
@@ -658,13 +661,26 @@ def _get_setitem_indexer(self, key):
658
661
659
662
if isinstance (key , tuple ):
660
663
with suppress (IndexingError ):
664
+ # suppress "Too many indexers"
661
665
return self ._convert_tuple (key )
662
666
663
667
if isinstance (key , range ):
664
668
return list (key )
665
669
666
670
return self ._convert_to_indexer (key , axis = 0 )
667
671
672
+ @final
673
+ def _tupleize_axis_indexer (self , key ) -> tuple :
674
+ """
675
+ If we have an axis, adapt the given key to be axis-independent.
676
+ """
677
+ new_key = [slice (None )] * self .ndim
678
+ # error: Invalid index type "Optional[Any]" for "List[slice]"; expected
679
+ # type "SupportsIndex"
680
+ new_key [self .axis ] = key # type:ignore[index]
681
+ return tuple (new_key )
682
+
683
+ @final
668
684
def _ensure_listlike_indexer (self , key , axis = None , value = None ):
669
685
"""
670
686
Ensure that a list-like of column labels are all present by adding them if
@@ -702,6 +718,7 @@ def _ensure_listlike_indexer(self, key, axis=None, value=None):
702
718
keys , axis = 0 , consolidate = False , only_slice = True
703
719
)
704
720
721
+ @final
705
722
def __setitem__ (self , key , value ):
706
723
check_deprecated_indexers (key )
707
724
if isinstance (key , tuple ):
@@ -737,6 +754,7 @@ def _validate_key(self, key, axis: int):
737
754
"""
738
755
raise AbstractMethodError (self )
739
756
757
+ @final
740
758
def _expand_ellipsis (self , tup : tuple ) -> tuple :
741
759
"""
742
760
If a tuple key includes an Ellipsis, replace it with an appropriate
@@ -758,6 +776,7 @@ def _expand_ellipsis(self, tup: tuple) -> tuple:
758
776
# by _validate_key_length
759
777
return tup
760
778
779
+ @final
761
780
def _validate_tuple_indexer (self , key : tuple ) -> tuple :
762
781
"""
763
782
Check the key for valid keys across my indexer.
@@ -774,6 +793,7 @@ def _validate_tuple_indexer(self, key: tuple) -> tuple:
774
793
) from err
775
794
return key
776
795
796
+ @final
777
797
def _is_nested_tuple_indexer (self , tup : tuple ) -> bool :
778
798
"""
779
799
Returns
@@ -784,23 +804,18 @@ def _is_nested_tuple_indexer(self, tup: tuple) -> bool:
784
804
return any (is_nested_tuple (tup , ax ) for ax in self .obj .axes )
785
805
return False
786
806
787
- def _convert_tuple (self , key ):
807
+ @final
808
+ def _convert_tuple (self , key : tuple ) -> tuple :
809
+ # Note: we assume _tupleize_axis_indexer has been called, if necessary.
788
810
keyidx = []
789
- if self .axis is not None :
790
- axis = self .obj ._get_axis_number (self .axis )
791
- for i in range (self .ndim ):
792
- if i == axis :
793
- keyidx .append (self ._convert_to_indexer (key , axis = axis ))
794
- else :
795
- keyidx .append (slice (None ))
796
- else :
797
- self ._validate_key_length (key )
798
- for i , k in enumerate (key ):
799
- idx = self ._convert_to_indexer (k , axis = i )
800
- keyidx .append (idx )
811
+ self ._validate_key_length (key )
812
+ for i , k in enumerate (key ):
813
+ idx = self ._convert_to_indexer (k , axis = i )
814
+ keyidx .append (idx )
801
815
802
816
return tuple (keyidx )
803
817
818
+ @final
804
819
def _validate_key_length (self , key : tuple ) -> tuple :
805
820
if len (key ) > self .ndim :
806
821
if key [0 ] is Ellipsis :
@@ -812,6 +827,7 @@ def _validate_key_length(self, key: tuple) -> tuple:
812
827
raise IndexingError ("Too many indexers" )
813
828
return key
814
829
830
+ @final
815
831
def _getitem_tuple_same_dim (self , tup : tuple ):
816
832
"""
817
833
Index with indexers that should return an object of the same dimension
@@ -831,6 +847,7 @@ def _getitem_tuple_same_dim(self, tup: tuple):
831
847
832
848
return retval
833
849
850
+ @final
834
851
def _getitem_lowerdim (self , tup : tuple ):
835
852
836
853
# we can directly get the axis result since the axis is specified
@@ -892,6 +909,7 @@ def _getitem_lowerdim(self, tup: tuple):
892
909
893
910
raise IndexingError ("not applicable" )
894
911
912
+ @final
895
913
def _getitem_nested_tuple (self , tup : tuple ):
896
914
# we have a nested tuple so have at least 1 multi-index level
897
915
# we should be able to match up the dimensionality here
@@ -951,6 +969,7 @@ def _getitem_nested_tuple(self, tup: tuple):
951
969
def _convert_to_indexer (self , key , axis : int ):
952
970
raise AbstractMethodError (self )
953
971
972
+ @final
954
973
def __getitem__ (self , key ):
955
974
check_deprecated_indexers (key )
956
975
if type (key ) is tuple :
@@ -978,6 +997,7 @@ def _getitem_axis(self, key, axis: int):
978
997
def _has_valid_setitem_indexer (self , indexer ) -> bool :
979
998
raise AbstractMethodError (self )
980
999
1000
+ @final
981
1001
def _getbool_axis (self , key , axis : int ):
982
1002
# caller is responsible for ensuring non-None axis
983
1003
labels = self .obj ._get_axis (axis )
@@ -1544,7 +1564,7 @@ def _get_setitem_indexer(self, key):
1544
1564
key = list (key )
1545
1565
1546
1566
if self .axis is not None :
1547
- return self ._convert_tuple (key )
1567
+ key = self ._tupleize_axis_indexer (key )
1548
1568
1549
1569
return key
1550
1570
0 commit comments