Skip to content

Commit fb8bc3e

Browse files
gh-137065: Unmerge types.UnionType and typing.Union
Partially revert GH-105499. types.UnionType no longer an alias of typing.Union and no longer subscriptable, but subscribing typing.Union returns an instance of types.UnionType. typing.Union can no longer be used in the isinstance() checks.
1 parent 6a285f9 commit fb8bc3e

22 files changed

+168
-105
lines changed

Doc/deprecations/pending-removal-in-future.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ although there is currently no date scheduled for their removal.
123123
* :class:`typing.Text` (:gh:`92332`).
124124

125125
* The internal class ``typing._UnionGenericAlias`` is no longer used to implement
126-
:class:`typing.Union`. To preserve compatibility with users using this private
126+
:data:`typing.Union`. To preserve compatibility with users using this private
127127
class, a compatibility shim will be provided until at least Python 3.17. (Contributed by
128128
Jelle Zijlstra in :gh:`105499`.)
129129

Doc/library/functools.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@ The :mod:`functools` module defines the following functions:
526526
... for i, elem in enumerate(arg):
527527
... print(i, elem)
528528

529-
:class:`typing.Union` can also be used::
529+
:data:`typing.Union` can also be used::
530530

531531
>>> @fun.register
532532
... def _(arg: int | float, verbose=False):
@@ -663,7 +663,7 @@ The :mod:`functools` module defines the following functions:
663663

664664
.. versionchanged:: 3.11
665665
The :func:`~singledispatch.register` attribute now supports
666-
:class:`typing.Union` as a type annotation.
666+
:data:`typing.Union` as a type annotation.
667667

668668

669669
.. class:: singledispatchmethod(func)

Doc/library/stdtypes.rst

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5573,7 +5573,7 @@ Union Type
55735573
A union object holds the value of the ``|`` (bitwise or) operation on
55745574
multiple :ref:`type objects <bltin-type-objects>`. These types are intended
55755575
primarily for :term:`type annotations <annotation>`. The union type expression
5576-
enables cleaner type hinting syntax compared to subscripting :class:`typing.Union`.
5576+
enables cleaner type hinting syntax compared to subscripting :data:`typing.Union`.
55775577

55785578
.. describe:: X | Y | ...
55795579

@@ -5609,7 +5609,7 @@ enables cleaner type hinting syntax compared to subscripting :class:`typing.Unio
56095609

56105610
int | str == str | int
56115611

5612-
* It creates instances of :class:`typing.Union`::
5612+
* It creates instances of :class:`types.UnionType`::
56135613

56145614
int | str == typing.Union[int, str]
56155615
type(int | str) is typing.Union
@@ -5638,15 +5638,15 @@ enables cleaner type hinting syntax compared to subscripting :class:`typing.Unio
56385638
TypeError: isinstance() argument 2 cannot be a parameterized generic
56395639

56405640
The user-exposed type for the union object can be accessed from
5641-
:class:`typing.Union` and used for :func:`isinstance` checks::
5641+
:class:`types.UnionType` and used for :func:`isinstance` checks::
56425642

5643-
>>> import typing
5644-
>>> isinstance(int | str, typing.Union)
5643+
>>> import types
5644+
>>> isinstance(int | str, types.UnionType)
56455645
True
5646-
>>> typing.Union()
5646+
>>> types.UnionType()
56475647
Traceback (most recent call last):
56485648
File "<stdin>", line 1, in <module>
5649-
TypeError: cannot create 'typing.Union' instances
5649+
TypeError: cannot create 'types.UnionType' instances
56505650

56515651
.. note::
56525652
The :meth:`!__or__` method for type objects was added to support the syntax
@@ -5673,11 +5673,6 @@ The user-exposed type for the union object can be accessed from
56735673

56745674
.. versionadded:: 3.10
56755675

5676-
.. versionchanged:: 3.14
5677-
5678-
Union objects are now instances of :class:`typing.Union`. Previously, they were instances
5679-
of :class:`types.UnionType`, which remains an alias for :class:`typing.Union`.
5680-
56815676

