Skip to content

TYP: replace Label alias from pandas._typing with Hashable #39107

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions pandas/_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,8 @@
FrameOrSeries = TypeVar("FrameOrSeries", bound="NDFrame")

Axis = Union[str, int]
Label = Optional[Hashable]
IndexLabel = Union[Label, Sequence[Label]]
Level = Union[Label, int]
IndexLabel = Union[Hashable, Sequence[Hashable]]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great i would add some comments here on when to use IndexLabel and that Hashable is a thing. (can be a followup)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe a sperate PR since we may want to discuss renaming to IndexLabelArg for consistency. not thought it through thoroughly yet though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

main reason for this is to have it clear to the maintainer which annotations we should be using where, for consistency.

Level = Union[Hashable, int]
Shape = Tuple[int, ...]
Suffixes = Tuple[str, str]
Ordered = Optional[bool]
Expand All @@ -99,11 +98,11 @@
"ExtensionDtype", NpDtype, Type[Union[str, float, int, complex, bool, object]]
]
# DtypeArg specifies all allowable dtypes in a functions its dtype argument
DtypeArg = Union[Dtype, Dict[Label, Dtype]]
DtypeArg = Union[Dtype, Dict[Hashable, Dtype]]
DtypeObj = Union[np.dtype, "ExtensionDtype"]

# For functions like rename that convert one label to another
Renamer = Union[Mapping[Label, Any], Callable[[Label], Label]]
Renamer = Union[Mapping[Hashable, Any], Callable[[Hashable], Hashable]]

# to maintain type information across generic functions and parametrization
T = TypeVar("T")
Expand All @@ -120,7 +119,7 @@

# types of `func` kwarg for DataFrame.aggregate and Series.aggregate
AggFuncTypeBase = Union[Callable, str]
AggFuncTypeDict = Dict[Label, Union[AggFuncTypeBase, List[AggFuncTypeBase]]]
AggFuncTypeDict = Dict[Hashable, Union[AggFuncTypeBase, List[AggFuncTypeBase]]]
AggFuncType = Union[
AggFuncTypeBase,
List[AggFuncTypeBase],
Expand Down Expand Up @@ -155,8 +154,8 @@
FormattersType = Union[
List[Callable], Tuple[Callable, ...], Mapping[Union[str, int], Callable]
]
ColspaceType = Mapping[Label, Union[str, int]]
ColspaceType = Mapping[Hashable, Union[str, int]]
FloatFormatType = Union[str, Callable, "EngFormatter"]
ColspaceArgType = Union[
str, int, Sequence[Union[str, int]], Mapping[Label, Union[str, int]]
str, int, Sequence[Union[str, int]], Mapping[Hashable, Union[str, int]]
]
10 changes: 5 additions & 5 deletions pandas/core/aggregation.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
Callable,
DefaultDict,
Dict,
Hashable,
Iterable,
List,
Optional,
Expand All @@ -28,7 +29,6 @@
Axis,
FrameOrSeries,
FrameOrSeriesUnion,
Label,
)

