From dc237d3f0eb87765700160040fa684c42f959023 Mon Sep 17 00:00:00 2001 From: Guillaume Mollard Date: Mon, 24 Apr 2023 14:47:53 +0200 Subject: [PATCH 1/7] added typing IntervalClosedType where needed --- pandas/_libs/interval.pyi | 2 +- pandas/_libs/interval.pyx | 2 +- pandas/core/arrays/interval.py | 2 +- pandas/core/dtypes/dtypes.py | 5 +++-- pandas/core/generic.py | 4 ++-- pandas/core/indexes/interval.py | 2 +- pandas/io/formats/style.py | 5 +++-- 7 files changed, 12 insertions(+), 10 deletions(-) diff --git a/pandas/_libs/interval.pyi b/pandas/_libs/interval.pyi index 4c36246e04d23..587fdf84f2f85 100644 --- a/pandas/_libs/interval.pyi +++ b/pandas/_libs/interval.pyi @@ -148,7 +148,7 @@ class Interval(IntervalMixin, Generic[_OrderableT]): def intervals_to_interval_bounds( intervals: np.ndarray, validate_closed: bool = ... -) -> tuple[np.ndarray, np.ndarray, str]: ... +) -> tuple[np.ndarray, np.ndarray, IntervalClosedType]: ... class IntervalTree(IntervalMixin): def __init__( diff --git a/pandas/_libs/interval.pyx b/pandas/_libs/interval.pyx index 14b7baf7f5a08..fe405b98f218c 100644 --- a/pandas/_libs/interval.pyx +++ b/pandas/_libs/interval.pyx @@ -612,7 +612,7 @@ def intervals_to_interval_bounds(ndarray intervals, bint validate_closed=True): tuple of left : ndarray right : ndarray - closed: str + closed: IntervalClosedType """ cdef: object closed = None, interval diff --git a/pandas/core/arrays/interval.py b/pandas/core/arrays/interval.py index b8442205c331e..2ba66006a0645 100644 --- a/pandas/core/arrays/interval.py +++ b/pandas/core/arrays/interval.py @@ -226,7 +226,7 @@ def ndim(self) -> Literal[1]: def __new__( cls, data, - closed=None, + closed: IntervalClosedType | None = None, dtype: Dtype | None = None, copy: bool = False, verify_integrity: bool = True, diff --git a/pandas/core/dtypes/dtypes.py b/pandas/core/dtypes/dtypes.py index 479bfdc557a07..71dbb5d02bb0c 100644 --- a/pandas/core/dtypes/dtypes.py +++ b/pandas/core/dtypes/dtypes.py @@ -53,6 +53,7 @@ from pandas._typing import ( Dtype, DtypeObj, + IntervalClosedType, Ordered, npt, type_t, @@ -1099,7 +1100,7 @@ class IntervalDtype(PandasExtensionDtype): _cache_dtypes: dict[str_type, PandasExtensionDtype] = {} - def __new__(cls, subtype=None, closed: str_type | None = None): + def __new__(cls, subtype=None, closed: IntervalClosedType | None = None): from pandas.core.dtypes.common import ( is_string_dtype, pandas_dtype, @@ -1175,7 +1176,7 @@ def _can_hold_na(self) -> bool: return True @property - def closed(self): + def closed(self) -> IntervalClosedType: return self._closed @property diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 582a043a8a78a..02039964def38 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -8593,7 +8593,7 @@ def resample( self, rule, axis: Axis | lib.NoDefault = lib.no_default, - closed: str | None = None, + closed: IntervalClosedType | None = None, label: str | None = None, convention: str = "start", kind: str | None = None, @@ -11499,7 +11499,7 @@ def rolling( win_type: str | None = None, on: str | None = None, axis: Axis | lib.NoDefault = lib.no_default, - closed: str | None = None, + closed: IntervalClosedType | None = None, step: int | None = None, method: str = "single", ) -> Window | Rolling: diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index ca01b1fd5fe6f..9841ebee89b79 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -218,7 +218,7 @@ class IntervalIndex(ExtensionIndex): def __new__( cls, data, - closed=None, + closed: IntervalClosedType | None = None, dtype: Dtype | None = None, copy: bool = False, name: Hashable = None, diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index e2c5ed2ea92b6..8ddf14175a6da 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -65,6 +65,7 @@ AxisInt, FilePath, IndexLabel, + IntervalClosedType, Level, QuantileInterpolation, Scalar, @@ -3185,7 +3186,7 @@ def highlight_between( axis: Axis | None = 0, left: Scalar | Sequence | None = None, right: Scalar | Sequence | None = None, - inclusive: str = "both", + inclusive: IntervalClosedType = "both", props: str | None = None, ) -> Styler: """ @@ -3294,7 +3295,7 @@ def highlight_quantile( q_left: float = 0.0, q_right: float = 1.0, interpolation: QuantileInterpolation = "linear", - inclusive: str = "both", + inclusive: IntervalClosedType = "both", props: str | None = None, ) -> Styler: """ From e1cd083fdc2ac0e3e509e81d7808d98a62d5686c Mon Sep 17 00:00:00 2001 From: Guillaume Mollard Date: Mon, 24 Apr 2023 15:17:08 +0200 Subject: [PATCH 2/7] reformat due to check failed --- pandas/core/generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 7ffbcb30399be..1595e74d1c396 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -8546,7 +8546,7 @@ def between_time( self, start_time, end_time, - inclusive = "both", + inclusive="both", axis: Axis | None = None, ) -> Self: """ From e05f3a2b086f15befcdb5c11937af1f984525bd6 Mon Sep 17 00:00:00 2001 From: Guillaume Mollard Date: Mon, 24 Apr 2023 16:17:32 +0200 Subject: [PATCH 3/7] revert wrong modification --- pandas/core/generic.py | 126 ++++++++++++----------------------------- 1 file changed, 37 insertions(+), 89 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 1595e74d1c396..582a043a8a78a 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -68,9 +68,7 @@ Manager, NaPosition, NDFrameT, - OpenFileErrors, RandomState, - ReindexMethod, Renamer, Scalar, Self, @@ -112,6 +110,7 @@ ensure_str, is_bool, is_bool_dtype, + is_datetime64_any_dtype, is_dict_like, is_dtype_equal, is_extension_array_dtype, @@ -590,7 +589,6 @@ def _get_cleaned_column_resolvers(self) -> dict[Hashable, Series]: clean_column_name(k): v for k, v in self.items() if not isinstance(k, int) } - @final @property def _info_axis(self) -> Index: return getattr(self, self._info_axis_name) @@ -970,7 +968,6 @@ def squeeze(self, axis: Axis | None = None): # ---------------------------------------------------------------------- # Rename - @final def _rename( self, mapper: Renamer | None = None, @@ -1476,10 +1473,6 @@ def bool(self) -> bool_t: """ Return the bool of a single element Series or DataFrame. - .. deprecated:: 2.1.0 - - bool is deprecated and will be removed in future version of pandas - This must be a boolean scalar value, either True or False. It will raise a ValueError if the Series or DataFrame does not have exactly 1 element, or that element is not boolean (integer values 0 and 1 will also raise an exception). @@ -1499,14 +1492,14 @@ def bool(self) -> bool_t: -------- The method will only work for single element objects with a boolean value: - >>> pd.Series([True]).bool() # doctest: +SKIP + >>> pd.Series([True]).bool() True - >>> pd.Series([False]).bool() # doctest: +SKIP + >>> pd.Series([False]).bool() False - >>> pd.DataFrame({'col': [True]}).bool() # doctest: +SKIP + >>> pd.DataFrame({'col': [True]}).bool() True - >>> pd.DataFrame({'col': [False]}).bool() # doctest: +SKIP + >>> pd.DataFrame({'col': [False]}).bool() False """ @@ -2132,7 +2125,7 @@ def to_excel( index_label: IndexLabel = None, startrow: int = 0, startcol: int = 0, - engine: Literal["openpyxl", "xlsxwriter"] | None = None, + engine: str | None = None, merge_cells: bool_t = True, inf_rep: str = "inf", freeze_panes: tuple[int, int] | None = None, @@ -2279,8 +2272,7 @@ def to_excel( def to_json( self, path_or_buf: FilePath | WriteBuffer[bytes] | WriteBuffer[str] | None = None, - orient: Literal["split", "records", "index", "table", "columns", "values"] - | None = None, + orient: str | None = None, date_format: str | None = None, double_precision: int = 10, force_ascii: bool_t = True, @@ -2574,7 +2566,7 @@ def to_hdf( nan_rep=None, dropna: bool_t | None = None, data_columns: Literal[True] | list[str] | None = None, - errors: OpenFileErrors = "strict", + errors: str = "strict", encoding: str = "UTF-8", ) -> None: """ @@ -2721,7 +2713,7 @@ def to_sql( index_label: IndexLabel = None, chunksize: int | None = None, dtype: DtypeArg | None = None, - method: Literal["multi"] | Callable | None = None, + method: str | None = None, ) -> int | None: """ Write records stored in a DataFrame to a SQL database. @@ -3478,7 +3470,6 @@ def _wrap(x, alt_format_): render_kwargs=render_kwargs_, ) - @final def _to_latex_via_styler( self, buf=None, @@ -3568,7 +3559,7 @@ def to_csv( doublequote: bool_t = ..., escapechar: str | None = ..., decimal: str = ..., - errors: OpenFileErrors = ..., + errors: str = ..., storage_options: StorageOptions = ..., ) -> str: ... @@ -3595,7 +3586,7 @@ def to_csv( doublequote: bool_t = ..., escapechar: str | None = ..., decimal: str = ..., - errors: OpenFileErrors = ..., + errors: str = ..., storage_options: StorageOptions = ..., ) -> None: ... @@ -3626,7 +3617,7 @@ def to_csv( doublequote: bool_t = True, escapechar: str | None = None, decimal: str = ".", - errors: OpenFileErrors = "strict", + errors: str = "strict", storage_options: StorageOptions = None, ) -> str | None: r""" @@ -4296,7 +4287,6 @@ def _check_setitem_copy(self, t: str = "setting", force: bool_t = False): if value == "warn": warnings.warn(t, SettingWithCopyWarning, stacklevel=find_stack_level()) - @final def __delitem__(self, key) -> None: """ Delete item @@ -4862,8 +4852,8 @@ def sort_values( axis: Axis = ..., ascending: bool_t | Sequence[bool_t] = ..., inplace: Literal[False] = ..., - kind: SortKind = ..., - na_position: NaPosition = ..., + kind: str = ..., + na_position: str = ..., ignore_index: bool_t = ..., key: ValueKeyFunc = ..., ) -> Self: @@ -4876,8 +4866,8 @@ def sort_values( axis: Axis = ..., ascending: bool_t | Sequence[bool_t] = ..., inplace: Literal[True], - kind: SortKind = ..., - na_position: NaPosition = ..., + kind: str = ..., + na_position: str = ..., ignore_index: bool_t = ..., key: ValueKeyFunc = ..., ) -> None: @@ -4890,8 +4880,8 @@ def sort_values( axis: Axis = ..., ascending: bool_t | Sequence[bool_t] = ..., inplace: bool_t = ..., - kind: SortKind = ..., - na_position: NaPosition = ..., + kind: str = ..., + na_position: str = ..., ignore_index: bool_t = ..., key: ValueKeyFunc = ..., ) -> Self | None: @@ -4903,8 +4893,8 @@ def sort_values( axis: Axis = 0, ascending: bool_t | Sequence[bool_t] = True, inplace: bool_t = False, - kind: SortKind = "quicksort", - na_position: NaPosition = "last", + kind: str = "quicksort", + na_position: str = "last", ignore_index: bool_t = False, key: ValueKeyFunc = None, ) -> Self | None: @@ -5163,7 +5153,7 @@ def reindex( index=None, columns=None, axis: Axis | None = None, - method: ReindexMethod | None = None, + method: str | None = None, copy: bool_t | None = None, level: Level | None = None, fill_value: Scalar | None = np.nan, @@ -6073,7 +6063,6 @@ def __finalize__(self, other, method: str | None = None, **kwargs) -> Self: return self - @final def __getattr__(self, name: str): """ After regular attribute access, try looking up the name @@ -6090,7 +6079,6 @@ def __getattr__(self, name: str): return self[name] return object.__getattribute__(self, name) - @final def __setattr__(self, name: str, value) -> None: """ After regular attribute access, try setting the name @@ -6261,7 +6249,6 @@ def dtypes(self): data = self._mgr.get_dtypes() return self._constructor_sliced(data, index=self._info_axis, dtype=np.object_) - @final def astype( self, dtype, copy: bool_t | None = None, errors: IgnoreRaise = "raise" ) -> Self: @@ -7135,7 +7122,6 @@ def ffill( ) -> Self | None: ... - @final @doc(klass=_shared_doc_kwargs["klass"]) def ffill( self, @@ -7157,7 +7143,6 @@ def ffill( method="ffill", axis=axis, inplace=inplace, limit=limit, downcast=downcast ) - @final @doc(klass=_shared_doc_kwargs["klass"]) def pad( self, @@ -7220,7 +7205,6 @@ def bfill( ) -> Self | None: ... - @final @doc(klass=_shared_doc_kwargs["klass"]) def bfill( self, @@ -7242,7 +7226,6 @@ def bfill( method="bfill", axis=axis, inplace=inplace, limit=limit, downcast=downcast ) - @final @doc(klass=_shared_doc_kwargs["klass"]) def backfill( self, @@ -7512,36 +7495,15 @@ def replace( else: return result.__finalize__(self, method="replace") - @final def interpolate( self, - method: Literal[ - "linear", - "time", - "index", - "values", - "pad", - "nearest", - "zero", - "slinear", - "quadratic", - "cubic", - "barycentric", - "polynomial", - "krogh", - "piecewise_polynomial", - "spline", - "pchip", - "akima", - "cubicspline", - "from_derivatives", - ] = "linear", + method: str = "linear", *, axis: Axis = 0, limit: int | None = None, inplace: bool_t = False, - limit_direction: Literal["forward", "backward", "both"] | None = None, - limit_area: Literal["inside", "outside"] | None = None, + limit_direction: str | None = None, + limit_area: str | None = None, downcast: str | None = None, **kwargs, ) -> Self | None: @@ -7792,8 +7754,8 @@ def interpolate( methods = {"index", "values", "nearest", "time"} is_numeric_or_datetime = ( is_numeric_dtype(index.dtype) - or isinstance(index.dtype, DatetimeTZDtype) - or lib.is_np_dtype(index.dtype, "mM") + or is_datetime64_any_dtype(index.dtype) + or lib.is_np_dtype(index.dtype, "m") ) if method not in methods and not is_numeric_or_datetime: raise ValueError( @@ -8197,7 +8159,6 @@ def _clip_with_one_bound(self, threshold, method, axis, inplace): # GH 40420 return self.where(subset, threshold, axis=axis, inplace=inplace) - @final def clip( self, lower=None, @@ -8364,7 +8325,7 @@ def asfreq( self, freq: Frequency, method: FillnaOptions | None = None, - how: Literal["start", "end"] | None = None, + how: str | None = None, normalize: bool_t = False, fill_value: Hashable = None, ) -> Self: @@ -8546,7 +8507,7 @@ def between_time( self, start_time, end_time, - inclusive="both", + inclusive: IntervalClosedType = "both", axis: Axis | None = None, ) -> Self: """ @@ -8632,10 +8593,10 @@ def resample( self, rule, axis: Axis | lib.NoDefault = lib.no_default, - closed: Literal["right", "left"] | None = None, - label: Literal["right", "left"] | None = None, - convention: Literal["start", "end", "s", "e"] = "start", - kind: Literal["timestamp", "period"] | None = None, + closed: str | None = None, + label: str | None = None, + convention: str = "start", + kind: str | None = None, on: Level = None, level: Level = None, origin: str | TimestampConvertibleTypes = "start_day", @@ -9192,9 +9153,9 @@ def last(self, offset) -> Self: def rank( self, axis: Axis = 0, - method: Literal["average", "min", "max", "first", "dense"] = "average", + method: str = "average", numeric_only: bool_t = False, - na_option: Literal["keep", "top", "bottom"] = "keep", + na_option: str = "keep", ascending: bool_t = True, pct: bool_t = False, ) -> Self: @@ -10009,7 +9970,6 @@ def where( ) -> Self | None: ... - @final @doc( klass=_shared_doc_kwargs["klass"], cond="True", @@ -10202,7 +10162,6 @@ def mask( ) -> Self | None: ... - @final @doc( where, klass=_shared_doc_kwargs["klass"], @@ -10383,7 +10342,6 @@ def shift( result = self.set_axis(new_ax, axis=axis) return result.__finalize__(self, method="shift") - @final def truncate( self, before=None, @@ -11541,7 +11499,7 @@ def rolling( win_type: str | None = None, on: str | None = None, axis: Axis | lib.NoDefault = lib.no_default, - closed: IntervalClosedType | None = None, + closed: str | None = None, step: int | None = None, method: str = "single", ) -> Window | Rolling: @@ -11600,7 +11558,7 @@ def expanding( self, min_periods: int = 1, axis: Axis | lib.NoDefault = lib.no_default, - method: Literal["single", "table"] = "single", + method: str = "single", ) -> Expanding: if axis is not lib.no_default: axis = self._get_axis_number(axis) @@ -11638,7 +11596,7 @@ def ewm( ignore_na: bool_t = False, axis: Axis | lib.NoDefault = lib.no_default, times: np.ndarray | DataFrame | Series | None = None, - method: Literal["single", "table"] = "single", + method: str = "single", ) -> ExponentialMovingWindow: if axis is not lib.no_default: axis = self._get_axis_number(axis) @@ -11709,56 +11667,46 @@ def _inplace_method(self, other, op) -> Self: ) return self - @final def __iadd__(self, other) -> Self: # error: Unsupported left operand type for + ("Type[NDFrame]") return self._inplace_method(other, type(self).__add__) # type: ignore[operator] - @final def __isub__(self, other) -> Self: # error: Unsupported left operand type for - ("Type[NDFrame]") return self._inplace_method(other, type(self).__sub__) # type: ignore[operator] - @final def __imul__(self, other) -> Self: # error: Unsupported left operand type for * ("Type[NDFrame]") return self._inplace_method(other, type(self).__mul__) # type: ignore[operator] - @final def __itruediv__(self, other) -> Self: # error: Unsupported left operand type for / ("Type[NDFrame]") return self._inplace_method( other, type(self).__truediv__ # type: ignore[operator] ) - @final def __ifloordiv__(self, other) -> Self: # error: Unsupported left operand type for // ("Type[NDFrame]") return self._inplace_method( other, type(self).__floordiv__ # type: ignore[operator] ) - @final def __imod__(self, other) -> Self: # error: Unsupported left operand type for % ("Type[NDFrame]") return self._inplace_method(other, type(self).__mod__) # type: ignore[operator] - @final def __ipow__(self, other) -> Self: # error: Unsupported left operand type for ** ("Type[NDFrame]") return self._inplace_method(other, type(self).__pow__) # type: ignore[operator] - @final def __iand__(self, other) -> Self: # error: Unsupported left operand type for & ("Type[NDFrame]") return self._inplace_method(other, type(self).__and__) # type: ignore[operator] - @final def __ior__(self, other) -> Self: # error: Unsupported left operand type for | ("Type[NDFrame]") return self._inplace_method(other, type(self).__or__) # type: ignore[operator] - @final def __ixor__(self, other) -> Self: # error: Unsupported left operand type for ^ ("Type[NDFrame]") return self._inplace_method(other, type(self).__xor__) # type: ignore[operator] From ec73cde138d9b9c8fc64439298056f8a624a497a Mon Sep 17 00:00:00 2001 From: Guillaume Mollard Date: Mon, 24 Apr 2023 16:25:32 +0200 Subject: [PATCH 4/7] correct generic.py --- pandas/core/generic.py | 124 +++++++++++++++++++++++++++++------------ 1 file changed, 88 insertions(+), 36 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 582a043a8a78a..f3de296841510 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -68,7 +68,9 @@ Manager, NaPosition, NDFrameT, + OpenFileErrors, RandomState, + ReindexMethod, Renamer, Scalar, Self, @@ -110,7 +112,6 @@ ensure_str, is_bool, is_bool_dtype, - is_datetime64_any_dtype, is_dict_like, is_dtype_equal, is_extension_array_dtype, @@ -589,6 +590,7 @@ def _get_cleaned_column_resolvers(self) -> dict[Hashable, Series]: clean_column_name(k): v for k, v in self.items() if not isinstance(k, int) } + @final @property def _info_axis(self) -> Index: return getattr(self, self._info_axis_name) @@ -968,6 +970,7 @@ def squeeze(self, axis: Axis | None = None): # ---------------------------------------------------------------------- # Rename + @final def _rename( self, mapper: Renamer | None = None, @@ -1473,6 +1476,10 @@ def bool(self) -> bool_t: """ Return the bool of a single element Series or DataFrame. + .. deprecated:: 2.1.0 + + bool is deprecated and will be removed in future version of pandas + This must be a boolean scalar value, either True or False. It will raise a ValueError if the Series or DataFrame does not have exactly 1 element, or that element is not boolean (integer values 0 and 1 will also raise an exception). @@ -1492,14 +1499,14 @@ def bool(self) -> bool_t: -------- The method will only work for single element objects with a boolean value: - >>> pd.Series([True]).bool() + >>> pd.Series([True]).bool() # doctest: +SKIP True - >>> pd.Series([False]).bool() + >>> pd.Series([False]).bool() # doctest: +SKIP False - >>> pd.DataFrame({'col': [True]}).bool() + >>> pd.DataFrame({'col': [True]}).bool() # doctest: +SKIP True - >>> pd.DataFrame({'col': [False]}).bool() + >>> pd.DataFrame({'col': [False]}).bool() # doctest: +SKIP False """ @@ -2125,7 +2132,7 @@ def to_excel( index_label: IndexLabel = None, startrow: int = 0, startcol: int = 0, - engine: str | None = None, + engine: Literal["openpyxl", "xlsxwriter"] | None = None, merge_cells: bool_t = True, inf_rep: str = "inf", freeze_panes: tuple[int, int] | None = None, @@ -2272,7 +2279,8 @@ def to_excel( def to_json( self, path_or_buf: FilePath | WriteBuffer[bytes] | WriteBuffer[str] | None = None, - orient: str | None = None, + orient: Literal["split", "records", "index", "table", "columns", "values"] + | None = None, date_format: str | None = None, double_precision: int = 10, force_ascii: bool_t = True, @@ -2566,7 +2574,7 @@ def to_hdf( nan_rep=None, dropna: bool_t | None = None, data_columns: Literal[True] | list[str] | None = None, - errors: str = "strict", + errors: OpenFileErrors = "strict", encoding: str = "UTF-8", ) -> None: """ @@ -2713,7 +2721,7 @@ def to_sql( index_label: IndexLabel = None, chunksize: int | None = None, dtype: DtypeArg | None = None, - method: str | None = None, + method: Literal["multi"] | Callable | None = None, ) -> int | None: """ Write records stored in a DataFrame to a SQL database. @@ -3470,6 +3478,7 @@ def _wrap(x, alt_format_): render_kwargs=render_kwargs_, ) + @final def _to_latex_via_styler( self, buf=None, @@ -3559,7 +3568,7 @@ def to_csv( doublequote: bool_t = ..., escapechar: str | None = ..., decimal: str = ..., - errors: str = ..., + errors: OpenFileErrors = ..., storage_options: StorageOptions = ..., ) -> str: ... @@ -3586,7 +3595,7 @@ def to_csv( doublequote: bool_t = ..., escapechar: str | None = ..., decimal: str = ..., - errors: str = ..., + errors: OpenFileErrors = ..., storage_options: StorageOptions = ..., ) -> None: ... @@ -3617,7 +3626,7 @@ def to_csv( doublequote: bool_t = True, escapechar: str | None = None, decimal: str = ".", - errors: str = "strict", + errors: OpenFileErrors = "strict", storage_options: StorageOptions = None, ) -> str | None: r""" @@ -4287,6 +4296,7 @@ def _check_setitem_copy(self, t: str = "setting", force: bool_t = False): if value == "warn": warnings.warn(t, SettingWithCopyWarning, stacklevel=find_stack_level()) + @final def __delitem__(self, key) -> None: """ Delete item @@ -4852,8 +4862,8 @@ def sort_values( axis: Axis = ..., ascending: bool_t | Sequence[bool_t] = ..., inplace: Literal[False] = ..., - kind: str = ..., - na_position: str = ..., + kind: SortKind = ..., + na_position: NaPosition = ..., ignore_index: bool_t = ..., key: ValueKeyFunc = ..., ) -> Self: @@ -4866,8 +4876,8 @@ def sort_values( axis: Axis = ..., ascending: bool_t | Sequence[bool_t] = ..., inplace: Literal[True], - kind: str = ..., - na_position: str = ..., + kind: SortKind = ..., + na_position: NaPosition = ..., ignore_index: bool_t = ..., key: ValueKeyFunc = ..., ) -> None: @@ -4880,8 +4890,8 @@ def sort_values( axis: Axis = ..., ascending: bool_t | Sequence[bool_t] = ..., inplace: bool_t = ..., - kind: str = ..., - na_position: str = ..., + kind: SortKind = ..., + na_position: NaPosition = ..., ignore_index: bool_t = ..., key: ValueKeyFunc = ..., ) -> Self | None: @@ -4893,8 +4903,8 @@ def sort_values( axis: Axis = 0, ascending: bool_t | Sequence[bool_t] = True, inplace: bool_t = False, - kind: str = "quicksort", - na_position: str = "last", + kind: SortKind = "quicksort", + na_position: NaPosition = "last", ignore_index: bool_t = False, key: ValueKeyFunc = None, ) -> Self | None: @@ -5153,7 +5163,7 @@ def reindex( index=None, columns=None, axis: Axis | None = None, - method: str | None = None, + method: ReindexMethod | None = None, copy: bool_t | None = None, level: Level | None = None, fill_value: Scalar | None = np.nan, @@ -6063,6 +6073,7 @@ def __finalize__(self, other, method: str | None = None, **kwargs) -> Self: return self + @final def __getattr__(self, name: str): """ After regular attribute access, try looking up the name @@ -6079,6 +6090,7 @@ def __getattr__(self, name: str): return self[name] return object.__getattribute__(self, name) + @final def __setattr__(self, name: str, value) -> None: """ After regular attribute access, try setting the name @@ -6249,6 +6261,7 @@ def dtypes(self): data = self._mgr.get_dtypes() return self._constructor_sliced(data, index=self._info_axis, dtype=np.object_) + @final def astype( self, dtype, copy: bool_t | None = None, errors: IgnoreRaise = "raise" ) -> Self: @@ -7122,6 +7135,7 @@ def ffill( ) -> Self | None: ... + @final @doc(klass=_shared_doc_kwargs["klass"]) def ffill( self, @@ -7143,6 +7157,7 @@ def ffill( method="ffill", axis=axis, inplace=inplace, limit=limit, downcast=downcast ) + @final @doc(klass=_shared_doc_kwargs["klass"]) def pad( self, @@ -7205,6 +7220,7 @@ def bfill( ) -> Self | None: ... + @final @doc(klass=_shared_doc_kwargs["klass"]) def bfill( self, @@ -7226,6 +7242,7 @@ def bfill( method="bfill", axis=axis, inplace=inplace, limit=limit, downcast=downcast ) + @final @doc(klass=_shared_doc_kwargs["klass"]) def backfill( self, @@ -7495,15 +7512,36 @@ def replace( else: return result.__finalize__(self, method="replace") + @final def interpolate( self, - method: str = "linear", + method: Literal[ + "linear", + "time", + "index", + "values", + "pad", + "nearest", + "zero", + "slinear", + "quadratic", + "cubic", + "barycentric", + "polynomial", + "krogh", + "piecewise_polynomial", + "spline", + "pchip", + "akima", + "cubicspline", + "from_derivatives", + ] = "linear", *, axis: Axis = 0, limit: int | None = None, inplace: bool_t = False, - limit_direction: str | None = None, - limit_area: str | None = None, + limit_direction: Literal["forward", "backward", "both"] | None = None, + limit_area: Literal["inside", "outside"] | None = None, downcast: str | None = None, **kwargs, ) -> Self | None: @@ -7754,8 +7792,8 @@ def interpolate( methods = {"index", "values", "nearest", "time"} is_numeric_or_datetime = ( is_numeric_dtype(index.dtype) - or is_datetime64_any_dtype(index.dtype) - or lib.is_np_dtype(index.dtype, "m") + or isinstance(index.dtype, DatetimeTZDtype) + or lib.is_np_dtype(index.dtype, "mM") ) if method not in methods and not is_numeric_or_datetime: raise ValueError( @@ -8159,6 +8197,7 @@ def _clip_with_one_bound(self, threshold, method, axis, inplace): # GH 40420 return self.where(subset, threshold, axis=axis, inplace=inplace) + @final def clip( self, lower=None, @@ -8325,7 +8364,7 @@ def asfreq( self, freq: Frequency, method: FillnaOptions | None = None, - how: str | None = None, + how: Literal["start", "end"] | None = None, normalize: bool_t = False, fill_value: Hashable = None, ) -> Self: @@ -8593,10 +8632,10 @@ def resample( self, rule, axis: Axis | lib.NoDefault = lib.no_default, - closed: str | None = None, - label: str | None = None, - convention: str = "start", - kind: str | None = None, + closed: Literal["right", "left"] | None = None, + label: Literal["right", "left"] | None = None, + convention: Literal["start", "end", "s", "e"] = "start", + kind: Literal["timestamp", "period"] | None = None, on: Level = None, level: Level = None, origin: str | TimestampConvertibleTypes = "start_day", @@ -9153,9 +9192,9 @@ def last(self, offset) -> Self: def rank( self, axis: Axis = 0, - method: str = "average", + method: Literal["average", "min", "max", "first", "dense"] = "average", numeric_only: bool_t = False, - na_option: str = "keep", + na_option: Literal["keep", "top", "bottom"] = "keep", ascending: bool_t = True, pct: bool_t = False, ) -> Self: @@ -9970,6 +10009,7 @@ def where( ) -> Self | None: ... + @final @doc( klass=_shared_doc_kwargs["klass"], cond="True", @@ -10162,6 +10202,7 @@ def mask( ) -> Self | None: ... + @final @doc( where, klass=_shared_doc_kwargs["klass"], @@ -10342,6 +10383,7 @@ def shift( result = self.set_axis(new_ax, axis=axis) return result.__finalize__(self, method="shift") + @final def truncate( self, before=None, @@ -11499,7 +11541,7 @@ def rolling( win_type: str | None = None, on: str | None = None, axis: Axis | lib.NoDefault = lib.no_default, - closed: str | None = None, + closed: IntervalClosedType | None = None, step: int | None = None, method: str = "single", ) -> Window | Rolling: @@ -11558,7 +11600,7 @@ def expanding( self, min_periods: int = 1, axis: Axis | lib.NoDefault = lib.no_default, - method: str = "single", + method: Literal["single", "table"] = "single", ) -> Expanding: if axis is not lib.no_default: axis = self._get_axis_number(axis) @@ -11596,7 +11638,7 @@ def ewm( ignore_na: bool_t = False, axis: Axis | lib.NoDefault = lib.no_default, times: np.ndarray | DataFrame | Series | None = None, - method: str = "single", + method: Literal["single", "table"] = "single", ) -> ExponentialMovingWindow: if axis is not lib.no_default: axis = self._get_axis_number(axis) @@ -11667,46 +11709,56 @@ def _inplace_method(self, other, op) -> Self: ) return self + @final def __iadd__(self, other) -> Self: # error: Unsupported left operand type for + ("Type[NDFrame]") return self._inplace_method(other, type(self).__add__) # type: ignore[operator] + @final def __isub__(self, other) -> Self: # error: Unsupported left operand type for - ("Type[NDFrame]") return self._inplace_method(other, type(self).__sub__) # type: ignore[operator] + @final def __imul__(self, other) -> Self: # error: Unsupported left operand type for * ("Type[NDFrame]") return self._inplace_method(other, type(self).__mul__) # type: ignore[operator] + @final def __itruediv__(self, other) -> Self: # error: Unsupported left operand type for / ("Type[NDFrame]") return self._inplace_method( other, type(self).__truediv__ # type: ignore[operator] ) + @final def __ifloordiv__(self, other) -> Self: # error: Unsupported left operand type for // ("Type[NDFrame]") return self._inplace_method( other, type(self).__floordiv__ # type: ignore[operator] ) + @final def __imod__(self, other) -> Self: # error: Unsupported left operand type for % ("Type[NDFrame]") return self._inplace_method(other, type(self).__mod__) # type: ignore[operator] + @final def __ipow__(self, other) -> Self: # error: Unsupported left operand type for ** ("Type[NDFrame]") return self._inplace_method(other, type(self).__pow__) # type: ignore[operator] + @final def __iand__(self, other) -> Self: # error: Unsupported left operand type for & ("Type[NDFrame]") return self._inplace_method(other, type(self).__and__) # type: ignore[operator] + @final def __ior__(self, other) -> Self: # error: Unsupported left operand type for | ("Type[NDFrame]") return self._inplace_method(other, type(self).__or__) # type: ignore[operator] + @final def __ixor__(self, other) -> Self: # error: Unsupported left operand type for ^ ("Type[NDFrame]") return self._inplace_method(other, type(self).__xor__) # type: ignore[operator] From 2549d57eed5cb18b467f3d8e86c8475c8e0af052 Mon Sep 17 00:00:00 2001 From: Guillaume Mollard Date: Mon, 24 Apr 2023 17:16:08 +0200 Subject: [PATCH 5/7] fix type --- pandas/core/dtypes/dtypes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/dtypes/dtypes.py b/pandas/core/dtypes/dtypes.py index 71dbb5d02bb0c..7d495fb3d4fc7 100644 --- a/pandas/core/dtypes/dtypes.py +++ b/pandas/core/dtypes/dtypes.py @@ -1138,7 +1138,7 @@ def __new__(cls, subtype=None, closed: IntervalClosedType | None = None): "'closed' keyword does not match value " "specified in dtype string" ) - closed = gd["closed"] + closed: IntervalClosedType = gd["closed"] try: subtype = pandas_dtype(subtype) From e1e8ae51df8fe8d632a04d34020cf4f438615038 Mon Sep 17 00:00:00 2001 From: Guillaume Mollard Date: Mon, 24 Apr 2023 18:42:08 +0200 Subject: [PATCH 6/7] remove type check in dtypes.py as it creates unconsistency --- pandas/core/dtypes/dtypes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/core/dtypes/dtypes.py b/pandas/core/dtypes/dtypes.py index 7d495fb3d4fc7..01d09ebc56afd 100644 --- a/pandas/core/dtypes/dtypes.py +++ b/pandas/core/dtypes/dtypes.py @@ -1100,7 +1100,7 @@ class IntervalDtype(PandasExtensionDtype): _cache_dtypes: dict[str_type, PandasExtensionDtype] = {} - def __new__(cls, subtype=None, closed: IntervalClosedType | None = None): + def __new__(cls, subtype=None, closed=None): from pandas.core.dtypes.common import ( is_string_dtype, pandas_dtype, @@ -1138,7 +1138,7 @@ def __new__(cls, subtype=None, closed: IntervalClosedType | None = None): "'closed' keyword does not match value " "specified in dtype string" ) - closed: IntervalClosedType = gd["closed"] + closed = gd["closed"] try: subtype = pandas_dtype(subtype) From 7bc058c7356c030069138d9b72599919ec2bed31 Mon Sep 17 00:00:00 2001 From: Guillaume Mollard Date: Tue, 25 Apr 2023 10:59:14 +0200 Subject: [PATCH 7/7] set type in dtypes.py and ignore assignment to avoid mypy error --- pandas/core/dtypes/dtypes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/core/dtypes/dtypes.py b/pandas/core/dtypes/dtypes.py index 01d09ebc56afd..014d7a4c5a330 100644 --- a/pandas/core/dtypes/dtypes.py +++ b/pandas/core/dtypes/dtypes.py @@ -1100,7 +1100,7 @@ class IntervalDtype(PandasExtensionDtype): _cache_dtypes: dict[str_type, PandasExtensionDtype] = {} - def __new__(cls, subtype=None, closed=None): + def __new__(cls, subtype=None, closed: IntervalClosedType | None = None): from pandas.core.dtypes.common import ( is_string_dtype, pandas_dtype, @@ -1138,7 +1138,7 @@ def __new__(cls, subtype=None, closed=None): "'closed' keyword does not match value " "specified in dtype string" ) - closed = gd["closed"] + closed = gd["closed"] # type: ignore[assignment] try: subtype = pandas_dtype(subtype)