From 160ebaf0a178260193daf3e2080df7e7064e9e95 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Sat, 25 Sep 2021 10:38:57 -0700 Subject: [PATCH 1/2] Improved the type stubs in the _libs directory to help with type checking. --- pandas/_libs/interval.pyi | 47 +++++++++++++ pandas/_libs/missing.pyi | 12 ++++ pandas/_libs/properties.pyi | 3 + pandas/_libs/tslibs/ccalendar.pyi | 2 + pandas/_libs/tslibs/dtypes.pyi | 46 ++++++------- pandas/_libs/tslibs/nattype.pyi | 1 + pandas/_libs/tslibs/np_datetime.pyi | 1 + pandas/_libs/tslibs/offsets.pyi | 102 ++++++++++++++++++++++++++++ pandas/_libs/tslibs/period.pyi | 4 ++ pandas/_libs/tslibs/timestamps.pyi | 1 - 10 files changed, 195 insertions(+), 24 deletions(-) create mode 100644 pandas/_libs/interval.pyi create mode 100644 pandas/_libs/missing.pyi create mode 100644 pandas/_libs/properties.pyi create mode 100644 pandas/_libs/tslibs/np_datetime.pyi create mode 100644 pandas/_libs/tslibs/offsets.pyi diff --git a/pandas/_libs/interval.pyi b/pandas/_libs/interval.pyi new file mode 100644 index 0000000000000..fef7c2531b680 --- /dev/null +++ b/pandas/_libs/interval.pyi @@ -0,0 +1,47 @@ +from typing import FrozenSet, Tuple + +import numpy as np + +class IntervalMixin: + @property + def _left(self) -> object: ... + @property + def _right(self) -> object: ... + @property + def closed_left(self) -> bool: ... + @property + def closed_right(self) -> bool: ... + @property + def open_left(self) -> bool: ... + @property + def open_right(self) -> bool: ... + @property + def mid(self) -> float: ... + @property + def length(self) -> float: ... + @property + def is_empty(self) -> bool: ... + def _check_closed_matches(self, other: IntervalMixin, name: str=...) -> None: ... + +class Interval(IntervalMixin): + def __init__(self, left: object, right: object, closed: str=...) -> None: ... + @property + def closed(self) -> str: ... + @property + def left(self) -> object: ... + @property + def right(self) -> object: ... + def __str__(self) -> str: ... + def __add__(self, y: Interval) -> Interval: ... + def __sub__(self, y: Interval) -> Interval: ... + def __mul__(self, y: Interval) -> Interval: ... + def __trudeiv__(self, y: Interval) -> Interval: ... + def __floordiv__(self, y: Interval) -> Interval: ... + def __overlaps__(self, other: Interval) -> bool: ... + +VALID_CLOSED: FrozenSet[str] + +def intervals_to_interval_bounds( + intervals: np.ndarray, + valdiate_closed: bool = ... +) -> Tuple[object, object, str]: ... \ No newline at end of file diff --git a/pandas/_libs/missing.pyi b/pandas/_libs/missing.pyi new file mode 100644 index 0000000000000..afe823ac32f5a --- /dev/null +++ b/pandas/_libs/missing.pyi @@ -0,0 +1,12 @@ +class C_NAType: + ... + + +class NAType(C_NAType): + ... + +NA: NAType + +def is_matching_na(left: object, right: object, nan_matches_none: bool = ...) -> bool: + ... + diff --git a/pandas/_libs/properties.pyi b/pandas/_libs/properties.pyi new file mode 100644 index 0000000000000..6d97877b185ba --- /dev/null +++ b/pandas/_libs/properties.pyi @@ -0,0 +1,3 @@ + +cache_readonly = property + diff --git a/pandas/_libs/tslibs/ccalendar.pyi b/pandas/_libs/tslibs/ccalendar.pyi index 993f18a61d74a..5d5b935ffa54b 100644 --- a/pandas/_libs/tslibs/ccalendar.pyi +++ b/pandas/_libs/tslibs/ccalendar.pyi @@ -8,5 +8,7 @@ def get_firstbday(year: int, month: int) -> int: ... def get_lastbday(year: int, month: int) -> int: ... def get_day_of_year(year: int, month: int, day: int) -> int: ... def get_iso_calendar(year: int, month: int, day: int) -> tuple[int, int, int]: ... +def is_leapyear(year: int) -> bool: ... def get_week_of_year(year: int, month: int, day: int) -> int: ... def get_days_in_month(year: int, month: int) -> int: ... +def dayofweek(y: int, m: int, d: int) -> int: ... diff --git a/pandas/_libs/tslibs/dtypes.pyi b/pandas/_libs/tslibs/dtypes.pyi index f6a8d7887ced1..638663b91062c 100644 --- a/pandas/_libs/tslibs/dtypes.pyi +++ b/pandas/_libs/tslibs/dtypes.pyi @@ -16,33 +16,33 @@ class PeriodDtypeBase: def from_date_offset(cls, offset: BaseOffset) -> PeriodDtypeBase: ... class FreqGroup(Enum): - FR_ANN: int = ... - FR_QTR: int = ... - FR_MTH: int = ... - FR_WK: int = ... - FR_BUS: int = ... - FR_DAY: int = ... - FR_HR: int = ... - FR_MIN: int = ... - FR_SEC: int = ... - FR_MS: int = ... - FR_US: int = ... - FR_NS: int = ... - FR_UND: int = ... + FR_ANN: int + FR_QTR: int + FR_MTH: int + FR_WK: int + FR_BUS: int + FR_DAY: int + FR_HR: int + FR_MIN: int + FR_SEC: int + FR_MS: int + FR_US: int + FR_NS: int + FR_UND: int @staticmethod def get_freq_group(code: int) -> FreqGroup: ... class Resolution(Enum): - RESO_NS: int = ... - RESO_US: int = ... - RESO_MS: int = ... - RESO_SEC: int = ... - RESO_MIN: int = ... - RESO_HR: int = ... - RESO_DAY: int = ... - RESO_MTH: int = ... - RESO_QTR: int = ... - RESO_YR: int = ... + RESO_NS: int + RESO_US: int + RESO_MS: int + RESO_SEC: int + RESO_MIN: int + RESO_HR: int + RESO_DAY: int + RESO_MTH: int + RESO_QTR: int + RESO_YR: int def __lt__(self, other: Resolution) -> bool: ... def __ge__(self, other: Resolution) -> bool: ... @property diff --git a/pandas/_libs/tslibs/nattype.pyi b/pandas/_libs/tslibs/nattype.pyi index 22e6395a1fe99..6dd5b7dba29ea 100644 --- a/pandas/_libs/tslibs/nattype.pyi +++ b/pandas/_libs/tslibs/nattype.pyi @@ -13,6 +13,7 @@ iNaT: int nat_strings: set[str] def is_null_datetimelike(val: object, inat_is_null: bool = ...) -> bool: ... +def checknull_with_nat(val: object) -> bool: ... class NaTType(datetime): value: np.int64 diff --git a/pandas/_libs/tslibs/np_datetime.pyi b/pandas/_libs/tslibs/np_datetime.pyi new file mode 100644 index 0000000000000..db0c277b73bd5 --- /dev/null +++ b/pandas/_libs/tslibs/np_datetime.pyi @@ -0,0 +1 @@ +class OutOfBoundsDatetime(ValueError): ... diff --git a/pandas/_libs/tslibs/offsets.pyi b/pandas/_libs/tslibs/offsets.pyi new file mode 100644 index 0000000000000..ba11ac256936a --- /dev/null +++ b/pandas/_libs/tslibs/offsets.pyi @@ -0,0 +1,102 @@ +from __future__ import annotations +from datetime import datetime +from typing import Any, Tuple, Union +from datetime import timedelta + +class BaseOffset: + def __init__(self, n: int = ..., normalize: bool = ...) -> None: ... + def __eq__(self, other) -> bool: ... + def __ne__(self, other) -> bool: ... + def __hash__(self) -> int: ... + @property + def kwds(self) -> dict: ... + @property + def base(self) -> BaseOffset: ... + def __add__(self, other) -> BaseOffset: ... + def __sub__(self, other) -> BaseOffset: ... + def __call__(self, other): ... + def __mul__(self, other): ... + def __neg__(self) -> BaseOffset: ... + def copy(self) -> BaseOffset: ... + def __repr__(self) -> str: ... + @property + def name(self) -> str: ... + @property + def rule_code(self) -> str: ... + def freqstr(self) -> str: ... + # Next one is problematic due to circular imports + #def apply_index(self, dtindex: DatetimeIndex) -> DatetimeIndex: ... + def apply_index(self, dtindex): ... + def _apply_array(self, dtarr) -> None: ... + def rollback(self, dt: datetime) -> datetime: ... + def rollforward(self, dt: datetime) -> datetime: ... + def is_on_offset(self, dt: datetime) -> bool: ... + def __setstate__(self, state) -> None: ... + def __getstate__(self): ... + @property + def nanos(self) -> int: ... + def onOffset(self, dt: datetime) -> bool: ... + def isAnchored(self) -> bool: ... + def is_anchored(self) -> bool: ... + +class SingleConstructorOffset(BaseOffset): + @classmethod + def _from_name(cls, suffix=None): ... + def __reduce__(self): ... + +def to_offset(freq: Union[str, Tuple, timedelta, BaseOffset, None]) -> Union[BaseOffset, None]: ... + +class Tick(SingleConstructorOffset): + def __init__(self, n: int = ..., normalize: bool = ...) -> None: ... + +class Day(Tick): ... +class Hour(Tick): ... +class Minute(Tick): ... +class Second(Tick): ... +class Milli(Tick): ... +class Micro(Tick): ... +class Nano(Tick): ... +class RelativeDeltaOffset(BaseOffset): + def __init__(self, n: int = ..., normalize: bool = ..., **kwds: Any) -> None: ... +class BusinessMixin(SingleConstructorOffset): ... +class BusinessDay(BusinessMixin): ... +class BusinessHour(BusinessMixin): ... +class WeekOfMonthMixin(SingleConstructorOffset): ... +class YearOffset(SingleConstructorOffset): ... +class BYearEnd(YearOffset): ... +class BYearBegin(YearOffset): ... +class YearEnd(YearOffset): ... +class YearBegin(YearOffset): ... +class QuarterOffset(SingleConstructorOffset): ... +class BQuarterEnd(QuarterOffset): ... +class BQuarterBegin(QuarterOffset): ... +class QuarterEnd(QuarterOffset): ... +class QuarterBegin(QuarterOffset): ... +class MonthOffset(SingleConstructorOffset): ... +class MonthEnd(MonthOffset): ... +class MonthBegin(MonthOffset): ... +class BusinessMonthEnd(MonthOffset): ... +class BusinessMonthBegin(MonthOffset): ... +class SemiMonthOffset(SingleConstructorOffset): ... +class SemiMonthEnd(SemiMonthOffset): ... +class SemiMonthBegin(SemiMonthOffset): ... +class Week(SingleConstructorOffset): ... +class WeekOfMonth(WeekOfMonthMixin): ... +class LastWeekOfMonth(WeekOfMonthMixin): ... +class FY5253Mixin(SingleConstructorOffset): ... +class FY5253(FY5253Mixin): ... +class FY5253Quarter(FY5253Mixin): ... +class Easter(SingleConstructorOffset): ... +class _CustomBusinessMonth(BusinessMixin): ... +class CustomBusinessDay(BusinessDay): ... +class CustomBusinessHour(BusinessHour): ... +class CustomBusinessMonthEnd(_CustomBusinessMonth): ... +class CustomBusinessMonthBegin(_CustomBusinessMonth): ... +class DateOffset(RelativeDeltaOffset): ... + +BDay = BusinessDay +BMonthEnd = BusinessMonthEnd +BMonthBegin = BusinessMonthBegin +CBMonthEnd = CustomBusinessMonthEnd +CBMonthBegin = CustomBusinessMonthBegin +CDay = CustomBusinessDay diff --git a/pandas/_libs/tslibs/period.pyi b/pandas/_libs/tslibs/period.pyi index e5455fa55c5ef..43ffc32941cec 100644 --- a/pandas/_libs/tslibs/period.pyi +++ b/pandas/_libs/tslibs/period.pyi @@ -1,3 +1,4 @@ +from datetime import datetime from typing import Literal import numpy as np @@ -14,6 +15,9 @@ from pandas._typing import ( INVALID_FREQ_ERR_MSG: str DIFFERENT_FREQ: str +def is_period_object(obj: object) -> bool: ... +def get_period_ordinal(dts: datetime, freq: int) -> int: ... + class IncompatibleFrequency(ValueError): ... def periodarr_to_dt64arr( diff --git a/pandas/_libs/tslibs/timestamps.pyi b/pandas/_libs/tslibs/timestamps.pyi index ff6b18835322e..4f56eef91d26e 100644 --- a/pandas/_libs/tslibs/timestamps.pyi +++ b/pandas/_libs/tslibs/timestamps.pyi @@ -18,7 +18,6 @@ import numpy as np from pandas._libs.tslibs import ( BaseOffset, - NaT, NaTType, Period, Timedelta, From 095eada36c32fde3705f6e3e126bb97da5ccaa43 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Sat, 25 Sep 2021 10:51:43 -0700 Subject: [PATCH 2/2] Fixed formatting issues --- pandas/_libs/interval.pyi | 9 ++++----- pandas/_libs/missing.pyi | 14 +++++--------- pandas/_libs/properties.pyi | 2 -- pandas/_libs/tslibs/offsets.pyi | 8 ++++++-- 4 files changed, 15 insertions(+), 18 deletions(-) diff --git a/pandas/_libs/interval.pyi b/pandas/_libs/interval.pyi index fef7c2531b680..6e201601911da 100644 --- a/pandas/_libs/interval.pyi +++ b/pandas/_libs/interval.pyi @@ -21,10 +21,10 @@ class IntervalMixin: def length(self) -> float: ... @property def is_empty(self) -> bool: ... - def _check_closed_matches(self, other: IntervalMixin, name: str=...) -> None: ... + def _check_closed_matches(self, other: IntervalMixin, name: str = ...) -> None: ... class Interval(IntervalMixin): - def __init__(self, left: object, right: object, closed: str=...) -> None: ... + def __init__(self, left: object, right: object, closed: str = ...) -> None: ... @property def closed(self) -> str: ... @property @@ -42,6 +42,5 @@ class Interval(IntervalMixin): VALID_CLOSED: FrozenSet[str] def intervals_to_interval_bounds( - intervals: np.ndarray, - valdiate_closed: bool = ... -) -> Tuple[object, object, str]: ... \ No newline at end of file + intervals: np.ndarray, valdiate_closed: bool = ... +) -> Tuple[object, object, str]: ... diff --git a/pandas/_libs/missing.pyi b/pandas/_libs/missing.pyi index afe823ac32f5a..e405e33060026 100644 --- a/pandas/_libs/missing.pyi +++ b/pandas/_libs/missing.pyi @@ -1,12 +1,8 @@ -class C_NAType: - ... - - -class NAType(C_NAType): - ... +class C_NAType: ... +class NAType(C_NAType): ... NA: NAType -def is_matching_na(left: object, right: object, nan_matches_none: bool = ...) -> bool: - ... - +def is_matching_na( + left: object, right: object, nan_matches_none: bool = ... +) -> bool: ... diff --git a/pandas/_libs/properties.pyi b/pandas/_libs/properties.pyi index 6d97877b185ba..117ff93f2ea1b 100644 --- a/pandas/_libs/properties.pyi +++ b/pandas/_libs/properties.pyi @@ -1,3 +1 @@ - cache_readonly = property - diff --git a/pandas/_libs/tslibs/offsets.pyi b/pandas/_libs/tslibs/offsets.pyi index ba11ac256936a..4e5448612c0d9 100644 --- a/pandas/_libs/tslibs/offsets.pyi +++ b/pandas/_libs/tslibs/offsets.pyi @@ -25,7 +25,7 @@ class BaseOffset: def rule_code(self) -> str: ... def freqstr(self) -> str: ... # Next one is problematic due to circular imports - #def apply_index(self, dtindex: DatetimeIndex) -> DatetimeIndex: ... + # def apply_index(self, dtindex: DatetimeIndex) -> DatetimeIndex: ... def apply_index(self, dtindex): ... def _apply_array(self, dtarr) -> None: ... def rollback(self, dt: datetime) -> datetime: ... @@ -44,7 +44,9 @@ class SingleConstructorOffset(BaseOffset): def _from_name(cls, suffix=None): ... def __reduce__(self): ... -def to_offset(freq: Union[str, Tuple, timedelta, BaseOffset, None]) -> Union[BaseOffset, None]: ... +def to_offset( + freq: Union[str, Tuple, timedelta, BaseOffset, None] +) -> Union[BaseOffset, None]: ... class Tick(SingleConstructorOffset): def __init__(self, n: int = ..., normalize: bool = ...) -> None: ... @@ -56,8 +58,10 @@ class Second(Tick): ... class Milli(Tick): ... class Micro(Tick): ... class Nano(Tick): ... + class RelativeDeltaOffset(BaseOffset): def __init__(self, n: int = ..., normalize: bool = ..., **kwds: Any) -> None: ... + class BusinessMixin(SingleConstructorOffset): ... class BusinessDay(BusinessMixin): ... class BusinessHour(BusinessMixin): ...