56825677
.. _typesother:
56835678

Doc/library/types.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,9 @@ Standard names are defined for the following types:
316316

317317
.. versionchanged:: 3.14
318318

319-
This is now an alias for :class:`typing.Union`.
319+
Added read-only attributes :attr:`!__name__`, :attr:`!__qualname__`
320+
and :attr:`!__origin__`.
321+
320322

321323
.. class:: TracebackType(tb_next, tb_frame, tb_lasti, tb_lineno)
322324

Doc/library/typing.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,7 +1086,7 @@ Special forms
10861086
These can be used as types in annotations. They all support subscription using
10871087
``[]``, but each has a unique syntax.
10881088

1089-
.. class:: Union
1089+
.. data:: Union
10901090

10911091
Union type; ``Union[X, Y]`` is equivalent to ``X | Y`` and means either X or Y.
10921092

@@ -1128,10 +1128,10 @@ These can be used as types in annotations. They all support subscription using
11281128
:ref:`union type expressions<types-union>`.
11291129

11301130
.. versionchanged:: 3.14
1131-
:class:`types.UnionType` is now an alias for :class:`Union`, and both
1132-
``Union[int, str]`` and ``int | str`` create instances of the same class.
1133-
To check whether an object is a ``Union`` at runtime, use
1134-
``isinstance(obj, Union)``. For compatibility with earlier versions of
1131+
Both ``Union[int, str]`` and ``int | str`` now create instances of
1132+
the same class, :class:`types.UnionType`.
1133+
To check whether an object is a union at runtime, use
1134+
``isinstance(obj, types.UnionType)``. For compatibility with earlier versions of
11351135
Python, use
11361136
``get_origin(obj) is typing.Union or get_origin(obj) is types.UnionType``.
11371137

Doc/whatsnew/3.10.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -723,10 +723,10 @@ PEP 604: New Type Union Operator
723723
724724
A new type union operator was introduced which enables the syntax ``X | Y``.
725725
This provides a cleaner way of expressing 'either type X or type Y' instead of
726-
using :class:`typing.Union`, especially in type hints.
726+
using :data:`typing.Union`, especially in type hints.
727727
728728
In previous versions of Python, to apply a type hint for functions accepting
729-
arguments of multiple types, :class:`typing.Union` was used::
729+
arguments of multiple types, :data:`typing.Union` was used::
730730
731731
def square(number: Union[int, float]) -> Union[int, float]:
732732
return number ** 2

Doc/whatsnew/3.11.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ functools
741741
---------
742742

743743
* :func:`functools.singledispatch` now supports :class:`types.UnionType`
744-
and :class:`typing.Union` as annotations to the dispatch argument.::
744+
and :data:`typing.Union` as annotations to the dispatch argument.::
745745

746746
>>> from functools import singledispatch
747747
>>> @singledispatch

Doc/whatsnew/3.14.rst

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2089,8 +2089,8 @@ turtle
20892089
types
20902090
-----
20912091

2092-
* :class:`types.UnionType` is now an alias for :class:`typing.Union`.
2093-
See :ref:`below <whatsnew314-typing-union>` for more details.
2092+
* Add read-only attributes :attr:`!__name__`, :attr:`!__qualname__` and
2093+
:attr:`!__origin__` for :class:`types.UnionType` instances.
20942094
(Contributed by Jelle Zijlstra in :gh:`105499`.)
20952095

20962096

@@ -2099,38 +2099,22 @@ typing
20992099

21002100
.. _whatsnew314-typing-union:
21012101

2102-
* :class:`types.UnionType` and :class:`typing.Union` are now aliases for each other,
2103-
meaning that both old-style unions (created with ``Union[int, str]``) and new-style
2104-
unions (``int | str``) now create instances of the same runtime type. This unifies
2102+
* Both old-style unions (created with ``Union[int, str]``) and new-style
2103+
unions (``int | str``) now create instances of the same runtime type,
2104+
:class:`types.UnionType`. This unifies
21052105
the behavior between the two syntaxes, but leads to some differences in behavior that
21062106
may affect users who introspect types at runtime:
21072107

