diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 8470ef7ba5efb..255c45d5a45aa 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -49,6 +49,7 @@ TimedeltaConvertibleTypes, TimestampConvertibleTypes, ValueKeyFunc, + final, ) from pandas.compat._optional import import_optional_dependency from pandas.compat.numpy import function as nv @@ -240,6 +241,7 @@ def attrs(self) -> Dict[Optional[Hashable], Any]: def attrs(self, value: Mapping[Optional[Hashable], Any]) -> None: self._attrs = dict(value) + @final @property def flags(self) -> Flags: """ @@ -280,6 +282,7 @@ def flags(self) -> Flags: """ return self._flags + @final def set_flags( self: FrameOrSeries, *, @@ -330,6 +333,7 @@ def set_flags( df.flags["allows_duplicate_labels"] = allows_duplicate_labels return df + @final @classmethod def _validate_dtype(cls, dtype): """ validate the passed dtype """ @@ -375,6 +379,7 @@ def _constructor_expanddim(self): # ---------------------------------------------------------------------- # Internals + @final @property def _data(self): # GH#33054 retained because some downstream packages uses this, @@ -405,12 +410,14 @@ def _AXIS_NAMES(self) -> Dict[int, str]: warnings.warn("_AXIS_NAMES has been deprecated.", FutureWarning, stacklevel=3) return {0: "index"} + @final def _construct_axes_dict(self, axes=None, **kwargs): """Return an axes dictionary for myself.""" d = {a: self._get_axis(a) for a in (axes or self._AXIS_ORDERS)} d.update(kwargs) return d + @final @classmethod def _construct_axes_from_arguments( cls, args, kwargs, require_all: bool = False, sentinel=None @@ -442,6 +449,7 @@ def _construct_axes_from_arguments( axes = {a: kwargs.pop(a, sentinel) for a in cls._AXIS_ORDERS} return axes, kwargs + @final @classmethod def _get_axis_number(cls, axis: Axis) -> int: try: @@ -449,16 +457,19 @@ def _get_axis_number(cls, axis: Axis) -> int: except KeyError: raise ValueError(f"No axis named {axis} for object type {cls.__name__}") + @final @classmethod def _get_axis_name(cls, axis: Axis) -> str: axis_number = cls._get_axis_number(axis) return cls._AXIS_ORDERS[axis_number] + @final def _get_axis(self, axis: Axis) -> Index: axis_number = self._get_axis_number(axis) assert axis_number in {0, 1} return self.index if axis_number == 0 else self.columns + @final @classmethod def _get_block_manager_axis(cls, axis: Axis) -> int: """Map the axis to the block_manager axis.""" @@ -468,6 +479,7 @@ def _get_block_manager_axis(cls, axis: Axis) -> int: return m - axis return axis + @final def _get_axis_resolvers(self, axis: str) -> Dict[str, Union[Series, MultiIndex]]: # index or columns axis_index = getattr(self, axis) @@ -498,6 +510,7 @@ def _get_axis_resolvers(self, axis: str) -> Dict[str, Union[Series, MultiIndex]] d[axis] = dindex return d + @final def _get_index_resolvers(self) -> Dict[str, Union[Series, MultiIndex]]: from pandas.core.computation.parsing import clean_column_name @@ -507,6 +520,7 @@ def _get_index_resolvers(self) -> Dict[str, Union[Series, MultiIndex]]: return {clean_column_name(k): v for k, v in d.items() if not isinstance(k, int)} + @final def _get_cleaned_column_resolvers(self) -> Dict[str, ABCSeries]: """ Return the special character free column resolvers of a dataframe. @@ -596,11 +610,13 @@ def size(self) -> int: """ return np.prod(self.shape) + @final @property def _selected_obj(self: FrameOrSeries) -> FrameOrSeries: """ internal compat with SelectionMixin """ return self + @final @property def _obj_with_exclusions(self: FrameOrSeries) -> FrameOrSeries: """ internal compat with SelectionMixin """ @@ -636,6 +652,7 @@ def set_axis(self, labels, axis: Axis = 0, inplace: bool = False): self._check_inplace_and_allows_duplicate_labels(inplace) return self._set_axis_nocheck(labels, axis, inplace) + @final def _set_axis_nocheck(self, labels, axis: Axis, inplace: bool): # NDFrame.rename with inplace=False calls set_axis(inplace=True) on a copy. if inplace: @@ -650,6 +667,7 @@ def _set_axis(self, axis: int, labels: Index) -> None: self._mgr.set_axis(axis, labels) self._clear_item_cache() + @final def swapaxes(self: FrameOrSeries, axis1, axis2, copy=True) -> FrameOrSeries: """ Interchange axes and swap values axes appropriately. @@ -679,6 +697,7 @@ def swapaxes(self: FrameOrSeries, axis1, axis2, copy=True) -> FrameOrSeries: new_values, *new_axes # type: ignore[arg-type] ).__finalize__(self, method="swapaxes") + @final def droplevel(self: FrameOrSeries, level, axis=0) -> FrameOrSeries: """ Return DataFrame with requested index / column level(s) removed. @@ -751,6 +770,7 @@ def pop(self, item: Label) -> Union[Series, Any]: return result + @final def squeeze(self, axis=None): """ Squeeze 1 dimensional axis objects into scalars. @@ -1215,6 +1235,7 @@ class name if not inplace: return result + @final def _set_axis_name(self, name, axis=0, inplace=False): """ Set the name(s) of the axis. @@ -1277,11 +1298,13 @@ def _set_axis_name(self, name, axis=0, inplace=False): # ---------------------------------------------------------------------- # Comparison Methods + @final def _indexed_same(self, other) -> bool: return all( self._get_axis(a).equals(other._get_axis(a)) for a in self._AXIS_ORDERS ) + @final def equals(self, other: object) -> bool: """ Test whether two objects contain the same elements. @@ -1368,6 +1391,7 @@ def equals(self, other: object) -> bool: # ------------------------------------------------------------------------- # Unary Methods + @final def __neg__(self): values = self._values if is_bool_dtype(values): @@ -1382,6 +1406,7 @@ def __neg__(self): raise TypeError(f"Unary negative expects numeric dtype, not {values.dtype}") return self.__array_wrap__(arr) + @final def __pos__(self): values = self._values if is_bool_dtype(values): @@ -1399,6 +1424,7 @@ def __pos__(self): ) return self.__array_wrap__(arr) + @final def __invert__(self): if not self.size: # inv fails with 0 len @@ -1408,6 +1434,7 @@ def __invert__(self): result = self._constructor(new_data).__finalize__(self, method="__invert__") return result + @final def __nonzero__(self): raise ValueError( f"The truth value of a {type(self).__name__} is ambiguous. " @@ -1416,6 +1443,7 @@ def __nonzero__(self): __bool__ = __nonzero__ + @final def bool(self): """ Return the bool of a single element Series or DataFrame. @@ -1460,9 +1488,11 @@ def bool(self): self.__nonzero__() + @final def __abs__(self: FrameOrSeries) -> FrameOrSeries: return self.abs() + @final def __round__(self: FrameOrSeries, decimals: int = 0) -> FrameOrSeries: return self.round(decimals) @@ -1474,6 +1504,7 @@ def __round__(self: FrameOrSeries, decimals: int = 0) -> FrameOrSeries: # operations should utilize/extend these methods when possible so that we # have consistent precedence and validation logic throughout the library. + @final def _is_level_reference(self, key, axis=0): """ Test whether a key is a level reference for a given axis. @@ -1504,6 +1535,7 @@ def _is_level_reference(self, key, axis=0): and not self._is_label_reference(key, axis=axis) ) + @final def _is_label_reference(self, key, axis=0) -> bool_t: """ Test whether a key is a label reference for a given axis. @@ -1533,6 +1565,7 @@ def _is_label_reference(self, key, axis=0) -> bool_t: and any(key in self.axes[ax] for ax in other_axes) ) + @final def _is_label_or_level_reference(self, key: str, axis: int = 0) -> bool_t: """ Test whether a key is a label or level reference for a given axis. @@ -1557,6 +1590,7 @@ def _is_label_or_level_reference(self, key: str, axis: int = 0) -> bool_t: key, axis=axis ) + @final def _check_label_or_level_ambiguity(self, key, axis: int = 0) -> None: """ Check whether `key` is ambiguous. @@ -1600,6 +1634,7 @@ def _check_label_or_level_ambiguity(self, key, axis: int = 0) -> None: ) raise ValueError(msg) + @final def _get_label_or_level_values(self, key: str, axis: int = 0) -> np.ndarray: """ Return a 1-D array of values associated with `key`, a label or level @@ -1664,6 +1699,7 @@ def _get_label_or_level_values(self, key: str, axis: int = 0) -> np.ndarray: return values + @final def _drop_labels_or_levels(self, keys, axis: int = 0): """ Drop labels and/or levels for the given `axis`. @@ -1794,6 +1830,7 @@ def __len__(self) -> int: """Returns length of info axis""" return len(self._info_axis) + @final def __contains__(self, key) -> bool_t: """True if the key is in the info axis""" return key in self._info_axis @@ -1901,6 +1938,7 @@ def __array_wrap__( # ---------------------------------------------------------------------- # Picklability + @final def __getstate__(self) -> Dict[str, Any]: meta = {k: getattr(self, k, None) for k in self._metadata} return dict( @@ -1912,6 +1950,7 @@ def __getstate__(self) -> Dict[str, Any]: **meta, ) + @final def __setstate__(self, state): if isinstance(state, BlockManager): self._mgr = state @@ -1956,6 +1995,7 @@ def __repr__(self) -> str: prepr = f"[{','.join(map(pprint_thing, self))}]" return f"{type(self).__name__}({prepr})" + @final def _repr_latex_(self): """ Returns a LaTeX representation for a particular object. @@ -1966,6 +2006,7 @@ def _repr_latex_(self): else: return None + @final def _repr_data_resource_(self): """ Not a real Jupyter special repr method, but we use the same @@ -1982,6 +2023,7 @@ def _repr_data_resource_(self): # ---------------------------------------------------------------------- # I/O Methods + @final @doc(klass="object") def to_excel( self, @@ -2134,6 +2176,7 @@ def to_excel( engine=engine, ) + @final def to_json( self, path_or_buf: Optional[FilePathOrBuffer] = None, @@ -2421,6 +2464,7 @@ def to_json( storage_options=storage_options, ) + @final def to_hdf( self, path_or_buf, @@ -2562,6 +2606,7 @@ def to_hdf( encoding=encoding, ) + @final def to_sql( self, name: str, @@ -2729,6 +2774,7 @@ def to_sql( method=method, ) + @final def to_pickle( self, path, @@ -2806,6 +2852,7 @@ def to_pickle( storage_options=storage_options, ) + @final def to_clipboard( self, excel: bool_t = True, sep: Optional[str] = None, **kwargs ) -> None: @@ -2867,6 +2914,7 @@ def to_clipboard( clipboards.to_clipboard(self, excel=excel, sep=sep, **kwargs) + @final def to_xarray(self): """ Return an xarray object from the pandas object. @@ -2950,6 +2998,7 @@ class (index) object 'bird' 'bird' 'mammal' 'mammal' else: return xarray.Dataset.from_dataframe(self) + @final @doc(returns=fmt.return_docstring) def to_latex( self, @@ -3135,6 +3184,7 @@ def to_latex( position=position, ) + @final def to_csv( self, path_or_buf: Optional[FilePathOrBuffer] = None, @@ -3344,6 +3394,7 @@ def to_csv( # ---------------------------------------------------------------------- # Lookup Caching + @final def _set_as_cached(self, item, cacher) -> None: """ Set the _cacher attribute on the calling object with a weakref to @@ -3351,6 +3402,7 @@ def _set_as_cached(self, item, cacher) -> None: """ self._cacher = (item, weakref.ref(cacher)) + @final def _reset_cacher(self) -> None: """ Reset the cacher. @@ -3358,6 +3410,7 @@ def _reset_cacher(self) -> None: if hasattr(self, "_cacher"): del self._cacher + @final def _maybe_cache_changed(self, item, value) -> None: """ The object has called back to us saying maybe it has changed. @@ -3365,11 +3418,13 @@ def _maybe_cache_changed(self, item, value) -> None: loc = self._info_axis.get_loc(item) self._mgr.iset(loc, value) + @final @property def _is_cached(self) -> bool_t: """Return boolean indicating if self is cached or not.""" return getattr(self, "_cacher", None) is not None + @final def _get_cacher(self): """return my cacher or None""" cacher = getattr(self, "_cacher", None) @@ -3377,6 +3432,7 @@ def _get_cacher(self): cacher = cacher[1]() return cacher + @final def _maybe_update_cacher( self, clear: bool_t = False, verify_is_copy: bool_t = True ) -> None: @@ -3414,6 +3470,7 @@ def _maybe_update_cacher( if clear: self._clear_item_cache() + @final def _clear_item_cache(self) -> None: self._item_cache.clear() @@ -3519,6 +3576,7 @@ class max_speed ) return self._constructor(new_data).__finalize__(self, method="take") + @final def _take_with_is_copy(self: FrameOrSeries, indices, axis=0) -> FrameOrSeries: """ Internal version of the `take` method that sets the `_is_copy` @@ -3533,6 +3591,7 @@ def _take_with_is_copy(self: FrameOrSeries, indices, axis=0) -> FrameOrSeries: result._set_is_copy(self) return result + @final def xs(self, key, axis=0, level=None, drop_level: bool_t = True): """ Return cross-section from the Series/DataFrame. @@ -3701,6 +3760,7 @@ class animal locomotion def __getitem__(self, item): raise AbstractMethodError(self) + @final def _get_item_cache(self, item): """Return the cached item, item represents a label indexer.""" cache = self._item_cache @@ -3751,6 +3811,7 @@ def _set_item(self, key, value) -> None: NDFrame._iset_item(self, loc, value) + @final def _set_is_copy(self, ref, copy: bool_t = True) -> None: if not copy: self._is_copy = None @@ -3758,6 +3819,7 @@ def _set_is_copy(self, ref, copy: bool_t = True) -> None: assert ref is not None self._is_copy = weakref.ref(ref) + @final def _check_is_chained_assignment_possible(self) -> bool_t: """ Check if we are a view, have a cacher, and are of mixed type. @@ -3778,6 +3840,7 @@ def _check_is_chained_assignment_possible(self) -> bool_t: self._check_setitem_copy(stacklevel=4, t="referent") return False + @final def _check_setitem_copy(self, stacklevel=4, t="setting", force=False): """ @@ -3892,6 +3955,7 @@ def __delitem__(self, key) -> None: # ---------------------------------------------------------------------- # Unsorted + @final def _check_inplace_and_allows_duplicate_labels(self, inplace): if inplace and not self.flags.allows_duplicate_labels: raise ValueError( @@ -3899,6 +3963,7 @@ def _check_inplace_and_allows_duplicate_labels(self, inplace): "'self.flags.allows_duplicate_labels' is False." ) + @final def get(self, key, default=None): """ Get item from object for given key (ex: DataFrame column). @@ -3918,11 +3983,13 @@ def get(self, key, default=None): except (KeyError, ValueError, IndexError): return default + @final @property def _is_view(self) -> bool_t: """Return boolean indicating if self is view of another array """ return self._mgr.is_view + @final def reindex_like( self: FrameOrSeries, other, @@ -4070,6 +4137,7 @@ def drop( else: return obj + @final def _drop_axis( self: FrameOrSeries, labels, axis, level=None, errors: str = "raise" ) -> FrameOrSeries: @@ -4125,6 +4193,7 @@ def _drop_axis( return result + @final def _update_inplace(self, result, verify_is_copy: bool_t = True) -> None: """ Replace self internals with result. @@ -4142,6 +4211,7 @@ def _update_inplace(self, result, verify_is_copy: bool_t = True) -> None: self._mgr = result._mgr self._maybe_update_cacher(verify_is_copy=verify_is_copy) + @final def add_prefix(self: FrameOrSeries, prefix: str) -> FrameOrSeries: """ Prefix labels with string `prefix`. @@ -4205,6 +4275,7 @@ def add_prefix(self: FrameOrSeries, prefix: str) -> FrameOrSeries: # "**Dict[str, partial[str]]"; expected "Union[str, int, None]" return self.rename(**mapper) # type: ignore[return-value, arg-type] + @final def add_suffix(self: FrameOrSeries, suffix: str) -> FrameOrSeries: """ Suffix labels with string `suffix`. @@ -4719,6 +4790,7 @@ def reindex(self: FrameOrSeries, *args, **kwargs) -> FrameOrSeries: axes, level, limit, tolerance, method, fill_value, copy ).__finalize__(self, method="reindex") + @final def _reindex_axes( self: FrameOrSeries, axes, level, limit, tolerance, method, fill_value, copy ) -> FrameOrSeries: @@ -4744,6 +4816,7 @@ def _reindex_axes( return obj + @final def _needs_reindex_multi(self, axes, method, level) -> bool_t: """Check if we do need a multi reindex.""" return ( @@ -4756,6 +4829,7 @@ def _needs_reindex_multi(self, axes, method, level) -> bool_t: def _reindex_multi(self, axes, copy, fill_value): raise AbstractMethodError(self) + @final def _reindex_with_indexers( self: FrameOrSeries, reindexers, @@ -4897,6 +4971,7 @@ def f(x) -> bool: else: raise TypeError("Must pass either `items`, `like`, or `regex`") + @final def head(self: FrameOrSeries, n: int = 5) -> FrameOrSeries: """ Return the first `n` rows. @@ -4969,6 +5044,7 @@ def head(self: FrameOrSeries, n: int = 5) -> FrameOrSeries: """ return self.iloc[:n] + @final def tail(self: FrameOrSeries, n: int = 5) -> FrameOrSeries: """ Return the last `n` rows. @@ -5043,6 +5119,7 @@ def tail(self: FrameOrSeries, n: int = 5) -> FrameOrSeries: return self.iloc[0:0] return self.iloc[-n:] + @final def sample( self: FrameOrSeries, n=None, @@ -5251,6 +5328,7 @@ def sample( locs = rs.choice(axis_length, size=n, replace=replace, p=weights) return self.take(locs, axis=axis) + @final @doc(klass=_shared_doc_kwargs["klass"]) def pipe(self, func, *args, **kwargs): r""" @@ -5308,6 +5386,7 @@ def pipe(self, func, *args, **kwargs): # ---------------------------------------------------------------------- # Attribute access + @final def __finalize__( self: FrameOrSeries, other, method: Optional[str] = None, **kwargs ) -> FrameOrSeries: @@ -5404,6 +5483,7 @@ def __setattr__(self, name: str, value) -> None: ) object.__setattr__(self, name, value) + @final def _dir_additions(self) -> Set[str]: """ add the string-like attributes from the info_axis. @@ -5417,6 +5497,7 @@ def _dir_additions(self) -> Set[str]: # ---------------------------------------------------------------------- # Consolidation of internals + @final def _protect_consolidate(self, f): """ Consolidate _mgr -- if the blocks have changed, then clear the @@ -5428,6 +5509,7 @@ def _protect_consolidate(self, f): self._clear_item_cache() return result + @final def _consolidate_inplace(self) -> None: """Consolidate data in place and return None""" @@ -5436,6 +5518,7 @@ def f(): self._protect_consolidate(f) + @final def _consolidate(self): """ Compute NDFrame with "consolidated" internals (data of each dtype @@ -5449,6 +5532,7 @@ def _consolidate(self): cons_data = self._protect_consolidate(f) return self._constructor(cons_data).__finalize__(self) + @final @property def _is_mixed_type(self) -> bool_t: if self._mgr.is_single_block: @@ -5461,6 +5545,7 @@ def _is_mixed_type(self) -> bool_t: return self.dtypes.nunique() > 1 + @final def _check_inplace_setting(self, value) -> bool_t: """ check whether we allow in-place setting with this type of value """ if self._is_mixed_type: @@ -5477,9 +5562,11 @@ def _check_inplace_setting(self, value) -> bool_t: return True + @final def _get_numeric_data(self): return self._constructor(self._mgr.get_numeric_data()).__finalize__(self) + @final def _get_bool_data(self): return self._constructor(self._mgr.get_bool_data()).__finalize__(self) @@ -5599,6 +5686,7 @@ def dtypes(self): data = self._mgr.get_dtypes() return self._constructor_sliced(data, index=self._info_axis, dtype=np.object_) + @final def _to_dict_of_blocks(self, copy: bool_t = True): """ Return a dict of dtype -> Constructor Types that @@ -5776,6 +5864,7 @@ def astype( result.columns = self.columns return result + @final def copy(self: FrameOrSeries, deep: bool_t = True) -> FrameOrSeries: """ Make a copy of this object's indices and data. @@ -5885,9 +5974,11 @@ def copy(self: FrameOrSeries, deep: bool_t = True) -> FrameOrSeries: self._clear_item_cache() return self._constructor(data).__finalize__(self, method="copy") + @final def __copy__(self: FrameOrSeries, deep: bool_t = True) -> FrameOrSeries: return self.copy(deep=deep) + @final def __deepcopy__(self: FrameOrSeries, memo=None) -> FrameOrSeries: """ Parameters @@ -5897,6 +5988,7 @@ def __deepcopy__(self: FrameOrSeries, memo=None) -> FrameOrSeries: """ return self.copy(deep=True) + @final def _convert( self: FrameOrSeries, datetime: bool_t = False, @@ -5938,6 +6030,7 @@ def _convert( ) ).__finalize__(self) + @final def infer_objects(self: FrameOrSeries) -> FrameOrSeries: """ Attempt to infer better dtypes for object columns. @@ -5985,6 +6078,7 @@ def infer_objects(self: FrameOrSeries) -> FrameOrSeries: ) ).__finalize__(self, method="infer_objects") + @final def convert_dtypes( self: FrameOrSeries, infer_objects: bool_t = True, @@ -6309,6 +6403,7 @@ def fillna( else: return result.__finalize__(self, method="fillna") + @final def ffill( self: FrameOrSeries, axis=None, @@ -6330,6 +6425,7 @@ def ffill( pad = ffill + @final def bfill( self: FrameOrSeries, axis=None, @@ -6805,6 +6901,7 @@ def replace( else: return result.__finalize__(self, method="replace") + @final def interpolate( self: FrameOrSeries, method: str = "linear", @@ -7103,6 +7200,7 @@ def interpolate( # ---------------------------------------------------------------------- # Timeseries methods Methods + @final def asof(self, where, subset=None): """ Return the last row(s) without any NaNs before `where`. @@ -7407,6 +7505,7 @@ def notna(self: FrameOrSeries) -> FrameOrSeries: def notnull(self: FrameOrSeries) -> FrameOrSeries: return notna(self).__finalize__(self, method="notnull") + @final def _clip_with_scalar(self, lower, upper, inplace: bool_t = False): if (lower is not None and np.any(isna(lower))) or ( upper is not None and np.any(isna(upper)) @@ -7432,6 +7531,7 @@ def _clip_with_scalar(self, lower, upper, inplace: bool_t = False): else: return result + @final def _clip_with_one_bound(self, threshold, method, axis, inplace): if axis is not None: @@ -7455,6 +7555,7 @@ def _clip_with_one_bound(self, threshold, method, axis, inplace): threshold = align_method_FRAME(self, threshold, axis, flex=None)[1] return self.where(subset, threshold, axis=axis, inplace=inplace) + @final def clip( self: FrameOrSeries, lower=None, @@ -7581,6 +7682,7 @@ def clip( return result + @final def asfreq( self: FrameOrSeries, freq, @@ -7692,6 +7794,7 @@ def asfreq( fill_value=fill_value, ) + @final def at_time( self: FrameOrSeries, time, asof: bool_t = False, axis=None ) -> FrameOrSeries: @@ -7750,6 +7853,7 @@ def at_time( indexer = index.indexer_at_time(time, asof=asof) return self._take_with_is_copy(indexer, axis=axis) + @final def between_time( self: FrameOrSeries, start_time, @@ -7834,6 +7938,7 @@ def between_time( ) return self._take_with_is_copy(indexer, axis=axis) + @final def resample( self, rule, @@ -8235,6 +8340,7 @@ def resample( offset=offset, ) + @final def first(self: FrameOrSeries, offset) -> FrameOrSeries: """ Select initial periods of time series data based on a date offset. @@ -8303,6 +8409,7 @@ def first(self: FrameOrSeries, offset) -> FrameOrSeries: return self.loc[:end] + @final def last(self: FrameOrSeries, offset) -> FrameOrSeries: """ Select final periods of time series data based on a date offset. @@ -8366,6 +8473,7 @@ def last(self: FrameOrSeries, offset) -> FrameOrSeries: start = self.index.searchsorted(start_date, side="right") return self.iloc[start:] + @final def rank( self: FrameOrSeries, axis=0, @@ -8686,6 +8794,7 @@ def align( else: # pragma: no cover raise TypeError(f"unsupported type: {type(other)}") + @final def _align_frame( self, other, @@ -8755,6 +8864,7 @@ def _align_frame( right.__finalize__(other), ) + @final def _align_series( self, other, @@ -8846,6 +8956,7 @@ def _align_series( right.__finalize__(other), ) + @final def _where( self, cond, @@ -8993,6 +9104,7 @@ def _where( result = self._constructor(new_data) return result.__finalize__(self) + @final @doc( klass=_shared_doc_kwargs["klass"], cond="True", @@ -9135,6 +9247,7 @@ def where( cond, other, inplace, axis, level, errors=errors, try_cast=try_cast ) + @final @doc( where, klass=_shared_doc_kwargs["klass"], @@ -9317,6 +9430,7 @@ def shift( result = self.set_axis(new_ax, axis) return result.__finalize__(self, method="shift") + @final def slice_shift(self: FrameOrSeries, periods: int = 1, axis=0) -> FrameOrSeries: """ Equivalent to `shift` without copying data. @@ -9365,6 +9479,7 @@ def slice_shift(self: FrameOrSeries, periods: int = 1, axis=0) -> FrameOrSeries: return new_obj.__finalize__(self, method="slice_shift") + @final def tshift( self: FrameOrSeries, periods: int = 1, freq=None, axis: Axis = 0 ) -> FrameOrSeries: @@ -9571,6 +9686,7 @@ def truncate( return result + @final def tz_convert( self: FrameOrSeries, tz, axis=0, level=None, copy: bool_t = True ) -> FrameOrSeries: @@ -9628,6 +9744,7 @@ def _tz_convert(ax, tz): result = result.set_axis(ax, axis=axis, inplace=False) return result.__finalize__(self, method="tz_convert") + @final def tz_localize( self: FrameOrSeries, tz, @@ -9801,6 +9918,7 @@ def _tz_localize(ax, tz, ambiguous, nonexistent): # ---------------------------------------------------------------------- # Numeric Methods + @final def abs(self: FrameOrSeries) -> FrameOrSeries: """ Return a Series/DataFrame with absolute numeric value of each element. @@ -9870,6 +9988,7 @@ def abs(self: FrameOrSeries) -> FrameOrSeries: """ return np.abs(self) + @final def describe( self: FrameOrSeries, percentiles=None, @@ -10143,7 +10262,7 @@ def describe( formatted_percentiles = format_percentiles(percentiles) - def describe_numeric_1d(series): + def describe_numeric_1d(series) -> "Series": stat_index = ( ["count", "mean", "std", "min"] + formatted_percentiles + ["max"] ) @@ -10154,7 +10273,7 @@ def describe_numeric_1d(series): ) return pd.Series(d, index=stat_index, name=series.name) - def describe_categorical_1d(data): + def describe_categorical_1d(data) -> "Series": names = ["count", "unique"] objcounts = data.value_counts() count_unique = len(objcounts[objcounts != 0]) @@ -10203,7 +10322,7 @@ def describe_categorical_1d(data): return pd.Series(result, index=names, name=data.name, dtype=dtype) - def describe_timestamp_1d(data): + def describe_timestamp_1d(data) -> "Series": # GH-30164 stat_index = ["count", "mean", "min"] + formatted_percentiles + ["max"] d = ( @@ -10213,7 +10332,7 @@ def describe_timestamp_1d(data): ) return pd.Series(d, index=stat_index, name=data.name) - def describe_1d(data): + def describe_1d(data) -> "Series": if is_bool_dtype(data.dtype): return describe_categorical_1d(data) elif is_numeric_dtype(data): @@ -10226,7 +10345,9 @@ def describe_1d(data): return describe_categorical_1d(data) if self.ndim == 1: - return describe_1d(self) + # Incompatible return value type + # (got "Series", expected "FrameOrSeries") [return-value] + return describe_1d(self) # type:ignore[return-value] elif (include is None) and (exclude is None): # when some numerics are found, keep only numerics default_include = [np.number] @@ -10256,6 +10377,7 @@ def describe_1d(data): d.columns = data.columns.copy() return d + @final def pct_change( self: FrameOrSeries, periods=1, @@ -10394,6 +10516,7 @@ def pct_change( rs = rs.reindex_like(data) return rs + @final def _agg_by_level(self, name, axis=0, level=0, skipna=True, **kwargs): if axis is None: raise ValueError("Must specify 'axis' when aggregating by level.") @@ -10405,6 +10528,7 @@ def _agg_by_level(self, name, axis=0, level=0, skipna=True, **kwargs): applyf = lambda x: method(x, axis=axis, skipna=skipna, **kwargs) return grouped.aggregate(applyf) + @final def _logical_func( self, name: str, func, axis=0, bool_only=None, skipna=True, level=None, **kwargs ): @@ -10442,6 +10566,7 @@ def all(self, axis=0, bool_only=None, skipna=True, level=None, **kwargs): "all", nanops.nanall, axis, bool_only, skipna, level, **kwargs ) + @final def _accum_func(self, name: str, func, axis=None, skipna=True, *args, **kwargs): skipna = nv.validate_cum_func_with_skipna(skipna, args, kwargs, name) if axis is None: @@ -10482,6 +10607,7 @@ def cumsum(self, axis=None, skipna=True, *args, **kwargs): def cumprod(self, axis=None, skipna=True, *args, **kwargs): return self._accum_func("cumprod", np.cumprod, axis, skipna, *args, **kwargs) + @final def _stat_function_ddof( self, name: str, @@ -10527,6 +10653,7 @@ def std( "std", nanops.nanstd, axis, skipna, level, ddof, numeric_only, **kwargs ) + @final def _stat_function( self, name: str, @@ -10583,6 +10710,7 @@ def kurt(self, axis=None, skipna=None, level=None, numeric_only=None, **kwargs): kurtosis = kurt + @final def _min_count_stat_function( self, name: str, @@ -11052,6 +11180,7 @@ def min(self, axis=None, skipna=None, level=None, numeric_only=None, **kwargs): # [assignment] cls.min = min # type: ignore[assignment] + @final @doc(Rolling) def rolling( self, @@ -11088,6 +11217,7 @@ def rolling( closed=closed, ) + @final @doc(Expanding) def expanding( self, min_periods: int = 1, center: Optional[bool_t] = None, axis: Axis = 0 @@ -11104,6 +11234,7 @@ def expanding( return Expanding(self, min_periods=min_periods, center=center, axis=axis) + @final @doc(ExponentialMovingWindow) def ewm( self, @@ -11134,6 +11265,7 @@ def ewm( # ---------------------------------------------------------------------- # Arithmetic Methods + @final def _inplace_method(self, other, op): """ Wrap arithmetic method to operate inplace. @@ -11192,6 +11324,7 @@ def __ixor__(self, other): # ---------------------------------------------------------------------- # Misc methods + @final def _find_valid_index(self, how: str): """ Retrieves the index of the first valid value. @@ -11210,6 +11343,7 @@ def _find_valid_index(self, how: str): return None return self.index[idxpos] + @final @doc(position="first", klass=_shared_doc_kwargs["klass"]) def first_valid_index(self): """ @@ -11226,6 +11360,7 @@ def first_valid_index(self): """ return self._find_valid_index("first") + @final @doc(first_valid_index, position="last", klass=_shared_doc_kwargs["klass"]) def last_valid_index(self): return self._find_valid_index("last") diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index 2739806a0f338..9744eb0ecbb88 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -802,7 +802,7 @@ def slice_indexer(self, start=None, end=None, step=None, kind=None): if (start is None or isinstance(start, str)) and ( end is None or isinstance(end, str) ): - mask = True + mask = np.array(True) if start is not None: start_casted = self._maybe_cast_slice_bound(start, "left", kind) mask = start_casted <= self @@ -811,9 +811,7 @@ def slice_indexer(self, start=None, end=None, step=None, kind=None): end_casted = self._maybe_cast_slice_bound(end, "right", kind) mask = (self <= end_casted) & mask - # pandas\core\indexes\datetimes.py:764: error: "bool" has no - # attribute "nonzero" [attr-defined] - indexer = mask.nonzero()[0][::step] # type: ignore[attr-defined] + indexer = mask.nonzero()[0][::step] if len(indexer) == len(self): return slice(None) else: diff --git a/pandas/io/formats/excel.py b/pandas/io/formats/excel.py index 9793f7a1e4613..0916494d8ab60 100644 --- a/pandas/io/formats/excel.py +++ b/pandas/io/formats/excel.py @@ -594,13 +594,13 @@ def _format_header_regular(self): # has incompatible type "Union[Sequence[Optional[Hashable]], # bool]"; expected "Sized" [arg-type] if len(self.header) != len(self.columns): # type: ignore[arg-type] - # pandas\io\formats\excel.py:595: error: Argument 1 to + # pandas\io\formats\excel.py:602: error: Argument 1 to # "len" has incompatible type # "Union[Sequence[Optional[Hashable]], bool]"; expected # "Sized" [arg-type] raise ValueError( - f"Writing {len(self.columns)} " # type: ignore[arg-type] - f"cols but got {len(self.header)} aliases" + f"Writing {len(self.columns)} cols " # type: ignore[arg-type] + f"but got {len(self.header)} aliases" ) else: colnames = self.header