from pandas.core.dtypes.cast import is_nested_object
Expand Down Expand Up @@ -294,9 +294,9 @@ def maybe_mangle_lambdas(agg_spec: Any) -> Any:
def relabel_result(
result: FrameOrSeries,
func: Dict[str, List[Union[Callable, str]]],
columns: Iterable[Label],
columns: Iterable[Hashable],
order: Iterable[int],
) -> Dict[Label, "Series"]:
) -> Dict[Hashable, "Series"]:
"""
Internal function to reorder result if relabelling is True for
dataframe.agg, and return the reordered result in dict.
Expand All @@ -323,7 +323,7 @@ def relabel_result(
reordered_indexes = [
pair[0] for pair in sorted(zip(columns, order), key=lambda t: t[1])
]
reordered_result_in_dict: Dict[Label, "Series"] = {}
reordered_result_in_dict: Dict[Hashable, "Series"] = {}
idx = 0

reorder_mask = not isinstance(result, ABCSeries) and len(result.columns) > 1
Expand Down Expand Up @@ -493,7 +493,7 @@ def transform_dict_like(
# GH 15931 - deprecation of renaming keys
raise SpecificationError("nested renamer is not supported")

results: Dict[Label, FrameOrSeriesUnion] = {}
results: Dict[Hashable, FrameOrSeriesUnion] = {}
for name, how in func.items():
colg = obj._gotitem(name, ndim=1)
try:
Expand Down
6 changes: 2 additions & 4 deletions pandas/core/computation/parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
from keyword import iskeyword
import token
import tokenize
from typing import Iterator, Tuple

from pandas._typing import Label
from typing import Hashable, Iterator, Tuple

# A token value Python's tokenizer probably will never use.
BACKTICK_QUOTED_STRING = 100
Expand Down Expand Up @@ -90,7 +88,7 @@ def clean_backtick_quoted_toks(tok: Tuple[int, str]) -> Tuple[int, str]:
return toknum, tokval


def clean_column_name(name: "Label") -> "Label":
def clean_column_name(name: Hashable) -> Hashable:
"""
Function to emulate the cleaning of a backtick quoted name.

Expand Down
33 changes: 16 additions & 17 deletions pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@
FrameOrSeriesUnion,
IndexKeyFunc,
IndexLabel,
Label,
Level,
PythonFuncType,
Renamer,
Expand Down Expand Up @@ -992,7 +991,7 @@ def style(self) -> Styler:
"""

@Appender(_shared_docs["items"])
def items(self) -> Iterable[Tuple[Label, Series]]:
def items(self) -> Iterable[Tuple[Hashable, Series]]:
if self.columns.is_unique and hasattr(self, "_item_cache"):
for k in self.columns:
yield k, self._get_item_cache(k)
Expand All @@ -1001,10 +1000,10 @@ def items(self) -> Iterable[Tuple[Label, Series]]:
yield k, self._ixs(i, axis=1)

@Appender(_shared_docs["items"])
def iteritems(self) -> Iterable[Tuple[Label, Series]]:
def iteritems(self) -> Iterable[Tuple[Hashable, Series]]:
yield from self.items()

def iterrows(self) -> Iterable[Tuple[Label, Series]]:
def iterrows(self) -> Iterable[Tuple[Hashable, Series]]:
"""
Iterate over DataFrame rows as (index, Series) pairs.

