Skip to content

Commit 5cd4a72

Browse files
gh-137065: Revert "gh-105499: Merge typing.Union and types.UnionType (#105511)"
This reverts commit d1db43c. This reverts commit 0f511d8. This reverts commit dc6d66f.
1 parent 4c0d7bc commit 5cd4a72

24 files changed

+332
-593
lines changed

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,6 @@ although there is currently no date scheduled for their removal.
122122

123123
* :class:`typing.Text` (:gh:`92332`).
124124

125-
* The internal class ``typing._UnionGenericAlias`` is no longer used to implement
126-
:class:`typing.Union`. To preserve compatibility with users using this private
127-
class, a compatibility shim will be provided until at least Python 3.17. (Contributed by
128-
Jelle Zijlstra in :gh:`105499`.)
129-
130125
* :class:`unittest.IsolatedAsyncioTestCase`: it is deprecated to return a value
131126
that is not ``None`` from a test case.
132127

Doc/library/functools.rst

Lines changed: 3 additions & 3 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+
:class:`types.UnionType` and :data:`typing.Union` can also be used::
530530

531531
>>> @fun.register
532532
... def _(arg: int | float, verbose=False):
@@ -662,8 +662,8 @@ The :mod:`functools` module defines the following functions:
662662
The :func:`~singledispatch.register` attribute now supports using type annotations.
663663

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

668668

669669
.. class:: singledispatchmethod(func)

Doc/library/stdtypes.rst

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

56545654
.. describe:: X | Y | ...
56555655

@@ -5685,10 +5685,9 @@ enables cleaner type hinting syntax compared to subscripting :class:`typing.Unio
56855685

56865686
int | str == str | int
56875687

5688-
* It creates instances of :class:`typing.Union`::
5688+
* It is compatible with :data:`typing.Union`::
56895689

56905690
int | str == typing.Union[int, str]
5691-
type(int | str) is typing.Union
56925691

56935692
* Optional types can be spelled as a union with ``None``::
56945693

@@ -5714,15 +5713,16 @@ enables cleaner type hinting syntax compared to subscripting :class:`typing.Unio
57145713
TypeError: isinstance() argument 2 cannot be a parameterized generic
57155714

57165715
The user-exposed type for the union object can be accessed from
5717-
:class:`typing.Union` and used for :func:`isinstance` checks::
5716+
:class:`types.UnionType` and used for :func:`isinstance` checks. An object cannot be
5717+
instantiated from the type::
57185718

5719-
>>> import typing
5720-
>>> isinstance(int | str, typing.Union)
5719+
>>> import types
5720+
>>> isinstance(int | str, types.UnionType)
57215721
True
5722-
>>> typing.Union()
5722+
>>> types.UnionType()
57235723
Traceback (most recent call last):
57245724
File "<stdin>", line 1, in <module>
5725-
TypeError: cannot create 'typing.Union' instances
5725+
TypeError: cannot create 'types.UnionType' instances
57265726

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

57505750
.. versionadded:: 3.10
57515751

5752-
.. versionchanged:: 3.14
5753-
5754-
Union objects are now instances of :class:`typing.Union`. Previously, they were instances
5755-
of :class:`types.UnionType`, which remains an alias for :class:`typing.Union`.
5756-
57575752

57585753
.. _typesother:
57595754

Doc/library/types.rst

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -314,10 +314,6 @@ Standard names are defined for the following types:
314314

315315
.. versionadded:: 3.10
316316

317-
.. versionchanged:: 3.14
318-
319-
This is now an alias for :class:`typing.Union`.
320-
321317
.. class:: TracebackType(tb_next, tb_frame, tb_lasti, tb_lineno)
322318

323319
The type of traceback objects such as found in ``sys.exception().__traceback__``.

Doc/library/typing.rst

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,7 +1091,7 @@ Special forms
10911091
These can be used as types in annotations. They all support subscription using
10921092
``[]``, but each has a unique syntax.
10931093

1094-
.. class:: Union
1094+
.. data:: Union
10951095

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

@@ -1132,14 +1132,6 @@ These can be used as types in annotations. They all support subscription using
11321132
Unions can now be written as ``X | Y``. See
11331133
:ref:`union type expressions<types-union>`.
11341134

1135-
.. versionchanged:: 3.14
1136-
:class:`types.UnionType` is now an alias for :class:`Union`, and both
1137-
``Union[int, str]`` and ``int | str`` create instances of the same class.
1138-
To check whether an object is a ``Union`` at runtime, use
1139-
``isinstance(obj, Union)``. For compatibility with earlier versions of
1140-
Python, use
1141-
``get_origin(obj) is typing.Union or get_origin(obj) is types.UnionType``.
1142-
11431135
.. data:: Optional
11441136

11451137
``Optional[X]`` is equivalent to ``X | None`` (or ``Union[X, None]``).

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: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2071,56 +2071,9 @@ turtle
20712071
(Contributed by Marie Roald and Yngve Mardal Moe in :gh:`126350`.)
20722072

20732073

2074-
types
2075-
-----
2076-
2077-
* :class:`types.UnionType` is now an alias for :class:`typing.Union`.
2078-
See :ref:`below <whatsnew314-typing-union>` for more details.
2079-
(Contributed by Jelle Zijlstra in :gh:`105499`.)
2080-
2081-
20822074
typing
20832075
------
20842076

