From a631519c3c5f4e1f85dbf2edb863b87e79b4274b Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Fri, 8 May 2026 12:38:57 -0700 Subject: [PATCH 1/2] Add Python 3.15 calendar datetime and difflib updates --- stdlib/@tests/stubtest_allowlists/py315.txt | 11 ------ stdlib/calendar.pyi | 11 ++++++ stdlib/datetime.pyi | 12 ++++--- stdlib/difflib.pyi | 37 +++++++++++++++------ 4 files changed, 45 insertions(+), 26 deletions(-) diff --git a/stdlib/@tests/stubtest_allowlists/py315.txt b/stdlib/@tests/stubtest_allowlists/py315.txt index cd9095754ce7..0570e5d6481b 100644 --- a/stdlib/@tests/stubtest_allowlists/py315.txt +++ b/stdlib/@tests/stubtest_allowlists/py315.txt @@ -118,10 +118,6 @@ binascii.b2a_base64 binascii.b2a_base85 binascii.unhexlify cProfile.label -calendar.HTMLCalendar.formatmonthpage -calendar.__all__ -calendar.standalone_month_abbr -calendar.standalone_month_name codecs.backslashreplace_errors codecs.ignore_errors codecs.namereplace_errors @@ -146,16 +142,9 @@ ctypes.SetPointerType dataclasses._MISSING_TYPE dataclasses.MISSING dataclasses.field -datetime.date.fromisoformat -datetime.date.strptime -datetime.datetime.fromisoformat -datetime.datetime.strptime -datetime.time.fromisoformat -datetime.time.strptime dbm.dumb._Database.reorganize dbm.sqlite3.REORGANIZE dbm.sqlite3._Database.reorganize -difflib.unified_diff doctest.DocTestRunner.report_skip enum.__all__ enum.auto.__init__ diff --git a/stdlib/calendar.pyi b/stdlib/calendar.pyi index 81c4ccf239c1..4e5ec628e27c 100644 --- a/stdlib/calendar.pyi +++ b/stdlib/calendar.pyi @@ -57,6 +57,8 @@ if sys.version_info >= (3, 12): "NOVEMBER", "DECEMBER", ] +if sys.version_info >= (3, 15): + __all__ += ["standalone_month_name", "standalone_month_abbr"] _LocaleType: TypeAlias = tuple[str | None, str | None] @@ -127,6 +129,11 @@ class HTMLCalendar(Calendar): def formatweekheader(self) -> str: ... def formatmonthname(self, theyear: int, themonth: int, withyear: bool = True) -> str: ... def formatmonth(self, theyear: int, themonth: int, withyear: bool = True) -> str: ... + if sys.version_info >= (3, 15): + def formatmonthpage( + self, theyear: int, themonth: int, width: int = 3, css: str | None = "calendar.css", encoding: str | None = None + ) -> bytes: ... + def formatyear(self, theyear: int, width: int = 3) -> str: ... def formatyearpage( self, theyear: int, width: int = 3, css: str | None = "calendar.css", encoding: str | None = None @@ -212,3 +219,7 @@ else: SUNDAY: Final = 6 EPOCH: Final = 1970 + +if sys.version_info >= (3, 15): + standalone_month_name: Sequence[str] + standalone_month_abbr: Sequence[str] diff --git a/stdlib/datetime.pyi b/stdlib/datetime.pyi index 225f95da4f6f..61c1f8583d77 100644 --- a/stdlib/datetime.pyi +++ b/stdlib/datetime.pyi @@ -64,7 +64,7 @@ class date: @classmethod def fromordinal(cls, n: int, /) -> Self: ... @classmethod - def fromisoformat(cls, date_string: str, /) -> Self: ... + def fromisoformat(cls, string: str, /) -> Self: ... @classmethod def fromisocalendar(cls, year: int, week: int, day: int) -> Self: ... @property @@ -77,7 +77,7 @@ class date: if sys.version_info >= (3, 14): @classmethod - def strptime(cls, date_string: str, format: str, /) -> Self: ... + def strptime(cls, string: str, format: str, /) -> Self: ... # On <3.12, the name of the parameter in the pure-Python implementation # didn't match the name in the C implementation, @@ -148,11 +148,11 @@ class time: def __hash__(self) -> int: ... def isoformat(self, timespec: str = "auto") -> str: ... @classmethod - def fromisoformat(cls, time_string: str, /) -> Self: ... + def fromisoformat(cls, string: str, /) -> Self: ... if sys.version_info >= (3, 14): @classmethod - def strptime(cls, date_string: str, format: str, /) -> Self: ... + def strptime(cls, string: str, format: str, /) -> Self: ... # On <3.12, the name of the parameter in the pure-Python implementation # didn't match the name in the C implementation, @@ -291,6 +291,8 @@ class datetime(date): def utcnow(cls) -> Self: ... @classmethod def combine(cls, date: _Date, time: _Time, tzinfo: _TzInfo | None = ...) -> Self: ... + @classmethod + def fromisoformat(cls, string: str, /) -> Self: ... def timestamp(self) -> float: ... def utctimetuple(self) -> struct_time: ... def date(self) -> _Date: ... @@ -328,7 +330,7 @@ class datetime(date): def astimezone(self, tz: _TzInfo | None = None) -> Self: ... def isoformat(self, sep: str = "T", timespec: str = "auto") -> str: ... @classmethod - def strptime(cls, date_string: str, format: str, /) -> Self: ... + def strptime(cls, string: str, format: str, /) -> Self: ... def utcoffset(self) -> timedelta | None: ... def tzname(self) -> str | None: ... def dst(self) -> timedelta | None: ... diff --git a/stdlib/difflib.pyi b/stdlib/difflib.pyi index 6efe68322bb6..4ab59ac637b2 100644 --- a/stdlib/difflib.pyi +++ b/stdlib/difflib.pyi @@ -69,16 +69,33 @@ else: def IS_LINE_JUNK(line: str, pat: Callable[[str], re.Match[str] | None] = ...) -> bool: ... def IS_CHARACTER_JUNK(ch: str, ws: str = " \t") -> bool: ... # ws is undocumented -def unified_diff( - a: Sequence[str], - b: Sequence[str], - fromfile: str = "", - tofile: str = "", - fromfiledate: str = "", - tofiledate: str = "", - n: int = 3, - lineterm: str = "\n", -) -> Iterator[str]: ... + +if sys.version_info >= (3, 15): + def unified_diff( + a: Sequence[str], + b: Sequence[str], + fromfile: str = "", + tofile: str = "", + fromfiledate: str = "", + tofiledate: str = "", + n: int = 3, + lineterm: str = "\n", + *, + color: bool = False, + ) -> Iterator[str]: ... + +else: + def unified_diff( + a: Sequence[str], + b: Sequence[str], + fromfile: str = "", + tofile: str = "", + fromfiledate: str = "", + tofiledate: str = "", + n: int = 3, + lineterm: str = "\n", + ) -> Iterator[str]: ... + def context_diff( a: Sequence[str], b: Sequence[str], From 5b9fc3d22bf6130f9e0736be8663d6dcbe42ca62 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Fri, 8 May 2026 13:01:00 -0700 Subject: [PATCH 2/2] Guard datetime 3.15 parameter names --- stdlib/datetime.pyi | 48 +++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/stdlib/datetime.pyi b/stdlib/datetime.pyi index 61c1f8583d77..5b109d922f3a 100644 --- a/stdlib/datetime.pyi +++ b/stdlib/datetime.pyi @@ -63,8 +63,13 @@ class date: def today(cls) -> Self: ... @classmethod def fromordinal(cls, n: int, /) -> Self: ... - @classmethod - def fromisoformat(cls, string: str, /) -> Self: ... + if sys.version_info >= (3, 15): + @classmethod + def fromisoformat(cls, string: str, /) -> Self: ... + else: + @classmethod + def fromisoformat(cls, date_string: str, /) -> Self: ... + @classmethod def fromisocalendar(cls, year: int, week: int, day: int) -> Self: ... @property @@ -76,8 +81,12 @@ class date: def ctime(self) -> str: ... if sys.version_info >= (3, 14): - @classmethod - def strptime(cls, string: str, format: str, /) -> Self: ... + if sys.version_info >= (3, 15): + @classmethod + def strptime(cls, string: str, format: str, /) -> Self: ... + else: + @classmethod + def strptime(cls, date_string: str, format: str, /) -> Self: ... # On <3.12, the name of the parameter in the pure-Python implementation # didn't match the name in the C implementation, @@ -147,12 +156,20 @@ class time: def __eq__(self, value: object, /) -> bool: ... def __hash__(self) -> int: ... def isoformat(self, timespec: str = "auto") -> str: ... - @classmethod - def fromisoformat(cls, string: str, /) -> Self: ... + if sys.version_info >= (3, 15): + @classmethod + def fromisoformat(cls, string: str, /) -> Self: ... + else: + @classmethod + def fromisoformat(cls, time_string: str, /) -> Self: ... if sys.version_info >= (3, 14): - @classmethod - def strptime(cls, string: str, format: str, /) -> Self: ... + if sys.version_info >= (3, 15): + @classmethod + def strptime(cls, string: str, format: str, /) -> Self: ... + else: + @classmethod + def strptime(cls, date_string: str, format: str, /) -> Self: ... # On <3.12, the name of the parameter in the pure-Python implementation # didn't match the name in the C implementation, @@ -291,8 +308,10 @@ class datetime(date): def utcnow(cls) -> Self: ... @classmethod def combine(cls, date: _Date, time: _Time, tzinfo: _TzInfo | None = ...) -> Self: ... - @classmethod - def fromisoformat(cls, string: str, /) -> Self: ... + if sys.version_info >= (3, 15): + @classmethod + def fromisoformat(cls, string: str, /) -> Self: ... + def timestamp(self) -> float: ... def utctimetuple(self) -> struct_time: ... def date(self) -> _Date: ... @@ -329,8 +348,13 @@ class datetime(date): ) -> Self: ... def astimezone(self, tz: _TzInfo | None = None) -> Self: ... def isoformat(self, sep: str = "T", timespec: str = "auto") -> str: ... - @classmethod - def strptime(cls, string: str, format: str, /) -> Self: ... + if sys.version_info >= (3, 15): + @classmethod + def strptime(cls, string: str, format: str, /) -> Self: ... + else: + @classmethod + def strptime(cls, date_string: str, format: str, /) -> Self: ... + def utcoffset(self) -> timedelta | None: ... def tzname(self) -> str | None: ... def dst(self) -> timedelta | None: ...