Expand Down Expand Up @@ -2121,14 +2120,14 @@ def _from_arrays(
def to_stata(
self,
path: FilePathOrBuffer,
convert_dates: Optional[Dict[Label, str]] = None,
convert_dates: Optional[Dict[Hashable, str]] = None,
write_index: bool = True,
byteorder: Optional[str] = None,
time_stamp: Optional[datetime.datetime] = None,
data_label: Optional[str] = None,
variable_labels: Optional[Dict[Label, str]] = None,
variable_labels: Optional[Dict[Hashable, str]] = None,
version: Optional[int] = 114,
convert_strl: Optional[Sequence[Label]] = None,
convert_strl: Optional[Sequence[Hashable]] = None,
compression: CompressionOptions = "infer",
storage_options: StorageOptions = None,
) -> None:
Expand Down Expand Up @@ -4483,7 +4482,7 @@ def fillna(
downcast=downcast,
)

def pop(self, item: Label) -> Series:
def pop(self, item: Hashable) -> Series:
"""
Return item and drop from frame. Raise KeyError if not found.

Expand Down Expand Up @@ -4546,7 +4545,7 @@ def replace(
)

def _replace_columnwise(
self, mapping: Dict[Label, Tuple[Any, Any]], inplace: bool, regex
self, mapping: Dict[Hashable, Tuple[Any, Any]], inplace: bool, regex
):
"""
Dispatch to Series.replace column-wise.
Expand Down Expand Up @@ -4724,7 +4723,7 @@ def set_index(
"one-dimensional arrays."
)

missing: List[Label] = []
missing: List[Hashable] = []
for col in keys:
if isinstance(col, (Index, Series, np.ndarray, list, abc.Iterator)):
# arrays are fine as long as they are one-dimensional
Expand Down Expand Up @@ -4752,7 +4751,7 @@ def set_index(
frame = self.copy()

arrays = []
names: List[Label] = []
names: List[Hashable] = []
if append:
names = list(self.index.names)
if isinstance(self.index, MultiIndex):
Expand All @@ -4761,7 +4760,7 @@ def set_index(
else:
arrays.append(self.index)

to_remove: List[Label] = []
to_remove: List[Hashable] = []
for col in keys:
if isinstance(col, MultiIndex):
for n in range(col.nlevels):
Expand Down Expand Up @@ -4819,7 +4818,7 @@ def reset_index( # type: ignore[misc]
drop: bool = ...,
inplace: Literal[False] = ...,
col_level: Hashable = ...,
col_fill: Label = ...,
col_fill: Hashable = ...,
) -> DataFrame:
...

Expand All @@ -4830,7 +4829,7 @@ def reset_index(
drop: bool = ...,
inplace: Literal[True] = ...,
col_level: Hashable = ...,
col_fill: Label = ...,
col_fill: Hashable = ...,
) -> None:
...

Expand All @@ -4840,7 +4839,7 @@ def reset_index(
drop: bool = False,
inplace: bool = False,
col_level: Hashable = 0,
col_fill: Label = "",
col_fill: Hashable = "",
) -> Optional[DataFrame]:
"""
Reset the index, or a level of it.
Expand Down Expand Up @@ -5630,7 +5629,7 @@ def sort_index(

def value_counts(
self,
subset: Optional[Sequence[Label]] = None,
subset: Optional[Sequence[Hashable]] = None,
normalize: bool = False,
sort: bool = True,
ascending: bool = False,
Expand Down Expand Up @@ -7511,7 +7510,7 @@ def diff(self, periods: int = 1, axis: Axis = 0) -> DataFrame:

def _gotitem(
self,
key: Union[Label, List[Label]],
key: IndexLabel,
ndim: int,
subset: Optional[FrameOrSeriesUnion] = None,
) -> FrameOrSeriesUnion:
Expand Down
11 changes: 5 additions & 6 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
IndexKeyFunc,
IndexLabel,
JSONSerializable,
Label,
Level,
NpDtype,
Renamer,
Expand Down Expand Up @@ -526,7 +525,7 @@ def _get_axis_resolvers(self, axis: str) -> Dict[str, Union[Series, MultiIndex]]
return d

@final
def _get_index_resolvers(self) -> Dict[Label, Union[Series, MultiIndex]]:
def _get_index_resolvers(self) -> Dict[Hashable, Union[Series, MultiIndex]]:
from pandas.core.computation.parsing import clean_column_name

d: Dict[str, Union[Series, MultiIndex]] = {}
Expand All @@ -536,7 +535,7 @@ def _get_index_resolvers(self) -> Dict[Label, Union[Series, MultiIndex]]:
return {clean_column_name(k): v for k, v in d.items() if not isinstance(k, int)}

@final
def _get_cleaned_column_resolvers(self) -> Dict[Label, Series]:
def _get_cleaned_column_resolvers(self) -> Dict[Hashable, Series]:
"""
Return the special character free column resolvers of a dataframe.

Expand Down Expand Up @@ -776,7 +775,7 @@ def droplevel(self: FrameOrSeries, level, axis=0) -> FrameOrSeries:
result = self.set_axis(new_labels, axis=axis, inplace=False)
return result

def pop(self, item: Label) -> Union[Series, Any]:
def pop(self, item: Hashable) -> Union[Series, Any]:
result = self[item]
del self[item]
if self.ndim == 2:
Expand Down Expand Up @@ -3225,7 +3224,7 @@ def to_csv(
sep: str = ",",
na_rep: str = "",
float_format: Optional[str] = None,
columns: Optional[Sequence[Label]] = None,
columns: Optional[Sequence[Hashable]] = None,
header: Union[bool_t, List[str]] = True,
index: bool_t = True,
index_label: Optional[IndexLabel] = None,
Expand Down Expand Up @@ -10214,7 +10213,7 @@ def describe_1d(data) -> "Series":

ldesc = [describe_1d(s) for _, s in data.items()]
# set a convenient order for rows
names: List[Label] = []
names: List[Hashable] = []
ldesc_indexes = sorted((x.index for x in ldesc), key=len)
for idxnames in ldesc_indexes:
for name in idxnames:
Expand Down
5 changes: 3 additions & 2 deletions pandas/core/groupby/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
Callable,
Dict,
FrozenSet,
Hashable,
Iterable,
List,
Mapping,
Expand All @@ -30,7 +31,7 @@
import numpy as np

from pandas._libs import lib, reduction as libreduction
from pandas._typing import ArrayLike, FrameOrSeries, FrameOrSeriesUnion, Label
from pandas._typing import ArrayLike, FrameOrSeries, FrameOrSeriesUnion
from pandas.util._decorators import Appender, Substitution, doc

from pandas.core.dtypes.cast import (
Expand Down Expand Up @@ -1129,7 +1130,7 @@ def _aggregate_frame(self, func, *args, **kwargs) -> DataFrame:
axis = self.axis
obj = self._obj_with_exclusions

result: Dict[Label, Union[NDFrame, np.ndarray]] = {}
result: Dict[Hashable, Union[NDFrame, np.ndarray]] = {}
if axis != obj._info_axis_number:
for name, data in self:
fres = func(data, *args, **kwargs)
Expand Down
5 changes: 2 additions & 3 deletions pandas/core/groupby/groupby.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ class providing the base-class of operations.
FrameOrSeries,
FrameOrSeriesUnion,
IndexLabel,
Label,
Scalar,
final,
)
Expand Down Expand Up @@ -522,7 +521,7 @@ def __init__(
axis: int = 0,
level: Optional[IndexLabel] = None,
grouper: Optional["ops.BaseGrouper"] = None,
exclusions: Optional[Set[Label]] = None,
exclusions: Optional[Set[Hashable]] = None,
selection: Optional[IndexLabel] = None,
as_index: bool = True,
sort: bool = True,
Expand Down Expand Up @@ -860,7 +859,7 @@ def get_group(self, name, obj=None):

return obj._take_with_is_copy(inds, axis=self.axis)

def __iter__(self) -> Iterator[Tuple[Label, FrameOrSeries]]:
def __iter__(self) -> Iterator[Tuple[Hashable, FrameOrSeries]]:
"""
Groupby iterator.

Expand Down
6 changes: 3 additions & 3 deletions pandas/core/groupby/grouper.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import numpy as np

from pandas._typing import FrameOrSeries, Label, final
from pandas._typing import FrameOrSeries, final
from pandas.errors import InvalidIndexError
from pandas.util._decorators import cache_readonly

Expand Down Expand Up @@ -616,7 +616,7 @@ def get_grouper(
mutated: bool = False,
validate: bool = True,
dropna: bool = True,
) -> Tuple["ops.BaseGrouper", Set[Label], FrameOrSeries]:
) -> Tuple["ops.BaseGrouper", Set[Hashable], FrameOrSeries]:
"""
Create and return a BaseGrouper, which is an internal
mapping of how to create the grouper indexers.
Expand Down Expand Up @@ -741,7 +741,7 @@ def get_grouper(
levels = [level] * len(keys)

groupings: List[Grouping] = []
exclusions: Set[Label] = set()
exclusions: Set[Hashable] = set()

# if the actual grouper should be obj[key]
def is_in_axis(key) -> bool:
Expand Down
Loading