diff --git a/pandas/compat/numpy/function.py b/pandas/compat/numpy/function.py index 69dc3ac417510..cea1b80d340c8 100644 --- a/pandas/compat/numpy/function.py +++ b/pandas/compat/numpy/function.py @@ -15,12 +15,9 @@ methods that are spread throughout the codebase. This module will make it easier to adjust to future upstream changes in the analogous numpy signatures. """ -from typing import ( - Any, - Dict, - Optional, - Union, -) +from __future__ import annotations + +from typing import Any from numpy import ndarray @@ -41,7 +38,7 @@ def __init__( self, defaults, fname=None, - method: Optional[str] = None, + method: str | None = None, max_fname_arg_count=None, ): self.fname = fname @@ -55,7 +52,7 @@ def __call__( kwargs, fname=None, max_fname_arg_count=None, - method: Optional[str] = None, + method: str | None = None, ) -> None: if args or kwargs: fname = self.fname if fname is None else fname @@ -119,7 +116,7 @@ def validate_argmax_with_skipna(skipna, args, kwargs): return skipna -ARGSORT_DEFAULTS: Dict[str, Optional[Union[int, str]]] = {} +ARGSORT_DEFAULTS: dict[str, int | str | None] = {} ARGSORT_DEFAULTS["axis"] = -1 ARGSORT_DEFAULTS["kind"] = "quicksort" ARGSORT_DEFAULTS["order"] = None @@ -132,7 +129,7 @@ def validate_argmax_with_skipna(skipna, args, kwargs): # two different signatures of argsort, this second validation for when the # `kind` param is supported -ARGSORT_DEFAULTS_KIND: Dict[str, Optional[int]] = {} +ARGSORT_DEFAULTS_KIND: dict[str, int | None] = {} ARGSORT_DEFAULTS_KIND["axis"] = -1 ARGSORT_DEFAULTS_KIND["order"] = None validate_argsort_kind = CompatValidator( @@ -155,7 +152,7 @@ def validate_argsort_with_ascending(ascending, args, kwargs): return ascending -CLIP_DEFAULTS: Dict[str, Any] = {"out": None} +CLIP_DEFAULTS: dict[str, Any] = {"out": None} validate_clip = CompatValidator( CLIP_DEFAULTS, fname="clip", method="both", max_fname_arg_count=3 ) @@ -176,7 +173,7 @@ def validate_clip_with_axis(axis, args, kwargs): return axis -CUM_FUNC_DEFAULTS: Dict[str, Any] = {} +CUM_FUNC_DEFAULTS: dict[str, Any] = {} CUM_FUNC_DEFAULTS["dtype"] = None CUM_FUNC_DEFAULTS["out"] = None validate_cum_func = CompatValidator( @@ -201,7 +198,7 @@ def validate_cum_func_with_skipna(skipna, args, kwargs, name): return skipna -ALLANY_DEFAULTS: Dict[str, Optional[bool]] = {} +ALLANY_DEFAULTS: dict[str, bool | None] = {} ALLANY_DEFAULTS["dtype"] = None ALLANY_DEFAULTS["out"] = None ALLANY_DEFAULTS["keepdims"] = False @@ -224,28 +221,28 @@ def validate_cum_func_with_skipna(skipna, args, kwargs, name): MINMAX_DEFAULTS, fname="max", method="both", max_fname_arg_count=1 ) -RESHAPE_DEFAULTS: Dict[str, str] = {"order": "C"} +RESHAPE_DEFAULTS: dict[str, str] = {"order": "C"} validate_reshape = CompatValidator( RESHAPE_DEFAULTS, fname="reshape", method="both", max_fname_arg_count=1 ) -REPEAT_DEFAULTS: Dict[str, Any] = {"axis": None} +REPEAT_DEFAULTS: dict[str, Any] = {"axis": None} validate_repeat = CompatValidator( REPEAT_DEFAULTS, fname="repeat", method="both", max_fname_arg_count=1 ) -ROUND_DEFAULTS: Dict[str, Any] = {"out": None} +ROUND_DEFAULTS: dict[str, Any] = {"out": None} validate_round = CompatValidator( ROUND_DEFAULTS, fname="round", method="both", max_fname_arg_count=1 ) -SORT_DEFAULTS: Dict[str, Optional[Union[int, str]]] = {} +SORT_DEFAULTS: dict[str, int | str | None] = {} SORT_DEFAULTS["axis"] = -1 SORT_DEFAULTS["kind"] = "quicksort" SORT_DEFAULTS["order"] = None validate_sort = CompatValidator(SORT_DEFAULTS, fname="sort", method="kwargs") -STAT_FUNC_DEFAULTS: Dict[str, Optional[Any]] = {} +STAT_FUNC_DEFAULTS: dict[str, Any | None] = {} STAT_FUNC_DEFAULTS["dtype"] = None STAT_FUNC_DEFAULTS["out"] = None @@ -279,13 +276,13 @@ def validate_cum_func_with_skipna(skipna, args, kwargs, name): MEDIAN_DEFAULTS, fname="median", method="both", max_fname_arg_count=1 ) -STAT_DDOF_FUNC_DEFAULTS: Dict[str, Optional[bool]] = {} +STAT_DDOF_FUNC_DEFAULTS: dict[str, bool | None] = {} STAT_DDOF_FUNC_DEFAULTS["dtype"] = None STAT_DDOF_FUNC_DEFAULTS["out"] = None STAT_DDOF_FUNC_DEFAULTS["keepdims"] = False validate_stat_ddof_func = CompatValidator(STAT_DDOF_FUNC_DEFAULTS, method="kwargs") -TAKE_DEFAULTS: Dict[str, Optional[str]] = {} +TAKE_DEFAULTS: dict[str, str | None] = {} TAKE_DEFAULTS["out"] = None TAKE_DEFAULTS["mode"] = "raise" validate_take = CompatValidator(TAKE_DEFAULTS, fname="take", method="kwargs") @@ -392,7 +389,7 @@ def validate_resampler_func(method: str, args, kwargs) -> None: raise TypeError("too many arguments passed in") -def validate_minmax_axis(axis: Optional[int], ndim: int = 1) -> None: +def validate_minmax_axis(axis: int | None, ndim: int = 1) -> None: """ Ensure that the axis argument passed to min, max, argmin, or argmax is zero or None, as otherwise it will be incorrectly ignored. diff --git a/pandas/core/array_algos/replace.py b/pandas/core/array_algos/replace.py index 2d3a168a31e1e..e800f5ac748ec 100644 --- a/pandas/core/array_algos/replace.py +++ b/pandas/core/array_algos/replace.py @@ -1,13 +1,13 @@ """ Methods used by Block.replace and related methods. """ +from __future__ import annotations + import operator import re from typing import ( Any, - Optional, Pattern, - Union, ) import numpy as np @@ -42,8 +42,8 @@ def should_use_regex(regex: bool, to_replace: Any) -> bool: def compare_or_regex_search( - a: ArrayLike, b: Union[Scalar, Pattern], regex: bool, mask: np.ndarray -) -> Union[ArrayLike, bool]: + a: ArrayLike, b: Scalar | Pattern, regex: bool, mask: np.ndarray +) -> ArrayLike | bool: """ Compare two array_like inputs of the same shape or two scalar values @@ -65,7 +65,7 @@ def compare_or_regex_search( return ~mask def _check_comparison_types( - result: Union[ArrayLike, bool], a: ArrayLike, b: Union[Scalar, Pattern] + result: ArrayLike | bool, a: ArrayLike, b: Scalar | Pattern ): """ Raises an error if the two arrays (a,b) cannot be compared. @@ -115,7 +115,7 @@ def _check_comparison_types( return result -def replace_regex(values: ArrayLike, rx: re.Pattern, value, mask: Optional[np.ndarray]): +def replace_regex(values: ArrayLike, rx: re.Pattern, value, mask: np.ndarray | None): """ Parameters ---------- diff --git a/pandas/core/computation/expr.py b/pandas/core/computation/expr.py index 02660539f4981..5fc2b6bceaada 100644 --- a/pandas/core/computation/expr.py +++ b/pandas/core/computation/expr.py @@ -1,6 +1,7 @@ """ :func:`~pandas.eval` parsers. """ +from __future__ import annotations import ast from functools import ( @@ -11,10 +12,6 @@ import tokenize from typing import ( Callable, - Optional, - Set, - Tuple, - Type, TypeVar, ) @@ -50,7 +47,7 @@ import pandas.io.formats.printing as printing -def _rewrite_assign(tok: Tuple[int, str]) -> Tuple[int, str]: +def _rewrite_assign(tok: tuple[int, str]) -> tuple[int, str]: """ Rewrite the assignment operator for PyTables expressions that use ``=`` as a substitute for ``==``. @@ -69,7 +66,7 @@ def _rewrite_assign(tok: Tuple[int, str]) -> Tuple[int, str]: return toknum, "==" if tokval == "=" else tokval -def _replace_booleans(tok: Tuple[int, str]) -> Tuple[int, str]: +def _replace_booleans(tok: tuple[int, str]) -> tuple[int, str]: """ Replace ``&`` with ``and`` and ``|`` with ``or`` so that bitwise precedence is changed to boolean precedence. @@ -94,7 +91,7 @@ def _replace_booleans(tok: Tuple[int, str]) -> Tuple[int, str]: return toknum, tokval -def _replace_locals(tok: Tuple[int, str]) -> Tuple[int, str]: +def _replace_locals(tok: tuple[int, str]) -> tuple[int, str]: """ Replace local variables with a syntactically valid name. @@ -271,7 +268,7 @@ def f(self, *args, **kwargs): _T = TypeVar("_T", bound="BaseExprVisitor") -def disallow(nodes: Set[str]) -> Callable[[Type[_T]], Type[_T]]: +def disallow(nodes: set[str]) -> Callable[[type[_T]], type[_T]]: """ Decorator to disallow certain nodes from parsing. Raises a NotImplementedError instead. @@ -281,7 +278,7 @@ def disallow(nodes: Set[str]) -> Callable[[Type[_T]], Type[_T]]: callable """ - def disallowed(cls: Type[_T]) -> Type[_T]: + def disallowed(cls: type[_T]) -> type[_T]: cls.unsupported_nodes = () for node in nodes: new_method = _node_not_implemented(node) @@ -352,7 +349,7 @@ class BaseExprVisitor(ast.NodeVisitor): preparser : callable """ - const_type: Type[Term] = Constant + const_type: type[Term] = Constant term_type = Term binary_ops = CMP_OPS_SYMS + BOOL_OPS_SYMS + ARITH_OPS_SYMS @@ -390,7 +387,7 @@ class BaseExprVisitor(ast.NodeVisitor): ast.NotIn: ast.NotIn, } - unsupported_nodes: Tuple[str, ...] + unsupported_nodes: tuple[str, ...] def __init__(self, env, engine, parser, preparser=_preparse): self.env = env @@ -798,7 +795,7 @@ def __init__( expr, engine: str = "numexpr", parser: str = "pandas", - env: Optional[Scope] = None, + env: Scope | None = None, level: int = 0, ): self.expr = expr diff --git a/pandas/core/computation/expressions.py b/pandas/core/computation/expressions.py index 2f87e0bcce70a..789e10d1de05d 100644 --- a/pandas/core/computation/expressions.py +++ b/pandas/core/computation/expressions.py @@ -5,12 +5,9 @@ Offer fast expression evaluation through numexpr """ +from __future__ import annotations + import operator -from typing import ( - List, - Optional, - Set, -) import warnings import numpy as np @@ -25,11 +22,11 @@ if NUMEXPR_INSTALLED: import numexpr as ne -_TEST_MODE: Optional[bool] = None -_TEST_RESULT: List[bool] = [] +_TEST_MODE: bool | None = None +_TEST_RESULT: list[bool] = [] USE_NUMEXPR = NUMEXPR_INSTALLED -_evaluate: Optional[FuncType] = None -_where: Optional[FuncType] = None +_evaluate: FuncType | None = None +_where: FuncType | None = None # the set of dtypes that we will allow pass to numexpr _ALLOWED_DTYPES = { @@ -79,7 +76,7 @@ def _can_use_numexpr(op, op_str, a, b, dtype_check): # required min elements (otherwise we are adding overhead) if a.size > _MIN_ELEMENTS: # check for dtype compatibility - dtypes: Set[str] = set() + dtypes: set[str] = set() for o in [a, b]: # ndarray and Series Case if hasattr(o, "dtype"): @@ -277,7 +274,7 @@ def _store_test_result(used_numexpr: bool) -> None: _TEST_RESULT.append(used_numexpr) -def get_test_result() -> List[bool]: +def get_test_result() -> list[bool]: """ Get test result and reset test_results. """ diff --git a/pandas/core/dtypes/common.py b/pandas/core/dtypes/common.py index 5b0f54c30d4af..6b2a878f82786 100644 --- a/pandas/core/dtypes/common.py +++ b/pandas/core/dtypes/common.py @@ -1,11 +1,11 @@ """ Common type operations. """ +from __future__ import annotations from typing import ( Any, Callable, - Union, ) import warnings @@ -102,7 +102,7 @@ def ensure_float(arr): ensure_object = algos.ensure_object -def ensure_str(value: Union[bytes, Any]) -> str: +def ensure_str(value: bytes | Any) -> str: """ Ensure that bytes and non-strings get converted into ``str`` objects. """ @@ -113,7 +113,7 @@ def ensure_str(value: Union[bytes, Any]) -> str: return value -def ensure_python_int(value: Union[int, np.integer]) -> int: +def ensure_python_int(value: int | np.integer) -> int: """ Ensure that a value is a python int. diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index 85cbea39b9b98..65f2eb7b042e9 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -1,4 +1,5 @@ """ implement the TimedeltaIndex """ +from __future__ import annotations from pandas._libs import ( index as libindex, diff --git a/pandas/io/parsers/python_parser.py b/pandas/io/parsers/python_parser.py index 3635d5b32faf4..670868c6f4261 100644 --- a/pandas/io/parsers/python_parser.py +++ b/pandas/io/parsers/python_parser.py @@ -18,10 +18,7 @@ import numpy as np import pandas._libs.lib as lib -from pandas._typing import ( - FilePathOrBuffer, - Union, -) +from pandas._typing import FilePathOrBuffer from pandas.errors import ( EmptyDataError, ParserError, @@ -42,7 +39,7 @@ class PythonParser(ParserBase): - def __init__(self, f: Union[FilePathOrBuffer, list], **kwds): + def __init__(self, f: FilePathOrBuffer | list, **kwds): """ Workhorse function for processing nested list into DataFrame """ diff --git a/pandas/io/parsers/readers.py b/pandas/io/parsers/readers.py index 4cac892255692..8a48e8970f1f7 100644 --- a/pandas/io/parsers/readers.py +++ b/pandas/io/parsers/readers.py @@ -1,18 +1,13 @@ """ Module contains tools for processing files into DataFrames or other objects """ +from __future__ import annotations + from collections import abc import csv import sys from textwrap import fill -from typing import ( - Any, - Dict, - List, - Optional, - Set, - Type, -) +from typing import Any import warnings import numpy as np @@ -24,7 +19,6 @@ DtypeArg, FilePathOrBuffer, StorageOptions, - Union, ) from pandas.errors import ( AbstractMethodError, @@ -413,8 +407,8 @@ _c_unsupported = {"skipfooter"} _python_unsupported = {"low_memory", "float_precision"} -_deprecated_defaults: Dict[str, Any] = {"error_bad_lines": None, "warn_bad_lines": None} -_deprecated_args: Set[str] = {"error_bad_lines", "warn_bad_lines"} +_deprecated_defaults: dict[str, Any] = {"error_bad_lines": None, "warn_bad_lines": None} +_deprecated_args: set[str] = {"error_bad_lines", "warn_bad_lines"} def validate_integer(name, val, min_val=0): @@ -518,7 +512,7 @@ def read_csv( prefix=lib.no_default, mangle_dupe_cols=True, # General Parsing Configuration - dtype: Optional[DtypeArg] = None, + dtype: DtypeArg | None = None, engine=None, converters=None, true_values=None, @@ -554,7 +548,7 @@ def read_csv( escapechar=None, comment=None, encoding=None, - encoding_errors: Optional[str] = "strict", + encoding_errors: str | None = "strict", dialect=None, # Error Handling error_bad_lines=None, @@ -616,7 +610,7 @@ def read_table( prefix=lib.no_default, mangle_dupe_cols=True, # General Parsing Configuration - dtype: Optional[DtypeArg] = None, + dtype: DtypeArg | None = None, engine=None, converters=None, true_values=None, @@ -659,7 +653,7 @@ def read_table( # TODO (2.0): set on_bad_lines to "error". # See _refine_defaults_read comment for why we do this. on_bad_lines=None, - encoding_errors: Optional[str] = "strict", + encoding_errors: str | None = "strict", # Internal delim_whitespace=False, low_memory=_c_parser_defaults["low_memory"], @@ -823,7 +817,7 @@ def _get_options_with_defaults(self, engine): kwds = self.orig_options options = {} - default: Optional[object] + default: object | None for argname, default in parser_defaults.items(): value = kwds.get(argname, default) @@ -1033,7 +1027,7 @@ def __next__(self): raise def _make_engine(self, engine="c"): - mapping: Dict[str, Type[ParserBase]] = { + mapping: dict[str, type[ParserBase]] = { "c": CParserWrapper, "python": PythonParser, "python-fwf": FixedWidthFieldParser, @@ -1147,7 +1141,7 @@ def TextParser(*args, **kwds): def _clean_na_values(na_values, keep_default_na=True): - na_fvalues: Union[Set, Dict] + na_fvalues: set | dict if na_values is None: if keep_default_na: na_values = STR_NA_VALUES @@ -1198,7 +1192,7 @@ def _floatify_na_values(na_values): def _stringify_na_values(na_values): """ return a stringified and numeric for these values """ - result: List[Union[int, str, float]] = [] + result: list[int | str | float] = [] for x in na_values: result.append(str(x)) result.append(x) @@ -1222,17 +1216,17 @@ def _stringify_na_values(na_values): def _refine_defaults_read( - dialect: Union[str, csv.Dialect], - delimiter: Union[str, object], + dialect: str | csv.Dialect, + delimiter: str | object, delim_whitespace: bool, engine: str, - sep: Union[str, object], - error_bad_lines: Optional[bool], - warn_bad_lines: Optional[bool], - on_bad_lines: Optional[str], - names: Union[Optional[ArrayLike], object], - prefix: Union[Optional[str], object], - defaults: Dict[str, Any], + sep: str | object, + error_bad_lines: bool | None, + warn_bad_lines: bool | None, + on_bad_lines: str | None, + names: ArrayLike | None | object, + prefix: str | None | object, + defaults: dict[str, Any], ): """Validate/refine default values of input parameters of read_csv, read_table. @@ -1287,7 +1281,7 @@ def _refine_defaults_read( """ # fix types for sep, delimiter to Union(str, Any) delim_default = defaults["delimiter"] - kwds: Dict[str, Any] = {} + kwds: dict[str, Any] = {} # gh-23761 # # When a dialect is passed, it overrides any of the overlapping @@ -1381,7 +1375,7 @@ def _refine_defaults_read( return kwds -def _extract_dialect(kwds: Dict[str, Any]) -> Optional[csv.Dialect]: +def _extract_dialect(kwds: dict[str, Any]) -> csv.Dialect | None: """ Extract concrete csv dialect instance. @@ -1427,8 +1421,8 @@ def _validate_dialect(dialect: csv.Dialect) -> None: def _merge_with_dialect_properties( dialect: csv.Dialect, - defaults: Dict[str, Any], -) -> Dict[str, Any]: + defaults: dict[str, Any], +) -> dict[str, Any]: """ Merge default kwargs in TextFileReader with dialect parameters. @@ -1477,7 +1471,7 @@ def _merge_with_dialect_properties( return kwds -def _validate_skipfooter(kwds: Dict[str, Any]) -> None: +def _validate_skipfooter(kwds: dict[str, Any]) -> None: """ Check whether skipfooter is compatible with other kwargs in TextFileReader. diff --git a/pandas/tests/arrays/test_datetimelike.py b/pandas/tests/arrays/test_datetimelike.py index 0bd10b36a8b5c..3f3f3a5ee8d18 100644 --- a/pandas/tests/arrays/test_datetimelike.py +++ b/pandas/tests/arrays/test_datetimelike.py @@ -1,8 +1,6 @@ +from __future__ import annotations + import re -from typing import ( - Type, - Union, -) import numpy as np import pytest @@ -80,7 +78,7 @@ def timedelta_index(): class SharedTests: - index_cls: Type[Union[DatetimeIndex, PeriodIndex, TimedeltaIndex]] + index_cls: type[DatetimeIndex | PeriodIndex | TimedeltaIndex] @pytest.fixture def arr1d(self): diff --git a/pandas/tests/frame/methods/test_replace.py b/pandas/tests/frame/methods/test_replace.py index 46a5a47e091dd..a89e089f3d8a2 100644 --- a/pandas/tests/frame/methods/test_replace.py +++ b/pandas/tests/frame/methods/test_replace.py @@ -1,11 +1,8 @@ +from __future__ import annotations + from datetime import datetime from io import StringIO import re -from typing import ( - Dict, - List, - Union, -) import numpy as np import pytest @@ -24,12 +21,12 @@ @pytest.fixture -def mix_ab() -> Dict[str, List[Union[int, str]]]: +def mix_ab() -> dict[str, list[int | str]]: return {"a": list(range(4)), "b": list("ab..")} @pytest.fixture -def mix_abc() -> Dict[str, List[Union[float, str]]]: +def mix_abc() -> dict[str, list[float | str]]: return {"a": list(range(4)), "b": list("ab.."), "c": ["a", "b", np.nan, "d"]}