From 714c6155ac88ded1377590b1e8ef42f7f2ce41fd Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 19 Mar 2025 15:54:59 +0100 Subject: [PATCH] [icalendar] Update to 6.1.2 Finish icalendar.prop annotations --- stubs/icalendar/@tests/stubtest_allowlist.txt | 9 + stubs/icalendar/METADATA.toml | 2 +- stubs/icalendar/icalendar/prop.pyi | 210 +++++++++++------- .../timezone/equivalent_timezone_ids.pyi | 6 +- 4 files changed, 136 insertions(+), 91 deletions(-) diff --git a/stubs/icalendar/@tests/stubtest_allowlist.txt b/stubs/icalendar/@tests/stubtest_allowlist.txt index 5c91cf0a219f..b03841be6f7f 100644 --- a/stubs/icalendar/@tests/stubtest_allowlist.txt +++ b/stubs/icalendar/@tests/stubtest_allowlist.txt @@ -12,3 +12,12 @@ icalendar.cal.Component.set_inline # Stubtest gets confused by multiple inheritance. icalendar.prop.vSkip.__new__ + +# Stubtest incorrectly reports that stub argument "cls" should be +# positional or keyword. +icalendar.vBoolean.__new__ +icalendar.vFloat.__new__ +icalendar.vInt.__new__ +icalendar.prop.vBoolean.__new__ +icalendar.prop.vFloat.__new__ +icalendar.prop.vInt.__new__ diff --git a/stubs/icalendar/METADATA.toml b/stubs/icalendar/METADATA.toml index b38656b30402..2892a10d6e38 100644 --- a/stubs/icalendar/METADATA.toml +++ b/stubs/icalendar/METADATA.toml @@ -1,4 +1,4 @@ -version = "6.1.*" +version = "~= 6.1.2" upstream_repository = "https://github.com/collective/icalendar" requires = ["types-python-dateutil", "types-pytz"] diff --git a/stubs/icalendar/icalendar/prop.pyi b/stubs/icalendar/icalendar/prop.pyi index 17d79298b676..ae5a7ec6942e 100644 --- a/stubs/icalendar/icalendar/prop.pyi +++ b/stubs/icalendar/icalendar/prop.pyi @@ -1,9 +1,9 @@ import datetime -from _typeshed import Incomplete, Unused -from collections.abc import Iterator +from _typeshed import ConvertibleToFloat, ConvertibleToInt, SupportsKeysAndGetItem, Unused +from collections.abc import Iterable, Iterator from enum import Enum from re import Pattern -from typing import Any, ClassVar, Final, TypeVar, overload +from typing import Any, ClassVar, Final, Literal, Protocol, SupportsIndex, overload from typing_extensions import Self, TypeAlias from .caselessdict import CaselessDict @@ -44,70 +44,80 @@ __all__ = [ ] _PropType: TypeAlias = type[Any] # any of the v* classes in this file -_vRecurT = TypeVar("_vRecurT", bound=vRecur) +_PeriodTuple: TypeAlias = tuple[datetime.datetime, datetime.datetime | datetime.timedelta] +_AnyTimeType: TypeAlias = datetime.datetime | datetime.date | datetime.timedelta | datetime.time | _PeriodTuple + +class _vType(Protocol): + def to_ical(self) -> bytes | str: ... DURATION_REGEX: Final[Pattern[str]] WEEKDAY_RULE: Final[Pattern[str]] class vBinary: - obj: Incomplete + obj: str params: Parameters - def __init__(self, obj) -> None: ... + def __init__(self, obj: str | bytes) -> None: ... def to_ical(self) -> bytes: ... @staticmethod - def from_ical(ical): ... - def __eq__(self, other): ... + def from_ical(ical: ICAL_TYPE) -> bytes: ... + def __eq__(self, other: object) -> bool: ... class vBoolean(int): - BOOL_MAP: Incomplete + BOOL_MAP: Final[CaselessDict[bool]] params: Parameters - def __new__(cls, *args, **kwargs): ... - def to_ical(self) -> bytes: ... + def __new__(cls, x: ConvertibleToInt = ..., /, *, params: SupportsKeysAndGetItem[str, str] = {}) -> Self: ... + def to_ical(self) -> Literal[b"TRUE", b"FALSE"]: ... @classmethod - def from_ical(cls, ical): ... + def from_ical(cls, ical: ICAL_TYPE) -> bool: ... class vText(str): encoding: str params: Parameters - def __new__(cls, value: ICAL_TYPE, encoding: str = "utf-8") -> Self: ... + def __new__(cls, value: ICAL_TYPE, encoding: str = "utf-8", params: SupportsKeysAndGetItem[str, str] = {}) -> Self: ... def to_ical(self) -> bytes: ... @classmethod def from_ical(cls, ical: ICAL_TYPE) -> Self: ... class vCalAddress(str): params: Parameters - def __new__(cls, value, encoding="utf-8"): ... + def __new__(cls, value: ICAL_TYPE, encoding="utf-8", params: SupportsKeysAndGetItem[str, str] = {}) -> Self: ... def to_ical(self) -> bytes: ... @classmethod - def from_ical(cls, ical): ... + def from_ical(cls, ical: ICAL_TYPE) -> Self: ... + @property + def email(self) -> str: ... + @property + def name(self) -> str: ... + @name.setter + def name(self, value: str) -> None: ... class vFloat(float): params: Parameters - def __new__(cls, *args, **kwargs): ... + def __new__(cls, x: ConvertibleToFloat = ..., /, *, params: SupportsKeysAndGetItem[str, str] = {}) -> Self: ... def to_ical(self) -> bytes: ... @classmethod - def from_ical(cls, ical): ... + def from_ical(cls, ical: ICAL_TYPE) -> Self: ... class vInt(int): params: Parameters - def __new__(cls, *args, **kwargs): ... + def __new__(cls, x: ConvertibleToInt = ..., /, *, params: SupportsKeysAndGetItem[str, str] = {}) -> Self: ... def to_ical(self) -> bytes: ... @classmethod def from_ical(cls, ical: ICAL_TYPE) -> Self: ... class vDDDLists: params: Parameters - dts: Incomplete - def __init__(self, dt_list) -> None: ... + dts: list[vDDDTypes] + def __init__(self, dt_list: Iterable[_AnyTimeType] | _AnyTimeType) -> None: ... def to_ical(self) -> bytes: ... @staticmethod - def from_ical(ical, timezone: Incomplete | None = None): ... - def __eq__(self, other): ... + def from_ical(ical: str, timezone: str | datetime.timezone | None = None): ... + def __eq__(self, other: object) -> bool: ... class vCategory: - cats: Incomplete + cats: list[vText] params: Parameters - def __init__(self, c_list) -> None: ... + def __init__(self, c_list: Iterable[ICAL_TYPE] | ICAL_TYPE, params: SupportsKeysAndGetItem[str, str] = {}) -> None: ... def __iter__(self) -> Iterator[str]: ... def to_ical(self) -> bytes: ... @staticmethod @@ -116,80 +126,95 @@ class vCategory: class TimeBase: def __eq__(self, other: object) -> bool: ... - def __hash__(self): ... + def __hash__(self) -> int: ... class vDDDTypes(TimeBase): params: Parameters - dt: Incomplete - def __init__(self, dt) -> None: ... + dt: _AnyTimeType + def __init__(self, dt: _AnyTimeType) -> None: ... def to_ical(self) -> bytes: ... + @overload @classmethod - def from_ical(cls, ical, timezone: Incomplete | None = None): ... + def from_ical(cls, ical: Self, timezone: Unused | None = None) -> _AnyTimeType: ... + # Return type is one of vDuration, vPeriod, vDatetime, vDate, or vTime, + # depending on the ical string. + @overload + @classmethod + def from_ical(cls, ical: str, timezone: datetime.timezone | str | None = None) -> Any: ... class vDate(TimeBase): - dt: Incomplete + dt: datetime.date params: Parameters - def __init__(self, dt) -> None: ... + def __init__(self, dt: datetime.date) -> None: ... def to_ical(self) -> bytes: ... @staticmethod - def from_ical(ical): ... + def from_ical(ical: ICAL_TYPE) -> datetime.date: ... class vDatetime(TimeBase): - dt: Incomplete + dt: datetime.datetime params: Parameters - def __init__(self, dt) -> None: ... + def __init__(self, dt: datetime.datetime, params: SupportsKeysAndGetItem[str, str] = {}) -> None: ... def to_ical(self) -> bytes: ... @staticmethod - def from_ical(ical, timezone: datetime.timezone | str | None = None) -> datetime.datetime: ... + def from_ical(ical: ICAL_TYPE, timezone: datetime.timezone | str | None = None) -> datetime.datetime: ... class vDuration(TimeBase): - td: Incomplete + td: datetime.timedelta params: Parameters - def __init__(self, td) -> None: ... + def __init__(self, td: datetime.timedelta, params: SupportsKeysAndGetItem[str, str] = {}) -> None: ... def to_ical(self) -> bytes: ... @staticmethod - def from_ical(ical): ... + def from_ical(ical: str) -> datetime.timedelta: ... @property - def dt(self): ... + def dt(self) -> datetime.timedelta: ... class vPeriod(TimeBase): params: Parameters - start: Incomplete - end: Incomplete - by_duration: Incomplete - duration: Incomplete - def __init__(self, per) -> None: ... - def overlaps(self, other): ... + start: datetime.datetime + end: datetime.datetime + by_duration: bool + duration: datetime.timedelta + def __init__(self, per: _PeriodTuple) -> None: ... + def overlaps(self, other: vPeriod) -> bool: ... def to_ical(self) -> bytes: ... + # Return type is a tuple of vDuration, vPeriod, vDatetime, vDate, or vTime, + # depending on the ical string. If the ical string is formed according to + # the iCalendar specification, this should always return a + # (datetime, datetime) or a (datetime, timedelta) tuple, but this is not + # enforced. @staticmethod - def from_ical(ical, timezone: Incomplete | None = None): ... + def from_ical(ical: str, timezone: datetime.timezone | str | None = None) -> tuple[Any, Any]: ... @property - def dt(self): ... + def dt(self) -> _PeriodTuple: ... class vWeekday(str): - week_days: Incomplete - relative: Incomplete + week_days: Final[CaselessDict[int]] + weekday: Literal["SU", "MO", "TU", "WE", "TH", "FR", "SA"] | None + relative: int | None params: Parameters - def __new__(cls, value, encoding="utf-8"): ... + def __new__(cls, value: ICAL_TYPE, encoding: str = "utf-8", params: SupportsKeysAndGetItem[str, str] = {}) -> Self: ... def to_ical(self) -> bytes: ... @classmethod - def from_ical(cls, ical): ... + def from_ical(cls, ical: ICAL_TYPE) -> Self: ... class vFrequency(str): - frequencies: Incomplete + frequencies: Final[CaselessDict[str]] params: Parameters - def __new__(cls, value, encoding="utf-8"): ... + def __new__(cls, value: ICAL_TYPE, encoding: str = "utf-8", params: SupportsKeysAndGetItem[str, str] = {}) -> Self: ... def to_ical(self) -> bytes: ... @classmethod - def from_ical(cls, ical): ... + def from_ical(cls, ical: ICAL_TYPE) -> Self: ... class vMonth(int): - leap: bool params: Parameters - def __new__(cls, month: vMonth | str | int) -> Self: ... + def __new__(cls, month: vMonth | str | int, params: SupportsKeysAndGetItem[str, str] = {}) -> Self: ... def to_ical(self) -> bytes: ... @classmethod def from_ical(cls, ical: vMonth | str | int) -> Self: ... + @property + def leap(self) -> bool: ... + @leap.setter + def leap(self, value: bool) -> None: ... class vSkip(vText, Enum): OMIT = "OMIT" @@ -198,69 +223,82 @@ class vSkip(vText, Enum): def __reduce_ex__(self, proto: Unused) -> tuple[Any, ...]: ... -class vRecur(CaselessDict[Incomplete]): - frequencies: ClassVar[list[str]] - canonical_order: ClassVar[tuple[str, ...]] - types: ClassVar[CaselessDict[_PropType]] +# The type of the values depend on the key. Each key maps to a v* class, and +# the allowed types are the types that the corresponding v* class can parse. +class vRecur(CaselessDict[Iterable[Any] | Any]): params: Parameters - def __init__(self, *args, **kwargs) -> None: ... + frequencies: Final[list[str]] + canonical_order: ClassVar[tuple[str, ...]] + types: Final[CaselessDict[_PropType]] + def __init__( + self, *args, params: SupportsKeysAndGetItem[str, str] = {}, **kwargs: list[Any] | tuple[Any, ...] | Any + ) -> None: ... def to_ical(self) -> bytes: ... @classmethod - def parse_type(cls, key, values): ... + def parse_type(cls, key: str, values: str) -> list[Any]: ... # Returns a list of v* objects @classmethod - @overload - def from_ical(cls, ical: _vRecurT) -> _vRecurT: ... - @classmethod - @overload - def from_ical(cls, ical: str) -> Self: ... + def from_ical(cls, ical: vRecur | str) -> Self: ... class vTime(TimeBase): - dt: Incomplete + dt: datetime.time | datetime.datetime params: Parameters - def __init__(self, *args) -> None: ... - def to_ical(self) -> bytes: ... + @overload + def __init__(self, dt: datetime.time | datetime.datetime, /) -> None: ... + # args are passed to the datetime.time() constructor + @overload + def __init__( + self, + hour: SupportsIndex = ..., + minute: SupportsIndex = ..., + second: SupportsIndex = ..., + microsecond: SupportsIndex = ..., + tzinfo: datetime.tzinfo | None = ..., + /, + ) -> None: ... + def to_ical(self) -> str: ... @staticmethod - def from_ical(ical): ... + def from_ical(ical: ICAL_TYPE) -> datetime.time: ... class vUri(str): params: Parameters - def __new__(cls, value, encoding="utf-8"): ... + def __new__(cls, value: ICAL_TYPE, encoding: str = "utf-8", params: SupportsKeysAndGetItem[str, str] = {}) -> Self: ... def to_ical(self) -> bytes: ... @classmethod - def from_ical(cls, ical): ... + def from_ical(cls, ical: ICAL_TYPE) -> Self: ... class vGeo: - latitude: Incomplete - longitude: Incomplete + latitude: float + longitude: float params: Parameters - def __init__(self, geo) -> None: ... - def to_ical(self) -> bytes: ... + def __init__(self, geo: tuple[float | str, float | str], params: SupportsKeysAndGetItem[str, str] = {}) -> None: ... + def to_ical(self) -> str: ... @staticmethod - def from_ical(ical): ... - def __eq__(self, other): ... + def from_ical(ical: str) -> tuple[float, float]: ... + def __eq__(self, other: _vType) -> bool: ... # type: ignore[override] class vUTCOffset: ignore_exceptions: bool td: datetime.timedelta params: Parameters - def __init__(self, td: datetime.timedelta) -> None: ... - def to_ical(self) -> bytes: ... + def __init__(self, td: datetime.timedelta, params: SupportsKeysAndGetItem[str, str] = {}) -> None: ... + def to_ical(self) -> str: ... @classmethod - def from_ical(cls, ical): ... + def from_ical(cls, ical: Self | ICAL_TYPE) -> datetime.timedelta: ... def __eq__(self, other: object) -> bool: ... def __hash__(self) -> int: ... class vInline(str): params: Parameters - def __new__(cls, value, encoding="utf-8"): ... + def __new__(cls, value: ICAL_TYPE, encoding: str = "utf-8", params: SupportsKeysAndGetItem[str, str] = {}) -> Self: ... def to_ical(self) -> bytes: ... @classmethod - def from_ical(cls, ical): ... + def from_ical(cls, ical: ICAL_TYPE) -> Self: ... class TypesFactory(CaselessDict[_PropType]): all_types: tuple[_PropType, ...] - def __init__(self, *args, **kwargs) -> None: ... types_map: CaselessDict[str] def for_property(self, name: str) -> _PropType: ... - def to_ical(self, name: str, value) -> bytes: ... - def from_ical(self, name: str, value): ... + # value is str | bytes, depending on what the v* class supports + def to_ical(self, name: str, value: Any) -> bytes: ... + # value and return type depend on what the v* class supports + def from_ical(self, name: str, value: Any) -> Any: ... diff --git a/stubs/icalendar/icalendar/timezone/equivalent_timezone_ids.pyi b/stubs/icalendar/icalendar/timezone/equivalent_timezone_ids.pyi index 046385bb0c92..f07cf5d17bdc 100644 --- a/stubs/icalendar/icalendar/timezone/equivalent_timezone_ids.pyi +++ b/stubs/icalendar/icalendar/timezone/equivalent_timezone_ids.pyi @@ -4,12 +4,10 @@ from typing import Final __all__ = ["main"] -def check(dt: datetime.datetime, tz: datetime.tzinfo) -> tuple[datetime.datetime, datetime.timedelta]: ... -def checks(tz: datetime.tzinfo) -> list[tuple[datetime.datetime, datetime.timedelta]]: ... - START: Final[datetime.datetime] END: Final[datetime.datetime] +DISTANCE_FROM_TIMEZONE_CHANGE: Final[datetime.timedelta] DTS: Final[list[datetime.datetime]] -def main(create_timezones: list[Callable[[str], datetime.tzinfo]], name: str, pool_size: int = ...) -> None: ... +def main(create_timezones: list[Callable[[str], datetime.tzinfo]], name: str) -> None: ...