2085-
.. _whatsnew314-typing-union:
2086-
2087-
* :class:`types.UnionType` and :class:`typing.Union` are now aliases for each other,
2088-
meaning that both old-style unions (created with ``Union[int, str]``) and new-style
2089-
unions (``int | str``) now create instances of the same runtime type. This unifies
2090-
the behavior between the two syntaxes, but leads to some differences in behavior that
2091-
may affect users who introspect types at runtime:
2092-
2093-
- Both syntaxes for creating a union now produce the same string representation in
2094-
``repr()``. For example, ``repr(Union[int, str])``
2095-
is now ``"int | str"`` instead of ``"typing.Union[int, str]"``.
2096-
- Unions created using the old syntax are no longer cached. Previously, running
2097-
``Union[int, str]`` multiple times would return the same object
2098-
(``Union[int, str] is Union[int, str]`` would be ``True``), but now it will
2099-
return two different objects. Users should use ``==`` to compare unions for equality, not
2100-
``is``. New-style unions have never been cached this way.
2101-
This change could increase memory usage for some programs that use a large number of
2102-
unions created by subscripting ``typing.Union``. However, several factors offset this cost:
2103-
unions used in annotations are no longer evaluated by default in Python 3.14
2104-
because of :pep:`649`; an instance of :class:`types.UnionType` is
2105-
itself much smaller than the object returned by ``Union[]`` was on prior Python
2106-
versions; and removing the cache also saves some space. It is therefore
2107-
unlikely that this change will cause a significant increase in memory usage for most
2108-
users.
2109-
- Previously, old-style unions were implemented using the private class
2110-
``typing._UnionGenericAlias``. This class is no longer needed for the implementation,
2111-
but it has been retained for backward compatibility, with removal scheduled for Python
2112-
3.17. Users should use documented introspection helpers like :func:`typing.get_origin`
2113-
and :func:`typing.get_args` instead of relying on private implementation details.
2114-
- It is now possible to use :class:`typing.Union` itself in :func:`isinstance` checks.
2115-
For example, ``isinstance(int | str, typing.Union)`` will return ``True``; previously
2116-
this raised :exc:`TypeError`.
2117-
- The ``__args__`` attribute of :class:`typing.Union` objects is no longer writable.
2118-
- It is no longer possible to set any attributes on :class:`typing.Union` objects.
2119-
This only ever worked for dunder attributes on previous versions, was never
2120-
documented to work, and was subtly broken in many cases.
2121-
2122-
(Contributed by Jelle Zijlstra in :gh:`105499`.)
2123-
21242077
* :class:`typing.TypeAliasType` now supports star unpacking.
21252078

21262079

@@ -3189,11 +3142,6 @@ Changes in the Python API
31893142
This temporary change affects other threads.
31903143
(Contributed by Serhiy Storchaka in :gh:`69998`.)
31913144

3192-
* :class:`types.UnionType` is now an alias for :class:`typing.Union`,
3193-
causing changes in some behaviors.
3194-
See :ref:`above <whatsnew314-typing-union>` for more details.
3195-
(Contributed by Jelle Zijlstra in :gh:`105499`.)
3196-
31973145
* The runtime behavior of annotations has changed in various ways; see
31983146
:ref:`above <whatsnew314-pep649>` for details. While most code that interacts
31993147
with annotations should continue to work, some undocumented details may behave

Include/internal/pycore_unionobject.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ PyAPI_FUNC(PyObject *) _Py_union_type_or(PyObject *, PyObject *);
1818
extern PyObject *_Py_subs_parameters(PyObject *, PyObject *, PyObject *, PyObject *);
1919
extern PyObject *_Py_make_parameters(PyObject *);
2020
extern PyObject *_Py_union_args(PyObject *self);
21-
extern PyObject *_Py_union_from_tuple(PyObject *args);
2221

2322
#ifdef __cplusplus
2423
}

Lib/functools.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -929,11 +929,16 @@ def dispatch(cls):
929929
dispatch_cache[cls] = impl
930930
return impl
931931

932+
def _is_union_type(cls):
933+
from typing import get_origin, Union
934+
return get_origin(cls) in {Union, UnionType}
935+
932936
def _is_valid_dispatch_type(cls):
933937
if isinstance(cls, type):
934938
return True
935-
return (isinstance(cls, UnionType) and
936-
all(isinstance(arg, type) for arg in cls.__args__))
939+
from typing import get_args
940+
return (_is_union_type(cls) and
941+
all(isinstance(arg, type) for arg in get_args(cls)))
937942

938943
def register(cls, func=None):
939944
"""generic_func.register(cls, func) -> func
@@ -965,7 +970,7 @@ def register(cls, func=None):
965970
from annotationlib import Format, ForwardRef
966971
argname, cls = next(iter(get_type_hints(func, format=Format.FORWARDREF).items()))
967972
if not _is_valid_dispatch_type(cls):
968-
if isinstance(cls, UnionType):
973+
if _is_union_type(cls):
969974
raise TypeError(
970975
f"Invalid annotation for {argname!r}. "
971976
f"{cls!r} not all arguments are classes."
@@ -981,8 +986,10 @@ def register(cls, func=None):
981986
f"{cls!r} is not a class."
982987
)
983988

984-
if isinstance(cls, UnionType):
985-
for arg in cls.__args__:
989+
if _is_union_type(cls):
990+
from typing import get_args
991+
992+
for arg in get_args(cls):
986993
registry[arg] = func
987994
else:
988995
registry[cls] = func

0 commit comments

Comments
 (0)