12
12
from typing import (
13
13
TYPE_CHECKING ,
14
14
Literal ,
15
+ final ,
15
16
)
16
17
import warnings
17
18
@@ -274,6 +275,7 @@ def __init__(
274
275
275
276
self ._validate_color_args ()
276
277
278
+ @final
277
279
def _validate_subplots_kwarg (
278
280
self , subplots : bool | Sequence [Sequence [str ]]
279
281
) -> bool | list [tuple [int , ...]]:
@@ -420,6 +422,7 @@ def _validate_color_args(self):
420
422
"other or pass 'style' without a color symbol"
421
423
)
422
424
425
+ @final
423
426
def _iter_data (self , data = None , keep_index : bool = False , fillna = None ):
424
427
if data is None :
425
428
data = self .data
@@ -445,9 +448,11 @@ def nseries(self) -> int:
445
448
else :
446
449
return self .data .shape [1 ]
447
450
451
+ @final
448
452
def draw (self ) -> None :
449
453
self .plt .draw_if_interactive ()
450
454
455
+ @final
451
456
def generate (self ) -> None :
452
457
self ._args_adjust ()
453
458
self ._compute_plot_data ()
@@ -465,11 +470,13 @@ def generate(self) -> None:
465
470
def _args_adjust (self ) -> None :
466
471
pass
467
472
473
+ @final
468
474
def _has_plotted_object (self , ax : Axes ) -> bool :
469
475
"""check whether ax has data"""
470
476
return len (ax .lines ) != 0 or len (ax .artists ) != 0 or len (ax .containers ) != 0
471
477
472
- def _maybe_right_yaxis (self , ax : Axes , axes_num ):
478
+ @final
479
+ def _maybe_right_yaxis (self , ax : Axes , axes_num : int ):
473
480
if not self .on_right (axes_num ):
474
481
# secondary axes may be passed via ax kw
475
482
return self ._get_ax_layer (ax )
@@ -497,6 +504,7 @@ def _maybe_right_yaxis(self, ax: Axes, axes_num):
497
504
new_ax .set_yscale ("symlog" )
498
505
return new_ax
499
506
507
+ @final
500
508
def _setup_subplots (self ) -> Figure :
501
509
if self .subplots :
502
510
naxes = (
@@ -567,6 +575,7 @@ def result(self):
567
575
else :
568
576
return self .axes [0 ]
569
577
578
+ @final
570
579
def _convert_to_ndarray (self , data ):
571
580
# GH31357: categorical columns are processed separately
572
581
if isinstance (data .dtype , CategoricalDtype ):
@@ -585,6 +594,7 @@ def _convert_to_ndarray(self, data):
585
594
586
595
return data
587
596
597
+ @final
588
598
def _compute_plot_data (self ):
589
599
data = self .data
590
600
@@ -642,6 +652,7 @@ def _compute_plot_data(self):
642
652
def _make_plot (self , fig : Figure ):
643
653
raise AbstractMethodError (self )
644
654
655
+ @final
645
656
def _add_table (self ) -> None :
646
657
if self .table is False :
647
658
return
@@ -652,6 +663,7 @@ def _add_table(self) -> None:
652
663
ax = self ._get_ax (0 )
653
664
tools .table (ax , data )
654
665
666
+ @final
655
667
def _post_plot_logic_common (self , ax , data ):
656
668
"""Common post process for each axes"""
657
669
if self .orientation == "vertical" or self .orientation is None :
@@ -674,6 +686,7 @@ def _post_plot_logic_common(self, ax, data):
674
686
def _post_plot_logic (self , ax , data ) -> None :
675
687
"""Post process for each axes. Overridden in child classes"""
676
688
689
+ @final
677
690
def _adorn_subplots (self , fig : Figure ):
678
691
"""Common post process unrelated to data"""
679
692
if len (self .axes ) > 0 :
@@ -735,6 +748,7 @@ def _adorn_subplots(self, fig: Figure):
735
748
raise ValueError (msg )
736
749
self .axes [0 ].set_title (self .title )
737
750
751
+ @final
738
752
def _apply_axis_properties (
739
753
self , axis : Axis , rot = None , fontsize : int | None = None
740
754
) -> None :
@@ -764,6 +778,7 @@ def legend_title(self) -> str | None:
764
778
stringified = map (pprint_thing , self .data .columns .names )
765
779
return "," .join (stringified )
766
780
781
+ @final
767
782
def _mark_right_label (self , label : str , index : int ) -> str :
768
783
"""
769
784
Append ``(right)`` to the label of a line if it's plotted on the right axis.
@@ -774,6 +789,7 @@ def _mark_right_label(self, label: str, index: int) -> str:
774
789
label += " (right)"
775
790
return label
776
791
792
+ @final
777
793
def _append_legend_handles_labels (self , handle : Artist , label : str ) -> None :
778
794
"""
779
795
Append current handle and label to ``legend_handles`` and ``legend_labels``.
@@ -819,6 +835,7 @@ def _make_legend(self) -> None:
819
835
if ax .get_visible ():
820
836
ax .legend (loc = "best" )
821
837
838
+ @final
822
839
def _get_ax_legend (self , ax : Axes ):
823
840
"""
824
841
Take in axes and return ax and legend under different scenarios
@@ -834,6 +851,7 @@ def _get_ax_legend(self, ax: Axes):
834
851
ax = other_ax
835
852
return ax , leg
836
853
854
+ @final
837
855
@cache_readonly
838
856
def plt (self ):
839
857
import matplotlib .pyplot as plt
@@ -842,6 +860,7 @@ def plt(self):
842
860
843
861
_need_to_set_index = False
844
862
863
+ @final
845
864
def _get_xticks (self , convert_period : bool = False ):
846
865
index = self .data .index
847
866
is_datetype = index .inferred_type in ("datetime" , "date" , "datetime64" , "time" )
@@ -896,6 +915,7 @@ def _get_custom_index_name(self):
896
915
"""Specify whether xlabel/ylabel should be used to override index name"""
897
916
return self .xlabel
898
917
918
+ @final
899
919
def _get_index_name (self ) -> str | None :
900
920
if isinstance (self .data .index , ABCMultiIndex ):
901
921
name = self .data .index .names
@@ -915,6 +935,7 @@ def _get_index_name(self) -> str | None:
915
935
916
936
return name
917
937
938
+ @final
918
939
@classmethod
919
940
def _get_ax_layer (cls , ax , primary : bool = True ):
920
941
"""get left (primary) or right (secondary) axes"""
@@ -923,6 +944,7 @@ def _get_ax_layer(cls, ax, primary: bool = True):
923
944
else :
924
945
return getattr (ax , "right_ax" , ax )
925
946
947
+ @final
926
948
def _col_idx_to_axis_idx (self , col_idx : int ) -> int :
927
949
"""Return the index of the axis where the column at col_idx should be plotted"""
928
950
if isinstance (self .subplots , list ):
@@ -936,6 +958,7 @@ def _col_idx_to_axis_idx(self, col_idx: int) -> int:
936
958
# subplots is True: one ax per column
937
959
return col_idx
938
960
961
+ @final
939
962
def _get_ax (self , i : int ):
940
963
# get the twinx ax if appropriate
941
964
if self .subplots :
@@ -950,6 +973,7 @@ def _get_ax(self, i: int):
950
973
ax .get_yaxis ().set_visible (True )
951
974
return ax
952
975
976
+ @final
953
977
@classmethod
954
978
def get_default_ax (cls , ax ) -> None :
955
979
import matplotlib .pyplot as plt
@@ -959,13 +983,15 @@ def get_default_ax(cls, ax) -> None:
959
983
ax = plt .gca ()
960
984
ax = cls ._get_ax_layer (ax )
961
985
962
- def on_right (self , i ):
986
+ @final
987
+ def on_right (self , i : int ):
963
988
if isinstance (self .secondary_y , bool ):
964
989
return self .secondary_y
965
990
966
991
if isinstance (self .secondary_y , (tuple , list , np .ndarray , ABCIndex )):
967
992
return self .data .columns [i ] in self .secondary_y
968
993
994
+ @final
969
995
def _apply_style_colors (self , colors , kwds , col_num , label : str ):
970
996
"""
971
997
Manage style and color based on column number and its label.
@@ -1006,6 +1032,7 @@ def _get_colors(
1006
1032
color = self .kwds .get (color_kwds ),
1007
1033
)
1008
1034
1035
+ @final
1009
1036
def _parse_errorbars (self , label , err ):
1010
1037
"""
1011
1038
Look for error keyword arguments and return the actual errorbar data
@@ -1095,6 +1122,7 @@ def match_labels(data, e):
1095
1122
1096
1123
return err
1097
1124
1125
+ @final
1098
1126
def _get_errorbars (
1099
1127
self , label = None , index = None , xerr : bool = True , yerr : bool = True
1100
1128
):
@@ -1116,6 +1144,7 @@ def _get_errorbars(
1116
1144
errors [kw ] = err
1117
1145
return errors
1118
1146
1147
+ @final
1119
1148
def _get_subplots (self , fig : Figure ):
1120
1149
from matplotlib .axes import Subplot
1121
1150
@@ -1125,6 +1154,7 @@ def _get_subplots(self, fig: Figure):
1125
1154
if (isinstance (ax , Subplot ) and ax .get_subplotspec () is not None )
1126
1155
]
1127
1156
1157
+ @final
1128
1158
def _get_axes_layout (self , fig : Figure ) -> tuple [int , int ]:
1129
1159
axes = self ._get_subplots (fig )
1130
1160
x_set = set ()
@@ -1163,17 +1193,20 @@ def __init__(self, data, x, y, **kwargs) -> None:
1163
1193
self .x = x
1164
1194
self .y = y
1165
1195
1196
+ @final
1166
1197
@property
1167
1198
def nseries (self ) -> int :
1168
1199
return 1
1169
1200
1201
+ @final
1170
1202
def _post_plot_logic (self , ax : Axes , data ) -> None :
1171
1203
x , y = self .x , self .y
1172
1204
xlabel = self .xlabel if self .xlabel is not None else pprint_thing (x )
1173
1205
ylabel = self .ylabel if self .ylabel is not None else pprint_thing (y )
1174
1206
ax .set_xlabel (xlabel )
1175
1207
ax .set_ylabel (ylabel )
1176
1208
1209
+ @final
1177
1210
def _plot_colorbar (self , ax : Axes , * , fig : Figure , ** kwds ):
1178
1211
# Addresses issues #10611 and #10678:
1179
1212
# When plotting scatterplots and hexbinplots in IPython
@@ -1353,10 +1386,12 @@ def __init__(self, data, **kwargs) -> None:
1353
1386
if "x_compat" in self .kwds :
1354
1387
self .x_compat = bool (self .kwds .pop ("x_compat" ))
1355
1388
1389
+ @final
1356
1390
def _is_ts_plot (self ) -> bool :
1357
1391
# this is slightly deceptive
1358
1392
return not self .x_compat and self .use_index and self ._use_dynamic_x ()
1359
1393
1394
+ @final
1360
1395
def _use_dynamic_x (self ):
1361
1396
return use_dynamic_x (self ._get_ax (0 ), self .data )
1362
1397
@@ -1424,6 +1459,7 @@ def _plot( # type: ignore[override]
1424
1459
cls ._update_stacker (ax , stacking_id , y )
1425
1460
return lines
1426
1461
1462
+ @final
1427
1463
def _ts_plot (self , ax : Axes , x , data , style = None , ** kwds ):
1428
1464
# accept x to be consistent with normal plot func,
1429
1465
# x is not passed to tsplot as it uses data.index as x coordinate
@@ -1444,12 +1480,14 @@ def _ts_plot(self, ax: Axes, x, data, style=None, **kwds):
1444
1480
format_dateaxis (ax , ax .freq , data .index )
1445
1481
return lines
1446
1482
1483
+ @final
1447
1484
def _get_stacking_id (self ):
1448
1485
if self .stacked :
1449
1486
return id (self .data )
1450
1487
else :
1451
1488
return None
1452
1489
1490
+ @final
1453
1491
@classmethod
1454
1492
def _initialize_stacker (cls , ax : Axes , stacking_id , n : int ) -> None :
1455
1493
if stacking_id is None :
@@ -1461,6 +1499,7 @@ def _initialize_stacker(cls, ax: Axes, stacking_id, n: int) -> None:
1461
1499
ax ._stacker_pos_prior [stacking_id ] = np .zeros (n )
1462
1500
ax ._stacker_neg_prior [stacking_id ] = np .zeros (n )
1463
1501
1502
+ @final
1464
1503
@classmethod
1465
1504
def _get_stacked_values (cls , ax : Axes , stacking_id , values , label ):
1466
1505
if stacking_id is None :
@@ -1480,6 +1519,7 @@ def _get_stacked_values(cls, ax: Axes, stacking_id, values, label):
1480
1519
f"Column '{ label } ' contains both positive and negative values"
1481
1520
)
1482
1521
1522
+ @final
1483
1523
@classmethod
1484
1524
def _update_stacker (cls , ax : Axes , stacking_id , values ) -> None :
1485
1525
if stacking_id is None :
0 commit comments