diff --git a/.libcst.codemod.yaml b/.libcst.codemod.yaml new file mode 100644 index 0000000000000..985e69b772e52 --- /dev/null +++ b/.libcst.codemod.yaml @@ -0,0 +1,18 @@ +# String that LibCST should look for in code which indicates that the +# module is generated code. +generated_code_marker: '@generated' +# Command line and arguments for invoking a code formatter. Anything +# specified here must be capable of taking code via stdin and returning +# formatted code via stdout. +formatter: ['black', '-'] +# List of regex patterns which LibCST will evaluate against filenames to +# determine if the module should be touched. +blacklist_patterns: [] +# List of modules that contain codemods inside of them. +modules: +- 'libcst.codemod.commands' +- 'autotyping' +# Absolute or relative path of the repository root, used for providing +# full-repo metadata. Relative paths should be specified with this file +# location as the base. +repo_root: '.' diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 23ff37f7f92f6..31f317636bd69 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -256,3 +256,14 @@ repos: /(__init__\.py)|(api\.py)|(_version\.py)|(testing\.py)|(conftest\.py)$ |/tests/ |/_testing/ + - id: autotyping + name: autotyping + entry: python -m libcst.tool codemod autotyping.AutotypeCommand --none-return --scalar-return --annotate-magics --annotate-imprecise-magics + types_or: [python, pyi] + files: ^pandas + exclude: ^(pandas/tests|pandas/io/clipboard) + language: python + additional_dependencies: + - autotyping==22.9.0 + - black==22.6.0 + - libcst==0.4.7 diff --git a/pandas/_libs/arrays.pyi b/pandas/_libs/arrays.pyi index 76e4321cc0c77..c9350ed9b8a75 100644 --- a/pandas/_libs/arrays.pyi +++ b/pandas/_libs/arrays.pyi @@ -10,7 +10,7 @@ from pandas._typing import ( class NDArrayBacked: _dtype: DtypeObj _ndarray: np.ndarray - def __init__(self, values: np.ndarray, dtype: DtypeObj): ... + def __init__(self, values: np.ndarray, dtype: DtypeObj) -> None: ... @classmethod def _simple_new(cls, values: np.ndarray, dtype: DtypeObj): ... def _from_backing_data(self, values: np.ndarray): ... diff --git a/pandas/_libs/hashtable.pyi b/pandas/_libs/hashtable.pyi index 8500fdf2f602e..8f035f967c8f4 100644 --- a/pandas/_libs/hashtable.pyi +++ b/pandas/_libs/hashtable.pyi @@ -13,7 +13,7 @@ def unique_label_indices( class Factorizer: count: int - def __init__(self, size_hint: int): ... + def __init__(self, size_hint: int) -> None: ... def get_count(self) -> int: ... class ObjectFactorizer(Factorizer): @@ -39,72 +39,72 @@ class Int64Factorizer(Factorizer): ) -> npt.NDArray[np.intp]: ... class Int64Vector: - def __init__(self, *args): ... + def __init__(self, *args) -> None: ... def __len__(self) -> int: ... def to_array(self) -> npt.NDArray[np.int64]: ... class Int32Vector: - def __init__(self, *args): ... + def __init__(self, *args) -> None: ... def __len__(self) -> int: ... def to_array(self) -> npt.NDArray[np.int32]: ... class Int16Vector: - def __init__(self, *args): ... + def __init__(self, *args) -> None: ... def __len__(self) -> int: ... def to_array(self) -> npt.NDArray[np.int16]: ... class Int8Vector: - def __init__(self, *args): ... + def __init__(self, *args) -> None: ... def __len__(self) -> int: ... def to_array(self) -> npt.NDArray[np.int8]: ... class UInt64Vector: - def __init__(self, *args): ... + def __init__(self, *args) -> None: ... def __len__(self) -> int: ... def to_array(self) -> npt.NDArray[np.uint64]: ... class UInt32Vector: - def __init__(self, *args): ... + def __init__(self, *args) -> None: ... def __len__(self) -> int: ... def to_array(self) -> npt.NDArray[np.uint32]: ... class UInt16Vector: - def __init__(self, *args): ... + def __init__(self, *args) -> None: ... def __len__(self) -> int: ... def to_array(self) -> npt.NDArray[np.uint16]: ... class UInt8Vector: - def __init__(self, *args): ... + def __init__(self, *args) -> None: ... def __len__(self) -> int: ... def to_array(self) -> npt.NDArray[np.uint8]: ... class Float64Vector: - def __init__(self, *args): ... + def __init__(self, *args) -> None: ... def __len__(self) -> int: ... def to_array(self) -> npt.NDArray[np.float64]: ... class Float32Vector: - def __init__(self, *args): ... + def __init__(self, *args) -> None: ... def __len__(self) -> int: ... def to_array(self) -> npt.NDArray[np.float32]: ... class Complex128Vector: - def __init__(self, *args): ... + def __init__(self, *args) -> None: ... def __len__(self) -> int: ... def to_array(self) -> npt.NDArray[np.complex128]: ... class Complex64Vector: - def __init__(self, *args): ... + def __init__(self, *args) -> None: ... def __len__(self) -> int: ... def to_array(self) -> npt.NDArray[np.complex64]: ... class StringVector: - def __init__(self, *args): ... + def __init__(self, *args) -> None: ... def __len__(self) -> int: ... def to_array(self) -> npt.NDArray[np.object_]: ... class ObjectVector: - def __init__(self, *args): ... + def __init__(self, *args) -> None: ... def __len__(self) -> int: ... def to_array(self) -> npt.NDArray[np.object_]: ... @@ -112,7 +112,7 @@ class HashTable: # NB: The base HashTable class does _not_ actually have these methods; # we are putting the here for the sake of mypy to avoid # reproducing them in each subclass below. - def __init__(self, size_hint: int = ...): ... + def __init__(self, size_hint: int = ...) -> None: ... def __len__(self) -> int: ... def __contains__(self, key: Hashable) -> bool: ... def sizeof(self, deep: bool = ...) -> int: ... diff --git a/pandas/_libs/index.pyi b/pandas/_libs/index.pyi index 575f83847b1b6..8fff335352617 100644 --- a/pandas/_libs/index.pyi +++ b/pandas/_libs/index.pyi @@ -7,8 +7,9 @@ from pandas.core.arrays import ExtensionArray class IndexEngine: over_size_threshold: bool - def __init__(self, values: np.ndarray): ... + def __init__(self, values: np.ndarray) -> None: ... def __contains__(self, val: object) -> bool: ... + # -> int | slice | np.ndarray[bool] def get_loc(self, val: object) -> int | slice | np.ndarray: ... def sizeof(self, deep: bool = ...) -> int: ... @@ -49,12 +50,13 @@ class BoolEngine(UInt8Engine): ... class BaseMultiIndexCodesEngine: levels: list[np.ndarray] offsets: np.ndarray # ndarray[uint64_t, ndim=1] + def __init__( self, levels: list[np.ndarray], # all entries hashable labels: list[np.ndarray], # all entries integer-dtyped offsets: np.ndarray, # np.ndarray[np.uint64, ndim=1] - ): ... + ) -> None: ... def get_indexer( self, target: npt.NDArray[np.object_], @@ -69,7 +71,7 @@ class BaseMultiIndexCodesEngine: ) -> npt.NDArray[np.intp]: ... class ExtensionEngine: - def __init__(self, values: ExtensionArray): ... + def __init__(self, values: ExtensionArray) -> None: ... def __contains__(self, val: object) -> bool: ... def get_loc(self, val: object) -> int | slice | np.ndarray: ... def get_indexer(self, values: np.ndarray) -> npt.NDArray[np.intp]: ... diff --git a/pandas/_libs/internals.pyi b/pandas/_libs/internals.pyi index 201c7b7b565cc..143f6b68deaa6 100644 --- a/pandas/_libs/internals.pyi +++ b/pandas/_libs/internals.pyi @@ -34,7 +34,7 @@ def update_blklocs_and_blknos( ) -> tuple[npt.NDArray[np.intp], npt.NDArray[np.intp]]: ... @final class BlockPlacement: - def __init__(self, val: int | slice | np.ndarray): ... + def __init__(self, val: int | slice | np.ndarray) -> None: ... @property def indexer(self) -> np.ndarray | slice: ... @property @@ -57,7 +57,9 @@ class SharedBlock: _mgr_locs: BlockPlacement ndim: int values: ArrayLike - def __init__(self, values: ArrayLike, placement: BlockPlacement, ndim: int): ... + def __init__( + self, values: ArrayLike, placement: BlockPlacement, ndim: int + ) -> None: ... class NumpyBlock(SharedBlock): values: np.ndarray @@ -80,6 +82,6 @@ class BlockManager: _blklocs: np.ndarray def __init__( self, blocks: tuple[B, ...], axes: list[Index], verify_integrity=... - ): ... + ) -> None: ... def get_slice(self: T, slobj: slice, axis: int = ...) -> T: ... def _rebuild_blknos_and_blklocs(self) -> None: ... diff --git a/pandas/_libs/parsers.pyi b/pandas/_libs/parsers.pyi index 6b0bbf183f07e..d888511916e27 100644 --- a/pandas/_libs/parsers.pyi +++ b/pandas/_libs/parsers.pyi @@ -62,7 +62,7 @@ class TextReader: float_precision: Literal["round_trip", "legacy", "high"] | None = ..., skip_blank_lines: bool = ..., encoding_errors: bytes | str = ..., - ): ... + ) -> None: ... def set_noconvert(self, i: int) -> None: ... def remove_noconvert(self, i: int) -> None: ... def close(self) -> None: ... diff --git a/pandas/_libs/sparse.pyi b/pandas/_libs/sparse.pyi index be5d251b2aea6..8c3989b818a71 100644 --- a/pandas/_libs/sparse.pyi +++ b/pandas/_libs/sparse.pyi @@ -12,7 +12,7 @@ _SparseIndexT = TypeVar("_SparseIndexT", bound=SparseIndex) class SparseIndex: length: int npoints: int - def __init__(self): ... + def __init__(self) -> None: ... @property def ngaps(self) -> int: ... @property @@ -31,13 +31,15 @@ class IntIndex(SparseIndex): indices: npt.NDArray[np.int32] def __init__( self, length: int, indices: Sequence[int], check_integrity: bool = ... - ): ... + ) -> None: ... class BlockIndex(SparseIndex): nblocks: int blocs: np.ndarray blengths: np.ndarray - def __init__(self, length: int, blocs: np.ndarray, blengths: np.ndarray): ... + def __init__( + self, length: int, blocs: np.ndarray, blengths: np.ndarray + ) -> None: ... def make_mask_object_ndarray( arr: npt.NDArray[np.object_], fill_value diff --git a/pandas/_testing/contexts.py b/pandas/_testing/contexts.py index 9647d46ac3391..d0f4b4b14acc6 100644 --- a/pandas/_testing/contexts.py +++ b/pandas/_testing/contexts.py @@ -5,6 +5,7 @@ from pathlib import Path from shutil import rmtree import tempfile +from types import TracebackType from typing import ( IO, Any, @@ -65,7 +66,7 @@ def set_timezone(tz: str) -> Generator[None, None, None]: import os import time - def setTZ(tz): + def setTZ(tz) -> None: if tz is None: try: del os.environ["TZ"] @@ -239,6 +240,11 @@ def __enter__(self) -> None: self.start_state = np.random.get_state() np.random.seed(self.seed) - def __exit__(self, exc_type, exc_value, traceback) -> None: + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> None: np.random.set_state(self.start_state) diff --git a/pandas/_version.py b/pandas/_version.py index 923b268919671..a5eec4222ca41 100644 --- a/pandas/_version.py +++ b/pandas/_version.py @@ -334,7 +334,7 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): return pieces -def plus_or_dot(pieces): +def plus_or_dot(pieces) -> str: """Return a + if we don't already have one, else return a .""" if "+" in pieces.get("closest-tag", ""): return "." diff --git a/pandas/compat/pickle_compat.py b/pandas/compat/pickle_compat.py index a9ae5f89b1a47..c233e3d8a4892 100644 --- a/pandas/compat/pickle_compat.py +++ b/pandas/compat/pickle_compat.py @@ -210,7 +210,7 @@ def find_class(self, module, name): Unpickler.dispatch[pkl.REDUCE[0]] = load_reduce -def load_newobj(self): +def load_newobj(self) -> None: args = self.stack.pop() cls = self.stack[-1] @@ -234,7 +234,7 @@ def load_newobj(self): Unpickler.dispatch[pkl.NEWOBJ[0]] = load_newobj -def load_newobj_ex(self): +def load_newobj_ex(self) -> None: kwargs = self.stack.pop() args = self.stack.pop() cls = self.stack.pop() diff --git a/pandas/conftest.py b/pandas/conftest.py index b6e1559b9f8cf..6f31e2a11486a 100644 --- a/pandas/conftest.py +++ b/pandas/conftest.py @@ -29,7 +29,10 @@ from decimal import Decimal import operator import os -from typing import Callable +from typing import ( + Callable, + Iterator, +) from dateutil.tz import ( tzlocal, @@ -132,7 +135,7 @@ def ignore_doctest_warning(item: pytest.Item, path: str, message: str) -> None: item.add_marker(pytest.mark.filterwarnings(f"ignore:{message}")) -def pytest_collection_modifyitems(items, config): +def pytest_collection_modifyitems(items, config) -> None: skip_slow = config.getoption("--skip-slow") only_slow = config.getoption("--only-slow") skip_network = config.getoption("--skip-network") @@ -512,10 +515,10 @@ def __init__(self, underlying_dict) -> None: def __getitem__(self, key): return self._data.__getitem__(key) - def __iter__(self): + def __iter__(self) -> Iterator: return self._data.__iter__() - def __len__(self): + def __len__(self) -> int: return self._data.__len__() return TestNonDictMapping diff --git a/pandas/core/accessor.py b/pandas/core/accessor.py index b66a91826b689..c1495a8e6ce69 100644 --- a/pandas/core/accessor.py +++ b/pandas/core/accessor.py @@ -59,7 +59,7 @@ def _delegate_method(self, name, *args, **kwargs): @classmethod def _add_delegate_accessors( cls, delegate, accessors, typ: str, overwrite: bool = False - ): + ) -> None: """ Add accessors to cls from the delegate class. diff --git a/pandas/core/array_algos/take.py b/pandas/core/array_algos/take.py index f82aeb6df5e32..63f8ccde8a883 100644 --- a/pandas/core/array_algos/take.py +++ b/pandas/core/array_algos/take.py @@ -337,7 +337,7 @@ def _get_take_nd_function( if func is None: - def func(arr, indexer, out, fill_value=np.nan): + def func(arr, indexer, out, fill_value=np.nan) -> None: indexer = ensure_platform_int(indexer) _take_nd_object( arr, indexer, out, axis=axis, fill_value=fill_value, mask_info=mask_info @@ -349,7 +349,7 @@ def func(arr, indexer, out, fill_value=np.nan): def _view_wrapper(f, arr_dtype=None, out_dtype=None, fill_wrap=None): def wrapper( arr: np.ndarray, indexer: np.ndarray, out: np.ndarray, fill_value=np.nan - ): + ) -> None: if arr_dtype is not None: arr = arr.view(arr_dtype) if out_dtype is not None: @@ -364,7 +364,7 @@ def wrapper( def _convert_wrapper(f, conv_dtype): def wrapper( arr: np.ndarray, indexer: np.ndarray, out: np.ndarray, fill_value=np.nan - ): + ) -> None: if conv_dtype == object: # GH#39755 avoid casting dt64/td64 to integers arr = ensure_wrapped_if_datetimelike(arr) @@ -506,7 +506,7 @@ def _take_nd_object( axis: int, fill_value, mask_info, -): +) -> None: if mask_info is not None: mask, needs_masking = mask_info else: diff --git a/pandas/core/arrays/base.py b/pandas/core/arrays/base.py index 1e3b137184660..ef7c676be6797 100644 --- a/pandas/core/arrays/base.py +++ b/pandas/core/arrays/base.py @@ -1698,7 +1698,7 @@ def _create_arithmetic_method(cls, op): raise AbstractMethodError(cls) @classmethod - def _add_arithmetic_ops(cls): + def _add_arithmetic_ops(cls) -> None: setattr(cls, "__add__", cls._create_arithmetic_method(operator.add)) setattr(cls, "__radd__", cls._create_arithmetic_method(roperator.radd)) setattr(cls, "__sub__", cls._create_arithmetic_method(operator.sub)) @@ -1723,7 +1723,7 @@ def _create_comparison_method(cls, op): raise AbstractMethodError(cls) @classmethod - def _add_comparison_ops(cls): + def _add_comparison_ops(cls) -> None: setattr(cls, "__eq__", cls._create_comparison_method(operator.eq)) setattr(cls, "__ne__", cls._create_comparison_method(operator.ne)) setattr(cls, "__lt__", cls._create_comparison_method(operator.lt)) @@ -1736,7 +1736,7 @@ def _create_logical_method(cls, op): raise AbstractMethodError(cls) @classmethod - def _add_logical_ops(cls): + def _add_logical_ops(cls) -> None: setattr(cls, "__and__", cls._create_logical_method(operator.and_)) setattr(cls, "__rand__", cls._create_logical_method(roperator.rand_)) setattr(cls, "__or__", cls._create_logical_method(operator.or_)) diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index fff7772c2cf7d..085c4563599fc 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -8,6 +8,7 @@ from typing import ( TYPE_CHECKING, Hashable, + Iterator, Literal, Sequence, TypeVar, @@ -2059,7 +2060,7 @@ def _codes(self) -> np.ndarray: return self._ndarray @_codes.setter - def _codes(self, value: np.ndarray): + def _codes(self, value: np.ndarray) -> None: warn( "Setting the codes on a Categorical is deprecated and will raise in " "a future version. Create a new Categorical object instead", @@ -2093,7 +2094,7 @@ def take_nd( ) return self.take(indexer, allow_fill=allow_fill, fill_value=fill_value) - def __iter__(self): + def __iter__(self) -> Iterator: """ Returns an Iterator over the values of this Categorical. """ diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index 9d32bc008eb25..26bcfb7439bca 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -10,6 +10,7 @@ TYPE_CHECKING, Any, Callable, + Iterator, Literal, Sequence, TypeVar, @@ -287,7 +288,7 @@ def _box_values(self, values) -> np.ndarray: """ return lib.map_infer(values, self._box_func, convert=False) - def __iter__(self): + def __iter__(self) -> Iterator: if self.ndim > 1: return (self[n] for n in range(len(self))) else: @@ -418,7 +419,7 @@ def __setitem__( # type: ignore[override] self._maybe_clear_freq() - def _maybe_clear_freq(self): + def _maybe_clear_freq(self) -> None: # inplace operations like __setitem__ may invalidate the freq of # DatetimeArray and TimedeltaArray pass @@ -1946,7 +1947,9 @@ class TimelikeOps(DatetimeLikeArrayMixin): _default_dtype: np.dtype - def __init__(self, values, dtype=None, freq=lib.no_default, copy: bool = False): + def __init__( + self, values, dtype=None, freq=lib.no_default, copy: bool = False + ) -> None: values = extract_array(values, extract_numpy=True) if isinstance(values, IntegerArray): values = values.to_numpy("int64", na_value=iNaT) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 64c15df64de3b..28cde46a03758 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -9,6 +9,7 @@ import inspect from typing import ( TYPE_CHECKING, + Iterator, Literal, cast, ) @@ -567,7 +568,7 @@ def __array__(self, dtype=None) -> np.ndarray: return super().__array__(dtype=dtype) - def __iter__(self): + def __iter__(self) -> Iterator: """ Return an iterator over the boxed values diff --git a/pandas/core/arrays/interval.py b/pandas/core/arrays/interval.py index 8f01dfaf867e7..446285da719af 100644 --- a/pandas/core/arrays/interval.py +++ b/pandas/core/arrays/interval.py @@ -8,6 +8,7 @@ import textwrap from typing import ( TYPE_CHECKING, + Iterator, Literal, Sequence, TypeVar, @@ -652,7 +653,7 @@ def size(self) -> int: # --------------------------------------------------------------------- # EA Interface - def __iter__(self): + def __iter__(self) -> Iterator: return iter(np.asarray(self)) def __len__(self) -> int: diff --git a/pandas/core/arrays/masked.py b/pandas/core/arrays/masked.py index 5c77a50f4a805..39debbf4fcd64 100644 --- a/pandas/core/arrays/masked.py +++ b/pandas/core/arrays/masked.py @@ -3,6 +3,7 @@ from typing import ( TYPE_CHECKING, Any, + Iterator, Literal, Sequence, TypeVar, @@ -239,7 +240,7 @@ def __setitem__(self, key, value) -> None: self._data[key] = value self._mask[key] = mask - def __iter__(self): + def __iter__(self) -> Iterator: if self.ndim == 1: for i in range(len(self)): if self._mask[i]: diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index e6ea7b0879100..7f896c5334313 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -342,7 +342,7 @@ def _unbox_scalar( # type: ignore[override] def _scalar_from_string(self, value: str) -> Period: return Period(value, freq=self.freq) - def _check_compatible_with(self, other, setitem: bool = False): + def _check_compatible_with(self, other, setitem: bool = False) -> None: if other is NaT: return self._require_matching_freq(other) diff --git a/pandas/core/arrays/sparse/array.py b/pandas/core/arrays/sparse/array.py index e2a0740dd214e..13818ef7c5d17 100644 --- a/pandas/core/arrays/sparse/array.py +++ b/pandas/core/arrays/sparse/array.py @@ -661,7 +661,7 @@ def fill_value(self): return self.dtype.fill_value @fill_value.setter - def fill_value(self, value): + def fill_value(self, value) -> None: self._dtype = SparseDtype(self.dtype.subtype, value) @property diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index 193ab6dc99350..12e3e9813a816 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -3,6 +3,7 @@ from datetime import timedelta from typing import ( TYPE_CHECKING, + Iterator, cast, ) @@ -304,7 +305,7 @@ def astype(self, dtype, copy: bool = True): return dtl.DatetimeLikeArrayMixin.astype(self, dtype, copy=copy) - def __iter__(self): + def __iter__(self) -> Iterator: if self.ndim > 1: for i in range(len(self)): yield self[i] diff --git a/pandas/core/base.py b/pandas/core/base.py index ca3ba5ec4bdd4..8f3b31caf8986 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -11,6 +11,7 @@ Any, Generic, Hashable, + Iterator, Literal, TypeVar, cast, @@ -158,7 +159,7 @@ class NoNewAttributesMixin: `object.__setattr__(self, key, value)`. """ - def _freeze(self): + def _freeze(self) -> None: """ Prevents setting additional attributes. """ @@ -739,7 +740,7 @@ def tolist(self): to_list = tolist - def __iter__(self): + def __iter__(self) -> Iterator: """ Return an iterator of the values. diff --git a/pandas/core/computation/expressions.py b/pandas/core/computation/expressions.py index a4b83fc557413..6c3d2cee593a0 100644 --- a/pandas/core/computation/expressions.py +++ b/pandas/core/computation/expressions.py @@ -71,7 +71,7 @@ def _evaluate_standard(op, op_str, a, b): return op(a, b) -def _can_use_numexpr(op, op_str, a, b, dtype_check): +def _can_use_numexpr(op, op_str, a, b, dtype_check) -> bool: """return a boolean if we WILL be using numexpr""" if op_str is not None: @@ -205,7 +205,7 @@ def _has_bool_dtype(x): _BOOL_OP_UNSUPPORTED = {"+": "|", "*": "&", "-": "^"} -def _bool_arith_fallback(op_str, a, b): +def _bool_arith_fallback(op_str, a, b) -> bool: """ Check if we should fallback to the python `_evaluate_standard` in case of an unsupported operation by numexpr, which is the case for some diff --git a/pandas/core/computation/ops.py b/pandas/core/computation/ops.py index cb7b33e40d989..f629538281d65 100644 --- a/pandas/core/computation/ops.py +++ b/pandas/core/computation/ops.py @@ -10,6 +10,7 @@ from typing import ( Callable, Iterable, + Iterator, Literal, ) @@ -170,7 +171,7 @@ def value(self): return self._value @value.setter - def value(self, new_value): + def value(self, new_value) -> None: self._value = new_value @property @@ -214,7 +215,7 @@ def __init__(self, op: str, operands: Iterable[Term | Op], encoding=None) -> Non self.operands = operands self.encoding = encoding - def __iter__(self): + def __iter__(self) -> Iterator: return iter(self.operands) def __repr__(self) -> str: @@ -329,7 +330,7 @@ def _not_in(x, y): _binary_ops_dict.update(d) -def _cast_inplace(terms, acceptable_dtypes, dtype): +def _cast_inplace(terms, acceptable_dtypes, dtype) -> None: """ Cast an expression inplace. diff --git a/pandas/core/computation/pytables.py b/pandas/core/computation/pytables.py index 5fbc26c057862..f0f3e7f19db50 100644 --- a/pandas/core/computation/pytables.py +++ b/pandas/core/computation/pytables.py @@ -112,7 +112,7 @@ def __init__(self, op: str, lhs, rhs, queryables: dict[str, Any], encoding) -> N self.encoding = encoding self.condition = None - def _disallow_scalar_only_bool_ops(self): + def _disallow_scalar_only_bool_ops(self) -> None: pass def prune(self, klass): @@ -261,7 +261,7 @@ def stringify(value): else: raise TypeError(f"Cannot compare {v} of type {type(v)} to {kind} column") - def convert_values(self): + def convert_values(self) -> None: pass diff --git a/pandas/core/config_init.py b/pandas/core/config_init.py index 2579f736a9703..3c3d21e58efaf 100644 --- a/pandas/core/config_init.py +++ b/pandas/core/config_init.py @@ -365,7 +365,7 @@ def is_terminal() -> bool: validator=is_one_of_factory([None, is_callable]), ) - def _deprecate_column_space(key): + def _deprecate_column_space(key) -> None: warnings.warn( "column_space is deprecated and will be removed " "in a future version. Use df.to_string(col_space=...) " @@ -390,7 +390,7 @@ def _deprecate_column_space(key): ) cf.register_option("max_categories", 8, pc_max_categories_doc, validator=is_int) - def _deprecate_negative_int_max_colwidth(key): + def _deprecate_negative_int_max_colwidth(key) -> None: value = cf.get_option(key) if value is not None and value < 0: warnings.warn( diff --git a/pandas/core/dtypes/base.py b/pandas/core/dtypes/base.py index 5ec2aaab98ba1..5efdef4a9385a 100644 --- a/pandas/core/dtypes/base.py +++ b/pandas/core/dtypes/base.py @@ -403,7 +403,7 @@ def __init__(self, storage=None) -> None: def __repr__(self) -> str: return f"{self.name}[{self.storage}]" - def __str__(self): + def __str__(self) -> str: return self.name def __eq__(self, other: Any) -> bool: diff --git a/pandas/core/dtypes/dtypes.py b/pandas/core/dtypes/dtypes.py index e2570e6be4879..03025ce342a57 100644 --- a/pandas/core/dtypes/dtypes.py +++ b/pandas/core/dtypes/dtypes.py @@ -675,8 +675,9 @@ class DatetimeTZDtype(PandasExtensionDtype): def na_value(self) -> NaTType: return NaT + # error: Signature of "str" incompatible with supertype "PandasExtensionDtype" @cache_readonly - def str(self): + def str(self) -> str: # type: ignore[override] return f"|M8[{self._unit}]" def __init__(self, unit: str_type | DatetimeTZDtype = "ns", tz=None) -> None: diff --git a/pandas/core/dtypes/generic.py b/pandas/core/dtypes/generic.py index a6634cca12e93..f9e96acf60e50 100644 --- a/pandas/core/dtypes/generic.py +++ b/pandas/core/dtypes/generic.py @@ -37,7 +37,7 @@ # define abstract base classes to enable isinstance type checking on our # objects def create_pandas_abc_type(name, attr, comp): - def _check(inst): + def _check(inst) -> bool: return getattr(inst, attr, "_typ") in comp # https://github.com/python/mypy/issues/1006 diff --git a/pandas/core/dtypes/missing.py b/pandas/core/dtypes/missing.py index e809e761ebbb2..cfad439e51ac7 100644 --- a/pandas/core/dtypes/missing.py +++ b/pandas/core/dtypes/missing.py @@ -234,7 +234,7 @@ def _isna(obj, inf_as_na: bool = False): return False -def _use_inf_as_na(key): +def _use_inf_as_na(key) -> None: """ Option change callback for na/inf behaviour. diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 4cdd62b038485..e471e7efb20ae 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -3978,7 +3978,7 @@ def __setitem__(self, key, value): # set column self._set_item(key, value) - def _setitem_slice(self, key: slice, value): + def _setitem_slice(self, key: slice, value) -> None: # NB: we can't just use self.loc[key] = value because that # operates on labels and we need to operate positional for # backwards-compat, xref GH#31469 diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 8b2a563fffd30..2dfa505bc4932 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -16,6 +16,7 @@ Callable, ClassVar, Hashable, + Iterator, Literal, Mapping, NoReturn, @@ -1951,7 +1952,7 @@ def _drop_labels_or_levels(self, keys, axis: int = 0): # "object" defined the type as "Callable[[object], int]") __hash__: ClassVar[None] # type: ignore[assignment] - def __iter__(self): + def __iter__(self) -> Iterator: """ Iterate over info axis. @@ -6000,7 +6001,7 @@ def _protect_consolidate(self, f): def _consolidate_inplace(self) -> None: """Consolidate data in place and return None""" - def f(): + def f() -> None: self._mgr = self._mgr.consolidate() self._protect_consolidate(f) @@ -6019,7 +6020,6 @@ def _consolidate(self): cons_data = self._protect_consolidate(f) return self._constructor(cons_data).__finalize__(self) - @final @property def _is_mixed_type(self) -> bool_t: if self._mgr.is_single_block: @@ -11619,7 +11619,7 @@ def mad( return np.abs(demeaned).mean(axis=axis, skipna=skipna) @classmethod - def _add_numeric_operations(cls): + def _add_numeric_operations(cls) -> None: """ Add the operations to the cls; evaluate the doc strings again """ diff --git a/pandas/core/groupby/grouper.py b/pandas/core/groupby/grouper.py index 72f54abdced27..5fc713d84e842 100644 --- a/pandas/core/groupby/grouper.py +++ b/pandas/core/groupby/grouper.py @@ -9,6 +9,7 @@ TYPE_CHECKING, Any, Hashable, + Iterator, final, ) import warnings @@ -564,7 +565,7 @@ def __init__( def __repr__(self) -> str: return f"Grouping({self.name})" - def __iter__(self): + def __iter__(self) -> Iterator: return iter(self.indices) @cache_readonly @@ -950,7 +951,7 @@ def _convert_grouper(axis: Index, grouper): return grouper -def _check_deprecated_resample_kwargs(kwargs, origin): +def _check_deprecated_resample_kwargs(kwargs, origin) -> None: """ Check for use of deprecated parameters in ``resample`` and related functions. diff --git a/pandas/core/groupby/ops.py b/pandas/core/groupby/ops.py index 04960379fbc42..ba808e1f2e07f 100644 --- a/pandas/core/groupby/ops.py +++ b/pandas/core/groupby/ops.py @@ -1323,7 +1323,7 @@ def _sort_idx(self) -> npt.NDArray[np.intp]: # Counting sort indexer return get_group_index_sorter(self.labels, self.ngroups) - def __iter__(self): + def __iter__(self) -> Iterator: sdata = self.sorted_data if self.ngroups == 0: diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 6da1b22b5a1dc..7ea017e322bd3 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -3212,7 +3212,7 @@ def _validate_sort_keyword(self, sort): ) @final - def _deprecate_dti_setop(self, other: Index, setop: str_t): + def _deprecate_dti_setop(self, other: Index, setop: str_t) -> None: """ Deprecate setop behavior between timezone-aware DatetimeIndexes with mismatched timezones. diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index 80138c25b0c27..b91fbb8244cb5 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -798,7 +798,7 @@ def slice_indexer(self, start=None, end=None, step=None, kind=lib.no_default): if isinstance(start, time) or isinstance(end, time): raise KeyError("Cannot mix time and non-time slice keys") - def check_str_or_none(point): + def check_str_or_none(point) -> bool: return point is not None and not isinstance(point, str) # GH#33146 if start and end are combinations of str and None and Index is not diff --git a/pandas/core/indexes/extension.py b/pandas/core/indexes/extension.py index 5bf30dde33ba4..81d502b60d609 100644 --- a/pandas/core/indexes/extension.py +++ b/pandas/core/indexes/extension.py @@ -77,7 +77,7 @@ def fget(self): return Index(result, name=self.name) return result - def fset(self, value): + def fset(self, value) -> None: setattr(self._data, name, value) fget.__name__ = name diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index 6bf00bc5bc366..ad69f15a375ca 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -1270,7 +1270,7 @@ def dtype(self) -> np.dtype: def _is_memory_usage_qualified(self) -> bool: """return a boolean if we need a qualified .info display""" - def f(level): + def f(level) -> bool: return "mixed" in level or "string" in level or "unicode" in level return any(f(level) for level in self._inferred_type_levels) diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index 0fb499088868a..27ca114519f77 100644 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -769,7 +769,7 @@ def _maybe_mask_setitem_value(self, indexer, value): return indexer, value @final - def _ensure_listlike_indexer(self, key, axis=None, value=None): + def _ensure_listlike_indexer(self, key, axis=None, value=None) -> None: """ Ensure that a list-like of column labels are all present by adding them if they do not already exist. @@ -1955,7 +1955,7 @@ def _setitem_with_indexer_frame_value(self, indexer, value: DataFrame, name: str self._setitem_single_column(loc, val, pi) - def _setitem_single_column(self, loc: int, value, plane_indexer): + def _setitem_single_column(self, loc: int, value, plane_indexer) -> None: """ Parameters @@ -2038,7 +2038,7 @@ def _setitem_single_column(self, loc: int, value, plane_indexer): # TODO: what if we got here indirectly via loc? return - def _setitem_single_block(self, indexer, value, name: str): + def _setitem_single_block(self, indexer, value, name: str) -> None: """ _setitem_with_indexer for the case when we have a single Block. """ diff --git a/pandas/core/internals/concat.py b/pandas/core/internals/concat.py index 0df8aa5a055b0..c8bc9efd824b2 100644 --- a/pandas/core/internals/concat.py +++ b/pandas/core/internals/concat.py @@ -359,7 +359,7 @@ def _get_mgr_concatenation_plan(mgr: BlockManager, indexers: dict[int, np.ndarra class JoinUnit: - def __init__(self, block: Block, shape: Shape, indexers=None): + def __init__(self, block: Block, shape: Shape, indexers=None) -> None: # Passing shape explicitly is required for cases when block is None. # Note: block is None implies indexers is None, but not vice-versa if indexers is None: diff --git a/pandas/core/internals/managers.py b/pandas/core/internals/managers.py index 9f4c799941afd..900bb077b6014 100644 --- a/pandas/core/internals/managers.py +++ b/pandas/core/internals/managers.py @@ -1974,7 +1974,7 @@ def unpickle_block(values, mgr_locs, ndim: int) -> Block: self._post_setstate() - def _post_setstate(self): + def _post_setstate(self) -> None: pass @cache_readonly @@ -2090,7 +2090,7 @@ def fast_xs(self, loc): """ raise NotImplementedError("Use series._values[loc] instead") - def set_values(self, values: ArrayLike): + def set_values(self, values: ArrayLike) -> None: """ Set the values of the single block in place. diff --git a/pandas/core/internals/ops.py b/pandas/core/internals/ops.py index 5febb302a9de9..477dc98aa2b2b 100644 --- a/pandas/core/internals/ops.py +++ b/pandas/core/internals/ops.py @@ -86,7 +86,7 @@ def operate_blockwise( return new_mgr -def _reset_block_mgr_locs(nbs: list[Block], locs): +def _reset_block_mgr_locs(nbs: list[Block], locs) -> None: """ Reset mgr_locs to correspond to our original DataFrame. """ diff --git a/pandas/core/missing.py b/pandas/core/missing.py index 6005e11efbac4..997a7dbc9ceb8 100644 --- a/pandas/core/missing.py +++ b/pandas/core/missing.py @@ -376,7 +376,7 @@ def _interpolate_1d( bounds_error: bool = False, order: int | None = None, **kwargs, -): +) -> None: """ Logic for the 1-d interpolation. The input indices and yvalues will each be 1-d arrays of the same length. diff --git a/pandas/core/ops/methods.py b/pandas/core/ops/methods.py index e8a930083a778..be7c1205305e4 100644 --- a/pandas/core/ops/methods.py +++ b/pandas/core/ops/methods.py @@ -119,6 +119,6 @@ def _create_methods(cls, arith_method, comp_method): return new_methods -def _add_methods(cls, new_methods): +def _add_methods(cls, new_methods) -> None: for name, method in new_methods.items(): setattr(cls, name, method) diff --git a/pandas/core/series.py b/pandas/core/series.py index bf313925905f7..167590331754d 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -1178,7 +1178,7 @@ def _set_with_engine(self, key, value) -> None: # this is equivalent to self._values[key] = value self._mgr.setitem_inplace(loc, value) - def _set_with(self, key, value): + def _set_with(self, key, value) -> None: # We got here via exception-handling off of InvalidIndexError, so # key should always be listlike at this point. assert not isinstance(key, tuple) @@ -1216,7 +1216,7 @@ def _set_values(self, key, value) -> None: self._mgr = self._mgr.setitem(indexer=key, value=value) self._maybe_update_cacher() - def _set_value(self, label, value, takeable: bool = False): + def _set_value(self, label, value, takeable: bool = False) -> None: """ Quickly set single value at passed label. @@ -1329,7 +1329,7 @@ def _maybe_update_cacher( # Unsorted @property - def _is_mixed_type(self): + def _is_mixed_type(self) -> bool: return False def repeat(self, repeats: int | Sequence[int], axis: None = None) -> Series: diff --git a/pandas/core/strings/accessor.py b/pandas/core/strings/accessor.py index 44ebfbd7f3e9c..f9852005314a4 100644 --- a/pandas/core/strings/accessor.py +++ b/pandas/core/strings/accessor.py @@ -8,6 +8,7 @@ TYPE_CHECKING, Callable, Hashable, + Iterator, cast, ) import warnings @@ -239,7 +240,7 @@ def __getitem__(self, key): result = self._data.array._str_getitem(key) return self._wrap_result(result) - def __iter__(self): + def __iter__(self) -> Iterator: warnings.warn( "Columnar iteration over characters will be deprecated in future releases.", FutureWarning, diff --git a/pandas/core/strings/object_array.py b/pandas/core/strings/object_array.py index f884264e9ab75..407357d2c79e3 100644 --- a/pandas/core/strings/object_array.py +++ b/pandas/core/strings/object_array.py @@ -32,7 +32,7 @@ class ObjectStringArrayMixin(BaseStringArrayMethods): _str_na_value = np.nan - def __len__(self): + def __len__(self) -> int: # For typing, _str_map relies on the object being sized. raise NotImplementedError diff --git a/pandas/core/window/rolling.py b/pandas/core/window/rolling.py index 3fc48b121419a..3225b9c0d2174 100644 --- a/pandas/core/window/rolling.py +++ b/pandas/core/window/rolling.py @@ -14,6 +14,7 @@ Any, Callable, Hashable, + Iterator, Sized, ) import warnings @@ -369,7 +370,7 @@ def __repr__(self) -> str: attrs = ",".join(attrs_list) return f"{type(self).__name__} [{attrs}]" - def __iter__(self): + def __iter__(self) -> Iterator: obj = self._selected_obj.set_axis(self._on) obj = self._create_data(obj) indexer = self._get_window_indexer() @@ -1861,7 +1862,7 @@ def _validate(self): elif not is_integer(self.window) or self.window < 0: raise ValueError("window must be an integer 0 or greater") - def _validate_datetimelike_monotonic(self): + def _validate_datetimelike_monotonic(self) -> None: """ Validate self._on is monotonic (increasing or decreasing) and has no NaT values for frequency windows. diff --git a/pandas/io/excel/_base.py b/pandas/io/excel/_base.py index 79dc5ee3789e3..10b8a5b202872 100644 --- a/pandas/io/excel/_base.py +++ b/pandas/io/excel/_base.py @@ -7,6 +7,7 @@ from io import BytesIO import os from textwrap import fill +from types import TracebackType from typing import ( IO, Any, @@ -1326,7 +1327,7 @@ def __init__( if_sheet_exists = "error" self._if_sheet_exists = if_sheet_exists - def _deprecate(self, attr: str): + def _deprecate(self, attr: str) -> None: """ Deprecate attribute or method for ExcelWriter. """ @@ -1449,7 +1450,12 @@ def check_extension(cls, ext: str) -> Literal[True]: def __enter__(self) -> ExcelWriter: return self - def __exit__(self, exc_type, exc_value, traceback) -> None: + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> None: self.close() def close(self) -> None: @@ -1746,7 +1752,12 @@ def close(self) -> None: def __enter__(self) -> ExcelFile: return self - def __exit__(self, exc_type, exc_value, traceback) -> None: + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> None: self.close() def __del__(self) -> None: diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index d572ca7e66d47..912c088d8b520 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1985,7 +1985,7 @@ def _trim_zeros_float( trimmed = str_floats number_regex = re.compile(rf"^\s*[\+-]?[0-9]+\{decimal}[0-9]*$") - def is_number_with_decimal(x): + def is_number_with_decimal(x) -> bool: return re.match(number_regex, x) is not None def should_trim(values: np.ndarray | list[str]) -> bool: diff --git a/pandas/io/formats/latex.py b/pandas/io/formats/latex.py index 6bf4412be95d4..4bc9da96885f1 100644 --- a/pandas/io/formats/latex.py +++ b/pandas/io/formats/latex.py @@ -180,7 +180,7 @@ def pad_empties(x): return strcols @property - def _empty_info_line(self): + def _empty_info_line(self) -> str: return ( f"Empty {type(self.frame).__name__}\n" f"Columns: {self.frame.columns}\n" @@ -211,7 +211,7 @@ def _format_multicolumn(self, row: list[str]) -> list[str]: ncol = 1 coltext = "" - def append_col(): + def append_col() -> None: # write multicolumn if needed if ncol > 1: row2.append( @@ -773,7 +773,7 @@ def _get_column_format_based_on_dtypes(self) -> str: Right alignment for numbers and left - for strings. """ - def get_col_type(dtype): + def get_col_type(dtype) -> str: if issubclass(dtype.type, np.number): return "r" return "l" diff --git a/pandas/io/formats/style_render.py b/pandas/io/formats/style_render.py index 7631ae2405585..07a09677caf13 100644 --- a/pandas/io/formats/style_render.py +++ b/pandas/io/formats/style_render.py @@ -627,7 +627,7 @@ def _check_trim( element, css=None, value="...", - ): + ) -> bool: """ Indicates whether to break render loops and append a trimming indicator diff --git a/pandas/io/html.py b/pandas/io/html.py index acf98a2f83921..3cfd450e48257 100644 --- a/pandas/io/html.py +++ b/pandas/io/html.py @@ -856,7 +856,7 @@ def _parse_tfoot_tr(self, table): return table.xpath(".//tfoot//tr") -def _expand_elements(body): +def _expand_elements(body) -> None: data = [len(elem) for elem in body] lens = create_series_with_explicit_dtype(data, dtype_if_empty=object) lens_max = lens.max() diff --git a/pandas/io/json/_json.py b/pandas/io/json/_json.py index 7614413692b03..701f72f605989 100644 --- a/pandas/io/json/_json.py +++ b/pandas/io/json/_json.py @@ -8,6 +8,7 @@ import functools from io import StringIO from itertools import islice +from types import TracebackType from typing import ( TYPE_CHECKING, Any, @@ -991,7 +992,12 @@ def __next__(self) -> DataFrame | Series: def __enter__(self) -> JsonReader[FrameSeriesStrT]: return self - def __exit__(self, exc_type, exc_value, traceback) -> None: + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> None: self.close() @@ -1076,7 +1082,7 @@ def _parse_numpy(self): def _parse_no_numpy(self): raise AbstractMethodError(self) - def _convert_axes(self): + def _convert_axes(self) -> None: """ Try to convert axes. """ @@ -1225,7 +1231,7 @@ class SeriesParser(Parser): _default_orient = "index" _split_keys = ("name", "index", "data") - def _parse_no_numpy(self): + def _parse_no_numpy(self) -> None: data = loads(self.json, precise_float=self.precise_float) if self.orient == "split": @@ -1235,7 +1241,7 @@ def _parse_no_numpy(self): else: self.obj = create_series_with_explicit_dtype(data, dtype_if_empty=object) - def _parse_numpy(self): + def _parse_numpy(self) -> None: load_kwargs = { "dtype": None, "numpy": True, @@ -1259,7 +1265,7 @@ def _parse_numpy(self): else: self.obj = create_series_with_explicit_dtype(data, dtype_if_empty=object) - def _try_convert_types(self): + def _try_convert_types(self) -> None: if self.obj is None: return obj, result = self._try_convert_data( @@ -1273,7 +1279,7 @@ class FrameParser(Parser): _default_orient = "columns" _split_keys = ("columns", "index", "data") - def _parse_numpy(self): + def _parse_numpy(self) -> None: json = self.json orient = self.orient @@ -1311,7 +1317,7 @@ def _parse_numpy(self): ) ) - def _parse_no_numpy(self): + def _parse_no_numpy(self) -> None: json = self.json orient = self.orient @@ -1340,7 +1346,7 @@ def _parse_no_numpy(self): loads(json, precise_float=self.precise_float), dtype=None ) - def _process_converter(self, f, filt=None): + def _process_converter(self, f, filt=None) -> None: """ Take a conversion function and possibly recreate the frame. """ @@ -1367,7 +1373,7 @@ def _process_converter(self, f, filt=None): new_frame.columns = obj.columns self.obj = new_frame - def _try_convert_types(self): + def _try_convert_types(self) -> None: if self.obj is None: return if self.convert_dates: @@ -1377,7 +1383,7 @@ def _try_convert_types(self): lambda col, c: self._try_convert_data(col, c, convert_dates=False) ) - def _try_convert_dates(self): + def _try_convert_dates(self) -> None: if self.obj is None: return diff --git a/pandas/io/json/_normalize.py b/pandas/io/json/_normalize.py index e77d60d2d4950..627092f632042 100644 --- a/pandas/io/json/_normalize.py +++ b/pandas/io/json/_normalize.py @@ -485,7 +485,7 @@ def _pull_records(js: dict[str, Any], spec: list | str) -> list: meta_vals: DefaultDict = defaultdict(list) meta_keys = [sep.join(val) for val in _meta] - def _recursive_extract(data, path, seen_meta, level=0): + def _recursive_extract(data, path, seen_meta, level=0) -> None: if isinstance(data, dict): data = [data] if len(path) > 1: diff --git a/pandas/io/parsers/arrow_parser_wrapper.py b/pandas/io/parsers/arrow_parser_wrapper.py index bb62b1405da3a..a644ce24347c1 100644 --- a/pandas/io/parsers/arrow_parser_wrapper.py +++ b/pandas/io/parsers/arrow_parser_wrapper.py @@ -42,7 +42,7 @@ def _parse_kwds(self): ) self.na_values = list(self.kwds["na_values"]) - def _get_pyarrow_options(self): + def _get_pyarrow_options(self) -> None: """ Rename some arguments to pass to pyarrow """ diff --git a/pandas/io/parsers/readers.py b/pandas/io/parsers/readers.py index 4c8437736ea35..249831a7dc579 100644 --- a/pandas/io/parsers/readers.py +++ b/pandas/io/parsers/readers.py @@ -8,6 +8,7 @@ import inspect import sys from textwrap import fill +from types import TracebackType from typing import ( IO, Any, @@ -1806,7 +1807,12 @@ def get_chunk(self, size: int | None = None) -> DataFrame: def __enter__(self) -> TextFileReader: return self - def __exit__(self, exc_type, exc_value, traceback) -> None: + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> None: self.close() diff --git a/pandas/io/pytables.py b/pandas/io/pytables.py index 77f35bc09abd3..9e940dc6d4110 100644 --- a/pandas/io/pytables.py +++ b/pandas/io/pytables.py @@ -15,6 +15,7 @@ import os import re from textwrap import dedent +from types import TracebackType from typing import ( TYPE_CHECKING, Any, @@ -632,7 +633,12 @@ def __repr__(self) -> str: def __enter__(self) -> HDFStore: return self - def __exit__(self, exc_type, exc_value, traceback) -> None: + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> None: self.close() def keys(self, include: str = "pandas") -> list[str]: @@ -1903,7 +1909,7 @@ def __init__( self.auto_close = auto_close - def __iter__(self): + def __iter__(self) -> Iterator: # iterate current = self.start if self.coordinates is None: @@ -2125,7 +2131,7 @@ def cvalues(self): """return my cython values""" return self.values - def __iter__(self): + def __iter__(self) -> Iterator: return iter(self.values) def maybe_set_size(self, min_itemsize=None) -> None: diff --git a/pandas/io/sas/sas7bdat.py b/pandas/io/sas/sas7bdat.py index 7282affe1b5e6..3248463aeeaf9 100644 --- a/pandas/io/sas/sas7bdat.py +++ b/pandas/io/sas/sas7bdat.py @@ -405,7 +405,7 @@ def _process_page_meta(self) -> bool: or self._current_page_data_subheader_pointers != [] ) - def _read_page_header(self): + def _read_page_header(self) -> None: bit_offset = self._page_bit_offset tx = const.page_type_offset + bit_offset self._current_page_type = ( diff --git a/pandas/io/sas/sasreader.py b/pandas/io/sas/sasreader.py index 359174166f980..2b6472913a4d3 100644 --- a/pandas/io/sas/sasreader.py +++ b/pandas/io/sas/sasreader.py @@ -7,6 +7,7 @@ ABCMeta, abstractmethod, ) +from types import TracebackType from typing import ( TYPE_CHECKING, Hashable, @@ -48,7 +49,12 @@ def close(self) -> None: def __enter__(self) -> ReaderBase: return self - def __exit__(self, exc_type, exc_value, traceback) -> None: + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> None: self.close() diff --git a/pandas/io/sql.py b/pandas/io/sql.py index 219b8105561ee..b4432abd1061a 100644 --- a/pandas/io/sql.py +++ b/pandas/io/sql.py @@ -819,7 +819,7 @@ def sql_schema(self) -> str: return str(CreateTable(self.table).compile(self.pd_sql.connectable)) - def _execute_create(self): + def _execute_create(self) -> None: # Inserting table into database, add to MetaData object self.table = self.table.to_metadata(self.pd_sql.meta) self.table.create(bind=self.pd_sql.connectable) @@ -1102,7 +1102,7 @@ def _create_table_setup(self): meta = MetaData() return Table(self.name, meta, *columns, schema=schema) - def _harmonize_columns(self, parse_dates=None): + def _harmonize_columns(self, parse_dates=None) -> None: """ Make the DataFrame's column types align with the SQL table column types. @@ -1856,7 +1856,7 @@ def __init__(self, *args, **kwargs) -> None: # this will transform time(12,34,56,789) into '12:34:56.000789' # (this is what sqlalchemy does) - def _adapt_time(t): + def _adapt_time(t) -> str: # This is faster than strftime return f"{t.hour:02d}:{t.minute:02d}:{t.second:02d}.{t.microsecond:06d}" @@ -1866,7 +1866,7 @@ def _adapt_time(t): def sql_schema(self) -> str: return str(";\n".join(self.table)) - def _execute_create(self): + def _execute_create(self) -> None: with self.pd_sql.run_transaction() as conn: for stmt in self.table: conn.execute(stmt) diff --git a/pandas/io/stata.py b/pandas/io/stata.py index a0b9a0d247533..f51b46e1c4783 100644 --- a/pandas/io/stata.py +++ b/pandas/io/stata.py @@ -18,6 +18,7 @@ import os import struct import sys +from types import TracebackType from typing import ( IO, TYPE_CHECKING, @@ -1178,7 +1179,12 @@ def __enter__(self) -> StataReader: """enter context manager""" return self - def __exit__(self, exc_type, exc_value, traceback) -> None: + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> None: """exit context manager""" self.close() diff --git a/pandas/plotting/_matplotlib/boxplot.py b/pandas/plotting/_matplotlib/boxplot.py index d85495b70e6c3..cd34f2264f44f 100644 --- a/pandas/plotting/_matplotlib/boxplot.py +++ b/pandas/plotting/_matplotlib/boxplot.py @@ -59,7 +59,7 @@ def __init__(self, data, return_type: str = "axes", **kwargs) -> None: self.return_type = return_type MPLPlot.__init__(self, data, **kwargs) - def _args_adjust(self): + def _args_adjust(self) -> None: if self.subplots: # Disable label ax sharing. Otherwise, all subplots shows last # column label @@ -118,7 +118,7 @@ def _validate_color_args(self): self._medians_c = colors[2] self._caps_c = colors[0] - def _get_colors(self, num_colors=None, color_kwds="color"): + def _get_colors(self, num_colors=None, color_kwds="color") -> None: pass def maybe_color_bp(self, bp) -> None: @@ -146,7 +146,7 @@ def maybe_color_bp(self, bp) -> None: if not self.kwds.get("capprops"): setp(bp["caps"], color=caps, alpha=1) - def _make_plot(self): + def _make_plot(self) -> None: if self.subplots: self._return_obj = pd.Series(dtype=object) @@ -198,16 +198,16 @@ def _make_plot(self): labels = [pprint_thing(key) for key in range(len(labels))] self._set_ticklabels(ax, labels) - def _set_ticklabels(self, ax: Axes, labels): + def _set_ticklabels(self, ax: Axes, labels) -> None: if self.orientation == "vertical": ax.set_xticklabels(labels) else: ax.set_yticklabels(labels) - def _make_legend(self): + def _make_legend(self) -> None: pass - def _post_plot_logic(self, ax, data): + def _post_plot_logic(self, ax, data) -> None: # GH 45465: make sure that the boxplot doesn't ignore xlabel/ylabel if self.xlabel: ax.set_xlabel(pprint_thing(self.xlabel)) @@ -215,7 +215,7 @@ def _post_plot_logic(self, ax, data): ax.set_ylabel(pprint_thing(self.ylabel)) @property - def orientation(self): + def orientation(self) -> Literal["horizontal", "vertical"]: if self.kwds.get("vert", True): return "vertical" else: @@ -343,7 +343,7 @@ def _get_colors(): return result - def maybe_color_bp(bp, **kwds): + def maybe_color_bp(bp, **kwds) -> None: # GH 30346, when users specifying those arguments explicitly, our defaults # for these four kwargs should be overridden; if not, use Pandas settings if not kwds.get("boxprops"): diff --git a/pandas/plotting/_matplotlib/converter.py b/pandas/plotting/_matplotlib/converter.py index 5fe97534112b4..6eb77b63f5356 100644 --- a/pandas/plotting/_matplotlib/converter.py +++ b/pandas/plotting/_matplotlib/converter.py @@ -606,7 +606,7 @@ def first_label(label_flags): day_start = period_break(dates_, "day") month_start = period_break(dates_, "month") - def _hour_finder(label_interval, force_year_start): + def _hour_finder(label_interval, force_year_start) -> None: _hour = dates_.hour _prev_hour = (dates_ - 1 * dates_.freq).hour hour_start = (_hour - _prev_hour) != 0 @@ -619,7 +619,7 @@ def _hour_finder(label_interval, force_year_start): if force_year_start and not has_level_label(year_start, vmin_orig): info_fmt[first_label(day_start)] = "%H:%M\n%d-%b\n%Y" - def _minute_finder(label_interval): + def _minute_finder(label_interval) -> None: hour_start = period_break(dates_, "hour") _minute = dates_.minute _prev_minute = (dates_ - 1 * dates_.freq).minute @@ -632,7 +632,7 @@ def _minute_finder(label_interval): info_fmt[day_start] = "%H:%M\n%d-%b" info_fmt[year_start] = "%H:%M\n%d-%b\n%Y" - def _second_finder(label_interval): + def _second_finder(label_interval) -> None: minute_start = period_break(dates_, "minute") _second = dates_.second _prev_second = (dates_ - 1 * dates_.freq).second diff --git a/pandas/plotting/_matplotlib/core.py b/pandas/plotting/_matplotlib/core.py index 7a469f9f19d80..2b90c6dd66540 100644 --- a/pandas/plotting/_matplotlib/core.py +++ b/pandas/plotting/_matplotlib/core.py @@ -457,7 +457,7 @@ def generate(self) -> None: self._post_plot_logic_common(ax, self.data) self._post_plot_logic(ax, self.data) - def _args_adjust(self): + def _args_adjust(self) -> None: pass def _has_plotted_object(self, ax: Axes) -> bool: @@ -638,7 +638,7 @@ def _compute_plot_data(self): def _make_plot(self): raise AbstractMethodError(self) - def _add_table(self): + def _add_table(self) -> None: if self.table is False: return elif self.table is True: @@ -666,7 +666,7 @@ def _post_plot_logic_common(self, ax, data): else: # pragma no cover raise ValueError - def _post_plot_logic(self, ax, data): + def _post_plot_logic(self, ax, data) -> None: """Post process for each axes. Overridden in child classes""" pass @@ -731,7 +731,7 @@ def _adorn_subplots(self): raise ValueError(msg) self.axes[0].set_title(self.title) - def _apply_axis_properties(self, axis: Axis, rot=None, fontsize=None): + def _apply_axis_properties(self, axis: Axis, rot=None, fontsize=None) -> None: """ Tick creation within matplotlib is reasonably expensive and is internally deferred until accessed as Ticks are created/destroyed @@ -1153,7 +1153,7 @@ def __init__(self, data, x, y, **kwargs) -> None: def nseries(self) -> int: return 1 - def _post_plot_logic(self, ax: Axes, data): + def _post_plot_logic(self, ax: Axes, data) -> None: x, y = self.x, self.y xlabel = self.xlabel if self.xlabel is not None else pprint_thing(x) ylabel = self.ylabel if self.ylabel is not None else pprint_thing(y) @@ -1285,7 +1285,7 @@ def __init__(self, data, x, y, C=None, **kwargs) -> None: C = self.data.columns[C] self.C = C - def _make_plot(self): + def _make_plot(self) -> None: x, y, data, C = self.x, self.y, self.data, self.C ax = self.axes[0] # pandas uses colormap, matplotlib uses cmap. @@ -1302,7 +1302,7 @@ def _make_plot(self): if cb: self._plot_colorbar(ax) - def _make_legend(self): + def _make_legend(self) -> None: pass @@ -1334,7 +1334,7 @@ def _is_ts_plot(self) -> bool: def _use_dynamic_x(self): return use_dynamic_x(self._get_ax(0), self.data) - def _make_plot(self): + def _make_plot(self) -> None: if self._is_ts_plot(): data = maybe_convert_index(self._get_ax(0), self.data) @@ -1426,7 +1426,7 @@ def _get_stacking_id(self): return None @classmethod - def _initialize_stacker(cls, ax: Axes, stacking_id, n: int): + def _initialize_stacker(cls, ax: Axes, stacking_id, n: int) -> None: if stacking_id is None: return if not hasattr(ax, "_stacker_pos_prior"): @@ -1456,7 +1456,7 @@ def _get_stacked_values(cls, ax: Axes, stacking_id, values, label): ) @classmethod - def _update_stacker(cls, ax: Axes, stacking_id, values): + def _update_stacker(cls, ax: Axes, stacking_id, values) -> None: if stacking_id is None: return if (values >= 0).all(): @@ -1464,7 +1464,7 @@ def _update_stacker(cls, ax: Axes, stacking_id, values): elif (values <= 0).all(): ax._stacker_neg_prior[stacking_id] += values - def _post_plot_logic(self, ax: Axes, data): + def _post_plot_logic(self, ax: Axes, data) -> None: from matplotlib.ticker import FixedLocator def get_label(i): @@ -1568,7 +1568,7 @@ def _plot( # type: ignore[override] res = [rect] return res - def _post_plot_logic(self, ax: Axes, data): + def _post_plot_logic(self, ax: Axes, data) -> None: LinePlot._post_plot_logic(self, ax, data) is_shared_y = len(list(ax.get_shared_y_axes())) > 0 @@ -1623,7 +1623,7 @@ def __init__(self, data, **kwargs) -> None: self.ax_pos = self.tick_pos - self.tickoffset - def _args_adjust(self): + def _args_adjust(self) -> None: if is_list_like(self.bottom): self.bottom = np.array(self.bottom) if is_list_like(self.left): @@ -1640,7 +1640,7 @@ def _plot( # type: ignore[override] def _start_base(self): return self.bottom - def _make_plot(self): + def _make_plot(self) -> None: import matplotlib as mpl colors = self._get_colors() @@ -1716,7 +1716,7 @@ def _make_plot(self): ) self._append_legend_handles_labels(rect, label) - def _post_plot_logic(self, ax: Axes, data): + def _post_plot_logic(self, ax: Axes, data) -> None: if self.use_index: str_index = [pprint_thing(key) for key in data.index] else: @@ -1727,7 +1727,7 @@ def _post_plot_logic(self, ax: Axes, data): self._decorate_ticks(ax, self._get_index_name(), str_index, s_edge, e_edge) - def _decorate_ticks(self, ax: Axes, name, ticklabels, start_edge, end_edge): + def _decorate_ticks(self, ax: Axes, name, ticklabels, start_edge, end_edge) -> None: ax.set_xlim((start_edge, end_edge)) if self.xticks is not None: @@ -1765,7 +1765,7 @@ def _plot( # type: ignore[override] def _get_custom_index_name(self): return self.ylabel - def _decorate_ticks(self, ax: Axes, name, ticklabels, start_edge, end_edge): + def _decorate_ticks(self, ax: Axes, name, ticklabels, start_edge, end_edge) -> None: # horizontal bars ax.set_ylim((start_edge, end_edge)) ax.set_yticks(self.tick_pos) @@ -1788,16 +1788,16 @@ def __init__(self, data, kind=None, **kwargs) -> None: raise ValueError(f"{self._kind} plot doesn't allow negative values") MPLPlot.__init__(self, data, kind=kind, **kwargs) - def _args_adjust(self): + def _args_adjust(self) -> None: self.grid = False self.logy = False self.logx = False self.loglog = False - def _validate_color_args(self): + def _validate_color_args(self) -> None: pass - def _make_plot(self): + def _make_plot(self) -> None: colors = self._get_colors(num_colors=len(self.data), color_kwds="colors") self.kwds.setdefault("colors", colors) diff --git a/pandas/plotting/_matplotlib/hist.py b/pandas/plotting/_matplotlib/hist.py index d69f68d9e0b66..cad03b1923e9d 100644 --- a/pandas/plotting/_matplotlib/hist.py +++ b/pandas/plotting/_matplotlib/hist.py @@ -62,7 +62,7 @@ def __init__( # Do not call LinePlot.__init__ which may fill nan MPLPlot.__init__(self, data, **kwargs) - def _args_adjust(self): + def _args_adjust(self) -> None: # calculate bin number separately in different subplots # where subplots are created based on by argument if is_integer(self.bins): @@ -109,7 +109,7 @@ def _plot( cls._update_stacker(ax, stacking_id, n) return patches - def _make_plot(self): + def _make_plot(self) -> None: colors = self._get_colors() stacking_id = self._get_stacking_id() @@ -166,7 +166,7 @@ def _make_plot_keywords(self, kwds, y): kwds["bins"] = self.bins return kwds - def _post_plot_logic(self, ax: Axes, data): + def _post_plot_logic(self, ax: Axes, data) -> None: if self.orientation == "horizontal": ax.set_xlabel("Frequency") else: @@ -194,7 +194,7 @@ def __init__(self, data, bw_method=None, ind=None, **kwargs) -> None: self.bw_method = bw_method self.ind = ind - def _args_adjust(self): + def _args_adjust(self) -> None: pass def _get_ind(self, y): @@ -243,7 +243,7 @@ def _make_plot_keywords(self, kwds, y): kwds["ind"] = self._get_ind(y) return kwds - def _post_plot_logic(self, ax, data): + def _post_plot_logic(self, ax, data) -> None: ax.set_ylabel("Density") @@ -341,7 +341,7 @@ def _grouped_hist( else: kwargs["label"] = column - def plot_group(group, ax): + def plot_group(group, ax) -> None: ax.hist(group.dropna().values, bins=bins, **kwargs) if legend: ax.legend() diff --git a/pandas/plotting/_matplotlib/timeseries.py b/pandas/plotting/_matplotlib/timeseries.py index 06aac478bfb11..366fcf3442ed6 100644 --- a/pandas/plotting/_matplotlib/timeseries.py +++ b/pandas/plotting/_matplotlib/timeseries.py @@ -93,7 +93,7 @@ def _is_sup(f1: str, f2: str) -> bool: ) -def _upsample_others(ax: Axes, freq, kwargs): +def _upsample_others(ax: Axes, freq, kwargs) -> None: legend = ax.get_legend() lines, labels = _replot_ax(ax, freq, kwargs) _replot_ax(ax, freq, kwargs) @@ -146,7 +146,7 @@ def _replot_ax(ax: Axes, freq, kwargs): return lines, labels -def decorate_axes(ax: Axes, freq, kwargs): +def decorate_axes(ax: Axes, freq, kwargs) -> None: """Initialize axes for time-series plotting""" if not hasattr(ax, "_plot_data"): ax._plot_data = [] diff --git a/pandas/plotting/_matplotlib/tools.py b/pandas/plotting/_matplotlib/tools.py index 8f0ea70ab4124..5daf1683b28e3 100644 --- a/pandas/plotting/_matplotlib/tools.py +++ b/pandas/plotting/_matplotlib/tools.py @@ -38,14 +38,14 @@ ) -def do_adjust_figure(fig: Figure): +def do_adjust_figure(fig: Figure) -> bool: """Whether fig has constrained_layout enabled.""" if not hasattr(fig, "get_constrained_layout"): return False return not fig.get_constrained_layout() -def maybe_adjust_figure(fig: Figure, *args, **kwargs): +def maybe_adjust_figure(fig: Figure, *args, **kwargs) -> None: """Call fig.subplots_adjust unless fig has constrained_layout enabled.""" if do_adjust_figure(fig): fig.subplots_adjust(*args, **kwargs) @@ -318,7 +318,7 @@ def create_subplots( return fig, axes -def _remove_labels_from_axis(axis: Axis): +def _remove_labels_from_axis(axis: Axis) -> None: for t in axis.get_majorticklabels(): t.set_visible(False) @@ -392,7 +392,7 @@ def handle_shared_axes( ncols: int, sharex: bool, sharey: bool, -): +) -> None: if nplots > 1: row_num = lambda x: x.get_subplotspec().rowspan.start col_num = lambda x: x.get_subplotspec().colspan.start diff --git a/pandas/tests/dtypes/test_inference.py b/pandas/tests/dtypes/test_inference.py index f08d6b8c9feb8..46bc6d82b55db 100644 --- a/pandas/tests/dtypes/test_inference.py +++ b/pandas/tests/dtypes/test_inference.py @@ -18,6 +18,7 @@ from numbers import Number import re import sys +from typing import Iterator import numpy as np import pytest @@ -95,7 +96,7 @@ class MockNumpyLikeArray: def __init__(self, values) -> None: self._values = values - def __iter__(self): + def __iter__(self) -> Iterator: iter_values = iter(self._values) def it_outer(): @@ -103,7 +104,7 @@ def it_outer(): return it_outer() - def __len__(self): + def __len__(self) -> int: return len(self._values) def __array__(self, t=None): @@ -1954,7 +1955,7 @@ class Numeric(Number): def __init__(self, value) -> None: self.value = value - def __int__(self): + def __int__(self) -> int: return self.value num = Numeric(1) diff --git a/pandas/tests/extension/arrow/arrays.py b/pandas/tests/extension/arrow/arrays.py index 26b94ebe5a8da..b4e7a99a3d6f5 100644 --- a/pandas/tests/extension/arrow/arrays.py +++ b/pandas/tests/extension/arrow/arrays.py @@ -91,7 +91,7 @@ def _from_sequence(cls, values, dtype=None, copy=False): arr = pa.chunked_array([pa.array(np.asarray(values))]) return cls(arr) - def __repr__(self): + def __repr__(self) -> str: return f"{type(self).__name__}({repr(self._data)})" def __contains__(self, obj) -> bool: diff --git a/pandas/tests/frame/constructors/test_from_records.py b/pandas/tests/frame/constructors/test_from_records.py index c6d54e28ca1c8..3b5a0c5a32bc4 100644 --- a/pandas/tests/frame/constructors/test_from_records.py +++ b/pandas/tests/frame/constructors/test_from_records.py @@ -1,5 +1,6 @@ from datetime import datetime from decimal import Decimal +from typing import Iterator import numpy as np import pytest @@ -200,7 +201,7 @@ def __init__(self, *args) -> None: def __getitem__(self, i): return self.args[i] - def __iter__(self): + def __iter__(self) -> Iterator: return iter(self.args) recs = [Record(1, 2, 3), Record(4, 5, 6), Record(7, 8, 9)] diff --git a/pandas/tests/frame/test_arithmetic.py b/pandas/tests/frame/test_arithmetic.py index 25257a2c102fd..9fc3161a7b004 100644 --- a/pandas/tests/frame/test_arithmetic.py +++ b/pandas/tests/frame/test_arithmetic.py @@ -2032,7 +2032,7 @@ def _constructor_expanddim(self): class SubclassedDataFrame(DataFrame): _metadata = ["my_extra_data"] - def __init__(self, my_extra_data, *args, **kwargs): + def __init__(self, my_extra_data, *args, **kwargs) -> None: self.my_extra_data = my_extra_data super().__init__(*args, **kwargs) diff --git a/pandas/tests/frame/test_constructors.py b/pandas/tests/frame/test_constructors.py index b4f027f3a832a..37e08adcfdf88 100644 --- a/pandas/tests/frame/test_constructors.py +++ b/pandas/tests/frame/test_constructors.py @@ -10,6 +10,7 @@ import functools import itertools import re +from typing import Iterator import warnings import numpy as np @@ -1394,7 +1395,7 @@ def __init__(self, lst) -> None: def __getitem__(self, n): return self._lst.__getitem__(n) - def __len__(self): + def __len__(self) -> int: return self._lst.__len__() lst_containers = [DummyContainer([1, "a"]), DummyContainer([2, "b"])] @@ -1430,7 +1431,7 @@ def test_constructor_list_of_ranges(self): def test_constructor_iterable(self): # GH 21987 class Iter: - def __iter__(self): + def __iter__(self) -> Iterator: for i in range(10): yield [1, 2, 3] diff --git a/pandas/tests/io/formats/test_format.py b/pandas/tests/io/formats/test_format.py index 443aa743a6444..01d26c267f628 100644 --- a/pandas/tests/io/formats/test_format.py +++ b/pandas/tests/io/formats/test_format.py @@ -2816,7 +2816,7 @@ def name(self): return "DtypeStub" class ExtTypeStub(pd.api.extensions.ExtensionArray): - def __len__(self): + def __len__(self) -> int: return 2 def __getitem__(self, ix): diff --git a/pandas/tests/io/json/test_readlines.py b/pandas/tests/io/json/test_readlines.py index 6fa0c4d5c51a1..b371990178d28 100644 --- a/pandas/tests/io/json/test_readlines.py +++ b/pandas/tests/io/json/test_readlines.py @@ -1,5 +1,6 @@ from io import StringIO from pathlib import Path +from typing import Iterator import pytest @@ -289,7 +290,7 @@ def read(self, *args): self.read_count += 1 return self.stringio.read(*args) - def __iter__(self): + def __iter__(self) -> Iterator: self.read_count += 1 return iter(self.stringio) diff --git a/pandas/tests/io/parser/test_python_parser_only.py b/pandas/tests/io/parser/test_python_parser_only.py index 1d3392b124895..5f067b205a72d 100644 --- a/pandas/tests/io/parser/test_python_parser_only.py +++ b/pandas/tests/io/parser/test_python_parser_only.py @@ -11,6 +11,7 @@ BytesIO, StringIO, ) +from typing import Iterator import pytest @@ -322,7 +323,7 @@ class NoNextBuffer: def __init__(self, csv_data) -> None: self.data = csv_data - def __iter__(self): + def __iter__(self) -> Iterator: return self.data.__iter__() def read(self): diff --git a/pandas/tests/io/test_html.py b/pandas/tests/io/test_html.py index de0d4c1b49ea5..c250a474cb3ca 100644 --- a/pandas/tests/io/test_html.py +++ b/pandas/tests/io/test_html.py @@ -8,6 +8,7 @@ from pathlib import Path import re import threading +from typing import Iterator from urllib.error import URLError import numpy as np @@ -1277,7 +1278,7 @@ def seek(self, offset): def seekable(self): return True - def __iter__(self): + def __iter__(self) -> Iterator: # to fool `is_file_like`, should never end up here assert False diff --git a/pandas/tests/reshape/concat/test_concat.py b/pandas/tests/reshape/concat/test_concat.py index 4ba231523af14..8e7be925a87c6 100644 --- a/pandas/tests/reshape/concat/test_concat.py +++ b/pandas/tests/reshape/concat/test_concat.py @@ -3,6 +3,7 @@ deque, ) from decimal import Decimal +from typing import Iterator from warnings import ( catch_warnings, simplefilter, @@ -463,7 +464,7 @@ def __getitem__(self, index): tm.assert_frame_equal(concat(CustomIterator1(), ignore_index=True), expected) class CustomIterator2(abc.Iterable): - def __iter__(self): + def __iter__(self) -> Iterator: yield df1 yield df2 diff --git a/pandas/tests/series/test_constructors.py b/pandas/tests/series/test_constructors.py index f79714ae6455c..9f8ae880a1b3e 100644 --- a/pandas/tests/series/test_constructors.py +++ b/pandas/tests/series/test_constructors.py @@ -3,6 +3,7 @@ datetime, timedelta, ) +from typing import Iterator from dateutil.tz import tzoffset import numpy as np @@ -252,7 +253,7 @@ def test_constructor_series(self): def test_constructor_iterable(self): # GH 21987 class Iter: - def __iter__(self): + def __iter__(self) -> Iterator: yield from range(10) expected = Series(list(range(10)), dtype="int64") diff --git a/pandas/tseries/holiday.py b/pandas/tseries/holiday.py index 6426dbcd54489..158db45996f4d 100644 --- a/pandas/tseries/holiday.py +++ b/pandas/tseries/holiday.py @@ -356,7 +356,7 @@ def _apply_rule(self, dates): holiday_calendars = {} -def register(cls): +def register(cls) -> None: try: name = cls.name except AttributeError: diff --git a/pandas/util/_decorators.py b/pandas/util/_decorators.py index 86c945f1321f5..75112b6a23918 100644 --- a/pandas/util/_decorators.py +++ b/pandas/util/_decorators.py @@ -215,7 +215,7 @@ def wrapper(*args, **kwargs) -> Callable[..., Any]: return _deprecate_kwarg -def _format_argument_list(allow_args: list[str]): +def _format_argument_list(allow_args: list[str]) -> str: """ Convert the allow_args argument (either string or integer) of `deprecate_nonkeyword_arguments` function to a string describing diff --git a/pandas/util/_doctools.py b/pandas/util/_doctools.py index cb4ceb052a8e0..80ec9724931bc 100644 --- a/pandas/util/_doctools.py +++ b/pandas/util/_doctools.py @@ -136,7 +136,7 @@ def _insert_index(self, data): data.columns = col return data - def _make_table(self, ax, df, title: str, height: float | None = None): + def _make_table(self, ax, df, title: str, height: float | None = None) -> None: if df is None: ax.set_visible(False) return diff --git a/pandas/util/_test_decorators.py b/pandas/util/_test_decorators.py index f94b2511da678..ca856fe2482ca 100644 --- a/pandas/util/_test_decorators.py +++ b/pandas/util/_test_decorators.py @@ -112,18 +112,20 @@ def safe_import(mod_name: str, min_version: str | None = None): return False -def _skip_if_no_mpl(): +def _skip_if_no_mpl() -> bool | None: mod = safe_import("matplotlib") if mod: mod.use("Agg") + return None else: return True -def _skip_if_not_us_locale(): +def _skip_if_not_us_locale() -> bool | None: lang, _ = locale.getlocale() if lang != "en_US": return True + return None def _skip_if_no_scipy() -> bool: @@ -191,14 +193,19 @@ def skip_if_no(package: str, min_version: str | None = None): ) +# error: Argument 1 to "__call__" of "_SkipifMarkDecorator" has incompatible type +# "Optional[bool]"; expected "Union[str, bool]" skip_if_no_mpl = pytest.mark.skipif( - _skip_if_no_mpl(), reason="Missing matplotlib dependency" + _skip_if_no_mpl(), reason="Missing matplotlib dependency" # type: ignore[arg-type] ) skip_if_mpl = pytest.mark.skipif(not _skip_if_no_mpl(), reason="matplotlib is present") skip_if_32bit = pytest.mark.skipif(not IS64, reason="skipping for 32 bit") skip_if_windows = pytest.mark.skipif(is_platform_windows(), reason="Running on Windows") +# error: Argument 1 to "__call__" of "_SkipifMarkDecorator" has incompatible type +# "Optional[bool]"; expected "Union[str, bool]" skip_if_not_us_locale = pytest.mark.skipif( - _skip_if_not_us_locale(), reason=f"Specific locale is set {locale.getlocale()[0]}" + _skip_if_not_us_locale(), # type: ignore[arg-type] + reason=f"Specific locale is set {locale.getlocale()[0]}", ) skip_if_no_scipy = pytest.mark.skipif( _skip_if_no_scipy(), reason="Missing SciPy requirement" diff --git a/pandas/util/_tester.py b/pandas/util/_tester.py index 1b018a6a1ba34..3fe7c4d589993 100644 --- a/pandas/util/_tester.py +++ b/pandas/util/_tester.py @@ -11,7 +11,7 @@ PKG = os.path.dirname(os.path.dirname(__file__)) -def test(extra_args: list[str] | None = None): +def test(extra_args: list[str] | None = None) -> None: """ Run the pandas test suite using pytest. diff --git a/pyright_reportGeneralTypeIssues.json b/pyright_reportGeneralTypeIssues.json index 3f20611f2c46d..4a82c579262e3 100644 --- a/pyright_reportGeneralTypeIssues.json +++ b/pyright_reportGeneralTypeIssues.json @@ -17,6 +17,7 @@ # and all files that currently don't pass "pandas/_testing/__init__.py", "pandas/_testing/_hypothesis.py", + "pandas/compat/pickle_compat.py", "pandas/core/algorithms.py", "pandas/core/apply.py", "pandas/core/array_algos/take.py",