From ca70b6de1c484bdabedc82c5852be5db91e2f103 Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Thu, 25 Dec 2025 16:48:27 -0600 Subject: [PATCH 1/3] Deprecate curframe_locals --- stdlib/@tests/stubtest_allowlists/py313.txt | 2 ++ stdlib/pdb.pyi | 12 ++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/stdlib/@tests/stubtest_allowlists/py313.txt b/stdlib/@tests/stubtest_allowlists/py313.txt index 12553bf684ee..a79fc83fe0c7 100644 --- a/stdlib/@tests/stubtest_allowlists/py313.txt +++ b/stdlib/@tests/stubtest_allowlists/py313.txt @@ -166,6 +166,8 @@ inspect._ParameterKind.description # Still exists, but stubtest can't see it typing\._SpecialForm.* # Super-special typing primitive typing\.LiteralString # Super-special typing primitive +# Don't always exist at runtime +(pdb.Pdb.curframe_locals)? # ================================================================== # Allowlist entries that cannot or should not be fixed; 3.11 to 3.13 diff --git a/stdlib/pdb.pyi b/stdlib/pdb.pyi index f936e94cda90..99df777e279e 100644 --- a/stdlib/pdb.pyi +++ b/stdlib/pdb.pyi @@ -8,7 +8,7 @@ from linecache import _ModuleGlobals from rlcompleter import Completer from types import CodeType, FrameType, TracebackType from typing import IO, Any, ClassVar, Final, Literal, TypeVar -from typing_extensions import ParamSpec, Self, TypeAlias +from typing_extensions import ParamSpec, Self, TypeAlias, deprecated __all__ = ["run", "pm", "Pdb", "runeval", "runctx", "runcall", "set_trace", "post_mortem", "help"] if sys.version_info >= (3, 14): @@ -60,7 +60,15 @@ class Pdb(Bdb, Cmd): stack: list[tuple[FrameType, int]] curindex: int curframe: FrameType | None - curframe_locals: Mapping[str, Any] + if sys.version_info >= (3, 13): + @property + @deprecated("curframe_locals is deprecated. Derived debuggers should access pdb.Pdb.curframe.f_locals instead.") + def curframe_locals(self) -> Mapping[str, Any]: ... + @curframe_locals.setter + @deprecated("curframe_locals is deprecated. Derived debuggers should access pdb.Pdb.curframe.f_locals instead.") + def curframe_locals(self, value: Mapping[str, Any]) -> None: ... + else: + curframe_locals: Mapping[str, Any] if sys.version_info >= (3, 14): mode: _Mode | None colorize: bool From 38ce56fe873e91673b788a504b780b699cb37dbc Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Thu, 25 Dec 2025 16:50:16 -0600 Subject: [PATCH 2/3] Have deprecation messages match cpython --- stdlib/pdb.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/pdb.pyi b/stdlib/pdb.pyi index 99df777e279e..90f583553ffa 100644 --- a/stdlib/pdb.pyi +++ b/stdlib/pdb.pyi @@ -62,10 +62,10 @@ class Pdb(Bdb, Cmd): curframe: FrameType | None if sys.version_info >= (3, 13): @property - @deprecated("curframe_locals is deprecated. Derived debuggers should access pdb.Pdb.curframe.f_locals instead.") + @deprecated("The frame locals reference is no longer cached. Use 'curframe.f_locals' instead.") def curframe_locals(self) -> Mapping[str, Any]: ... @curframe_locals.setter - @deprecated("curframe_locals is deprecated. Derived debuggers should access pdb.Pdb.curframe.f_locals instead.") + @deprecated("Setting 'curframe_locals' no longer has any effect. Update the contents of 'curframe.f_locals' instead.") def curframe_locals(self, value: Mapping[str, Any]) -> None: ... else: curframe_locals: Mapping[str, Any] From c2672e3dda4e709ad145dc44dacfa8957ce8cffb Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Thu, 25 Dec 2025 16:51:54 -0600 Subject: [PATCH 3/3] tweak deprecation message --- stdlib/pdb.pyi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stdlib/pdb.pyi b/stdlib/pdb.pyi index 90f583553ffa..dc1cf3b28086 100644 --- a/stdlib/pdb.pyi +++ b/stdlib/pdb.pyi @@ -65,7 +65,9 @@ class Pdb(Bdb, Cmd): @deprecated("The frame locals reference is no longer cached. Use 'curframe.f_locals' instead.") def curframe_locals(self) -> Mapping[str, Any]: ... @curframe_locals.setter - @deprecated("Setting 'curframe_locals' no longer has any effect. Update the contents of 'curframe.f_locals' instead.") + @deprecated( + "Setting 'curframe_locals' no longer has any effect as of 3.14. Update the contents of 'curframe.f_locals' instead." + ) def curframe_locals(self, value: Mapping[str, Any]) -> None: ... else: curframe_locals: Mapping[str, Any]