diff --git a/pandas/_libs/tslibs/conversion.pyx b/pandas/_libs/tslibs/conversion.pyx index cb13cde7a4bed..1b20ffbe52493 100644 --- a/pandas/_libs/tslibs/conversion.pyx +++ b/pandas/_libs/tslibs/conversion.pyx @@ -61,7 +61,6 @@ from pandas._libs.tslibs.nattype cimport ( c_nat_strings as nat_strings, ) from pandas._libs.tslibs.parsing cimport parse_datetime_string -from pandas._libs.tslibs.timestamps cimport _Timestamp from pandas._libs.tslibs.timezones cimport ( get_utcoffset, is_utc, @@ -761,7 +760,7 @@ cdef int64_t parse_pydatetime( _ts.ensure_reso(NPY_FR_ns) result = _ts.value else: - if isinstance(val, _Timestamp): + if isinstance(val, ABCTimestamp): result = val.as_unit("ns")._value else: result = pydatetime_to_dt64(val, dts) diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index fd89d0e795ecc..3e1554e8b79b3 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -22,7 +22,7 @@ from numpy cimport ( cnp.import_array() -from cpython.datetime cimport ( # alias bc `tzinfo` is a kwarg below +from cpython.datetime cimport ( # alias tzinfo_type bc `tzinfo` is a kwarg below PyDate_Check, PyDateTime_Check, PyDelta_Check, diff --git a/pandas/_libs/tslibs/util.pxd b/pandas/_libs/tslibs/util.pxd index 4e55bc1c48fd0..243c65a6e516e 100644 --- a/pandas/_libs/tslibs/util.pxd +++ b/pandas/_libs/tslibs/util.pxd @@ -10,6 +10,7 @@ cdef extern from "Python.h": bint PyComplex_Check(object obj) nogil bint PyObject_TypeCheck(object obj, PyTypeObject* type) nogil + # TODO(cython3): cimport this, xref GH#49670 # Note that following functions can potentially raise an exception, # thus they cannot be declared 'nogil'. Also PyUnicode_AsUTF8AndSize() can # potentially allocate memory inside in unlikely case of when underlying diff --git a/pandas/core/computation/align.py b/pandas/core/computation/align.py index fff605eb7cf59..a8ca08c58c261 100644 --- a/pandas/core/computation/align.py +++ b/pandas/core/computation/align.py @@ -133,9 +133,8 @@ def _align_core(terms): w, category=PerformanceWarning, stacklevel=find_stack_level() ) - f = partial(ti.reindex, reindexer, axis=axis, copy=False) - - terms[i].update(f()) + obj = ti.reindex(reindexer, axis=axis, copy=False) + terms[i].update(obj) terms[i].update(terms[i].value.values) diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py index 3929775283f6a..2d45158cf2a9f 100644 --- a/pandas/core/dtypes/cast.py +++ b/pandas/core/dtypes/cast.py @@ -50,7 +50,6 @@ ensure_str, is_bool, is_complex, - is_extension_array_dtype, is_float, is_integer, is_object_dtype, @@ -903,7 +902,8 @@ def infer_dtype_from_array( if not is_list_like(arr): raise TypeError("'arr' must be list-like") - if pandas_dtype and is_extension_array_dtype(arr): + arr_dtype = getattr(arr, "dtype", None) + if pandas_dtype and isinstance(arr_dtype, ExtensionDtype): return arr.dtype, arr elif isinstance(arr, ABCSeries): diff --git a/pandas/core/dtypes/missing.py b/pandas/core/dtypes/missing.py index 2fb8d3563b792..4e854ff3cf91a 100644 --- a/pandas/core/dtypes/missing.py +++ b/pandas/core/dtypes/missing.py @@ -26,7 +26,6 @@ TD64NS_DTYPE, ensure_object, is_dtype_equal, - is_extension_array_dtype, is_scalar, is_string_or_object_np_dtype, ) @@ -56,6 +55,7 @@ npt, ) + from pandas import Series from pandas.core.indexes.base import Index @@ -642,11 +642,11 @@ def na_value_for_dtype(dtype: DtypeObj, compat: bool = True): return np.nan -def remove_na_arraylike(arr): +def remove_na_arraylike(arr: Series | Index | np.ndarray): """ Return array-like containing only true/non-NaN values, possibly empty. """ - if is_extension_array_dtype(arr): + if isinstance(arr.dtype, ExtensionDtype): return arr[notna(arr)] else: return arr[notna(np.asarray(arr))] diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 9cbb652b33b46..f3de296841510 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -590,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) @@ -969,6 +970,7 @@ def squeeze(self, axis: Axis | None = None): # ---------------------------------------------------------------------- # Rename + @final def _rename( self, mapper: Renamer | None = None, @@ -3476,6 +3478,7 @@ def _wrap(x, alt_format_): render_kwargs=render_kwargs_, ) + @final def _to_latex_via_styler( self, buf=None, @@ -4293,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 @@ -6069,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 @@ -6085,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 @@ -6255,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: @@ -7128,6 +7135,7 @@ def ffill( ) -> Self | None: ... + @final @doc(klass=_shared_doc_kwargs["klass"]) def ffill( self, @@ -7149,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, @@ -7211,6 +7220,7 @@ def bfill( ) -> Self | None: ... + @final @doc(klass=_shared_doc_kwargs["klass"]) def bfill( self, @@ -7232,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, @@ -7501,6 +7512,7 @@ def replace( else: return result.__finalize__(self, method="replace") + @final def interpolate( self, method: Literal[ @@ -8185,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, @@ -9996,6 +10009,7 @@ def where( ) -> Self | None: ... + @final @doc( klass=_shared_doc_kwargs["klass"], cond="True", @@ -10188,6 +10202,7 @@ def mask( ) -> Self | None: ... + @final @doc( where, klass=_shared_doc_kwargs["klass"], @@ -10368,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, @@ -11693,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] diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index fe24f9b7c4d7f..694f2201d9f34 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -922,18 +922,20 @@ def __array_ufunc__(self, ufunc: np.ufunc, method: str_t, *inputs, **kwargs): return self.__array_wrap__(result) + @final def __array_wrap__(self, result, context=None): """ Gets called after a ufunc and other functions e.g. np.split. """ result = lib.item_from_zerodim(result) if ( - (not isinstance(result, Index) and is_bool_dtype(result)) + (not isinstance(result, Index) and is_bool_dtype(result.dtype)) or lib.is_scalar(result) or np.ndim(result) > 1 ): # exclude Index to avoid warning from is_bool_dtype deprecation; # in the Index case it doesn't matter which path we go down. + # reached in plotting tests with e.g. np.nonzero(index) return result return Index(result, name=self.name) diff --git a/pandas/core/indexes/category.py b/pandas/core/indexes/category.py index 4854a919fb272..d2ef607635abb 100644 --- a/pandas/core/indexes/category.py +++ b/pandas/core/indexes/category.py @@ -17,6 +17,7 @@ ) from pandas.core.dtypes.common import is_scalar +from pandas.core.dtypes.concat import concat_compat from pandas.core.dtypes.dtypes import CategoricalDtype from pandas.core.dtypes.missing import ( is_valid_na_for_dtype, @@ -478,7 +479,6 @@ def _concat(self, to_concat: list[Index], name: Hashable) -> Index: ) except TypeError: # not all to_concat elements are among our categories (or NA) - from pandas.core.dtypes.concat import concat_compat res = concat_compat([x._values for x in to_concat]) return Index(res, name=name) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index ca01b1fd5fe6f..13c87a9d06b66 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -113,6 +113,7 @@ def _get_next_label(label): + # see test_slice_locs_with_ints_and_floats_succeeds dtype = getattr(label, "dtype", type(label)) if isinstance(label, (Timestamp, Timedelta)): dtype = "datetime64[ns]" @@ -129,6 +130,7 @@ def _get_next_label(label): def _get_prev_label(label): + # see test_slice_locs_with_ints_and_floats_succeeds dtype = getattr(label, "dtype", type(label)) if isinstance(label, (Timestamp, Timedelta)): dtype = "datetime64[ns]" diff --git a/pandas/core/reshape/melt.py b/pandas/core/reshape/melt.py index df9112faa2a47..8e61754002cdb 100644 --- a/pandas/core/reshape/melt.py +++ b/pandas/core/reshape/melt.py @@ -10,10 +10,7 @@ from pandas.util._decorators import Appender -from pandas.core.dtypes.common import ( - is_extension_array_dtype, - is_list_like, -) +from pandas.core.dtypes.common import is_list_like from pandas.core.dtypes.concat import concat_compat from pandas.core.dtypes.missing import notna @@ -126,7 +123,8 @@ def melt( mdata: dict[Hashable, AnyArrayLike] = {} for col in id_vars: id_data = frame.pop(col) - if is_extension_array_dtype(id_data): + if not isinstance(id_data.dtype, np.dtype): + # i.e. ExtensionDtype if K > 0: mdata[col] = concat([id_data] * K, ignore_index=True) else: diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index 0f775f959c4ce..e5cd2f51e6165 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -18,12 +18,12 @@ from pandas.core.dtypes.cast import maybe_downcast_to_dtype from pandas.core.dtypes.common import ( - is_extension_array_dtype, is_integer_dtype, is_list_like, is_nested_list_like, is_scalar, ) +from pandas.core.dtypes.dtypes import ExtensionDtype from pandas.core.dtypes.generic import ( ABCDataFrame, ABCSeries, @@ -326,7 +326,7 @@ def _add_margins( row_names = result.index.names # check the result column and leave floats for dtype in set(result.dtypes): - if is_extension_array_dtype(dtype): + if isinstance(dtype, ExtensionDtype): # Can hold NA already continue diff --git a/pandas/core/reshape/reshape.py b/pandas/core/reshape/reshape.py index e14a0e681b02c..65fd9137313f1 100644 --- a/pandas/core/reshape/reshape.py +++ b/pandas/core/reshape/reshape.py @@ -21,7 +21,6 @@ from pandas.core.dtypes.common import ( ensure_platform_int, is_1d_only_ea_dtype, - is_extension_array_dtype, is_integer, needs_i8_conversion, ) @@ -47,6 +46,7 @@ if TYPE_CHECKING: from pandas._typing import ( + ArrayLike, Level, npt, ) @@ -591,13 +591,14 @@ def factorize(index): verify_integrity=False, ) + new_values: ArrayLike if not frame.empty and frame._is_homogeneous_type: # For homogeneous EAs, frame._values will coerce to object. So # we concatenate instead. dtypes = list(frame.dtypes._values) dtype = dtypes[0] - if is_extension_array_dtype(dtype): + if isinstance(dtype, ExtensionDtype): arr = dtype.construct_array_type() new_values = arr._concat_same_type( [col._values for _, col in frame.items()] @@ -753,7 +754,7 @@ def _convert_level_number(level_num: int, columns: Index): else: subset = this.iloc[:, loc] dtype = find_common_type(subset.dtypes.tolist()) - if is_extension_array_dtype(dtype): + if isinstance(dtype, ExtensionDtype): # TODO(EA2D): won't need special case, can go through .values # paths below (might change to ._values) value_slice = dtype.construct_array_type()._concat_same_type( diff --git a/pandas/core/series.py b/pandas/core/series.py index 43ebdc2f9dff0..96971736f113b 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -5606,9 +5606,6 @@ def _binop(self, other: Series, func, level=None, fill_value=None) -> Series: ------- Series """ - if not isinstance(other, Series): - raise AssertionError("Other operand must be Series") - this = self if not self.index.equals(other.index): @@ -5674,7 +5671,7 @@ def _flex_method(self, other, op, *, level=None, fill_value=None, axis: Axis = 0 raise ValueError("Lengths must be equal") other = self._constructor(other, self.index, copy=False) result = self._binop(other, op, level=level, fill_value=fill_value) - result.name = res_name + result._name = res_name return result else: if fill_value is not None: diff --git a/pandas/io/json/_table_schema.py b/pandas/io/json/_table_schema.py index 7decab539da34..97680923554d5 100644 --- a/pandas/io/json/_table_schema.py +++ b/pandas/io/json/_table_schema.py @@ -316,7 +316,7 @@ def build_table_schema( return schema -def parse_table_schema(json, precise_float): +def parse_table_schema(json, precise_float: bool) -> DataFrame: """ Builds a DataFrame from a given schema diff --git a/pandas/plotting/_matplotlib/core.py b/pandas/plotting/_matplotlib/core.py index d1e8f92ffc36b..f11d663f39cea 100644 --- a/pandas/plotting/_matplotlib/core.py +++ b/pandas/plotting/_matplotlib/core.py @@ -22,7 +22,6 @@ from pandas.core.dtypes.common import ( is_any_real_numeric_dtype, - is_extension_array_dtype, is_float, is_float_dtype, is_hashable, @@ -33,7 +32,10 @@ is_number, is_numeric_dtype, ) -from pandas.core.dtypes.dtypes import CategoricalDtype +from pandas.core.dtypes.dtypes import ( + CategoricalDtype, + ExtensionDtype, +) from pandas.core.dtypes.generic import ( ABCDataFrame, ABCIndex, @@ -567,9 +569,9 @@ def _convert_to_ndarray(self, data): return data # GH32073: cast to float if values contain nulled integers - if ( - is_integer_dtype(data.dtype) or is_float_dtype(data.dtype) - ) and is_extension_array_dtype(data.dtype): + if (is_integer_dtype(data.dtype) or is_float_dtype(data.dtype)) and isinstance( + data.dtype, ExtensionDtype + ): return data.to_numpy(dtype="float", na_value=np.nan) # GH25587: cast ExtensionArray of pandas (IntegerArray, etc.) to diff --git a/pandas/tests/strings/test_cat.py b/pandas/tests/strings/test_cat.py index ff2898107a9e4..a6303610b2037 100644 --- a/pandas/tests/strings/test_cat.py +++ b/pandas/tests/strings/test_cat.py @@ -13,13 +13,6 @@ ) -def assert_series_or_index_equal(left, right): - if isinstance(left, Series): - tm.assert_series_equal(left, right) - else: # Index - tm.assert_index_equal(left, right) - - @pytest.mark.parametrize("other", [None, Series, Index]) def test_str_cat_name(index_or_series, other): # GH 21053 @@ -57,11 +50,11 @@ def test_str_cat(index_or_series): # Series/Index with array result = s.str.cat(t, na_rep="-") - assert_series_or_index_equal(result, expected) + tm.assert_equal(result, expected) # Series/Index with list result = s.str.cat(list(t), na_rep="-") - assert_series_or_index_equal(result, expected) + tm.assert_equal(result, expected) # errors for incorrect lengths rgx = r"If `others` contains arrays or lists \(or other list-likes.*" @@ -100,16 +93,16 @@ def test_str_cat_categorical(index_or_series, dtype_caller, dtype_target, sep): # Series/Index with unaligned Index -> t.values result = s.str.cat(t.values, sep=sep) - assert_series_or_index_equal(result, expected) + tm.assert_equal(result, expected) # Series/Index with Series having matching Index t = Series(t.values, index=s) result = s.str.cat(t, sep=sep) - assert_series_or_index_equal(result, expected) + tm.assert_equal(result, expected) # Series/Index with Series.values result = s.str.cat(t.values, sep=sep) - assert_series_or_index_equal(result, expected) + tm.assert_equal(result, expected) # Series/Index with Series having different Index t = Series(t.values, index=t.values) @@ -117,7 +110,7 @@ def test_str_cat_categorical(index_or_series, dtype_caller, dtype_target, sep): expected = expected if box == Index else Series(expected, index=expected.str[:1]) result = s.str.cat(t, sep=sep) - assert_series_or_index_equal(result, expected) + tm.assert_equal(result, expected) @pytest.mark.parametrize( @@ -155,37 +148,37 @@ def test_str_cat_mixed_inputs(index_or_series): # Series/Index with DataFrame result = s.str.cat(d) - assert_series_or_index_equal(result, expected) + tm.assert_equal(result, expected) # Series/Index with two-dimensional ndarray result = s.str.cat(d.values) - assert_series_or_index_equal(result, expected) + tm.assert_equal(result, expected) # Series/Index with list of Series result = s.str.cat([t, s]) - assert_series_or_index_equal(result, expected) + tm.assert_equal(result, expected) # Series/Index with mixed list of Series/array result = s.str.cat([t, s.values]) - assert_series_or_index_equal(result, expected) + tm.assert_equal(result, expected) # Series/Index with list of Series; different indexes t.index = ["b", "c", "d", "a"] expected = box(["aDa", "bAb", "cBc", "dCd"]) expected = expected if box == Index else Series(expected.values, index=s.values) result = s.str.cat([t, s]) - assert_series_or_index_equal(result, expected) + tm.assert_equal(result, expected) # Series/Index with mixed list; different index result = s.str.cat([t, s.values]) - assert_series_or_index_equal(result, expected) + tm.assert_equal(result, expected) # Series/Index with DataFrame; different indexes d.index = ["b", "c", "d", "a"] expected = box(["aDd", "bAa", "cBb", "dCc"]) expected = expected if box == Index else Series(expected.values, index=s.values) result = s.str.cat(d) - assert_series_or_index_equal(result, expected) + tm.assert_equal(result, expected) # errors for incorrect lengths rgx = r"If `others` contains arrays or lists \(or other list-likes.*" @@ -261,7 +254,7 @@ def test_str_cat_align_indexed(index_or_series, join): expected = Index(expected) result = s.str.cat(t, join=join, na_rep="-") - assert_series_or_index_equal(result, expected) + tm.assert_equal(result, expected) @pytest.mark.parametrize("join", ["left", "outer", "inner", "right"]) @@ -332,7 +325,7 @@ def test_str_cat_all_na(index_or_series, index_or_series2): else: # box == Index expected = Index([np.nan] * 4, dtype=object) result = s.str.cat(t, join="left") - assert_series_or_index_equal(result, expected) + tm.assert_equal(result, expected) # all-NA caller (only for Series) if other == Series: diff --git a/pandas/tseries/holiday.py b/pandas/tseries/holiday.py index 34812aa491cd3..70190b16767cf 100644 --- a/pandas/tseries/holiday.py +++ b/pandas/tseries/holiday.py @@ -149,6 +149,10 @@ class Holiday: for observance. """ + start_date: Timestamp | None + end_date: Timestamp | None + days_of_week: tuple[int, ...] | None + def __init__( self, name: str, @@ -242,7 +246,9 @@ def __repr__(self) -> str: repr = f"Holiday: {self.name} ({info})" return repr - def dates(self, start_date, end_date, return_name: bool = False): + def dates( + self, start_date, end_date, return_name: bool = False + ) -> Series | DatetimeIndex: """ Calculate holidays observed between start date and end date @@ -253,6 +259,11 @@ def dates(self, start_date, end_date, return_name: bool = False): return_name : bool, optional, default=False If True, return a series that has dates and holiday names. False will only return dates. + + Returns + ------- + Series or DatetimeIndex + Series if return_name is True """ start_date = Timestamp(start_date) end_date = Timestamp(end_date) @@ -262,16 +273,21 @@ def dates(self, start_date, end_date, return_name: bool = False): if self.year is not None: dt = Timestamp(datetime(self.year, self.month, self.day)) + dti = DatetimeIndex([dt]) if return_name: - return Series(self.name, index=[dt]) + return Series(self.name, index=dti) else: - return [dt] + return dti dates = self._reference_dates(start_date, end_date) holiday_dates = self._apply_rule(dates) if self.days_of_week is not None: holiday_dates = holiday_dates[ - np.in1d(holiday_dates.dayofweek, self.days_of_week) + np.in1d( + # error: "DatetimeIndex" has no attribute "dayofweek" + holiday_dates.dayofweek, # type: ignore[attr-defined] + self.days_of_week, + ) ] if self.start_date is not None: @@ -289,7 +305,9 @@ def dates(self, start_date, end_date, return_name: bool = False): return Series(self.name, index=holiday_dates) return holiday_dates - def _reference_dates(self, start_date, end_date): + def _reference_dates( + self, start_date: Timestamp, end_date: Timestamp + ) -> DatetimeIndex: """ Get reference dates for the holiday. @@ -322,7 +340,7 @@ def _reference_dates(self, start_date, end_date): return dates - def _apply_rule(self, dates): + def _apply_rule(self, dates: DatetimeIndex) -> DatetimeIndex: """ Apply the given offset/observance to a DatetimeIndex of dates. @@ -459,9 +477,16 @@ def holidays(self, start=None, end=None, return_name: bool = False): rule.dates(start, end, return_name=True) for rule in self.rules ] if pre_holidays: - holidays = concat(pre_holidays) + # error: Argument 1 to "concat" has incompatible type + # "List[Union[Series, DatetimeIndex]]"; expected + # "Union[Iterable[DataFrame], Mapping[, DataFrame]]" + holidays = concat(pre_holidays) # type: ignore[arg-type] else: - holidays = Series(index=DatetimeIndex([]), dtype=object) + # error: Incompatible types in assignment (expression has type + # "Series", variable has type "DataFrame") + holidays = Series( + index=DatetimeIndex([]), dtype=object + ) # type: ignore[assignment] self._cache = (start, end, holidays.sort_index())