diff --git a/pandas/_config/config.py b/pandas/_config/config.py index c391939d22491..73d69105541d8 100644 --- a/pandas/_config/config.py +++ b/pandas/_config/config.py @@ -75,6 +75,7 @@ from collections.abc import ( Generator, Iterable, + Sequence, ) @@ -853,7 +854,7 @@ def inner(x) -> None: return inner -def is_instance_factory(_type) -> Callable[[Any], None]: +def is_instance_factory(_type: type | tuple[type, ...]) -> Callable[[Any], None]: """ Parameters @@ -866,8 +867,7 @@ def is_instance_factory(_type) -> Callable[[Any], None]: ValueError if x is not an instance of `_type` """ - if isinstance(_type, (tuple, list)): - _type = tuple(_type) + if isinstance(_type, tuple): type_repr = "|".join(map(str, _type)) else: type_repr = f"'{_type}'" @@ -879,7 +879,7 @@ def inner(x) -> None: return inner -def is_one_of_factory(legal_values) -> Callable[[Any], None]: +def is_one_of_factory(legal_values: Sequence) -> Callable[[Any], None]: callables = [c for c in legal_values if callable(c)] legal_values = [c for c in legal_values if not callable(c)] @@ -930,7 +930,7 @@ def is_nonnegative_int(value: object) -> None: is_text = is_instance_factory((str, bytes)) -def is_callable(obj) -> bool: +def is_callable(obj: object) -> bool: """ Parameters diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index 2930b979bfe78..df5ec356175bf 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -759,7 +759,7 @@ def asfreq(self, freq=None, how: str = "E") -> Self: # ------------------------------------------------------------------ # Rendering Methods - def _formatter(self, boxed: bool = False): + def _formatter(self, boxed: bool = False) -> Callable[[object], str]: if boxed: return str return "'{}'".format diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index 1b885a2bdcd47..58455f8cb8398 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -1080,7 +1080,7 @@ def sequence_to_td64ns( return data, inferred_freq -def _ints_to_td64ns(data, unit: str = "ns"): +def _ints_to_td64ns(data, unit: str = "ns") -> tuple[np.ndarray, bool]: """ Convert an ndarray with integer-dtype to timedelta64[ns] dtype, treating the integers as multiples of the given timedelta unit. @@ -1120,7 +1120,9 @@ def _ints_to_td64ns(data, unit: str = "ns"): return data, copy_made -def _objects_to_td64ns(data, unit=None, errors: DateTimeErrorChoices = "raise"): +def _objects_to_td64ns( + data, unit=None, errors: DateTimeErrorChoices = "raise" +) -> np.ndarray: """ Convert a object-dtyped or string-dtyped array into an timedelta64[ns]-dtyped array. diff --git a/pandas/core/config_init.py b/pandas/core/config_init.py index a8b63f97141c2..0a9d5af7cbd42 100644 --- a/pandas/core/config_init.py +++ b/pandas/core/config_init.py @@ -329,7 +329,7 @@ def is_terminal() -> bool: "min_rows", 10, pc_min_rows_doc, - validator=is_instance_factory([type(None), int]), + validator=is_instance_factory((type(None), int)), ) cf.register_option("max_categories", 8, pc_max_categories_doc, validator=is_int) @@ -369,7 +369,7 @@ def is_terminal() -> bool: cf.register_option("chop_threshold", None, pc_chop_threshold_doc) cf.register_option("max_seq_items", 100, pc_max_seq_items) cf.register_option( - "width", 80, pc_width_doc, validator=is_instance_factory([type(None), int]) + "width", 80, pc_width_doc, validator=is_instance_factory((type(None), int)) ) cf.register_option( "memory_usage", @@ -850,14 +850,14 @@ def register_converter_cb(key) -> None: "format.thousands", None, styler_thousands, - validator=is_instance_factory([type(None), str]), + validator=is_instance_factory((type(None), str)), ) cf.register_option( "format.na_rep", None, styler_na_rep, - validator=is_instance_factory([type(None), str]), + validator=is_instance_factory((type(None), str)), ) cf.register_option( @@ -867,11 +867,15 @@ def register_converter_cb(key) -> None: validator=is_one_of_factory([None, "html", "latex", "latex-math"]), ) + # error: Argument 1 to "is_instance_factory" has incompatible type "tuple[ + # ..., , ...]"; expected "type | tuple[type, ...]" cf.register_option( "format.formatter", None, styler_formatter, - validator=is_instance_factory([type(None), dict, Callable, str]), + validator=is_instance_factory( + (type(None), dict, Callable, str) # type: ignore[arg-type] + ), ) cf.register_option("html.mathjax", True, styler_mathjax, validator=is_bool) @@ -898,7 +902,7 @@ def register_converter_cb(key) -> None: "latex.environment", None, styler_environment, - validator=is_instance_factory([type(None), str]), + validator=is_instance_factory((type(None), str)), ) diff --git a/pandas/core/dtypes/missing.py b/pandas/core/dtypes/missing.py index 4dc0d477f89e8..3e4227a8a2598 100644 --- a/pandas/core/dtypes/missing.py +++ b/pandas/core/dtypes/missing.py @@ -557,11 +557,13 @@ def _array_equivalent_float(left: np.ndarray, right: np.ndarray) -> bool: return bool(((left == right) | (np.isnan(left) & np.isnan(right))).all()) -def _array_equivalent_datetimelike(left: np.ndarray, right: np.ndarray): +def _array_equivalent_datetimelike(left: np.ndarray, right: np.ndarray) -> bool: return np.array_equal(left.view("i8"), right.view("i8")) -def _array_equivalent_object(left: np.ndarray, right: np.ndarray, strict_nan: bool): +def _array_equivalent_object( + left: np.ndarray, right: np.ndarray, strict_nan: bool +) -> bool: left = ensure_object(left) right = ensure_object(right) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index c24ef4d6d6d42..73b5804d8c168 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -233,6 +233,7 @@ IndexLabel, JoinValidate, Level, + ListLike, MergeHow, MergeValidate, MutableMappingT, @@ -5349,11 +5350,11 @@ def reindex( @overload def drop( self, - labels: IndexLabel = ..., + labels: IndexLabel | ListLike = ..., *, axis: Axis = ..., - index: IndexLabel = ..., - columns: IndexLabel = ..., + index: IndexLabel | ListLike = ..., + columns: IndexLabel | ListLike = ..., level: Level = ..., inplace: Literal[True], errors: IgnoreRaise = ..., @@ -5363,11 +5364,11 @@ def drop( @overload def drop( self, - labels: IndexLabel = ..., + labels: IndexLabel | ListLike = ..., *, axis: Axis = ..., - index: IndexLabel = ..., - columns: IndexLabel = ..., + index: IndexLabel | ListLike = ..., + columns: IndexLabel | ListLike = ..., level: Level = ..., inplace: Literal[False] = ..., errors: IgnoreRaise = ..., @@ -5377,11 +5378,11 @@ def drop( @overload def drop( self, - labels: IndexLabel = ..., + labels: IndexLabel | ListLike = ..., *, axis: Axis = ..., - index: IndexLabel = ..., - columns: IndexLabel = ..., + index: IndexLabel | ListLike = ..., + columns: IndexLabel | ListLike = ..., level: Level = ..., inplace: bool = ..., errors: IgnoreRaise = ..., @@ -5390,11 +5391,11 @@ def drop( def drop( self, - labels: IndexLabel | None = None, + labels: IndexLabel | ListLike = None, *, axis: Axis = 0, - index: IndexLabel | None = None, - columns: IndexLabel | None = None, + index: IndexLabel | ListLike = None, + columns: IndexLabel | ListLike = None, level: Level | None = None, inplace: bool = False, errors: IgnoreRaise = "raise", diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 91a150c63c5b6..9b70c24aa67c6 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -65,6 +65,7 @@ IntervalClosedType, JSONSerializable, Level, + ListLike, Manager, NaPosition, NDFrameT, @@ -4709,11 +4710,11 @@ def reindex_like( @overload def drop( self, - labels: IndexLabel = ..., + labels: IndexLabel | ListLike = ..., *, axis: Axis = ..., - index: IndexLabel = ..., - columns: IndexLabel = ..., + index: IndexLabel | ListLike = ..., + columns: IndexLabel | ListLike = ..., level: Level | None = ..., inplace: Literal[True], errors: IgnoreRaise = ..., @@ -4723,11 +4724,11 @@ def drop( @overload def drop( self, - labels: IndexLabel = ..., + labels: IndexLabel | ListLike = ..., *, axis: Axis = ..., - index: IndexLabel = ..., - columns: IndexLabel = ..., + index: IndexLabel | ListLike = ..., + columns: IndexLabel | ListLike = ..., level: Level | None = ..., inplace: Literal[False] = ..., errors: IgnoreRaise = ..., @@ -4737,11 +4738,11 @@ def drop( @overload def drop( self, - labels: IndexLabel = ..., + labels: IndexLabel | ListLike = ..., *, axis: Axis = ..., - index: IndexLabel = ..., - columns: IndexLabel = ..., + index: IndexLabel | ListLike = ..., + columns: IndexLabel | ListLike = ..., level: Level | None = ..., inplace: bool_t = ..., errors: IgnoreRaise = ..., @@ -4750,11 +4751,11 @@ def drop( def drop( self, - labels: IndexLabel | None = None, + labels: IndexLabel | ListLike = None, *, axis: Axis = 0, - index: IndexLabel | None = None, - columns: IndexLabel | None = None, + index: IndexLabel | ListLike = None, + columns: IndexLabel | ListLike = None, level: Level | None = None, inplace: bool_t = False, errors: IgnoreRaise = "raise", diff --git a/pandas/core/methods/selectn.py b/pandas/core/methods/selectn.py index a2f8ca94134b8..5256c0a1c73a4 100644 --- a/pandas/core/methods/selectn.py +++ b/pandas/core/methods/selectn.py @@ -10,6 +10,7 @@ ) from typing import ( TYPE_CHECKING, + Generic, cast, final, ) @@ -32,16 +33,25 @@ from pandas._typing import ( DtypeObj, IndexLabel, + NDFrameT, ) from pandas import ( DataFrame, Series, ) +else: + # Generic[...] requires a non-str, provide it with a plain TypeVar at + # runtime to avoid circular imports + from pandas._typing import T + NDFrameT = T + DataFrame = T + Series = T -class SelectN: - def __init__(self, obj, n: int, keep: str) -> None: + +class SelectN(Generic[NDFrameT]): + def __init__(self, obj: NDFrameT, n: int, keep: str) -> None: self.obj = obj self.n = n self.keep = keep @@ -49,15 +59,15 @@ def __init__(self, obj, n: int, keep: str) -> None: if self.keep not in ("first", "last", "all"): raise ValueError('keep must be either "first", "last" or "all"') - def compute(self, method: str) -> DataFrame | Series: + def compute(self, method: str) -> NDFrameT: raise NotImplementedError @final - def nlargest(self): + def nlargest(self) -> NDFrameT: return self.compute("nlargest") @final - def nsmallest(self): + def nsmallest(self) -> NDFrameT: return self.compute("nsmallest") @final @@ -72,7 +82,7 @@ def is_valid_dtype_n_method(dtype: DtypeObj) -> bool: return needs_i8_conversion(dtype) -class SelectNSeries(SelectN): +class SelectNSeries(SelectN[Series]): """ Implement n largest/smallest for Series @@ -163,7 +173,7 @@ def compute(self, method: str) -> Series: return concat([dropped.iloc[inds], nan_index]).iloc[:findex] -class SelectNFrame(SelectN): +class SelectNFrame(SelectN[DataFrame]): """ Implement n largest/smallest for DataFrame diff --git a/pandas/core/missing.py b/pandas/core/missing.py index d275445983b6f..0d857f6b21517 100644 --- a/pandas/core/missing.py +++ b/pandas/core/missing.py @@ -960,14 +960,11 @@ def _pad_2d( values: np.ndarray, limit: int | None = None, mask: npt.NDArray[np.bool_] | None = None, -): +) -> tuple[np.ndarray, npt.NDArray[np.bool_]]: mask = _fillna_prep(values, mask) if values.size: algos.pad_2d_inplace(values, mask, limit=limit) - else: - # for test coverage - pass return values, mask diff --git a/pandas/core/series.py b/pandas/core/series.py index e3b401cd3c88b..487f57b7390a8 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -179,6 +179,7 @@ IndexKeyFunc, IndexLabel, Level, + ListLike, MutableMappingT, NaPosition, NumpySorter, @@ -5192,11 +5193,11 @@ def rename_axis( @overload def drop( self, - labels: IndexLabel = ..., + labels: IndexLabel | ListLike = ..., *, axis: Axis = ..., - index: IndexLabel = ..., - columns: IndexLabel = ..., + index: IndexLabel | ListLike = ..., + columns: IndexLabel | ListLike = ..., level: Level | None = ..., inplace: Literal[True], errors: IgnoreRaise = ..., @@ -5206,11 +5207,11 @@ def drop( @overload def drop( self, - labels: IndexLabel = ..., + labels: IndexLabel | ListLike = ..., *, axis: Axis = ..., - index: IndexLabel = ..., - columns: IndexLabel = ..., + index: IndexLabel | ListLike = ..., + columns: IndexLabel | ListLike = ..., level: Level | None = ..., inplace: Literal[False] = ..., errors: IgnoreRaise = ..., @@ -5220,11 +5221,11 @@ def drop( @overload def drop( self, - labels: IndexLabel = ..., + labels: IndexLabel | ListLike = ..., *, axis: Axis = ..., - index: IndexLabel = ..., - columns: IndexLabel = ..., + index: IndexLabel | ListLike = ..., + columns: IndexLabel | ListLike = ..., level: Level | None = ..., inplace: bool = ..., errors: IgnoreRaise = ..., @@ -5233,11 +5234,11 @@ def drop( def drop( self, - labels: IndexLabel | None = None, + labels: IndexLabel | ListLike = None, *, axis: Axis = 0, - index: IndexLabel | None = None, - columns: IndexLabel | None = None, + index: IndexLabel | ListLike = None, + columns: IndexLabel | ListLike = None, level: Level | None = None, inplace: bool = False, errors: IgnoreRaise = "raise", diff --git a/pandas/core/tools/timedeltas.py b/pandas/core/tools/timedeltas.py index d772c908c4731..b80ed9ac50dce 100644 --- a/pandas/core/tools/timedeltas.py +++ b/pandas/core/tools/timedeltas.py @@ -89,7 +89,7 @@ def to_timedelta( | Series, unit: UnitChoices | None = None, errors: DateTimeErrorChoices = "raise", -) -> Timedelta | TimedeltaIndex | Series: +) -> Timedelta | TimedeltaIndex | Series | NaTType: """ Convert argument to timedelta. @@ -225,7 +225,7 @@ def to_timedelta( def _coerce_scalar_to_timedelta_type( r, unit: UnitChoices | None = "ns", errors: DateTimeErrorChoices = "raise" -): +) -> Timedelta | NaTType: """Convert string 'r' to a timedelta object.""" result: Timedelta | NaTType diff --git a/pandas/errors/__init__.py b/pandas/errors/__init__.py index 01094ba36b9dd..d3ca9c8521203 100644 --- a/pandas/errors/__init__.py +++ b/pandas/errors/__init__.py @@ -532,7 +532,7 @@ class ChainedAssignmentError(Warning): ) -def _check_cacher(obj): +def _check_cacher(obj) -> bool: # This is a mess, selection paths that return a view set the _cacher attribute # on the Series; most of them also set _item_cache which adds 1 to our relevant # reference count, but iloc does not, so we have to check if we are actually diff --git a/pandas/io/common.py b/pandas/io/common.py index 72c9deeb54fc7..57bc6c1379d77 100644 --- a/pandas/io/common.py +++ b/pandas/io/common.py @@ -1066,7 +1066,7 @@ class _IOWrapper: def __init__(self, buffer: BaseBuffer) -> None: self.buffer = buffer - def __getattr__(self, name: str): + def __getattr__(self, name: str) -> Any: return getattr(self.buffer, name) def readable(self) -> bool: @@ -1097,7 +1097,7 @@ def __init__(self, buffer: StringIO | TextIOBase, encoding: str = "utf-8") -> No # overflow to the front of the bytestring the next time reading is performed self.overflow = b"" - def __getattr__(self, attr: str): + def __getattr__(self, attr: str) -> Any: return getattr(self.buffer, attr) def read(self, n: int | None = -1) -> bytes: diff --git a/pandas/io/formats/css.py b/pandas/io/formats/css.py index ccce60c00a9e0..cddff9a97056a 100644 --- a/pandas/io/formats/css.py +++ b/pandas/io/formats/css.py @@ -340,7 +340,7 @@ def _update_other_units(self, props: dict[str, str]) -> dict[str, str]: return props def size_to_pt(self, in_val, em_pt=None, conversions=UNIT_RATIOS) -> str: - def _error(): + def _error() -> str: warnings.warn( f"Unhandled size: {repr(in_val)}", CSSWarning, diff --git a/pandas/io/gbq.py b/pandas/io/gbq.py index 350002bf461ff..fe8702c2e16ae 100644 --- a/pandas/io/gbq.py +++ b/pandas/io/gbq.py @@ -11,12 +11,14 @@ from pandas.util._exceptions import find_stack_level if TYPE_CHECKING: + from types import ModuleType + import google.auth from pandas import DataFrame -def _try_import(): +def _try_import() -> ModuleType: # since pandas is a dependency of pandas-gbq # we need to import on first use msg = ( diff --git a/pyproject.toml b/pyproject.toml index 430bb8e505df0..51d7603489cb8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -671,9 +671,7 @@ module = [ "pandas.io.sas.sas7bdat", # TODO "pandas.io.clipboards", # TODO "pandas.io.common", # TODO - "pandas.io.gbq", # TODO "pandas.io.html", # TODO - "pandas.io.gbq", # TODO "pandas.io.parquet", # TODO "pandas.io.pytables", # TODO "pandas.io.sql", # TODO