From 2f8a7820f755aa5a2fa07ff35ecf2a8c31089b52 Mon Sep 17 00:00:00 2001 From: Maciej Olko Date: Sun, 14 Dec 2025 23:02:45 +0100 Subject: [PATCH 1/7] Revert datetime-date inheritance --- stdlib/datetime.pyi | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/stdlib/datetime.pyi b/stdlib/datetime.pyi index 8a0536c006d5..a0e99030efab 100644 --- a/stdlib/datetime.pyi +++ b/stdlib/datetime.pyi @@ -243,7 +243,7 @@ class timedelta: def __hash__(self) -> int: ... @disjoint_base -class datetime(date): +class datetime: min: ClassVar[datetime] max: ClassVar[datetime] def __new__( @@ -332,13 +332,12 @@ class datetime(date): def utcoffset(self) -> timedelta | None: ... def tzname(self) -> str | None: ... def dst(self) -> timedelta | None: ... - def __le__(self, value: datetime, /) -> bool: ... # type: ignore[override] - def __lt__(self, value: datetime, /) -> bool: ... # type: ignore[override] - def __ge__(self, value: datetime, /) -> bool: ... # type: ignore[override] - def __gt__(self, value: datetime, /) -> bool: ... # type: ignore[override] + def __le__(self, value: datetime, /) -> bool: ... + def __lt__(self, value: datetime, /) -> bool: ... + def __ge__(self, value: datetime, /) -> bool: ... + def __gt__(self, value: datetime, /) -> bool: ... def __eq__(self, value: object, /) -> bool: ... def __hash__(self) -> int: ... - @overload # type: ignore[override] def __sub__(self, value: Self, /) -> timedelta: ... @overload def __sub__(self, value: timedelta, /) -> Self: ... From a05844292a524fce69c54f7dfbcafca9639221f5 Mon Sep 17 00:00:00 2001 From: Maciej Olko Date: Sun, 14 Dec 2025 23:39:08 +0100 Subject: [PATCH 2/7] Add missing methods stubs --- stdlib/datetime.pyi | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/stdlib/datetime.pyi b/stdlib/datetime.pyi index a0e99030efab..c49c92410156 100644 --- a/stdlib/datetime.pyi +++ b/stdlib/datetime.pyi @@ -246,6 +246,7 @@ class timedelta: class datetime: min: ClassVar[datetime] max: ClassVar[datetime] + resolution: ClassVar[timedelta] def __new__( cls, year: SupportsIndex, @@ -259,6 +260,22 @@ class datetime: *, fold: int = 0, ) -> Self: ... + @classmethod + def fromtimestamp(cls, timestamp: float, /) -> Self: ... + @classmethod + def today(cls) -> Self: ... + @classmethod + def fromordinal(cls, n: int, /) -> Self: ... + @classmethod + def fromisoformat(cls, date_string: str, /) -> Self: ... + @classmethod + def fromisocalendar(cls, year: int, week: int, day: int) -> Self: ... + @property + def year(self) -> int: ... + @property + def month(self) -> int: ... + @property + def day(self) -> int: ... @property def hour(self) -> int: ... @property @@ -271,15 +288,18 @@ class datetime: def tzinfo(self) -> _TzInfo | None: ... @property def fold(self) -> int: ... + def ctime(self) -> str: ... # On <3.12, the name of the first parameter in the pure-Python implementation # didn't match the name in the C implementation, # meaning it is only *safe* to pass it as a keyword argument on 3.12+ if sys.version_info >= (3, 12): @classmethod def fromtimestamp(cls, timestamp: float, tz: _TzInfo | None = None) -> Self: ... + def strftime(self, format: str) -> str: ... else: @classmethod def fromtimestamp(cls, timestamp: float, /, tz: _TzInfo | None = None) -> Self: ... + def strftime(self, format: str, /) -> str: ... @classmethod @deprecated("Use timezone-aware objects to represent datetimes in UTC; e.g. by calling .fromtimestamp(datetime.timezone.utc)") @@ -332,14 +352,21 @@ class datetime: def utcoffset(self) -> timedelta | None: ... def tzname(self) -> str | None: ... def dst(self) -> timedelta | None: ... + def timetuple(self) -> struct_time: ... + def toordinal(self) -> int: ... def __le__(self, value: datetime, /) -> bool: ... def __lt__(self, value: datetime, /) -> bool: ... def __ge__(self, value: datetime, /) -> bool: ... def __gt__(self, value: datetime, /) -> bool: ... def __eq__(self, value: object, /) -> bool: ... def __hash__(self) -> int: ... + def __add__(self, value: timedelta, /) -> Self: ... + def __radd__(self, value: timedelta, /) -> Self: ... def __sub__(self, value: Self, /) -> timedelta: ... @overload def __sub__(self, value: timedelta, /) -> Self: ... + def weekday(self) -> int: ... + def isoweekday(self) -> int: ... + def isocalendar(self) -> _IsoCalendarDate: ... datetime_CAPI: CapsuleType From 6122c725a672025f9c4581adc246c26362f82500 Mon Sep 17 00:00:00 2001 From: Maciej Olko Date: Tue, 16 Dec 2025 00:49:12 +0100 Subject: [PATCH 3/7] fromtimestamp already declared lower on datetime --- stdlib/datetime.pyi | 2 -- 1 file changed, 2 deletions(-) diff --git a/stdlib/datetime.pyi b/stdlib/datetime.pyi index c49c92410156..fd5c423aab8d 100644 --- a/stdlib/datetime.pyi +++ b/stdlib/datetime.pyi @@ -261,8 +261,6 @@ class datetime: fold: int = 0, ) -> Self: ... @classmethod - def fromtimestamp(cls, timestamp: float, /) -> Self: ... - @classmethod def today(cls) -> Self: ... @classmethod def fromordinal(cls, n: int, /) -> Self: ... From 285f1a8f2008c10340d59193e4a066651353ddb8 Mon Sep 17 00:00:00 2001 From: Maciej Olko Date: Tue, 16 Dec 2025 00:51:47 +0100 Subject: [PATCH 4/7] revert the overload decorator for __sub__ --- stdlib/datetime.pyi | 1 + 1 file changed, 1 insertion(+) diff --git a/stdlib/datetime.pyi b/stdlib/datetime.pyi index fd5c423aab8d..6fd01163ea42 100644 --- a/stdlib/datetime.pyi +++ b/stdlib/datetime.pyi @@ -360,6 +360,7 @@ class datetime: def __hash__(self) -> int: ... def __add__(self, value: timedelta, /) -> Self: ... def __radd__(self, value: timedelta, /) -> Self: ... + @overload def __sub__(self, value: Self, /) -> timedelta: ... @overload def __sub__(self, value: timedelta, /) -> Self: ... From a888e730fc0228f79cf4103a1f7e8b8064fa3dd7 Mon Sep 17 00:00:00 2001 From: Maciej Olko Date: Tue, 16 Dec 2025 22:01:32 +0100 Subject: [PATCH 5/7] Update icalendar stubs for the datetime inheritance removal --- stubs/icalendar/icalendar/tools.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stubs/icalendar/icalendar/tools.pyi b/stubs/icalendar/icalendar/tools.pyi index d63d649f8041..a91fd8198b68 100644 --- a/stubs/icalendar/icalendar/tools.pyi +++ b/stubs/icalendar/icalendar/tools.pyi @@ -18,7 +18,7 @@ class UIDGenerator: def uid(host_name: str = "example.com", unique: str = "") -> vText: ... def is_date(dt: datetime.date) -> bool: ... # and not datetime.date -def is_datetime(dt: datetime.date) -> TypeIs[datetime.datetime]: ... +def is_datetime(dt: datetime.date) -> Literal[False]: ... def to_datetime(dt: datetime.date) -> datetime.datetime: ... def is_pytz(tz: datetime.tzinfo) -> TypeIs[BaseTzInfo]: ... def is_pytz_dt(dt: datetime.date) -> TypeGuard[datetime.datetime]: ... # and dt.tzinfo is BaseTZInfo From 5eee010259a374dc2cec20d65a626062b31ce105 Mon Sep 17 00:00:00 2001 From: Maciej Olko Date: Tue, 16 Dec 2025 22:02:32 +0100 Subject: [PATCH 6/7] Update pony stubs for the datetime inheritance removal --- stubs/pony/pony/orm/sqltranslation.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stubs/pony/pony/orm/sqltranslation.pyi b/stubs/pony/pony/orm/sqltranslation.pyi index 816405de10c2..607b29571d69 100644 --- a/stubs/pony/pony/orm/sqltranslation.pyi +++ b/stubs/pony/pony/orm/sqltranslation.pyi @@ -620,7 +620,7 @@ class FuncTimedeltaMonad(FuncMonad): func: type[timedelta] def call(monad, days=None, seconds=None, microseconds=None, milliseconds=None, minutes=None, hours=None, weeks=None): ... -class FuncDatetimeMonad(FuncDateMonad): +class FuncDatetimeMonad(FuncMonad): func: type[datetime] def call(monad, year, month, day, hour=None, minute=None, second=None, microsecond=None): ... def call_now(monad): ... From 4dcc406e5e30fc48bc4e31b54c477aab8fd26125 Mon Sep 17 00:00:00 2001 From: Maciej Olko Date: Tue, 16 Dec 2025 22:32:28 +0100 Subject: [PATCH 7/7] Update icalendar stub for the datetime inheritance removal --- stubs/icalendar/icalendar/tools.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stubs/icalendar/icalendar/tools.pyi b/stubs/icalendar/icalendar/tools.pyi index a91fd8198b68..087f6d40d13d 100644 --- a/stubs/icalendar/icalendar/tools.pyi +++ b/stubs/icalendar/icalendar/tools.pyi @@ -1,6 +1,6 @@ import datetime from typing import Final -from typing_extensions import TypeGuard, TypeIs, deprecated +from typing_extensions import Literal, TypeGuard, TypeIs, deprecated from pytz.tzinfo import BaseTzInfo @@ -17,7 +17,7 @@ class UIDGenerator: @deprecated("Use the Python standard library's :func:`uuid.uuid5` instead.") def uid(host_name: str = "example.com", unique: str = "") -> vText: ... -def is_date(dt: datetime.date) -> bool: ... # and not datetime.date +def is_date(dt: datetime.date) -> Literal[True]: ... # and not datetime.date def is_datetime(dt: datetime.date) -> Literal[False]: ... def to_datetime(dt: datetime.date) -> datetime.datetime: ... def is_pytz(tz: datetime.tzinfo) -> TypeIs[BaseTzInfo]: ...