21082108
- Both syntaxes for creating a union now produce the same string representation in
21092109
``repr()``. For example, ``repr(Union[int, str])``
21102110
is now ``"int | str"`` instead of ``"typing.Union[int, str]"``.
2111-
- Unions created using the old syntax are no longer cached. Previously, running
2112-
``Union[int, str]`` multiple times would return the same object
2113-
(``Union[int, str] is Union[int, str]`` would be ``True``), but now it will
2114-
return two different objects. Users should use ``==`` to compare unions for equality, not
2115-
``is``. New-style unions have never been cached this way.
2116-
This change could increase memory usage for some programs that use a large number of
2117-
unions created by subscripting ``typing.Union``. However, several factors offset this cost:
2118-
unions used in annotations are no longer evaluated by default in Python 3.14
2119-
because of :pep:`649`; an instance of :class:`types.UnionType` is
2120-
itself much smaller than the object returned by ``Union[]`` was on prior Python
2121-
versions; and removing the cache also saves some space. It is therefore
2122-
unlikely that this change will cause a significant increase in memory usage for most
2123-
users.
21242111
- Previously, old-style unions were implemented using the private class
21252112
``typing._UnionGenericAlias``. This class is no longer needed for the implementation,
21262113
but it has been retained for backward compatibility, with removal scheduled for Python
21272114
3.17. Users should use documented introspection helpers like :func:`typing.get_origin`
21282115
and :func:`typing.get_args` instead of relying on private implementation details.
2129-
- It is now possible to use :class:`typing.Union` itself in :func:`isinstance` checks.
2130-
For example, ``isinstance(int | str, typing.Union)`` will return ``True``; previously
2131-
this raised :exc:`TypeError`.
2132-
- The ``__args__`` attribute of :class:`typing.Union` objects is no longer writable.
2133-
- It is no longer possible to set any attributes on :class:`typing.Union` objects.
2116+
- The ``__args__`` attribute of :data:`typing.Union` objects is no longer writable.
2117+
- It is no longer possible to set any attributes on the :data:`typing.Union` objects.
21342118
This only ever worked for dunder attributes on previous versions, was never
21352119
documented to work, and was subtly broken in many cases.
21362120

@@ -2782,8 +2766,8 @@ Changes in the Python API
27822766
This temporary change affects other threads.
27832767
(Contributed by Serhiy Storchaka in :gh:`69998`.)
27842768

2785-
* :class:`types.UnionType` is now an alias for :class:`typing.Union`,
2786-
causing changes in some behaviors.
2769+
* Subscription of :data:`typing.Union` now returns a :class:`types.UnionType`
2770+
instance, causing changes in some behaviors.
27872771
See :ref:`above <whatsnew314-typing-union>` for more details.
27882772
(Contributed by Jelle Zijlstra in :gh:`105499`.)
27892773

Lib/annotationlib.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import keyword
77
import sys
88
import types
9+
from _typing import _make_union
910

1011
__all__ = [
1112
"Format",
@@ -292,10 +293,10 @@ def __hash__(self):
292293
))
293294

294295
def __or__(self, other):
295-
return types.UnionType[self, other]
296+
return _make_union(self, other)
296297

297298
def __ror__(self, other):
298-
return types.UnionType[other, self]
299+
return _make_union(other, self)
299300

300301
def __repr__(self):
301302
extra = []

Lib/inspect.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1333,7 +1333,8 @@ def getargvalues(frame):
13331333
def formatannotation(annotation, base_module=None, *, quote_annotation_strings=True):
13341334
if not quote_annotation_strings and isinstance(annotation, str):
13351335
return annotation
1336-
if getattr(annotation, '__module__', None) == 'typing':
1336+
if (isinstance(annotation, types.UnionType)
1337+
or getattr(annotation, '__module__', None) == 'typing'):
13371338
def repl(match):
13381339
text = match.group()
13391340
return text.removeprefix('typing.')

0 commit comments

Comments
 (0)