Skip to content

CLN, TYP use string types in generics #39270

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

Closed
wants to merge 1 commit into from
Closed
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
8 changes: 7 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,15 @@ repos:
(?x)
\#\ type:\ (?!ignore)|
\#\ type:\s?ignore(?!\[)|
\)\ ->\ \"

# string return type annotation
\)\ ->\ \"|

# string type annotation in generic
(Callable|Dict|Iterable|Iterator|List|Mapping|MutableMapping|Sequence|Set|Tuple|Type|Union)\[[^\]]*\".+?\"[^\]]*\]
language: pygrep
types: [python]
exclude: ^pandas/_typing\.py$
Copy link
Member

Choose a reason for hiding this comment

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

is this because of aliases? If so, we may also define aliases local to a module, so we would need to allow if preceeded by =

Copy link
Member

@simonjayhawkins simonjayhawkins Jan 19, 2021

Choose a reason for hiding this comment

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

we also have the issue of casts and TypeVars, which still require the quoting.

Copy link
Member Author

Choose a reason for hiding this comment

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

It's not because of aliases (they're fine), but because in _typing we would otherwise get

ImportError while loading conftest '/home/marco/pandas-marco/pandas/conftest.py'.
pandas/__init__.py:22: in <module>
    from pandas.compat.numpy import (
pandas/compat/__init__.py:14: in <module>
    from pandas._typing import F
pandas/_typing.py:79: in <module>
    FrameOrSeriesUnion = Union["DataFrame", Series]
E   NameError: name 'Series' is not defined

because Series is only defined if TYPE_CHECKING (same situation as in the other comment)

Copy link
Member

Choose a reason for hiding this comment

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

yep, I wasn't clear. it's not just type aliases https://www.python.org/dev/peps/pep-0563/#forward-references

This PEP addresses the issue of forward references in type annotations. The use of string literals will no longer be required in this case. However, there are APIs in the typing module that use other syntactic constructs of the language, and those will still require working around forward references with string literals. The list includes:

- id: np-bool
name: Check for use of np.bool instead of np.bool_
entry: np\.bool[^_8]
Expand Down
6 changes: 4 additions & 2 deletions pandas/core/aggregation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
kwarg aggregations in groupby and DataFrame/Series aggregation
"""

from __future__ import annotations

from collections import defaultdict
from functools import partial
from typing import (
Expand Down Expand Up @@ -296,7 +298,7 @@ def relabel_result(
func: Dict[str, List[Union[Callable, str]]],
columns: Iterable[Hashable],
order: Iterable[int],
) -> Dict[Hashable, "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 +325,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[Hashable, "Series"] = {}
reordered_result_in_dict: Dict[Hashable, Series] = {}
idx = 0

reorder_mask = not isinstance(result, ABCSeries) and len(result.columns) > 1
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ def factorize(
sort: bool = False,
na_sentinel: Optional[int] = -1,
size_hint: Optional[int] = None,
) -> Tuple[np.ndarray, Union[np.ndarray, "Index"]]:
) -> Tuple[np.ndarray, Union[np.ndarray, Index]]:
"""
Encode the object as an enumerated type or categorical variable.

Expand Down
4 changes: 2 additions & 2 deletions pandas/core/arrays/boolean.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def numpy_dtype(self) -> np.dtype:
return np.dtype("bool")

@classmethod
def construct_array_type(cls) -> Type["BooleanArray"]:
def construct_array_type(cls) -> Type[BooleanArray]:
"""
Return the array type associated with this dtype.

Expand All @@ -94,7 +94,7 @@ def _is_numeric(self) -> bool:
return True

def __from_arrow__(
self, array: Union["pyarrow.Array", "pyarrow.ChunkedArray"]
self, array: Union[pyarrow.Array, pyarrow.ChunkedArray]
) -> BooleanArray:
"""
Construct BooleanArray from pyarrow Array/ChunkedArray.
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/arrays/categorical.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ def dtype(self) -> CategoricalDtype:
return self._dtype

@property
def _constructor(self) -> Type["Categorical"]:
def _constructor(self) -> Type[Categorical]:
return Categorical

@classmethod
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/arrays/floating.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def _is_numeric(self) -> bool:
return True

@classmethod
def construct_array_type(cls) -> Type["FloatingArray"]:
def construct_array_type(cls) -> Type[FloatingArray]:
"""
Return the array type associated with this dtype.

Expand Down
2 changes: 1 addition & 1 deletion pandas/core/arrays/integer.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def _is_numeric(self) -> bool:
return True

@classmethod
def construct_array_type(cls) -> Type["IntegerArray"]:
def construct_array_type(cls) -> Type[IntegerArray]:
"""
Return the array type associated with this dtype.

Expand Down
4 changes: 3 additions & 1 deletion pandas/core/arrays/numeric.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import datetime
import numbers
from typing import TYPE_CHECKING, Any, List, Union
Expand Down Expand Up @@ -25,7 +27,7 @@

class NumericDtype(BaseMaskedDtype):
def __from_arrow__(
self, array: Union["pyarrow.Array", "pyarrow.ChunkedArray"]
self, array: Union[pyarrow.Array, pyarrow.ChunkedArray]
) -> BaseMaskedArray:
"""
Construct IntegerArray/FloatingArray from pyarrow Array/ChunkedArray.
Expand Down
4 changes: 2 additions & 2 deletions pandas/core/arrays/numpy_.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def construct_from_string(cls, string: str) -> PandasDtype:
return cls(dtype)

@classmethod
def construct_array_type(cls) -> Type["PandasArray"]:
def construct_array_type(cls) -> Type[PandasArray]:
"""
Return the array type associated with this dtype.

Expand Down Expand Up @@ -155,7 +155,7 @@ class PandasArray(
# ------------------------------------------------------------------------
# Constructors

def __init__(self, values: Union[np.ndarray, "PandasArray"], copy: bool = False):
def __init__(self, values: Union[np.ndarray, PandasArray], copy: bool = False):
if isinstance(values, type(self)):
values = values._ndarray
if not isinstance(values, np.ndarray):
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/arrays/period.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ def _simple_new(

@classmethod
def _from_sequence(
cls: Type["PeriodArray"],
cls: Type[PeriodArray],
scalars: Union[Sequence[Optional[Period]], AnyArrayLike],
*,
dtype: Optional[Dtype] = None,
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/arrays/sparse/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,7 @@ def _take_with_fill(self, indices, fill_value=None) -> np.ndarray:

return taken

def _take_without_fill(self, indices) -> Union[np.ndarray, "SparseArray"]:
def _take_without_fill(self, indices) -> Union[np.ndarray, SparseArray]:
to_shift = indices < 0
indices = indices.copy()

Expand Down
2 changes: 1 addition & 1 deletion pandas/core/arrays/sparse/dtype.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ def __repr__(self) -> str:
return self.name

@classmethod
def construct_array_type(cls) -> Type["SparseArray"]:
def construct_array_type(cls) -> Type[SparseArray]:
"""
Return the array type associated with this dtype.

Expand Down
4 changes: 2 additions & 2 deletions pandas/core/arrays/string_.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def type(self) -> Type[str]:
return str

@classmethod
def construct_array_type(cls) -> Type["StringArray"]:
def construct_array_type(cls) -> Type[StringArray]:
"""
Return the array type associated with this dtype.

Expand All @@ -85,7 +85,7 @@ def __repr__(self) -> str:
return "StringDtype"

def __from_arrow__(
self, array: Union["pyarrow.Array", "pyarrow.ChunkedArray"]
self, array: Union[pyarrow.Array, pyarrow.ChunkedArray]
) -> StringArray:
"""
Construct StringArray from pyarrow Array/ChunkedArray.
Expand Down
4 changes: 2 additions & 2 deletions pandas/core/arrays/string_arrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def type(self) -> Type[str]:
return str

@classmethod
def construct_array_type(cls) -> Type["ArrowStringArray"]:
def construct_array_type(cls) -> Type[ArrowStringArray]:
"""
Return the array type associated with this dtype.

Expand All @@ -104,7 +104,7 @@ def __repr__(self) -> str:
return "ArrowStringDtype"

def __from_arrow__(
self, array: Union["pa.Array", "pa.ChunkedArray"]
self, array: Union[pa.Array, pa.ChunkedArray]
) -> ArrowStringArray:
"""
Construct StringArray from pyarrow Array/ChunkedArray.
Expand Down
4 changes: 3 additions & 1 deletion pandas/core/computation/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
Operator classes for eval.
"""

from __future__ import annotations

from datetime import datetime
from distutils.version import LooseVersion
from functools import partial
Expand Down Expand Up @@ -203,7 +205,7 @@ class Op:

op: str

def __init__(self, op: str, operands: Iterable[Union[Term, "Op"]], encoding=None):
def __init__(self, op: str, operands: Iterable[Union[Term, Op]], encoding=None):
self.op = _bool_op_map.get(op, op)
self.operands = operands
self.encoding = encoding
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/describe.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def describe_frame(
return d


def reorder_columns(ldesc: Sequence["Series"]) -> List[Hashable]:
def reorder_columns(ldesc: Sequence[Series]) -> List[Hashable]:
"""Set a convenient order for rows for display."""
names: List[Hashable] = []
ldesc_indexes = sorted((x.index for x in ldesc), key=len)
Expand Down
4 changes: 3 additions & 1 deletion pandas/core/dtypes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
Extend pandas with custom array types.
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Any, List, Optional, Tuple, Type, Union

import numpy as np
Expand Down Expand Up @@ -186,7 +188,7 @@ def names(self) -> Optional[List[str]]:
return None

@classmethod
def construct_array_type(cls) -> Type["ExtensionArray"]:
def construct_array_type(cls) -> Type[ExtensionArray]:
"""
Return the array type associated with this dtype.

Expand Down
2 changes: 1 addition & 1 deletion pandas/core/dtypes/cast.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ def maybe_cast_result_dtype(dtype: DtypeObj, how: str) -> DtypeObj:


def maybe_cast_to_extension_array(
cls: Type["ExtensionArray"], obj: ArrayLike, dtype: Optional[ExtensionDtype] = None
cls: Type[ExtensionArray], obj: ArrayLike, dtype: Optional[ExtensionDtype] = None
) -> ArrayLike:
"""
Call to `_from_sequence` that returns the object unchanged on Exception.
Expand Down
18 changes: 9 additions & 9 deletions pandas/core/dtypes/dtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class PandasExtensionDtype(ExtensionDtype):
base = None
isbuiltin = 0
isnative = 0
_cache: Dict[str_type, "PandasExtensionDtype"] = {}
_cache: Dict[str_type, PandasExtensionDtype] = {}

def __str__(self) -> str_type:
"""
Expand Down Expand Up @@ -445,7 +445,7 @@ def _hash_categories(categories, ordered: Ordered = True) -> int:
return np.bitwise_xor.reduce(hashed)

@classmethod
def construct_array_type(cls) -> Type["Categorical"]:
def construct_array_type(cls) -> Type[Categorical]:
"""
Return the array type associated with this dtype.

Expand Down Expand Up @@ -514,7 +514,7 @@ def validate_categories(categories, fastpath: bool = False):
return categories

def update_dtype(
self, dtype: Union[str_type, "CategoricalDtype"]
self, dtype: Union[str_type, CategoricalDtype]
) -> CategoricalDtype:
"""
Returns a CategoricalDtype with categories and ordered taken from dtype
Expand Down Expand Up @@ -647,7 +647,7 @@ class DatetimeTZDtype(PandasExtensionDtype):
_match = re.compile(r"(datetime64|M8)\[(?P<unit>.+), (?P<tz>.+)\]")
_cache: Dict[str_type, PandasExtensionDtype] = {}

def __init__(self, unit: Union[str_type, "DatetimeTZDtype"] = "ns", tz=None):
def __init__(self, unit: Union[str_type, DatetimeTZDtype] = "ns", tz=None):
if isinstance(unit, DatetimeTZDtype):
# error: "str" has no attribute "tz"
unit, tz = unit.unit, unit.tz # type: ignore[attr-defined]
Expand Down Expand Up @@ -694,7 +694,7 @@ def tz(self):
return self._tz

@classmethod
def construct_array_type(cls) -> Type["DatetimeArray"]:
def construct_array_type(cls) -> Type[DatetimeArray]:
"""
Return the array type associated with this dtype.

Expand Down Expand Up @@ -940,7 +940,7 @@ def is_dtype(cls, dtype: object) -> bool:
return super().is_dtype(dtype)

@classmethod
def construct_array_type(cls) -> Type["PeriodArray"]:
def construct_array_type(cls) -> Type[PeriodArray]:
"""
Return the array type associated with this dtype.

Expand All @@ -953,7 +953,7 @@ def construct_array_type(cls) -> Type["PeriodArray"]:
return PeriodArray

def __from_arrow__(
self, array: Union["pyarrow.Array", "pyarrow.ChunkedArray"]
self, array: Union[pyarrow.Array, pyarrow.ChunkedArray]
) -> PeriodArray:
"""
Construct PeriodArray from pyarrow Array/ChunkedArray.
Expand Down Expand Up @@ -1090,7 +1090,7 @@ def subtype(self):
return self._subtype

@classmethod
def construct_array_type(cls) -> Type["IntervalArray"]:
def construct_array_type(cls) -> Type[IntervalArray]:
"""
Return the array type associated with this dtype.

Expand Down Expand Up @@ -1184,7 +1184,7 @@ def is_dtype(cls, dtype: object) -> bool:
return super().is_dtype(dtype)

def __from_arrow__(
self, array: Union["pyarrow.Array", "pyarrow.ChunkedArray"]
self, array: Union[pyarrow.Array, pyarrow.ChunkedArray]
) -> IntervalArray:
"""
Construct IntervalArray from pyarrow Array/ChunkedArray.
Expand Down
4 changes: 2 additions & 2 deletions pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -9440,8 +9440,8 @@ def resample(
base: Optional[int] = None,
on=None,
level=None,
origin: Union[str, "TimestampConvertibleTypes"] = "start_day",
offset: Optional["TimedeltaConvertibleTypes"] = None,
origin: Union[str, TimestampConvertibleTypes] = "start_day",
offset: Optional[TimedeltaConvertibleTypes] = None,
) -> Resampler:
return super().resample(
rule=rule,
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/groupby/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -1690,7 +1690,7 @@ def _wrap_transformed_output(

return result

def _wrap_agged_blocks(self, blocks: Sequence["Block"], items: Index) -> DataFrame:
def _wrap_agged_blocks(self, blocks: Sequence[Block], items: Index) -> DataFrame:
if not self.as_index:
index = np.arange(blocks[0].values.shape[-1])
mgr = BlockManager(blocks, axes=[items, index])
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/groupby/groupby.py
Original file line number Diff line number Diff line change
Expand Up @@ -1371,7 +1371,7 @@ class GroupBy(BaseGroupBy[FrameOrSeries]):

@final
@property
def _obj_1d_constructor(self) -> Type["Series"]:
def _obj_1d_constructor(self) -> Type[Series]:
# GH28330 preserve subclassed Series/DataFrames
if isinstance(self.obj, DataFrame):
return self.obj._constructor_sliced
Expand Down
4 changes: 3 additions & 1 deletion pandas/core/groupby/grouper.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
Provide user facing operators for doing the split part of the
split-apply-combine paradigm.
"""
from __future__ import annotations

from typing import Dict, Hashable, List, Optional, Set, Tuple
import warnings

Expand Down Expand Up @@ -616,7 +618,7 @@ def get_grouper(
mutated: bool = False,
validate: bool = True,
dropna: bool = True,
) -> Tuple["ops.BaseGrouper", Set[Hashable], 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
4 changes: 2 additions & 2 deletions pandas/core/groupby/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class BaseGrouper:
def __init__(
self,
axis: Index,
groupings: Sequence["grouper.Grouping"],
groupings: Sequence[grouper.Grouping],
sort: bool = True,
group_keys: bool = True,
mutated: bool = False,
Expand All @@ -119,7 +119,7 @@ def __init__(
self.dropna = dropna

@property
def groupings(self) -> List["grouper.Grouping"]:
def groupings(self) -> List[grouper.Grouping]:
return self._groupings

@property
Expand Down
Loading