From dd0fb51927456aa17d6ecc644156119426b68e58 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Mon, 31 Mar 2025 07:34:09 -0700 Subject: [PATCH 1/5] gh-131933: Document UnionType/Union merger in What's New --- Doc/whatsnew/3.14.rst | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index ac5b53ef94bfb1..a15a3d79e64f63 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -959,6 +959,42 @@ turtle (Contributed by Marie Roald and Yngve Mardal Moe in :gh:`126350`.) +types +----- + +* :class:`types.UnionType` is now an alias for :class:`typing.Union` + See :ref:`below ` for more details. + (Contributed by Jelle Zijlstra in :gh:`105499`.) + +typing +------ + +.. _whatsnew314-typing-union: + +* :class:`types.UnionType` and :class:`typing.Union` are now aliases for each other, + meaning that both old-style unions (created with ``Union[int, str]``) and new-style + unions (``int | str``) now create instances of the same runtime type. This unifies + the behavior between the two syntaxes, but leads to some differences in behavior that + may affect users who introspect types at runtime: + + - Both syntaxes for creating a union now produce the same string representation in + ``repr()``. For example, ``repr(Union[int, str])`` + is now ``"int | str"`` instead of ``"typing.Union[int, str]"``. + - Unions created using the old syntax are no longer cached. Previously, running + ``Union[int, str]`` multiple times would return the same object + (``Union[int, str] is Union[int, str]`` would be ``True``), but now it will + return two different objects. Users should use ``==`` to compare unions for equality, not + ``is``. New-style unions already worked this way in earlier versions. + - Previously, old-style unions were implemented using the private class + ``typing._UnionGenericAlias``. This class is no longer needed for the implementation, + but it has been retained for backward compatibility, with removal scheduled for Python + 3.17. Users should use documented introspection helpers like :func:`typing.get_origin` + and :func:`typing.get_args` instead of relying on private implementation details. + - It is now possible to use :class:`typing.Union` in :func:`isinstance` checks. + - The ``__args__`` attribute of :class:`typing.Union` objects is no longer writable. + + (Contributed by Jelle Zijlstra in :gh:`105499`.) + unicodedata ----------- From befd9d44df61213719d0ac3ff4525562e06f02c1 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Mon, 31 Mar 2025 10:22:30 -0700 Subject: [PATCH 2/5] Update Doc/whatsnew/3.14.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Doc/whatsnew/3.14.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index a15a3d79e64f63..b384f3ee97e5fa 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -966,6 +966,7 @@ types See :ref:`below ` for more details. (Contributed by Jelle Zijlstra in :gh:`105499`.) + typing ------ From dbdca048de63b3c8a4203e0f9e1a8826e20e0149 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Mon, 31 Mar 2025 10:22:50 -0700 Subject: [PATCH 3/5] Update Doc/whatsnew/3.14.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Doc/whatsnew/3.14.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index b384f3ee97e5fa..02825e91ce0eef 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -996,6 +996,7 @@ typing (Contributed by Jelle Zijlstra in :gh:`105499`.) + unicodedata ----------- From 6d1aeb7dc7ae62a9c908067bdfcc602a1a723bca Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Fri, 4 Apr 2025 10:48:34 -0700 Subject: [PATCH 4/5] rewordings --- Doc/whatsnew/3.14.rst | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 99d6df8737faf2..f07ff7b095e6da 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -1078,7 +1078,7 @@ turtle types ----- -* :class:`types.UnionType` is now an alias for :class:`typing.Union` +* :class:`types.UnionType` is now an alias for :class:`typing.Union`. See :ref:`below ` for more details. (Contributed by Jelle Zijlstra in :gh:`105499`.) @@ -1101,13 +1101,20 @@ typing ``Union[int, str]`` multiple times would return the same object (``Union[int, str] is Union[int, str]`` would be ``True``), but now it will return two different objects. Users should use ``==`` to compare unions for equality, not - ``is``. New-style unions already worked this way in earlier versions. + ``is``. New-style unions have never been cached this way. + This change could increase memory usage for some programs that use a large number of + unions, but unions used in annotations are no longer evaluated by default in Python 3.14 + (because of :pep:`649`), the new union object is itself much smaller, and removing the + cache also saves some space, so it is unlikely that this change will cause a significant + increase in memory usage. - Previously, old-style unions were implemented using the private class ``typing._UnionGenericAlias``. This class is no longer needed for the implementation, but it has been retained for backward compatibility, with removal scheduled for Python 3.17. Users should use documented introspection helpers like :func:`typing.get_origin` and :func:`typing.get_args` instead of relying on private implementation details. - - It is now possible to use :class:`typing.Union` in :func:`isinstance` checks. + - It is now possible to use :class:`typing.Union` itself in :func:`isinstance` checks. + For example, ``isinstance(int | str, typing.Union)`` will return ``True``; previously + this raised :exc:`TypeError`. - The ``__args__`` attribute of :class:`typing.Union` objects is no longer writable. (Contributed by Jelle Zijlstra in :gh:`105499`.) @@ -1646,6 +1653,11 @@ Changes in the Python API This temporary change affects other threads. (Contributed by Serhiy Storchaka in :gh:`69998`.) +* :class:`types.UnionType` is now an alias for :class:`typing.Union`, + causing changes in some behaviors. + See :ref:`above ` for more details. + (Contributed by Jelle Zijlstra in :gh:`105499`.) + Build changes ============= From 151223da03ecaa4536359499793b7a011b2a16fb Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Fri, 4 Apr 2025 11:07:03 -0700 Subject: [PATCH 5/5] reword more --- Doc/whatsnew/3.14.rst | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index f07ff7b095e6da..d97874fe7a88d4 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -1103,10 +1103,13 @@ typing return two different objects. Users should use ``==`` to compare unions for equality, not ``is``. New-style unions have never been cached this way. This change could increase memory usage for some programs that use a large number of - unions, but unions used in annotations are no longer evaluated by default in Python 3.14 - (because of :pep:`649`), the new union object is itself much smaller, and removing the - cache also saves some space, so it is unlikely that this change will cause a significant - increase in memory usage. + unions created by subscripting ``typing.Union``. However, several factors offset this cost: + unions used in annotations are no longer evaluated by default in Python 3.14 + because of :pep:`649`; an instance of :class:`types.UnionType` is + itself much smaller than the object returned by ``Union[]`` was on prior Python + versions; and removing the cache also saves some space. It is therefore + unlikely that this change will cause a significant increase in memory usage for most + users. - Previously, old-style unions were implemented using the private class ``typing._UnionGenericAlias``. This class is no longer needed for the implementation, but it has been retained for backward compatibility, with removal scheduled for Python