From 4fd34d2e51bb3ed44ec24a286d328b2c84e69e71 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Mon, 24 Mar 2025 10:38:45 +0900 Subject: [PATCH 01/13] PEP 781: Adding __type_checking__ constant --- peps/pep-0781.rst | 87 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 peps/pep-0781.rst diff --git a/peps/pep-0781.rst b/peps/pep-0781.rst new file mode 100644 index 00000000000..cd718507585 --- /dev/null +++ b/peps/pep-0781.rst @@ -0,0 +1,87 @@ +PEP: 781 +Title: Adding __type_checking__ constant +Author: Inada Naoki +Discussions-To: https://discuss.python.org/t/85728 +Status: Draft +Type: Standards Track +Topic: Typing +Created: 24-Mar-2025 +Python-Version: 3.14 + + +Abstract +======== + +This PEP proposes adding a new keyword ``__type_checking__`` that serves the +same purpose as ``typing.TYPE_CHECKING``. +This constant is ``True`` when the code is being analyzed by a static type +checker, and ``False`` during normal runtime execution. + + +Motivation +========== + +For libraries that may be used in scripts where startup time is critical, +the time taken to import the ``typing`` module cannot be ignored. + +To avoid importing ``typing``, developers currently define a module-level +variable ``TYPE_CHECKING = False`` or use code like +``if False: # TYPE_CHECKING``. +Providing a standard method will allow many tools to implement the same +behavior consistently. + +Furthermore, this allows compilers to eliminate type-checking-only code at +compile time. This reduces bytecode size and memory usage, +and would help with writing type-hinted code for memory-constrained +environments like WASM or micropython. + + +Specification +============= + +``__type_checking__`` is a keyword and its value is ``False``. +It can be used in the same way as ``False``, except it can not be used as +a matching pattern. + +Similar to typing.TYPE_CHECKING, type checking tools should treat +``__type_checking__`` as True. + + +Rationale +========= + +Difference from ``__debug__`` +----------------------------- + +``__debug__`` is not a keyword, but a built-in constant. +Not adding a new keyword is attractive, but it requires special handling in +both the compiler and the runtime to change the value of the constant +depending on the startup option. + +By implementing ``__type_checking__`` the same way as ``False``, +we avoid the need for special handling in both the compiler and runtime. +Therefore, making it a keyword is the simpler approach. + + +How to teach this +================= + +Add this note to the ``typing.TYPE_CHECKING`` document: + +> If you don't want to import ``typing``, you can use ``__type_checking__``. +> Workaround like ``TYPE_CHECKING = False`` or +> ``if False: # TYPE_CHECKING`` are not recommended since Python 3.14. + + +Resources +========= + +* Previous discussion: https://discuss.python.org/t/76766 +* Reference Implementation: https://github.com/python/cpython/pull/131641 + + +Copyright +========= + +This document is placed in the public domain or under the +CC0-1.0-Universal license, whichever is more permissive. From f94601cf22d35d3a755b7578f28ca827f40cb4e2 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Tue, 25 Mar 2025 08:54:48 +0900 Subject: [PATCH 02/13] Apply suggestions from code review Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- peps/pep-0781.rst | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/peps/pep-0781.rst b/peps/pep-0781.rst index cd718507585..8320870e356 100644 --- a/peps/pep-0781.rst +++ b/peps/pep-0781.rst @@ -13,7 +13,7 @@ Abstract ======== This PEP proposes adding a new keyword ``__type_checking__`` that serves the -same purpose as ``typing.TYPE_CHECKING``. +same purpose as :data:`typing.TYPE_CHECKING`. This constant is ``True`` when the code is being analyzed by a static type checker, and ``False`` during normal runtime execution. @@ -43,8 +43,8 @@ Specification It can be used in the same way as ``False``, except it can not be used as a matching pattern. -Similar to typing.TYPE_CHECKING, type checking tools should treat -``__type_checking__`` as True. +Similar to :data:`typing.TYPE_CHECKING`, type checking tools should treat +``__type_checking__`` as ``True``. Rationale @@ -69,15 +69,14 @@ How to teach this Add this note to the ``typing.TYPE_CHECKING`` document: > If you don't want to import ``typing``, you can use ``__type_checking__``. -> Workaround like ``TYPE_CHECKING = False`` or +> Workarounds like ``TYPE_CHECKING = False`` or > ``if False: # TYPE_CHECKING`` are not recommended since Python 3.14. -Resources -========= +Reference Implementation +======================== -* Previous discussion: https://discuss.python.org/t/76766 -* Reference Implementation: https://github.com/python/cpython/pull/131641 +* `python/cpython#131641 `__ Copyright From a173c94c8c79ecfaa3b8ed15cce74ea73fb59119 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Tue, 25 Mar 2025 09:15:36 +0900 Subject: [PATCH 03/13] apply suggestions --- .github/CODEOWNERS | 2 ++ peps/pep-0781.rst | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5c50eff6393..1a6d70ec12e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -659,6 +659,8 @@ peps/pep-0777.rst @warsaw # ... peps/pep-0779.rst @Yhg1s @colesbury @mpage # ... +peps/pep-0781.rst @methane +# ... peps/pep-0789.rst @njsmith # ... peps/pep-0801.rst @warsaw diff --git a/peps/pep-0781.rst b/peps/pep-0781.rst index 8320870e356..b6faf4e4a23 100644 --- a/peps/pep-0781.rst +++ b/peps/pep-0781.rst @@ -2,6 +2,7 @@ PEP: 781 Title: Adding __type_checking__ constant Author: Inada Naoki Discussions-To: https://discuss.python.org/t/85728 +Post-History: 11-Jan-2025 https://discuss.python.org/t/76766 Status: Draft Type: Standards Track Topic: Typing @@ -39,7 +40,8 @@ environments like WASM or micropython. Specification ============= -``__type_checking__`` is a keyword and its value is ``False``. +``__type_checking__`` is a :ref:`keyword ` and its value is +``False``. It can be used in the same way as ``False``, except it can not be used as a matching pattern. @@ -53,7 +55,7 @@ Rationale Difference from ``__debug__`` ----------------------------- -``__debug__`` is not a keyword, but a built-in constant. +:data:`__debug__` is not a keyword, but a built-in constant. Not adding a new keyword is attractive, but it requires special handling in both the compiler and the runtime to change the value of the constant depending on the startup option. From 1651246a4cec3fc0f3a18c18f7efa22e5dad5f93 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Tue, 25 Mar 2025 09:28:11 +0900 Subject: [PATCH 04/13] update based on latest template --- peps/pep-0781.rst | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/peps/pep-0781.rst b/peps/pep-0781.rst index b6faf4e4a23..fd0d5b755ef 100644 --- a/peps/pep-0781.rst +++ b/peps/pep-0781.rst @@ -37,6 +37,24 @@ and would help with writing type-hinted code for memory-constrained environments like WASM or micropython. +Rationale +========= + +Using Keyword +------------- + +Avoiding the addition of a new :ref:`keyword ` +(like :data:`__debug__`) would be attractive because more keywords means more +complex language. + +However, adding a constant without a keyword (like :data:`__debug__`) requires +special handling in both the compiler and runtime. + +By implementing ``__type_checking__`` the same way as ``False``, we avoid the +need for the special handling. +Therefore, making it a keyword is the simpler approach. + + Specification ============= @@ -49,23 +67,7 @@ Similar to :data:`typing.TYPE_CHECKING`, type checking tools should treat ``__type_checking__`` as ``True``. -Rationale -========= - -Difference from ``__debug__`` ------------------------------ - -:data:`__debug__` is not a keyword, but a built-in constant. -Not adding a new keyword is attractive, but it requires special handling in -both the compiler and the runtime to change the value of the constant -depending on the startup option. - -By implementing ``__type_checking__`` the same way as ``False``, -we avoid the need for special handling in both the compiler and runtime. -Therefore, making it a keyword is the simpler approach. - - -How to teach this +How to Teach This ================= Add this note to the ``typing.TYPE_CHECKING`` document: From a9429265092d877c528e201f6ed23ed02ac5ac87 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Tue, 25 Mar 2025 09:42:03 +0900 Subject: [PATCH 05/13] update based on the feedback from the discussion --- peps/pep-0781.rst | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/peps/pep-0781.rst b/peps/pep-0781.rst index fd0d5b755ef..8d0ec8f907c 100644 --- a/peps/pep-0781.rst +++ b/peps/pep-0781.rst @@ -2,12 +2,12 @@ PEP: 781 Title: Adding __type_checking__ constant Author: Inada Naoki Discussions-To: https://discuss.python.org/t/85728 -Post-History: 11-Jan-2025 https://discuss.python.org/t/76766 Status: Draft Type: Standards Track Topic: Typing Created: 24-Mar-2025 Python-Version: 3.14 +Post-History: `11-Jan-2025 `__ Abstract @@ -66,15 +66,19 @@ a matching pattern. Similar to :data:`typing.TYPE_CHECKING`, type checking tools should treat ``__type_checking__`` as ``True``. +Once this PEP is accepted, ``__type_checking__`` will be the preferred way over +``typing.TYPE_CHECKING``. However, ``typing.TYPE_CHECKING`` will not be deprecated. +Instead, it will be implemented using ``__type_checking__``, allowing future type +checkers to focus on handling ``__type_checking__`` only. + How to Teach This ================= -Add this note to the ``typing.TYPE_CHECKING`` document: - -> If you don't want to import ``typing``, you can use ``__type_checking__``. -> Workarounds like ``TYPE_CHECKING = False`` or -> ``if False: # TYPE_CHECKING`` are not recommended since Python 3.14. +* Use ``__type_checking__`` for skipping type-checking code at runtime. +* Use :data:`typing.TYPE_CHECKING` to support Python versions before 3.14. +* Workarounds like ``TYPE_CHECKING = False`` or ``if False: # TYPE_CHECKING`` + are not recommended since Python 3.14. Reference Implementation From 059873039b661146b622dedeaef0139223d2b993 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Wed, 26 Mar 2025 21:01:31 +0900 Subject: [PATCH 06/13] Apply suggestions from code review Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- peps/pep-0781.rst | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/peps/pep-0781.rst b/peps/pep-0781.rst index 8d0ec8f907c..2ce4e4926bb 100644 --- a/peps/pep-0781.rst +++ b/peps/pep-0781.rst @@ -7,16 +7,20 @@ Type: Standards Track Topic: Typing Created: 24-Mar-2025 Python-Version: 3.14 +Post-History: `11-Jan-2025 `__, + `24-Mar-2025 `__, Post-History: `11-Jan-2025 `__ Abstract ======== -This PEP proposes adding a new keyword ``__type_checking__`` that serves the -same purpose as :data:`typing.TYPE_CHECKING`. -This constant is ``True`` when the code is being analyzed by a static type -checker, and ``False`` during normal runtime execution. +This PEP proposes adding a new keyword, :data:`!__type_checking__`, to improve +the experience of writing Python code with type annotations. It is evaluated +as ``True`` when the code is being analyzed by a static type checker, and as +``False`` during normal runtime execution. Unlike :data:`typing.TYPE_CHECKING`, +which this keyword replaces, it does not require an import statement, and +creates the opportunity for compiler optimizations, such as smaller bytecode. Motivation @@ -44,8 +48,8 @@ Using Keyword ------------- Avoiding the addition of a new :ref:`keyword ` -(like :data:`__debug__`) would be attractive because more keywords means more -complex language. +(like :data:`__debug__`) would be attractive because more keywords means +a more complex language. However, adding a constant without a keyword (like :data:`__debug__`) requires special handling in both the compiler and runtime. @@ -60,16 +64,17 @@ Specification ``__type_checking__`` is a :ref:`keyword ` and its value is ``False``. -It can be used in the same way as ``False``, except it can not be used as +It can be used in the same way as ``False``, except it cannot be used as a matching pattern. -Similar to :data:`typing.TYPE_CHECKING`, type checking tools should treat -``__type_checking__`` as ``True``. +Static type checkers must treat ``__type_checking__`` as ``True``, +similar to :data:`typing.TYPE_CHECKING`. -Once this PEP is accepted, ``__type_checking__`` will be the preferred way over -``typing.TYPE_CHECKING``. However, ``typing.TYPE_CHECKING`` will not be deprecated. -Instead, it will be implemented using ``__type_checking__``, allowing future type -checkers to focus on handling ``__type_checking__`` only. +If this PEP is accepted, ``__type_checking__`` will be the preferred approach, +instead of ``typing.TYPE_CHECKING``. However, ``typing.TYPE_CHECKING`` will not +be deprecated. +Instead, it will be implemented as ``TYPE_CHECKING = __type_checking__``, +allowing future type checkers to focus on only handling ``__type_checking__``. How to Teach This From aa9dcfee067c039368fba9e4710bafd8a96275e4 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Wed, 26 Mar 2025 21:27:34 +0900 Subject: [PATCH 07/13] Apply suggestions from code review Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- peps/pep-0781.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/peps/pep-0781.rst b/peps/pep-0781.rst index 2ce4e4926bb..f8cf701ad10 100644 --- a/peps/pep-0781.rst +++ b/peps/pep-0781.rst @@ -9,7 +9,6 @@ Created: 24-Mar-2025 Python-Version: 3.14 Post-History: `11-Jan-2025 `__, `24-Mar-2025 `__, -Post-History: `11-Jan-2025 `__ Abstract From 179c1b6e59d60783bc2246ef245ee24b842d7309 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Wed, 26 Mar 2025 21:29:09 +0900 Subject: [PATCH 08/13] Apply suggestions from code review Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> --- peps/pep-0781.rst | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/peps/pep-0781.rst b/peps/pep-0781.rst index f8cf701ad10..904cea02316 100644 --- a/peps/pep-0781.rst +++ b/peps/pep-0781.rst @@ -25,19 +25,37 @@ creates the opportunity for compiler optimizations, such as smaller bytecode. Motivation ========== -For libraries that may be used in scripts where startup time is critical, -the time taken to import the ``typing`` module cannot be ignored. - -To avoid importing ``typing``, developers currently define a module-level -variable ``TYPE_CHECKING = False`` or use code like -``if False: # TYPE_CHECKING``. -Providing a standard method will allow many tools to implement the same -behavior consistently. +Type annotations were defined for Python by :pep:`484`, and have enjoyed +widespread adoption. A challenge with fully-annotated code is that many +more imports are required in order to bring the relevant name into scope, +potentially causing import cycles without careful design. This has been +recognized by :pep:`563` and later :pep`649`, which introduce two different +mechanisms for deferred evaluation of type annotations. As :pep:`!563` notes, +"type hints are ... not computationally free". The :data:`typing.TYPE_CHECKING` +constant was thus introduced__, initially to aid in breaking cyclic imports. + +__ https://github.com/python/typing/issues/230 + +In situations where startup time is critical, such as command-line interfaces, +applications, or core libraries, programmers may place all import statements +not required for runtime execution within a 'TYPE_CHECKING block', or even +defer certain imports to within functions. The ``typing`` module itself though +can take as much as 10ms to import, longer than Python takes to initialize. +The time taken to import the ``typing`` module clearly cannot be ignored. + +To avoid importing ``TYPE_CHECKING`` from ``typing``, developers currently +define a module-level variable such as ``TYPE_CHECKING = False`` or use code +like ``if False: # TYPE_CHECKING``. Providing a standard method will allow +many tools to implement the same behavior consistently. It will also allow +third-party tools in the ecosystem to standardize on a single behavior +with guaranteed semantics, as for example some static type checkers currently +do not permit local constants, only recognizing ``typing.TYPE_CHECKING``. Furthermore, this allows compilers to eliminate type-checking-only code at -compile time. This reduces bytecode size and memory usage, -and would help with writing type-hinted code for memory-constrained -environments like WASM or micropython. +compile time, as the constant is guaranteed to be ``False`` and cannot be +reassigned. This reduces bytecode size and memory usage, and would help with +writing type-annotated code for memory-constrained environments such as WASM +or MicroPython. Rationale From ddc30759360b4642555df92ceead86e042b66abf Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+AA-Turner@users.noreply.github.com> Date: Wed, 26 Mar 2025 14:19:36 +0000 Subject: [PATCH 09/13] fix an incorrect role Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- peps/pep-0781.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peps/pep-0781.rst b/peps/pep-0781.rst index 904cea02316..b249fa52aaa 100644 --- a/peps/pep-0781.rst +++ b/peps/pep-0781.rst @@ -29,7 +29,7 @@ Type annotations were defined for Python by :pep:`484`, and have enjoyed widespread adoption. A challenge with fully-annotated code is that many more imports are required in order to bring the relevant name into scope, potentially causing import cycles without careful design. This has been -recognized by :pep:`563` and later :pep`649`, which introduce two different +recognized by :pep:`563` and later :pep:`649`, which introduce two different mechanisms for deferred evaluation of type annotations. As :pep:`!563` notes, "type hints are ... not computationally free". The :data:`typing.TYPE_CHECKING` constant was thus introduced__, initially to aid in breaking cyclic imports. From e915074615c6966a6bec7c9e1da8e4d8fc2e2c64 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+AA-Turner@users.noreply.github.com> Date: Wed, 26 Mar 2025 14:22:32 +0000 Subject: [PATCH 10/13] The pep role doesn't support suppressed cross-references --- peps/pep-0781.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peps/pep-0781.rst b/peps/pep-0781.rst index b249fa52aaa..e93b5680e13 100644 --- a/peps/pep-0781.rst +++ b/peps/pep-0781.rst @@ -30,7 +30,7 @@ widespread adoption. A challenge with fully-annotated code is that many more imports are required in order to bring the relevant name into scope, potentially causing import cycles without careful design. This has been recognized by :pep:`563` and later :pep:`649`, which introduce two different -mechanisms for deferred evaluation of type annotations. As :pep:`!563` notes, +mechanisms for deferred evaluation of type annotations. As PEP 563 notes, "type hints are ... not computationally free". The :data:`typing.TYPE_CHECKING` constant was thus introduced__, initially to aid in breaking cyclic imports. From 0cb92cb4c3a252c4ff6d3ae7047c0bbc4f32239e Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Thu, 27 Mar 2025 21:01:27 +0900 Subject: [PATCH 11/13] Add TYPE_CHECKING, not __type_checking__. --- peps/pep-0781.rst | 82 +++++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/peps/pep-0781.rst b/peps/pep-0781.rst index e93b5680e13..9935fd86a0e 100644 --- a/peps/pep-0781.rst +++ b/peps/pep-0781.rst @@ -1,5 +1,5 @@ PEP: 781 -Title: Adding __type_checking__ constant +Title: Make ``TYPE_CHECKING`` builtin Author: Inada Naoki Discussions-To: https://discuss.python.org/t/85728 Status: Draft @@ -14,12 +14,11 @@ Post-History: `11-Jan-2025 `__, Abstract ======== -This PEP proposes adding a new keyword, :data:`!__type_checking__`, to improve +This PEP proposes adding a new builtin, :data:`!TYPE_CHECKING`, to improve the experience of writing Python code with type annotations. It is evaluated as ``True`` when the code is being analyzed by a static type checker, and as ``False`` during normal runtime execution. Unlike :data:`typing.TYPE_CHECKING`, -which this keyword replaces, it does not require an import statement, and -creates the opportunity for compiler optimizations, such as smaller bytecode. +which this keyword replaces, it does not require an import statement. Motivation @@ -30,7 +29,7 @@ widespread adoption. A challenge with fully-annotated code is that many more imports are required in order to bring the relevant name into scope, potentially causing import cycles without careful design. This has been recognized by :pep:`563` and later :pep:`649`, which introduce two different -mechanisms for deferred evaluation of type annotations. As PEP 563 notes, +mechanisms for deferred evaluation of type annotations. As :pep:`563` notes, "type hints are ... not computationally free". The :data:`typing.TYPE_CHECKING` constant was thus introduced__, initially to aid in breaking cyclic imports. @@ -51,62 +50,67 @@ third-party tools in the ecosystem to standardize on a single behavior with guaranteed semantics, as for example some static type checkers currently do not permit local constants, only recognizing ``typing.TYPE_CHECKING``. -Furthermore, this allows compilers to eliminate type-checking-only code at -compile time, as the constant is guaranteed to be ``False`` and cannot be -reassigned. This reduces bytecode size and memory usage, and would help with -writing type-annotated code for memory-constrained environments such as WASM -or MicroPython. +Specification +============= -Rationale -========= +``TYPE_CHECKING`` is a built-in constant and its value is ``False``. +Unlike ``True``, ``False``, ``None``, and ``__debug__``, ``TYPE_CHECKING`` is +not a real constant; assigning to it will not raise a ``SyntaxError``. -Using Keyword -------------- +Static type checkers must treat ``TYPE_CHECKING`` as ``True``, similar to +:data:`typing.TYPE_CHECKING`. -Avoiding the addition of a new :ref:`keyword ` -(like :data:`__debug__`) would be attractive because more keywords means -a more complex language. +If this PEP is accepted, the new ``TYPE_CHECKING`` constant will be +the preferred approach, instead of the existing ``typing.TYPE_CHECKING``. +However, ``typing.TYPE_CHECKING`` will not be deprecated in the foreseeable +future. -However, adding a constant without a keyword (like :data:`__debug__`) requires -special handling in both the compiler and runtime. -By implementing ``__type_checking__`` the same way as ``False``, we avoid the -need for the special handling. -Therefore, making it a keyword is the simpler approach. +Backwards Compatibility +======================= +Since ``TYPE_CHECKING`` doesn't prohibit assignment, existing code using +``TYPE_CHECKING`` will continue to work. -Specification -============= +.. code-block:: python -``__type_checking__`` is a :ref:`keyword ` and its value is -``False``. -It can be used in the same way as ``False``, except it cannot be used as -a matching pattern. + # These code will work as before + TYPE_CHECKING = False + from typing import TYPE_CHECKING -Static type checkers must treat ``__type_checking__`` as ``True``, -similar to :data:`typing.TYPE_CHECKING`. -If this PEP is accepted, ``__type_checking__`` will be the preferred approach, -instead of ``typing.TYPE_CHECKING``. However, ``typing.TYPE_CHECKING`` will not -be deprecated. -Instead, it will be implemented as ``TYPE_CHECKING = __type_checking__``, -allowing future type checkers to focus on only handling ``__type_checking__``. +User can remove the assingment to ``TYPE_CHECKING`` after they stop using +Python before 3.14. How to Teach This ================= -* Use ``__type_checking__`` for skipping type-checking code at runtime. -* Use :data:`typing.TYPE_CHECKING` to support Python versions before 3.14. +* Use ``if TYPE_CHECKING:`` for skipping type-checking code at runtime. +* Use ``from typing import TYPE_CHECKING`` to support Python versions before 3.14. * Workarounds like ``TYPE_CHECKING = False`` or ``if False: # TYPE_CHECKING`` - are not recommended since Python 3.14. + are continued to work, but not recommended. Reference Implementation ======================== -* `python/cpython#131641 `__ +* `python/cpython#131793 `__ + + +Rejected Ideas +============== + +Eliminate type-checking-only Code +--------------------------------- + +It is considered to add real constant named ``__type_checking__`` +to eliminate type-checking-only code at compile time. + +However, adding real constant to language increase complexity of the language. +Benefit from eliminating type-checking-only code is estimated to be not enough +to justify the complexity. Copyright From f043cd62cc7a415cd81a48f8136748326f54442c Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 28 Mar 2025 08:03:56 +0900 Subject: [PATCH 12/13] Apply suggestions from code review Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> Co-authored-by: Vincent Poulailleau --- peps/pep-0781.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/peps/pep-0781.rst b/peps/pep-0781.rst index 9935fd86a0e..870944f2f09 100644 --- a/peps/pep-0781.rst +++ b/peps/pep-0781.rst @@ -1,5 +1,5 @@ PEP: 781 -Title: Make ``TYPE_CHECKING`` builtin +Title: Make ``TYPE_CHECKING`` a built-in constant Author: Inada Naoki Discussions-To: https://discuss.python.org/t/85728 Status: Draft @@ -14,11 +14,11 @@ Post-History: `11-Jan-2025 `__, Abstract ======== -This PEP proposes adding a new builtin, :data:`!TYPE_CHECKING`, to improve +This PEP proposes adding a new built-in variable, :data:`!TYPE_CHECKING`, to improve the experience of writing Python code with type annotations. It is evaluated as ``True`` when the code is being analyzed by a static type checker, and as ``False`` during normal runtime execution. Unlike :data:`typing.TYPE_CHECKING`, -which this keyword replaces, it does not require an import statement. +which this variable replaces, it does not require an import statement. Motivation @@ -29,7 +29,7 @@ widespread adoption. A challenge with fully-annotated code is that many more imports are required in order to bring the relevant name into scope, potentially causing import cycles without careful design. This has been recognized by :pep:`563` and later :pep:`649`, which introduce two different -mechanisms for deferred evaluation of type annotations. As :pep:`563` notes, +mechanisms for deferred evaluation of type annotations. As PEP 563 notes, "type hints are ... not computationally free". The :data:`typing.TYPE_CHECKING` constant was thus introduced__, initially to aid in breaking cyclic imports. @@ -75,13 +75,13 @@ Since ``TYPE_CHECKING`` doesn't prohibit assignment, existing code using .. code-block:: python - # These code will work as before + # This code will continue to work TYPE_CHECKING = False from typing import TYPE_CHECKING -User can remove the assingment to ``TYPE_CHECKING`` after they stop using -Python before 3.14. +User can remove the assignment to ``TYPE_CHECKING`` after they stop using +Python 3.13 or older versions. How to Teach This @@ -90,7 +90,7 @@ How to Teach This * Use ``if TYPE_CHECKING:`` for skipping type-checking code at runtime. * Use ``from typing import TYPE_CHECKING`` to support Python versions before 3.14. * Workarounds like ``TYPE_CHECKING = False`` or ``if False: # TYPE_CHECKING`` - are continued to work, but not recommended. + will continue to work, but are not recommended. Reference Implementation @@ -102,7 +102,7 @@ Reference Implementation Rejected Ideas ============== -Eliminate type-checking-only Code +Eliminate type-checking-only code --------------------------------- It is considered to add real constant named ``__type_checking__`` From 5fb51f219502f6e0c4834b2d959485e67aee4b4d Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Fri, 28 Mar 2025 01:12:14 +0000 Subject: [PATCH 13/13] Wrap to 80 columns --- peps/pep-0781.rst | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/peps/pep-0781.rst b/peps/pep-0781.rst index 870944f2f09..4c4c796ee04 100644 --- a/peps/pep-0781.rst +++ b/peps/pep-0781.rst @@ -14,11 +14,12 @@ Post-History: `11-Jan-2025 `__, Abstract ======== -This PEP proposes adding a new built-in variable, :data:`!TYPE_CHECKING`, to improve -the experience of writing Python code with type annotations. It is evaluated -as ``True`` when the code is being analyzed by a static type checker, and as -``False`` during normal runtime execution. Unlike :data:`typing.TYPE_CHECKING`, -which this variable replaces, it does not require an import statement. +This PEP proposes adding a new built-in variable, :data:`!TYPE_CHECKING`, to +improve the experience of writing Python code with type annotations. It is +evaluated as ``True`` when the code is being analyzed by a static type checker, +and as ``False`` during normal runtime execution. Unlike +:data:`typing.TYPE_CHECKING`, which this variable replaces, it does not require +an import statement. Motivation @@ -88,7 +89,8 @@ How to Teach This ================= * Use ``if TYPE_CHECKING:`` for skipping type-checking code at runtime. -* Use ``from typing import TYPE_CHECKING`` to support Python versions before 3.14. +* Use ``from typing import TYPE_CHECKING`` to support Python versions before + 3.14. * Workarounds like ``TYPE_CHECKING = False`` or ``if False: # TYPE_CHECKING`` will continue to work, but are not recommended.