diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 057457e6d183e..d927be76843e1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -54,7 +54,7 @@ repos: rev: v2.11.0 hooks: - id: pyupgrade - args: [--py37-plus, --keep-runtime-typing] + args: [--py37-plus] - repo: https://github.com/pre-commit/pygrep-hooks rev: v1.8.0 hooks: diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 6c13350df2fa3..07d2a31217c2c 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -20,16 +20,11 @@ TYPE_CHECKING, Any, Callable, - Dict, Hashable, Iterable, List, Mapping, - Optional, Sequence, - Tuple, - Type, - Union, cast, ) from unicodedata import east_asian_width @@ -203,7 +198,7 @@ class CategoricalFormatter: def __init__( self, categorical: Categorical, - buf: Optional[IO[str]] = None, + buf: IO[str] | None = None, length: bool = True, na_rep: str = "NaN", footer: bool = True, @@ -232,7 +227,7 @@ def _get_footer(self) -> str: return str(footer) - def _get_formatted_values(self) -> List[str]: + def _get_formatted_values(self) -> list[str]: return format_array( self.categorical._internal_get_values(), None, @@ -267,16 +262,16 @@ class SeriesFormatter: def __init__( self, series: Series, - buf: Optional[IO[str]] = None, - length: Union[bool, str] = True, + buf: IO[str] | None = None, + length: bool | str = True, header: bool = True, index: bool = True, na_rep: str = "NaN", name: bool = False, - float_format: Optional[str] = None, + float_format: str | None = None, dtype: bool = True, - max_rows: Optional[int] = None, - min_rows: Optional[int] = None, + max_rows: int | None = None, + min_rows: int | None = None, ): self.series = series self.buf = buf if buf is not None else StringIO() @@ -297,7 +292,7 @@ def __init__( self._chk_truncate() def _chk_truncate(self) -> None: - self.tr_row_num: Optional[int] + self.tr_row_num: int | None min_rows = self.min_rows max_rows = self.max_rows @@ -364,7 +359,7 @@ def _get_footer(self) -> str: return str(footer) - def _get_formatted_index(self) -> Tuple[List[str], bool]: + def _get_formatted_index(self) -> tuple[list[str], bool]: index = self.tr_series.index if isinstance(index, MultiIndex): @@ -375,7 +370,7 @@ def _get_formatted_index(self) -> Tuple[List[str], bool]: fmt_index = index.format(name=True) return fmt_index, have_header - def _get_formatted_values(self) -> List[str]: + def _get_formatted_values(self) -> list[str]: return format_array( self.tr_series._values, None, @@ -430,7 +425,7 @@ def __init__(self): def len(self, text: str) -> int: return len(text) - def justify(self, texts: Any, max_len: int, mode: str = "right") -> List[str]: + def justify(self, texts: Any, max_len: int, mode: str = "right") -> list[str]: return justify(texts, max_len, mode=mode) def adjoin(self, space: int, *lists, **kwargs) -> str: @@ -463,7 +458,7 @@ def len(self, text: str) -> int: def justify( self, texts: Iterable[str], max_len: int, mode: str = "right" - ) -> List[str]: + ) -> list[str]: # re-calculate padding space per str considering East Asian Width def _get_pad(t): return max_len - self.len(t) + len(t) @@ -493,20 +488,20 @@ class DataFrameFormatter: def __init__( self, frame: DataFrame, - columns: Optional[Sequence[str]] = None, - col_space: Optional[ColspaceArgType] = None, - header: Union[bool, Sequence[str]] = True, + columns: Sequence[str] | None = None, + col_space: ColspaceArgType | None = None, + header: bool | Sequence[str] = True, index: bool = True, na_rep: str = "NaN", - formatters: Optional[FormattersType] = None, - justify: Optional[str] = None, - float_format: Optional[FloatFormatType] = None, - sparsify: Optional[bool] = None, + formatters: FormattersType | None = None, + justify: str | None = None, + float_format: FloatFormatType | None = None, + sparsify: bool | None = None, index_names: bool = True, - max_rows: Optional[int] = None, - min_rows: Optional[int] = None, - max_cols: Optional[int] = None, - show_dimensions: Union[bool, str] = False, + max_rows: int | None = None, + min_rows: int | None = None, + max_cols: int | None = None, + show_dimensions: bool | str = False, decimal: str = ".", bold_rows: bool = False, escape: bool = True, @@ -537,7 +532,7 @@ def __init__( self.truncate() self.adj = get_adjustment() - def get_strcols(self) -> List[List[str]]: + def get_strcols(self) -> list[list[str]]: """ Render a DataFrame to a list of columns (as lists of strings). """ @@ -591,13 +586,13 @@ def show_col_idx_names(self) -> bool: def max_rows_displayed(self) -> int: return min(self.max_rows or len(self.frame), len(self.frame)) - def _initialize_sparsify(self, sparsify: Optional[bool]) -> bool: + def _initialize_sparsify(self, sparsify: bool | None) -> bool: if sparsify is None: return get_option("display.multi_sparse") return sparsify def _initialize_formatters( - self, formatters: Optional[FormattersType] + self, formatters: FormattersType | None ) -> FormattersType: if formatters is None: return {} @@ -609,13 +604,13 @@ def _initialize_formatters( f"DataFrame number of columns({len(self.frame.columns)})" ) - def _initialize_justify(self, justify: Optional[str]) -> str: + def _initialize_justify(self, justify: str | None) -> str: if justify is None: return get_option("display.colheader_justify") else: return justify - def _initialize_columns(self, columns: Optional[Sequence[str]]) -> Index: + def _initialize_columns(self, columns: Sequence[str] | None) -> Index: if columns is not None: cols = ensure_index(columns) self.frame = self.frame[cols] @@ -623,9 +618,7 @@ def _initialize_columns(self, columns: Optional[Sequence[str]]) -> Index: else: return self.frame.columns - def _initialize_colspace( - self, col_space: Optional[ColspaceArgType] - ) -> ColspaceType: + def _initialize_colspace(self, col_space: ColspaceArgType | None) -> ColspaceType: result: ColspaceType if col_space is None: @@ -649,7 +642,7 @@ def _initialize_colspace( result = dict(zip(self.frame.columns, col_space)) return result - def _calc_max_cols_fitted(self) -> Optional[int]: + def _calc_max_cols_fitted(self) -> int | None: """Number of columns fitting the screen.""" if not self._is_in_terminal(): return self.max_cols @@ -660,9 +653,9 @@ def _calc_max_cols_fitted(self) -> Optional[int]: else: return self.max_cols - def _calc_max_rows_fitted(self) -> Optional[int]: + def _calc_max_rows_fitted(self) -> int | None: """Number of rows with data fitting the screen.""" - max_rows: Optional[int] + max_rows: int | None if self._is_in_terminal(): _, height = get_terminal_size() @@ -679,7 +672,7 @@ def _calc_max_rows_fitted(self) -> Optional[int]: return self._adjust_max_rows(max_rows) - def _adjust_max_rows(self, max_rows: Optional[int]) -> Optional[int]: + def _adjust_max_rows(self, max_rows: int | None) -> int | None: """Adjust max_rows using display logic. See description here: @@ -771,8 +764,8 @@ def _truncate_vertically(self) -> None: self.tr_frame = self.tr_frame.iloc[:row_num, :] self.tr_row_num = row_num - def _get_strcols_without_index(self) -> List[List[str]]: - strcols: List[List[str]] = [] + def _get_strcols_without_index(self) -> list[list[str]]: + strcols: list[list[str]] = [] if not is_list_like(self.header) and not self.header: for i, c in enumerate(self.tr_frame): @@ -818,7 +811,7 @@ def _get_strcols_without_index(self) -> List[List[str]]: return strcols - def format_col(self, i: int) -> List[str]: + def format_col(self, i: int) -> list[str]: frame = self.tr_frame formatter = self._get_formatter(i) return format_array( @@ -831,7 +824,7 @@ def format_col(self, i: int) -> List[str]: leading_space=self.index, ) - def _get_formatter(self, i: Union[str, int]) -> Optional[Callable]: + def _get_formatter(self, i: str | int) -> Callable | None: if isinstance(self.formatters, (list, tuple)): if is_integer(i): i = cast(int, i) @@ -843,7 +836,7 @@ def _get_formatter(self, i: Union[str, int]) -> Optional[Callable]: i = self.columns[i] return self.formatters.get(i, None) - def _get_formatted_column_labels(self, frame: DataFrame) -> List[List[str]]: + def _get_formatted_column_labels(self, frame: DataFrame) -> list[list[str]]: from pandas.core.indexes.multi import sparsify_labels columns = frame.columns @@ -884,7 +877,7 @@ def space_format(x, y): # self.str_columns = str_columns return str_columns - def _get_formatted_index(self, frame: DataFrame) -> List[str]: + def _get_formatted_index(self, frame: DataFrame) -> list[str]: # Note: this is only used by to_string() and to_latex(), not by # to_html(). so safe to cast col_space here. col_space = {k: cast(int, v) for k, v in self.col_space.items()} @@ -924,8 +917,8 @@ def _get_formatted_index(self, frame: DataFrame) -> List[str]: else: return adjoined - def _get_column_name_list(self) -> List[str]: - names: List[str] = [] + def _get_column_name_list(self) -> list[str]: + names: list[str] = [] columns = self.frame.columns if isinstance(columns, MultiIndex): names.extend("" if name is None else name for name in columns.names) @@ -956,17 +949,17 @@ def __init__(self, fmt: DataFrameFormatter): def to_latex( self, - buf: Optional[FilePathOrBuffer[str]] = None, - column_format: Optional[str] = None, + buf: FilePathOrBuffer[str] | None = None, + column_format: str | None = None, longtable: bool = False, - encoding: Optional[str] = None, + encoding: str | None = None, multicolumn: bool = False, - multicolumn_format: Optional[str] = None, + multicolumn_format: str | None = None, multirow: bool = False, - caption: Optional[str] = None, - label: Optional[str] = None, - position: Optional[str] = None, - ) -> Optional[str]: + caption: str | None = None, + label: str | None = None, + position: str | None = None, + ) -> str | None: """ Render a DataFrame to a LaTeX tabular/longtable environment output. """ @@ -988,14 +981,14 @@ def to_latex( def to_html( self, - buf: Optional[FilePathOrBuffer[str]] = None, - encoding: Optional[str] = None, - classes: Optional[Union[str, List, Tuple]] = None, + buf: FilePathOrBuffer[str] | None = None, + encoding: str | None = None, + classes: str | list | tuple | None = None, notebook: bool = False, - border: Optional[int] = None, - table_id: Optional[str] = None, + border: int | None = None, + table_id: str | None = None, render_links: bool = False, - ) -> Optional[str]: + ) -> str | None: """ Render a DataFrame to a html table. @@ -1037,10 +1030,10 @@ def to_html( def to_string( self, - buf: Optional[FilePathOrBuffer[str]] = None, - encoding: Optional[str] = None, - line_width: Optional[int] = None, - ) -> Optional[str]: + buf: FilePathOrBuffer[str] | None = None, + encoding: str | None = None, + line_width: int | None = None, + ) -> str | None: """ Render a DataFrame to a console-friendly tabular output. @@ -1061,23 +1054,23 @@ def to_string( def to_csv( self, - path_or_buf: Optional[FilePathOrBuffer[str]] = None, - encoding: Optional[str] = None, + path_or_buf: FilePathOrBuffer[str] | None = None, + encoding: str | None = None, sep: str = ",", - columns: Optional[Sequence[Hashable]] = None, - index_label: Optional[IndexLabel] = None, + columns: Sequence[Hashable] | None = None, + index_label: IndexLabel | None = None, mode: str = "w", compression: CompressionOptions = "infer", - quoting: Optional[int] = None, + quoting: int | None = None, quotechar: str = '"', - line_terminator: Optional[str] = None, - chunksize: Optional[int] = None, - date_format: Optional[str] = None, + line_terminator: str | None = None, + chunksize: int | None = None, + date_format: str | None = None, doublequote: bool = True, - escapechar: Optional[str] = None, + escapechar: str | None = None, errors: str = "strict", storage_options: StorageOptions = None, - ) -> Optional[str]: + ) -> str | None: """ Render dataframe as comma-separated file. """ @@ -1121,9 +1114,9 @@ def to_csv( def save_to_buffer( string: str, - buf: Optional[FilePathOrBuffer[str]] = None, - encoding: Optional[str] = None, -) -> Optional[str]: + buf: FilePathOrBuffer[str] | None = None, + encoding: str | None = None, +) -> str | None: """ Perform serialization. Write to buf or return as string if buf is None. """ @@ -1135,7 +1128,7 @@ def save_to_buffer( @contextmanager -def get_buffer(buf: Optional[FilePathOrBuffer[str]], encoding: Optional[str] = None): +def get_buffer(buf: FilePathOrBuffer[str] | None, encoding: str | None = None): """ Context manager to open, yield and close buffer for filenames or Path-like objects, otherwise yield buf unchanged. @@ -1169,16 +1162,16 @@ def get_buffer(buf: Optional[FilePathOrBuffer[str]], encoding: Optional[str] = N def format_array( values: Any, - formatter: Optional[Callable], - float_format: Optional[FloatFormatType] = None, + formatter: Callable | None, + float_format: FloatFormatType | None = None, na_rep: str = "NaN", - digits: Optional[int] = None, - space: Optional[Union[str, int]] = None, + digits: int | None = None, + space: str | int | None = None, justify: str = "right", decimal: str = ".", - leading_space: Optional[bool] = True, - quoting: Optional[int] = None, -) -> List[str]: + leading_space: bool | None = True, + quoting: int | None = None, +) -> list[str]: """ Format an array for printing. @@ -1205,7 +1198,7 @@ def format_array( ------- List[str] """ - fmt_klass: Type[GenericArrayFormatter] + fmt_klass: type[GenericArrayFormatter] if is_datetime64_dtype(values.dtype): fmt_klass = Datetime64Formatter elif is_datetime64tz_dtype(values.dtype): @@ -1251,15 +1244,15 @@ def __init__( self, values: Any, digits: int = 7, - formatter: Optional[Callable] = None, + formatter: Callable | None = None, na_rep: str = "NaN", - space: Union[str, int] = 12, - float_format: Optional[FloatFormatType] = None, + space: str | int = 12, + float_format: FloatFormatType | None = None, justify: str = "right", decimal: str = ".", - quoting: Optional[int] = None, + quoting: int | None = None, fixed_width: bool = True, - leading_space: Optional[bool] = True, + leading_space: bool | None = True, ): self.values = values self.digits = digits @@ -1273,11 +1266,11 @@ def __init__( self.fixed_width = fixed_width self.leading_space = leading_space - def get_result(self) -> List[str]: + def get_result(self) -> list[str]: fmt_values = self._format_strings() return _make_fixed_width(fmt_values, self.justify) - def _format_strings(self) -> List[str]: + def _format_strings(self) -> list[str]: if self.float_format is None: float_format = get_option("display.float_format") if float_format is None: @@ -1361,8 +1354,8 @@ def __init__(self, *args, **kwargs): def _value_formatter( self, - float_format: Optional[FloatFormatType] = None, - threshold: Optional[Union[float, int]] = None, + float_format: FloatFormatType | None = None, + threshold: float | int | None = None, ) -> Callable: """Returns a function to be applied on each value to format it""" # the float_format parameter supersedes self.float_format @@ -1466,7 +1459,7 @@ def format_values_with(float_format): # There is a special default string when we are fixed-width # The default is otherwise to use str instead of a formatting string - float_format: Optional[FloatFormatType] + float_format: FloatFormatType | None if self.float_format is None: if self.fixed_width: if self.leading_space is True: @@ -1514,12 +1507,12 @@ def format_values_with(float_format): return formatted_values - def _format_strings(self) -> List[str]: + def _format_strings(self) -> list[str]: return list(self.get_result_as_array()) class IntArrayFormatter(GenericArrayFormatter): - def _format_strings(self) -> List[str]: + def _format_strings(self) -> list[str]: if self.leading_space is False: formatter_str = lambda x: f"{x:d}".format(x=x) else: @@ -1532,7 +1525,7 @@ def _format_strings(self) -> List[str]: class Datetime64Formatter(GenericArrayFormatter): def __init__( self, - values: Union[np.ndarray, Series, DatetimeIndex, DatetimeArray], + values: np.ndarray | Series | DatetimeIndex | DatetimeArray, nat_rep: str = "NaT", date_format: None = None, **kwargs, @@ -1541,7 +1534,7 @@ def __init__( self.nat_rep = nat_rep self.date_format = date_format - def _format_strings(self) -> List[str]: + def _format_strings(self) -> list[str]: """ we by definition have DO NOT have a TZ """ values = self.values @@ -1558,7 +1551,7 @@ def _format_strings(self) -> List[str]: class ExtensionArrayFormatter(GenericArrayFormatter): - def _format_strings(self) -> List[str]: + def _format_strings(self) -> list[str]: values = extract_array(self.values, extract_numpy=True) formatter = self.formatter @@ -1589,10 +1582,8 @@ def _format_strings(self) -> List[str]: def format_percentiles( - percentiles: Union[ - np.ndarray, List[Union[int, float]], List[float], List[Union[str, float]] - ] -) -> List[str]: + percentiles: (np.ndarray | list[int | float] | list[float] | list[str | float]), +) -> list[str]: """ Outputs rounded and formatted percentiles. @@ -1683,9 +1674,7 @@ def format_percentiles( return [i + "%" for i in out] -def is_dates_only( - values: Union[np.ndarray, DatetimeArray, Index, DatetimeIndex] -) -> bool: +def is_dates_only(values: np.ndarray | DatetimeArray | Index | DatetimeIndex) -> bool: # return a boolean if we are only dates (and don't have a timezone) if not isinstance(values, Index): values = values.ravel() @@ -1705,7 +1694,7 @@ def is_dates_only( return False -def _format_datetime64(x: Union[NaTType, Timestamp], nat_rep: str = "NaT") -> str: +def _format_datetime64(x: NaTType | Timestamp, nat_rep: str = "NaT") -> str: if x is NaT: return nat_rep @@ -1713,9 +1702,9 @@ def _format_datetime64(x: Union[NaTType, Timestamp], nat_rep: str = "NaT") -> st def _format_datetime64_dateonly( - x: Union[NaTType, Timestamp], + x: NaTType | Timestamp, nat_rep: str = "NaT", - date_format: Optional[str] = None, + date_format: str | None = None, ) -> str: if x is NaT: return nat_rep @@ -1730,7 +1719,7 @@ def _format_datetime64_dateonly( def get_format_datetime64( - is_dates_only: bool, nat_rep: str = "NaT", date_format: Optional[str] = None + is_dates_only: bool, nat_rep: str = "NaT", date_format: str | None = None ) -> Callable: if is_dates_only: @@ -1742,8 +1731,8 @@ def get_format_datetime64( def get_format_datetime64_from_values( - values: Union[np.ndarray, DatetimeArray, DatetimeIndex], date_format: Optional[str] -) -> Optional[str]: + values: np.ndarray | DatetimeArray | DatetimeIndex, date_format: str | None +) -> str | None: """ given values and a date_format, return a string format """ if isinstance(values, np.ndarray) and values.ndim > 1: # We don't actually care about the order of values, and DatetimeIndex @@ -1757,7 +1746,7 @@ def get_format_datetime64_from_values( class Datetime64TZFormatter(Datetime64Formatter): - def _format_strings(self) -> List[str]: + def _format_strings(self) -> list[str]: """ we by definition have a TZ """ values = self.values.astype(object) ido = is_dates_only(values) @@ -1772,7 +1761,7 @@ def _format_strings(self) -> List[str]: class Timedelta64Formatter(GenericArrayFormatter): def __init__( self, - values: Union[np.ndarray, TimedeltaIndex], + values: np.ndarray | TimedeltaIndex, nat_rep: str = "NaT", box: bool = False, **kwargs, @@ -1781,7 +1770,7 @@ def __init__( self.nat_rep = nat_rep self.box = box - def _format_strings(self) -> List[str]: + def _format_strings(self) -> list[str]: formatter = self.formatter or get_format_timedelta64( self.values, nat_rep=self.nat_rep, box=self.box ) @@ -1789,7 +1778,7 @@ def _format_strings(self) -> List[str]: def get_format_timedelta64( - values: Union[np.ndarray, TimedeltaIndex, TimedeltaArray], + values: np.ndarray | TimedeltaIndex | TimedeltaArray, nat_rep: str = "NaT", box: bool = False, ) -> Callable: @@ -1834,11 +1823,11 @@ def _formatter(x): def _make_fixed_width( - strings: List[str], + strings: list[str], justify: str = "right", - minimum: Optional[int] = None, - adj: Optional[TextAdjustment] = None, -) -> List[str]: + minimum: int | None = None, + adj: TextAdjustment | None = None, +) -> list[str]: if len(strings) == 0 or justify == "all": return strings @@ -1868,7 +1857,7 @@ def just(x: str) -> str: return result -def _trim_zeros_complex(str_complexes: np.ndarray, decimal: str = ".") -> List[str]: +def _trim_zeros_complex(str_complexes: np.ndarray, decimal: str = ".") -> list[str]: """ Separates the real and imaginary parts from the complex number, and executes the _trim_zeros_float method on each of those. @@ -1906,8 +1895,8 @@ def _trim_zeros_single_float(str_float: str) -> str: def _trim_zeros_float( - str_floats: Union[np.ndarray, List[str]], decimal: str = "." -) -> List[str]: + str_floats: np.ndarray | list[str], decimal: str = "." +) -> list[str]: """ Trims the maximum number of trailing zeros equally from all numbers containing decimals, leaving just one if @@ -1919,7 +1908,7 @@ def _trim_zeros_float( def is_number_with_decimal(x): return re.match(number_regex, x) is not None - def should_trim(values: Union[np.ndarray, List[str]]) -> bool: + def should_trim(values: np.ndarray | list[str]) -> bool: """ Determine if an array of strings should be trimmed. @@ -1976,11 +1965,11 @@ class EngFormatter: 24: "Y", } - def __init__(self, accuracy: Optional[int] = None, use_eng_prefix: bool = False): + def __init__(self, accuracy: int | None = None, use_eng_prefix: bool = False): self.accuracy = accuracy self.use_eng_prefix = use_eng_prefix - def __call__(self, num: Union[int, float]) -> str: + def __call__(self, num: int | float) -> str: """ Formats a number in engineering notation, appending a letter representing the power of 1000 of the original number. Some examples: @@ -2058,8 +2047,8 @@ def set_eng_float_format(accuracy: int = 3, use_eng_prefix: bool = False) -> Non def get_level_lengths( - levels: Any, sentinel: Union[bool, object, str] = "" -) -> List[Dict[int, int]]: + levels: Any, sentinel: bool | object | str = "" +) -> list[dict[int, int]]: """ For each index in each level the function returns lengths of indexes. @@ -2100,7 +2089,7 @@ def get_level_lengths( return result -def buffer_put_lines(buf: IO[str], lines: List[str]) -> None: +def buffer_put_lines(buf: IO[str], lines: list[str]) -> None: """ Appends lines to a buffer. diff --git a/pandas/io/formats/info.py b/pandas/io/formats/info.py index 2c1739998da08..e014d7d63a35f 100644 --- a/pandas/io/formats/info.py +++ b/pandas/io/formats/info.py @@ -10,11 +10,8 @@ TYPE_CHECKING, Iterable, Iterator, - List, Mapping, - Optional, Sequence, - Union, ) from pandas._config import get_option @@ -33,7 +30,7 @@ from pandas.core.frame import DataFrame -def _put_str(s: Union[str, Dtype], space: int) -> str: +def _put_str(s: str | Dtype, space: int) -> str: """ Make string of specified length, padding to the right if necessary. @@ -59,7 +56,7 @@ def _put_str(s: Union[str, Dtype], space: int) -> str: return str(s)[:space].ljust(space) -def _sizeof_fmt(num: Union[int, float], size_qualifier: str) -> str: +def _sizeof_fmt(num: int | float, size_qualifier: str) -> str: """ Return size in human readable format. @@ -91,8 +88,8 @@ def _sizeof_fmt(num: Union[int, float], size_qualifier: str) -> str: def _initialize_memory_usage( - memory_usage: Optional[Union[bool, str]] = None, -) -> Union[bool, str]: + memory_usage: bool | str | None = None, +) -> bool | str: """Get memory usage based on inputs and display options.""" if memory_usage is None: memory_usage = get_option("display.memory_usage") @@ -114,7 +111,7 @@ class BaseInfo(ABC): """ data: FrameOrSeriesUnion - memory_usage: Union[bool, str] + memory_usage: bool | str @property @abstractmethod @@ -174,10 +171,10 @@ def size_qualifier(self) -> str: def render( self, *, - buf: Optional[IO[str]], - max_cols: Optional[int], - verbose: Optional[bool], - show_counts: Optional[bool], + buf: IO[str] | None, + max_cols: int | None, + verbose: bool | None, + show_counts: bool | None, ) -> None: """ Print a concise summary of a %(klass)s. @@ -236,7 +233,7 @@ class DataFrameInfo(BaseInfo): def __init__( self, data: DataFrame, - memory_usage: Optional[Union[bool, str]] = None, + memory_usage: bool | str | None = None, ): self.data: DataFrame = data self.memory_usage = _initialize_memory_usage(memory_usage) @@ -290,10 +287,10 @@ def memory_usage_bytes(self) -> int: def render( self, *, - buf: Optional[IO[str]], - max_cols: Optional[int], - verbose: Optional[bool], - show_counts: Optional[bool], + buf: IO[str] | None, + max_cols: int | None, + verbose: bool | None, + show_counts: bool | None, ) -> None: printer = DataFrameInfoPrinter( info=self, @@ -309,7 +306,7 @@ class InfoPrinterAbstract: Class for printing dataframe or series info. """ - def to_buffer(self, buf: Optional[IO[str]] = None) -> None: + def to_buffer(self, buf: IO[str] | None = None) -> None: """Save dataframe info into buffer.""" table_builder = self._create_table_builder() lines = table_builder.get_lines() @@ -341,9 +338,9 @@ class DataFrameInfoPrinter(InfoPrinterAbstract): def __init__( self, info: DataFrameInfo, - max_cols: Optional[int] = None, - verbose: Optional[bool] = None, - show_counts: Optional[bool] = None, + max_cols: int | None = None, + verbose: bool | None = None, + show_counts: bool | None = None, ): self.info = info self.data = info.data @@ -371,12 +368,12 @@ def col_count(self) -> int: """Number of columns to be summarized.""" return self.info.col_count - def _initialize_max_cols(self, max_cols: Optional[int]) -> int: + def _initialize_max_cols(self, max_cols: int | None) -> int: if max_cols is None: return get_option("display.max_info_columns", self.col_count + 1) return max_cols - def _initialize_show_counts(self, show_counts: Optional[bool]) -> bool: + def _initialize_show_counts(self, show_counts: bool | None) -> bool: if show_counts is None: return bool(not self.exceeds_info_cols and not self.exceeds_info_rows) else: @@ -408,11 +405,11 @@ class TableBuilderAbstract(ABC): Abstract builder for info table. """ - _lines: List[str] + _lines: list[str] info: BaseInfo @abstractmethod - def get_lines(self) -> List[str]: + def get_lines(self) -> list[str]: """Product in a form of list of lines (strings).""" @property @@ -472,7 +469,7 @@ class DataFrameTableBuilder(TableBuilderAbstract): def __init__(self, *, info: DataFrameInfo): self.info: DataFrameInfo = info - def get_lines(self) -> List[str]: + def get_lines(self) -> list[str]: self._lines = [] if self.col_count == 0: self._fill_empty_info() diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index bcc87e55a3551..ba17e44fc66e0 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -168,13 +168,13 @@ class Styler: def __init__( self, data: FrameOrSeriesUnion, - precision: Optional[int] = None, - table_styles: Optional[CSSStyles] = None, - uuid: Optional[str] = None, - caption: Optional[str] = None, - table_attributes: Optional[str] = None, + precision: int | None = None, + table_styles: CSSStyles | None = None, + uuid: str | None = None, + caption: str | None = None, + table_attributes: str | None = None, cell_ids: bool = True, - na_rep: Optional[str] = None, + na_rep: str | None = None, uuid_len: int = 5, escape: bool = False, ): @@ -200,13 +200,13 @@ def __init__( # assign additional default vars self.hidden_index: bool = False self.hidden_columns: Sequence[int] = [] - self.ctx: DefaultDict[Tuple[int, int], CSSList] = defaultdict(list) - self.cell_context: DefaultDict[Tuple[int, int], str] = defaultdict(str) - self._todo: List[Tuple[Callable, Tuple, Dict]] = [] - self.tooltips: Optional[_Tooltips] = None + self.ctx: DefaultDict[tuple[int, int], CSSList] = defaultdict(list) + self.cell_context: DefaultDict[tuple[int, int], str] = defaultdict(str) + self._todo: list[tuple[Callable, tuple, dict]] = [] + self.tooltips: _Tooltips | None = None def_precision = get_option("display.precision") self._display_funcs: DefaultDict[ # maps (row, col) -> formatting function - Tuple[int, int], Callable[[Any], str] + tuple[int, int], Callable[[Any], str] ] = defaultdict(lambda: partial(_default_formatter, precision=def_precision)) self.precision = precision # can be removed on set_precision depr cycle self.na_rep = na_rep # can be removed on set_na_rep depr cycle @@ -221,8 +221,8 @@ def _repr_html_(self) -> str: def set_tooltips( self, ttips: DataFrame, - props: Optional[CSSProperties] = None, - css_class: Optional[str] = None, + props: CSSProperties | None = None, + css_class: str | None = None, ) -> Styler: """ Set the DataFrame of strings on ``Styler`` generating ``:hover`` tooltips. @@ -319,19 +319,19 @@ def to_excel( excel_writer, sheet_name: str = "Sheet1", na_rep: str = "", - float_format: Optional[str] = None, - columns: Optional[Sequence[Hashable]] = None, - header: Union[Sequence[Hashable], bool] = True, + float_format: str | None = None, + columns: Sequence[Hashable] | None = None, + header: Sequence[Hashable] | bool = True, index: bool = True, - index_label: Optional[IndexLabel] = None, + index_label: IndexLabel | None = None, startrow: int = 0, startcol: int = 0, - engine: Optional[str] = None, + engine: str | None = None, merge_cells: bool = True, - encoding: Optional[str] = None, + encoding: str | None = None, inf_rep: str = "inf", verbose: bool = True, - freeze_panes: Optional[Tuple[int, int]] = None, + freeze_panes: tuple[int, int] | None = None, ) -> None: from pandas.io.formats.excel import ExcelFormatter @@ -372,7 +372,7 @@ def _translate(self): # mapping variables ctx = self.ctx # td css styles from apply() and applymap() cell_context = self.cell_context # td css classes from set_td_classes() - cellstyle_map: DefaultDict[Tuple[CSSPair, ...], List[str]] = defaultdict(list) + cellstyle_map: DefaultDict[tuple[CSSPair, ...], list[str]] = defaultdict(list) # copied attributes hidden_index = self.hidden_index @@ -524,7 +524,7 @@ def _translate(self): body.append(row_es) d.update({"body": body}) - cellstyle: List[Dict[str, Union[CSSList, List[str]]]] = [ + cellstyle: list[dict[str, CSSList | list[str]]] = [ {"props": list(props), "selectors": selectors} for props, selectors in cellstyle_map.items() ] @@ -547,10 +547,10 @@ def _translate(self): def format( self, - formatter: Optional[ExtFormatter] = None, - subset: Optional[Union[slice, Sequence[Any]]] = None, - na_rep: Optional[str] = None, - precision: Optional[int] = None, + formatter: ExtFormatter | None = None, + subset: slice | Sequence[Any] | None = None, + na_rep: str | None = None, + precision: int | None = None, escape: bool = False, ) -> Styler: """ @@ -906,7 +906,7 @@ def _compute(self): def _apply( self, func: Callable[..., Styler], - axis: Optional[Axis] = 0, + axis: Axis | None = 0, subset=None, **kwargs, ) -> Styler: @@ -951,7 +951,7 @@ def _apply( def apply( self, func: Callable[..., Styler], - axis: Optional[Axis] = 0, + axis: Axis | None = 0, subset=None, **kwargs, ) -> Styler: @@ -1070,7 +1070,7 @@ def where( self, cond: Callable, value: str, - other: Optional[str] = None, + other: str | None = None, subset=None, **kwargs, ) -> Styler: @@ -1173,7 +1173,7 @@ def set_table_attributes(self, attributes: str) -> Styler: self.table_attributes = attributes return self - def export(self) -> List[Tuple[Callable, Tuple, Dict]]: + def export(self) -> list[tuple[Callable, tuple, dict]]: """ Export the styles applied to the current ``Styler``. @@ -1189,7 +1189,7 @@ def export(self) -> List[Tuple[Callable, Tuple, Dict]]: """ return self._todo - def use(self, styles: List[Tuple[Callable, Tuple, Dict]]) -> Styler: + def use(self, styles: list[tuple[Callable, tuple, dict]]) -> Styler: """ Set the styles on the current ``Styler``. @@ -1249,7 +1249,7 @@ def set_caption(self, caption: str) -> Styler: def set_table_styles( self, - table_styles: Union[Dict[Any, CSSStyles], CSSStyles], + table_styles: dict[Any, CSSStyles] | CSSStyles, axis: int = 0, overwrite: bool = True, ) -> Styler: @@ -1433,11 +1433,11 @@ def background_gradient( cmap="PuBu", low: float = 0, high: float = 0, - axis: Optional[Axis] = 0, + axis: Axis | None = 0, subset=None, text_color_threshold: float = 0.408, - vmin: Optional[float] = None, - vmax: Optional[float] = None, + vmin: float | None = None, + vmax: float | None = None, ) -> Styler: """ Color the background in a gradient style. @@ -1517,8 +1517,8 @@ def _background_gradient( low: float = 0, high: float = 0, text_color_threshold: float = 0.408, - vmin: Optional[float] = None, - vmax: Optional[float] = None, + vmin: float | None = None, + vmax: float | None = None, ): """ Color background in a range according to the data. @@ -1610,10 +1610,10 @@ def set_properties(self, subset=None, **kwargs) -> Styler: def _bar( s, align: str, - colors: List[str], + colors: list[str], width: float = 100, - vmin: Optional[float] = None, - vmax: Optional[float] = None, + vmin: float | None = None, + vmax: float | None = None, ): """ Draw bar chart in dataframe cells. @@ -1669,12 +1669,12 @@ def css(x): def bar( self, subset=None, - axis: Optional[Axis] = 0, + axis: Axis | None = 0, color="#d65f5f", width: float = 100, align: str = "left", - vmin: Optional[float] = None, - vmax: Optional[float] = None, + vmin: float | None = None, + vmax: float | None = None, ) -> Styler: """ Draw bar chart in the cell backgrounds. @@ -1754,8 +1754,8 @@ def bar( def highlight_null( self, null_color: str = "red", - subset: Optional[IndexLabel] = None, - props: Optional[str] = None, + subset: IndexLabel | None = None, + props: str | None = None, ) -> Styler: """ Highlight missing values with a style. @@ -1797,10 +1797,10 @@ def f(data: DataFrame, props: str) -> np.ndarray: def highlight_max( self, - subset: Optional[IndexLabel] = None, + subset: IndexLabel | None = None, color: str = "yellow", - axis: Optional[Axis] = 0, - props: Optional[str] = None, + axis: Axis | None = 0, + props: str | None = None, ) -> Styler: """ Highlight the maximum with a style. @@ -1844,10 +1844,10 @@ def f(data: FrameOrSeries, props: str) -> np.ndarray: def highlight_min( self, - subset: Optional[IndexLabel] = None, + subset: IndexLabel | None = None, color: str = "yellow", - axis: Optional[Axis] = 0, - props: Optional[str] = None, + axis: Axis | None = 0, + props: str | None = None, ) -> Styler: """ Highlight the minimum with a style. @@ -2100,7 +2100,7 @@ def _pseudo_css(self, uuid: str, name: str, row: int, col: int, text: str): }, ] - def _translate(self, styler_data: FrameOrSeriesUnion, uuid: str, d: Dict): + def _translate(self, styler_data: FrameOrSeriesUnion, uuid: str, d: dict): """ Mutate the render dictionary to allow for tooltips: @@ -2230,9 +2230,9 @@ def _default_formatter(x: Any, precision: int) -> Any: def _maybe_wrap_formatter( - formatter: Optional[BaseFormatter] = None, - na_rep: Optional[str] = None, - precision: Optional[int] = None, + formatter: BaseFormatter | None = None, + na_rep: str | None = None, + precision: int | None = None, escape: bool = False, ) -> Callable: """ diff --git a/pandas/io/json/_normalize.py b/pandas/io/json/_normalize.py index 39d12c5b05c2f..3d07b9d98f9a9 100644 --- a/pandas/io/json/_normalize.py +++ b/pandas/io/json/_normalize.py @@ -10,11 +10,7 @@ from typing import ( Any, DefaultDict, - Dict, Iterable, - List, - Optional, - Union, ) import numpy as np @@ -45,7 +41,7 @@ def nested_to_record( prefix: str = "", sep: str = ".", level: int = 0, - max_level: Optional[int] = None, + max_level: int | None = None, ): """ A simplified json_normalize @@ -124,9 +120,9 @@ def nested_to_record( def _normalise_json( data: Any, key_string: str, - normalized_dict: Dict[str, Any], + normalized_dict: dict[str, Any], separator: str, -) -> Dict[str, Any]: +) -> dict[str, Any]: """ Main recursive function Designed for the most basic use case of pd.json_normalize(data) @@ -161,7 +157,7 @@ def _normalise_json( return normalized_dict -def _normalise_json_ordered(data: Dict[str, Any], separator: str) -> Dict[str, Any]: +def _normalise_json_ordered(data: dict[str, Any], separator: str) -> dict[str, Any]: """ Order the top level keys and then recursively go to depth @@ -187,9 +183,9 @@ def _normalise_json_ordered(data: Dict[str, Any], separator: str) -> Dict[str, A def _simple_json_normalize( - ds: Union[Dict, List[Dict]], + ds: dict | list[dict], sep: str = ".", -) -> Union[Dict, List[Dict], Any]: +) -> dict | list[dict] | Any: """ A optimized basic json_normalize @@ -237,14 +233,14 @@ def _simple_json_normalize( def _json_normalize( - data: Union[Dict, List[Dict]], - record_path: Optional[Union[str, List]] = None, - meta: Optional[Union[str, List[Union[str, List[str]]]]] = None, - meta_prefix: Optional[str] = None, - record_prefix: Optional[str] = None, + data: dict | list[dict], + record_path: str | list | None = None, + meta: str | list[str | list[str]] | None = None, + meta_prefix: str | None = None, + record_prefix: str | None = None, errors: str = "raise", sep: str = ".", - max_level: Optional[int] = None, + max_level: int | None = None, ) -> DataFrame: """ Normalize semi-structured JSON data into a flat table. @@ -354,9 +350,7 @@ def _json_normalize( Returns normalized data with columns prefixed with the given string. """ - def _pull_field( - js: Dict[str, Any], spec: Union[List, str] - ) -> Union[Scalar, Iterable]: + def _pull_field(js: dict[str, Any], spec: list | str) -> Scalar | Iterable: """Internal function to pull field""" result = js if isinstance(spec, list): @@ -366,7 +360,7 @@ def _pull_field( result = result[spec] return result - def _pull_records(js: Dict[str, Any], spec: Union[List, str]) -> List: + def _pull_records(js: dict[str, Any], spec: list | str) -> list: """ Internal function to pull field for records, and similar to _pull_field, but require to return list. And will raise error @@ -432,7 +426,7 @@ def _pull_records(js: Dict[str, Any], spec: Union[List, str]) -> List: _meta = [m if isinstance(m, list) else [m] for m in meta] # Disastrously inefficient for now - records: List = [] + records: list = [] lengths = [] meta_vals: DefaultDict = defaultdict(list) diff --git a/pandas/io/sas/sas7bdat.py b/pandas/io/sas/sas7bdat.py index cd9667bb1ce4b..fb121d3aed105 100644 --- a/pandas/io/sas/sas7bdat.py +++ b/pandas/io/sas/sas7bdat.py @@ -24,7 +24,6 @@ from typing import ( IO, Any, - Union, cast, ) @@ -102,18 +101,18 @@ def __init__(self, offset: int, length: int, compression: int, ptype: int): class _Column: col_id: int - name: Union[str, bytes] - label: Union[str, bytes] - format: Union[str, bytes] # TODO: i think allowing bytes is from py2 days + name: str | bytes + label: str | bytes + format: str | bytes # TODO: i think allowing bytes is from py2 days ctype: bytes length: int def __init__( self, col_id: int, - name: Union[str, bytes], - label: Union[str, bytes], - format: Union[str, bytes], + name: str | bytes, + label: str | bytes, + format: str | bytes, ctype: bytes, length: int, ): diff --git a/pandas/io/sas/sasreader.py b/pandas/io/sas/sasreader.py index 69da038929482..b323ce39763a1 100644 --- a/pandas/io/sas/sasreader.py +++ b/pandas/io/sas/sasreader.py @@ -10,8 +10,6 @@ from typing import ( TYPE_CHECKING, Hashable, - Optional, - Union, overload, ) @@ -47,9 +45,9 @@ def __exit__(self, exc_type, exc_value, traceback): @overload def read_sas( filepath_or_buffer: FilePathOrBuffer, - format: Optional[str] = ..., - index: Optional[Hashable] = ..., - encoding: Optional[str] = ..., + format: str | None = ..., + index: Hashable | None = ..., + encoding: str | None = ..., chunksize: int = ..., iterator: bool = ..., ) -> ReaderBase: @@ -59,23 +57,23 @@ def read_sas( @overload def read_sas( filepath_or_buffer: FilePathOrBuffer, - format: Optional[str] = ..., - index: Optional[Hashable] = ..., - encoding: Optional[str] = ..., + format: str | None = ..., + index: Hashable | None = ..., + encoding: str | None = ..., chunksize: None = ..., iterator: bool = ..., -) -> Union[DataFrame, ReaderBase]: +) -> DataFrame | ReaderBase: ... def read_sas( filepath_or_buffer: FilePathOrBuffer, - format: Optional[str] = None, - index: Optional[Hashable] = None, - encoding: Optional[str] = None, - chunksize: Optional[int] = None, + format: str | None = None, + index: Hashable | None = None, + encoding: str | None = None, + chunksize: int | None = None, iterator: bool = False, -) -> Union[DataFrame, ReaderBase]: +) -> DataFrame | ReaderBase: """ Read SAS files stored as either XPORT or SAS7BDAT format files. diff --git a/pandas/plotting/_core.py b/pandas/plotting/_core.py index 1a5efee586ee1..55097054fec88 100644 --- a/pandas/plotting/_core.py +++ b/pandas/plotting/_core.py @@ -3,10 +3,7 @@ import importlib from typing import ( TYPE_CHECKING, - Optional, Sequence, - Tuple, - Union, ) from pandas._config import get_option @@ -37,13 +34,13 @@ def hist_series( by=None, ax=None, grid: bool = True, - xlabelsize: Optional[int] = None, - xrot: Optional[float] = None, - ylabelsize: Optional[int] = None, - yrot: Optional[float] = None, - figsize: Optional[Tuple[int, int]] = None, - bins: Union[int, Sequence[int]] = 10, - backend: Optional[str] = None, + xlabelsize: int | None = None, + xrot: float | None = None, + ylabelsize: int | None = None, + yrot: float | None = None, + figsize: tuple[int, int] | None = None, + bins: int | Sequence[int] = 10, + backend: str | None = None, legend: bool = False, **kwargs, ): @@ -120,17 +117,17 @@ def hist_frame( column: IndexLabel = None, by=None, grid: bool = True, - xlabelsize: Optional[int] = None, - xrot: Optional[float] = None, - ylabelsize: Optional[int] = None, - yrot: Optional[float] = None, + xlabelsize: int | None = None, + xrot: float | None = None, + ylabelsize: int | None = None, + yrot: float | None = None, ax=None, sharex: bool = False, sharey: bool = False, - figsize: Optional[Tuple[int, int]] = None, - layout: Optional[Tuple[int, int]] = None, - bins: Union[int, Sequence[int]] = 10, - backend: Optional[str] = None, + figsize: tuple[int, int] | None = None, + layout: tuple[int, int] | None = None, + bins: int | Sequence[int] = 10, + backend: str | None = None, legend: bool = False, **kwargs, ): diff --git a/pandas/plotting/_matplotlib/__init__.py b/pandas/plotting/_matplotlib/__init__.py index b12ca6187c945..75c61da03795a 100644 --- a/pandas/plotting/_matplotlib/__init__.py +++ b/pandas/plotting/_matplotlib/__init__.py @@ -1,10 +1,6 @@ from __future__ import annotations -from typing import ( - TYPE_CHECKING, - Dict, - Type, -) +from typing import TYPE_CHECKING from pandas.plotting._matplotlib.boxplot import ( BoxPlot, @@ -45,7 +41,7 @@ if TYPE_CHECKING: from pandas.plotting._matplotlib.core import MPLPlot -PLOT_CLASSES: Dict[str, Type[MPLPlot]] = { +PLOT_CLASSES: dict[str, type[MPLPlot]] = { "line": LinePlot, "bar": BarPlot, "barh": BarhPlot, diff --git a/pandas/plotting/_matplotlib/core.py b/pandas/plotting/_matplotlib/core.py index 86eee47962b85..c9c12d8d5788a 100644 --- a/pandas/plotting/_matplotlib/core.py +++ b/pandas/plotting/_matplotlib/core.py @@ -3,9 +3,6 @@ from typing import ( TYPE_CHECKING, Hashable, - List, - Optional, - Tuple, ) import warnings @@ -94,7 +91,7 @@ def _kind(self): _layout_type = "vertical" _default_rot = 0 - orientation: Optional[str] = None + orientation: str | None = None axes: np.ndarray # of Axes objects @@ -118,8 +115,8 @@ def __init__( ylim=None, xticks=None, yticks=None, - xlabel: Optional[Hashable] = None, - ylabel: Optional[Hashable] = None, + xlabel: Hashable | None = None, + ylabel: Hashable | None = None, sort_columns=False, fontsize=None, secondary_y=False, @@ -180,8 +177,8 @@ def __init__( self.grid = grid self.legend = legend - self.legend_handles: List[Artist] = [] - self.legend_labels: List[Hashable] = [] + self.legend_handles: list[Artist] = [] + self.legend_labels: list[Hashable] = [] self.logx = kwds.pop("logx", False) self.logy = kwds.pop("logy", False) @@ -569,7 +566,7 @@ def _apply_axis_properties(self, axis: Axis, rot=None, fontsize=None): label.set_fontsize(fontsize) @property - def legend_title(self) -> Optional[str]: + def legend_title(self) -> str | None: if not isinstance(self.data.columns, ABCMultiIndex): name = self.data.columns.name if name is not None: @@ -715,7 +712,7 @@ def _plot(cls, ax: Axes, x, y, style=None, is_errorbar: bool = False, **kwds): args = (x, y, style) if style is not None else (x, y) return ax.plot(*args, **kwds) - def _get_index_name(self) -> Optional[str]: + def _get_index_name(self) -> str | None: if isinstance(self.data.index, ABCMultiIndex): name = self.data.index.names if com.any_not_none(*name): @@ -922,7 +919,7 @@ def _get_subplots(self): ax for ax in self.axes[0].get_figure().get_axes() if isinstance(ax, Subplot) ] - def _get_axes_layout(self) -> Tuple[int, int]: + def _get_axes_layout(self) -> tuple[int, int]: axes = self._get_subplots() x_set = set() y_set = set() diff --git a/pandas/plotting/_matplotlib/misc.py b/pandas/plotting/_matplotlib/misc.py index eab5474fce541..6583328f916f1 100644 --- a/pandas/plotting/_matplotlib/misc.py +++ b/pandas/plotting/_matplotlib/misc.py @@ -3,11 +3,7 @@ import random from typing import ( TYPE_CHECKING, - Dict, Hashable, - List, - Optional, - Set, ) import matplotlib.lines as mlines @@ -141,7 +137,7 @@ def _get_marker_compat(marker): def radviz( frame: DataFrame, class_column, - ax: Optional[Axes] = None, + ax: Axes | None = None, color=None, colormap=None, **kwds, @@ -163,7 +159,7 @@ def normalize(series): ax.set_xlim(-1, 1) ax.set_ylim(-1, 1) - to_plot: Dict[Hashable, List[List]] = {} + to_plot: dict[Hashable, list[list]] = {} colors = get_standard_colors( num_colors=len(classes), colormap=colormap, color_type="random", color=color ) @@ -229,7 +225,7 @@ def normalize(series): def andrews_curves( frame: DataFrame, class_column, - ax: Optional[Axes] = None, + ax: Axes | None = None, samples: int = 200, color=None, colormap=None, @@ -267,7 +263,7 @@ def f(t): classes = frame[class_column].drop_duplicates() df = frame.drop(class_column, axis=1) t = np.linspace(-np.pi, np.pi, samples) - used_legends: Set[str] = set() + used_legends: set[str] = set() color_values = get_standard_colors( num_colors=len(classes), colormap=colormap, color_type="random", color=color @@ -295,7 +291,7 @@ def f(t): def bootstrap_plot( series: Series, - fig: Optional[Figure] = None, + fig: Figure | None = None, size: int = 50, samples: int = 500, **kwds, @@ -353,7 +349,7 @@ def parallel_coordinates( frame: DataFrame, class_column, cols=None, - ax: Optional[Axes] = None, + ax: Axes | None = None, color=None, use_columns=False, xticks=None, @@ -377,7 +373,7 @@ def parallel_coordinates( else: df = frame[cols] - used_legends: Set[str] = set() + used_legends: set[str] = set() ncols = len(df.columns) @@ -429,7 +425,7 @@ def parallel_coordinates( return ax -def lag_plot(series: Series, lag: int = 1, ax: Optional[Axes] = None, **kwds) -> Axes: +def lag_plot(series: Series, lag: int = 1, ax: Axes | None = None, **kwds) -> Axes: # workaround because `c='b'` is hardcoded in matplotlib's scatter method import matplotlib.pyplot as plt @@ -446,7 +442,7 @@ def lag_plot(series: Series, lag: int = 1, ax: Optional[Axes] = None, **kwds) -> return ax -def autocorrelation_plot(series: Series, ax: Optional[Axes] = None, **kwds) -> Axes: +def autocorrelation_plot(series: Series, ax: Axes | None = None, **kwds) -> Axes: import matplotlib.pyplot as plt n = len(series) diff --git a/pandas/plotting/_matplotlib/style.py b/pandas/plotting/_matplotlib/style.py index 2c9aadd9573cf..597c0dafa8cab 100644 --- a/pandas/plotting/_matplotlib/style.py +++ b/pandas/plotting/_matplotlib/style.py @@ -4,10 +4,7 @@ from typing import ( TYPE_CHECKING, Collection, - Dict, Iterator, - List, - Optional, Sequence, Union, cast, @@ -31,9 +28,9 @@ def get_standard_colors( num_colors: int, - colormap: Optional[Colormap] = None, + colormap: Colormap | None = None, color_type: str = "default", - color: Optional[Union[Dict[str, Color], Color, Collection[Color]]] = None, + color: dict[str, Color] | Color | Collection[Color] | None = None, ): """ Get standard colors based on `colormap`, `color_type` or `color` inputs. @@ -82,11 +79,11 @@ def get_standard_colors( def _derive_colors( *, - color: Optional[Union[Color, Collection[Color]]], - colormap: Optional[Union[str, Colormap]], + color: Color | Collection[Color] | None, + colormap: str | Colormap | None, color_type: str, num_colors: int, -) -> List[Color]: +) -> list[Color]: """ Derive colors from either `colormap`, `color_type` or `color` inputs. @@ -131,7 +128,7 @@ def _derive_colors( return _get_colors_from_color_type(color_type, num_colors=num_colors) -def _cycle_colors(colors: List[Color], num_colors: int) -> Iterator[Color]: +def _cycle_colors(colors: list[Color], num_colors: int) -> Iterator[Color]: """Cycle colors until achieving max of `num_colors` or length of `colors`. Extra colors will be ignored by matplotlib if there are more colors @@ -142,15 +139,15 @@ def _cycle_colors(colors: List[Color], num_colors: int) -> Iterator[Color]: def _get_colors_from_colormap( - colormap: Union[str, Colormap], + colormap: str | Colormap, num_colors: int, -) -> List[Color]: +) -> list[Color]: """Get colors from colormap.""" colormap = _get_cmap_instance(colormap) return [colormap(num) for num in np.linspace(0, 1, num=num_colors)] -def _get_cmap_instance(colormap: Union[str, Colormap]) -> Colormap: +def _get_cmap_instance(colormap: str | Colormap) -> Colormap: """Get instance of matplotlib colormap.""" if isinstance(colormap, str): cmap = colormap @@ -161,8 +158,8 @@ def _get_cmap_instance(colormap: Union[str, Colormap]) -> Colormap: def _get_colors_from_color( - color: Union[Color, Collection[Color]], -) -> List[Color]: + color: Color | Collection[Color], +) -> list[Color]: """Get colors from user input color.""" if len(color) == 0: raise ValueError(f"Invalid color argument: {color}") @@ -175,7 +172,7 @@ def _get_colors_from_color( return list(_gen_list_of_colors_from_iterable(color)) -def _is_single_color(color: Union[Color, Collection[Color]]) -> bool: +def _is_single_color(color: Color | Collection[Color]) -> bool: """Check if `color` is a single color, not a sequence of colors. Single color is of these kinds: @@ -208,7 +205,7 @@ def _gen_list_of_colors_from_iterable(color: Collection[Color]) -> Iterator[Colo raise ValueError(f"Invalid color {x}") -def _is_floats_color(color: Union[Color, Collection[Color]]) -> bool: +def _is_floats_color(color: Color | Collection[Color]) -> bool: """Check if color comprises a sequence of floats representing color.""" return bool( is_list_like(color) @@ -217,7 +214,7 @@ def _is_floats_color(color: Union[Color, Collection[Color]]) -> bool: ) -def _get_colors_from_color_type(color_type: str, num_colors: int) -> List[Color]: +def _get_colors_from_color_type(color_type: str, num_colors: int) -> list[Color]: """Get colors from user input color type.""" if color_type == "default": return _get_default_colors(num_colors) @@ -227,7 +224,7 @@ def _get_colors_from_color_type(color_type: str, num_colors: int) -> List[Color] raise ValueError("color_type must be either 'default' or 'random'") -def _get_default_colors(num_colors: int) -> List[Color]: +def _get_default_colors(num_colors: int) -> list[Color]: """Get `num_colors` of default colors from matplotlib rc params.""" import matplotlib.pyplot as plt @@ -235,12 +232,12 @@ def _get_default_colors(num_colors: int) -> List[Color]: return colors[0:num_colors] -def _get_random_colors(num_colors: int) -> List[Color]: +def _get_random_colors(num_colors: int) -> list[Color]: """Get `num_colors` of random colors.""" return [_random_color(num) for num in range(num_colors)] -def _random_color(column: int) -> List[float]: +def _random_color(column: int) -> list[float]: """Get a random color represented as a list of length 3""" # GH17525 use common._random_state to avoid resetting the seed rs = com.random_state(column) diff --git a/pandas/plotting/_matplotlib/timeseries.py b/pandas/plotting/_matplotlib/timeseries.py index 8374988708701..3b9c5eae70b42 100644 --- a/pandas/plotting/_matplotlib/timeseries.py +++ b/pandas/plotting/_matplotlib/timeseries.py @@ -5,7 +5,6 @@ import functools from typing import ( TYPE_CHECKING, - Optional, cast, ) @@ -186,7 +185,7 @@ def _get_ax_freq(ax: Axes): return ax_freq -def _get_period_alias(freq) -> Optional[str]: +def _get_period_alias(freq) -> str | None: freqstr = to_offset(freq).rule_code freq = get_period_alias(freqstr) @@ -239,7 +238,7 @@ def use_dynamic_x(ax: Axes, data: FrameOrSeriesUnion) -> bool: return True -def _get_index_freq(index: Index) -> Optional[BaseOffset]: +def _get_index_freq(index: Index) -> BaseOffset | None: freq = getattr(index, "freq", None) if freq is None: freq = getattr(index, "inferred_freq", None) diff --git a/pandas/plotting/_matplotlib/tools.py b/pandas/plotting/_matplotlib/tools.py index 03d73d1d36953..9bfa24b6371ab 100644 --- a/pandas/plotting/_matplotlib/tools.py +++ b/pandas/plotting/_matplotlib/tools.py @@ -5,10 +5,7 @@ from typing import ( TYPE_CHECKING, Iterable, - List, Sequence, - Tuple, - Union, ) import warnings @@ -81,7 +78,7 @@ def table( return table -def _get_layout(nplots: int, layout=None, layout_type: str = "box") -> Tuple[int, int]: +def _get_layout(nplots: int, layout=None, layout_type: str = "box") -> tuple[int, int]: if layout is not None: if not isinstance(layout, (tuple, list)) or len(layout) != 2: raise ValueError("Layout must be a tuple of (rows, columns)") @@ -434,7 +431,7 @@ def handle_shared_axes( _remove_labels_from_axis(ax.yaxis) -def flatten_axes(axes: Union[Axes, Sequence[Axes]]) -> np.ndarray: +def flatten_axes(axes: Axes | Sequence[Axes]) -> np.ndarray: if not is_list_like(axes): return np.array([axes]) elif isinstance(axes, (np.ndarray, ABCIndex)): @@ -443,7 +440,7 @@ def flatten_axes(axes: Union[Axes, Sequence[Axes]]) -> np.ndarray: def set_ticks_props( - axes: Union[Axes, Sequence[Axes]], + axes: Axes | Sequence[Axes], xlabelsize=None, xrot=None, ylabelsize=None, @@ -463,7 +460,7 @@ def set_ticks_props( return axes -def get_all_lines(ax: Axes) -> List[Line2D]: +def get_all_lines(ax: Axes) -> list[Line2D]: lines = ax.get_lines() if hasattr(ax, "right_ax"): @@ -475,7 +472,7 @@ def get_all_lines(ax: Axes) -> List[Line2D]: return lines -def get_xlim(lines: Iterable[Line2D]) -> Tuple[float, float]: +def get_xlim(lines: Iterable[Line2D]) -> tuple[float, float]: left, right = np.inf, -np.inf for line in lines: x = line.get_xdata(orig=False) diff --git a/pandas/tests/extension/arrow/arrays.py b/pandas/tests/extension/arrow/arrays.py index 27c8c8170e11b..1a330bb584ba5 100644 --- a/pandas/tests/extension/arrow/arrays.py +++ b/pandas/tests/extension/arrow/arrays.py @@ -11,11 +11,12 @@ import copy import itertools import operator -from typing import Type import numpy as np import pyarrow as pa +from pandas._typing import type_t + import pandas as pd from pandas.api.extensions import ( ExtensionArray, @@ -36,7 +37,7 @@ class ArrowBoolDtype(ExtensionDtype): na_value = pa.NULL @classmethod - def construct_array_type(cls) -> Type[ArrowBoolArray]: + def construct_array_type(cls) -> type_t[ArrowBoolArray]: """ Return the array type associated with this dtype. @@ -60,7 +61,7 @@ class ArrowStringDtype(ExtensionDtype): na_value = pa.NULL @classmethod - def construct_array_type(cls) -> Type[ArrowStringArray]: + def construct_array_type(cls) -> type_t[ArrowStringArray]: """ Return the array type associated with this dtype. diff --git a/pandas/tests/extension/arrow/test_timestamp.py b/pandas/tests/extension/arrow/test_timestamp.py index 819e5549d05ae..c61cc30950a23 100644 --- a/pandas/tests/extension/arrow/test_timestamp.py +++ b/pandas/tests/extension/arrow/test_timestamp.py @@ -1,10 +1,11 @@ from __future__ import annotations import datetime -from typing import Type import pytest +from pandas._typing import type_t + import pandas as pd from pandas.api.extensions import ( ExtensionDtype, @@ -27,7 +28,7 @@ class ArrowTimestampUSDtype(ExtensionDtype): na_value = pa.NULL @classmethod - def construct_array_type(cls) -> Type[ArrowTimestampUSArray]: + def construct_array_type(cls) -> type_t[ArrowTimestampUSArray]: """ Return the array type associated with this dtype. diff --git a/pandas/tests/extension/decimal/array.py b/pandas/tests/extension/decimal/array.py index 68dbdd9e0bf35..fe7ebe4f4fb51 100644 --- a/pandas/tests/extension/decimal/array.py +++ b/pandas/tests/extension/decimal/array.py @@ -4,13 +4,11 @@ import numbers import random import sys -from typing import ( - Type, - Union, -) import numpy as np +from pandas._typing import type_t + from pandas.core.dtypes.base import ExtensionDtype from pandas.core.dtypes.common import ( is_dtype_equal, @@ -49,7 +47,7 @@ def __repr__(self) -> str: return f"DecimalDtype(context={self.context})" @classmethod - def construct_array_type(cls) -> Type[DecimalArray]: + def construct_array_type(cls) -> type_t[DecimalArray]: """ Return the array type associated with this dtype. @@ -176,7 +174,7 @@ def __setitem__(self, key, value): def __len__(self) -> int: return len(self._data) - def __contains__(self, item) -> Union[bool, np.bool_]: + def __contains__(self, item) -> bool | np.bool_: if not isinstance(item, decimal.Decimal): return False elif item.is_nan(): diff --git a/pandas/tests/extension/json/array.py b/pandas/tests/extension/json/array.py index a63c849d25a9f..ffe2769730f34 100644 --- a/pandas/tests/extension/json/array.py +++ b/pandas/tests/extension/json/array.py @@ -25,11 +25,12 @@ from typing import ( Any, Mapping, - Type, ) import numpy as np +from pandas._typing import type_t + from pandas.core.dtypes.cast import construct_1d_object_array_from_listlike from pandas.core.dtypes.common import pandas_dtype @@ -48,7 +49,7 @@ class JSONDtype(ExtensionDtype): na_value: Mapping[str, Any] = UserDict() @classmethod - def construct_array_type(cls) -> Type[JSONArray]: + def construct_array_type(cls) -> type_t[JSONArray]: """ Return the array type associated with this dtype. diff --git a/pandas/tests/extension/list/array.py b/pandas/tests/extension/list/array.py index 4715bbdad6428..47015ed334ddf 100644 --- a/pandas/tests/extension/list/array.py +++ b/pandas/tests/extension/list/array.py @@ -8,10 +8,11 @@ import numbers import random import string -from typing import Type import numpy as np +from pandas._typing import type_t + from pandas.core.dtypes.base import ExtensionDtype import pandas as pd @@ -28,7 +29,7 @@ class ListDtype(ExtensionDtype): na_value = np.nan @classmethod - def construct_array_type(cls) -> Type[ListArray]: + def construct_array_type(cls) -> type_t[ListArray]: """ Return the array type associated with this dtype. diff --git a/pandas/tests/plotting/common.py b/pandas/tests/plotting/common.py index fa0a09a84a8f0..e2b6b5ab3319c 100644 --- a/pandas/tests/plotting/common.py +++ b/pandas/tests/plotting/common.py @@ -11,7 +11,6 @@ from typing import ( TYPE_CHECKING, Sequence, - Union, ) import warnings @@ -194,7 +193,7 @@ def _check_visible(self, collections, visible=True): assert patch.get_visible() == visible def _check_patches_all_filled( - self, axes: Union[Axes, Sequence[Axes]], filled: bool = True + self, axes: Axes | Sequence[Axes], filled: bool = True ) -> None: """ Check for each artist whether it is filled or not