#37527 TYP: use typing.final in indexes.base

Merged jbrockmendel Pseudo commit used to compare (109ee11...bd2d022)
Missing base report.

Unable to compare commits because the base of the pull request did not upload a coverage report.

Changes found in between 109ee11...bd2d022 (pseudo...base) which prevent comparing this pull request.

Showing 17 of 60 files from the diff.
Other files ignored by Codecov
pandas/_typing.py has changed.

@@ -329,8 +329,7 @@
Loading
329 329
                piece = piece.copy()
330 330
                try:
331 331
                    piece[all_key] = margin[key]
332 -
                except TypeError:
333 -
332 +
                except ValueError:
334 333
                    # we cannot reshape, so coerce the axis
335 334
                    piece.set_axis(
336 335
                        piece._get_axis(cat_axis)._to_safe_for_reshape(),

@@ -25,10 +25,12 @@
Loading
25 25
    Parameters
26 26
    ----------
27 27
    arg : str, timedelta, list-like or Series
28 -
        The data to be converted to timedelta.  The character M by itself,
29 -
        e.g. '1M', is treated as minute, not month. The characters Y and y
30 -
        are treated as the mean length of the Gregorian calendar year -
31 -
        365.2425 days or 365 days 5 hours 49 minutes 12 seconds.
28 +
        The data to be converted to timedelta.
29 +
30 +
        .. deprecated:: 1.2
31 +
            Strings with units 'M', 'Y' and 'y' do not represent
32 +
            unambiguous timedelta values and will be removed in a future version
33 +
32 34
    unit : str, optional
33 35
        Denotes the unit of the arg for numeric `arg`. Defaults to ``"ns"``.
34 36

@@ -873,30 +873,14 @@
Loading
873 873
    To learn more about the offsets & frequency strings, please see `this link
874 874
    <https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#offset-aliases>`__.
875 875
876 -
    The recognized win_types are:
877 -
878 -
    * ``boxcar``
879 -
    * ``triang``
880 -
    * ``blackman``
881 -
    * ``hamming``
882 -
    * ``bartlett``
883 -
    * ``parzen``
884 -
    * ``bohman``
885 -
    * ``blackmanharris``
886 -
    * ``nuttall``
887 -
    * ``barthann``
888 -
    * ``kaiser`` (needs parameter: beta)
889 -
    * ``gaussian`` (needs parameter: std)
890 -
    * ``general_gaussian`` (needs parameters: power, width)
891 -
    * ``slepian`` (needs parameter: width)
892 -
    * ``exponential`` (needs parameter: tau), center is set to None.
893 -
894 -
    If ``win_type=None`` all points are evenly weighted. To learn more about
895 -
    different window types see `scipy.signal window functions
876 +
    If ``win_type=None``, all points are evenly weighted; otherwise, ``win_type``
877 +
    can accept a string of any `scipy.signal window function
896 878
    <https://docs.scipy.org/doc/scipy/reference/signal.windows.html#module-scipy.signal.windows>`__.
897 879
898 -
    Certain window types require additional parameters to be passed. Please see
899 -
    the third example below on how to add the additional parameters.
880 +
    Certain Scipy window types require additional parameters to be passed
881 +
    in the aggregation function. The additional parameters must match
882 +
    the keywords specified in the Scipy window type method signature.
883 +
    Please see the third example below on how to add the additional parameters.
900 884
901 885
    Examples
902 886
    --------
@@ -1000,71 +984,22 @@
Loading
1000 984
    def validate(self):
1001 985
        super().validate()
1002 986
1003 -
        window = self.window
1004 -
        if isinstance(window, BaseIndexer):
987 +
        if isinstance(self.window, BaseIndexer):
1005 988
            raise NotImplementedError(
1006 989
                "BaseIndexer subclasses not implemented with win_types."
1007 990
            )
1008 -
        elif isinstance(window, (list, tuple, np.ndarray)):
1009 -
            pass
1010 -
        elif is_integer(window):
1011 -
            if window <= 0:
991 +
        elif is_integer(self.window):
992 +
            if self.window <= 0:
1012 993
                raise ValueError("window must be > 0 ")
1013 -
            import_optional_dependency(
1014 -
                "scipy", extra="Scipy is required to generate window weight."
994 +
            sig = import_optional_dependency(
995 +
                "scipy.signal", extra="Scipy is required to generate window weight."
1015 996
            )
1016 -
            import scipy.signal as sig
1017 -
1018 997
            if not isinstance(self.win_type, str):
1019 998
                raise ValueError(f"Invalid win_type {self.win_type}")
1020 999
            if getattr(sig, self.win_type, None) is None:
1021 1000
                raise ValueError(f"Invalid win_type {self.win_type}")
1022 1001
        else:
1023 -
            raise ValueError(f"Invalid window {window}")
1024 -
1025 -
    def _get_win_type(self, kwargs: Dict[str, Any]) -> Union[str, Tuple]:
1026 -
        """
1027 -
        Extract arguments for the window type, provide validation for it
1028 -
        and return the validated window type.
1029 -
1030 -
        Parameters
1031 -
        ----------
1032 -
        kwargs : dict
1033 -
1034 -
        Returns
1035 -
        -------
1036 -
        win_type : str, or tuple
1037 -
        """
1038 -
        # the below may pop from kwargs
1039 -
        def _validate_win_type(win_type, kwargs):
1040 -
            arg_map = {
1041 -
                "kaiser": ["beta"],
1042 -
                "gaussian": ["std"],
1043 -
                "general_gaussian": ["power", "width"],
1044 -
                "slepian": ["width"],
1045 -
                "exponential": ["tau"],
1046 -
            }
1047 -
1048 -
            if win_type in arg_map:
1049 -
                win_args = _pop_args(win_type, arg_map[win_type], kwargs)
1050 -
                if win_type == "exponential":
1051 -
                    # exponential window requires the first arg (center)
1052 -
                    # to be set to None (necessary for symmetric window)
1053 -
                    win_args.insert(0, None)
1054 -
1055 -
                return tuple([win_type] + win_args)
1056 -
1057 -
            return win_type
1058 -
1059 -
        def _pop_args(win_type, arg_names, kwargs):
1060 -
            all_args = []
1061 -
            for n in arg_names:
1062 -
                if n not in kwargs:
1063 -
                    raise ValueError(f"{win_type} window requires {n}")
1064 -
                all_args.append(kwargs.pop(n))
1065 -
            return all_args
1066 -
1067 -
        return _validate_win_type(self.win_type, kwargs)
1002 +
            raise ValueError(f"Invalid window {self.window}")
1068 1003
1069 1004
    def _center_window(self, result: np.ndarray, offset: int) -> np.ndarray:
1070 1005
        """
@@ -1079,31 +1014,6 @@
Loading
1079 1014
            result = np.copy(result[tuple(lead_indexer)])
1080 1015
        return result
1081 1016
1082 -
    def _get_window_weights(
1083 -
        self, win_type: Optional[Union[str, Tuple]] = None
1084 -
    ) -> np.ndarray:
1085 -
        """
1086 -
        Get the window, weights.
1087 -
1088 -
        Parameters
1089 -
        ----------
1090 -
        win_type : str, or tuple
1091 -
            type of window to create
1092 -
1093 -
        Returns
1094 -
        -------
1095 -
        window : ndarray
1096 -
            the window, weights
1097 -
        """
1098 -
        window = self.window
1099 -
        if isinstance(window, (list, tuple, np.ndarray)):
1100 -
            return com.asarray_tuplesafe(window).astype(float)
1101 -
        elif is_integer(window):
1102 -
            import scipy.signal as sig
1103 -
1104 -
            # GH #15662. `False` makes symmetric window, rather than periodic.
1105 -
            return sig.get_window(win_type, window, False).astype(float)
1106 -
1107 1017
    def _apply(
1108 1018
        self,
1109 1019
        func: Callable[[np.ndarray, int, int], np.ndarray],
@@ -1124,14 +1034,17 @@
Loading
1124 1034
            whether to cache a numba compiled function. Only available for numba
1125 1035
            enabled methods (so far only apply)
1126 1036
        **kwargs
1127 -
            additional arguments for rolling function and window function
1037 +
            additional arguments for scipy windows if necessary
1128 1038
1129 1039
        Returns
1130 1040
        -------
1131 1041
        y : type of input
1132 1042
        """
1133 -
        win_type = self._get_win_type(kwargs)
1134 -
        window = self._get_window_weights(win_type=win_type)
1043 +
        signal = import_optional_dependency(
1044 +
            "scipy.signal", extra="Scipy is required to generate window weight."
1045 +
        )
1046 +
        assert self.win_type is not None  # for mypy
1047 +
        window = getattr(signal, self.win_type)(self.window, **kwargs)
1135 1048
        offset = (len(window) - 1) // 2 if self.center else 0
1136 1049
1137 1050
        def homogeneous_func(values: np.ndarray):

@@ -507,7 +507,7 @@
Loading
507 507
            )
508 508
            fill_value = new_fill
509 509
510 -
        return self._unbox(fill_value)
510 +
        return self._unbox(fill_value, setitem=True)
511 511
512 512
    def _validate_scalar(self, value, allow_listlike: bool = False):
513 513
        """
@@ -1356,21 +1356,20 @@
Loading
1356 1356
        if axis is not None and abs(axis) >= self.ndim:
1357 1357
            raise ValueError("abs(axis) must be less than ndim")
1358 1358
1359 -
        if self.size == 0:
1360 -
            if self.ndim == 1 or axis is None:
1361 -
                return NaT
1362 -
            shape = list(self.shape)
1363 -
            del shape[axis]
1364 -
            shape = [1 if x == 0 else x for x in shape]
1365 -
            result = np.empty(shape, dtype="i8")
1366 -
            result.fill(iNaT)
1359 +
        if is_period_dtype(self.dtype):
1360 +
            # pass datetime64 values to nanops to get correct NaT semantics
1361 +
            result = nanops.nanmedian(
1362 +
                self._ndarray.view("M8[ns]"), axis=axis, skipna=skipna
1363 +
            )
1364 +
            result = result.view("i8")
1365 +
            if axis is None or self.ndim == 1:
1366 +
                return self._box_func(result)
1367 1367
            return self._from_backing_data(result)
1368 1368
1369 -
        mask = self.isna()
1370 -
        result = nanops.nanmedian(self.asi8, axis=axis, skipna=skipna, mask=mask)
1369 +
        result = nanops.nanmedian(self._ndarray, axis=axis, skipna=skipna)
1371 1370
        if axis is None or self.ndim == 1:
1372 1371
            return self._box_func(result)
1373 -
        return self._from_backing_data(result.astype("i8"))
1372 +
        return self._from_backing_data(result)
1374 1373
1375 1374
1376 1375
class DatelikeOps(DatetimeLikeArrayMixin):

@@ -714,7 +714,7 @@
Loading
714 714
            # lab is a Categorical with categories an IntervalIndex
715 715
            lab = cut(Series(val), bins, include_lowest=True)
716 716
            lev = lab.cat.categories
717 -
            lab = lev.take(lab.cat.codes)
717 +
            lab = lev.take(lab.cat.codes, allow_fill=True, fill_value=lev._na_value)
718 718
            llab = lambda lab, inc: lab[inc]._multiindex.codes[-1]
719 719
720 720
        if is_interval_dtype(lab.dtype):
@@ -1645,8 +1645,8 @@
Loading
1645 1645
        DataFrame
1646 1646
        """
1647 1647
        indexed_output = {key.position: val for key, val in output.items()}
1648 -
        name = self._obj_with_exclusions._get_axis(1 - self.axis).name
1649 -
        columns = Index([key.label for key in output], name=name)
1648 +
        columns = Index([key.label for key in output])
1649 +
        columns._set_names(self._obj_with_exclusions._get_axis(1 - self.axis).names)
1650 1650
1651 1651
        result = self.obj._constructor(indexed_output)
1652 1652
        result.columns = columns

Click to load this diff.
Loading diff...

Click to load this diff.
Loading diff...

Click to load this diff.
Loading diff...

Click to load this diff.
Loading diff...

Click to load this diff.
Loading diff...

Click to load this diff.
Loading diff...

Click to load this diff.
Loading diff...

Click to load this diff.
Loading diff...

Click to load this diff.
Loading diff...

Click to load this diff.
Loading diff...

Click to load this diff.
Loading diff...

Click to load this diff.
Loading diff...

Unable to process changes.

No base report to compare against.

29 Commits

Hiding 7 contexual commits
+2
+2
Hiding 14 contexual commits
-51
-40
-11
Hiding 5 contexual commits
+61
+56
+5
Pull Request Base Commit
Files Coverage
pandas 94.21%
Project Totals (214 files) 94.21%
Loading