From ffbdf1a95c88ad37ef0aeb20c54e75358961c512 Mon Sep 17 00:00:00 2001 From: Eric Mark Martin Date: Thu, 30 Apr 2026 01:51:59 -0400 Subject: [PATCH 1/3] Make TypeAliasType __module__ writable --- src/test_typing_extensions.py | 11 ++++++----- src/typing_extensions.py | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py index f07e1eb0..34469068 100644 --- a/src/test_typing_extensions.py +++ b/src/test_typing_extensions.py @@ -8244,11 +8244,12 @@ def test_cannot_set_attributes(self): "attribute '__parameters__' of 'typing.TypeAliasType' objects is not writable", ): Simple.__parameters__ = (T,) - with self.assertRaisesRegex( - AttributeError, - "attribute '__module__' of 'typing.TypeAliasType' objects is not writable", - ): - Simple.__module__ = 42 + + # __module__ is the exception---it's assignable + module_sentinel = object() + Simple.__module__ = module_sentinel + self.assertIs(Simple.__module__, module_sentinel) + with self.assertRaisesRegex( AttributeError, "'typing.TypeAliasType' object has no attribute 'some_attribute'", diff --git a/src/typing_extensions.py b/src/typing_extensions.py index 20c331ee..4c042ac8 100644 --- a/src/typing_extensions.py +++ b/src/typing_extensions.py @@ -3733,7 +3733,7 @@ def __init__(self, name: str, value, *, type_params=()): self.__name__ = name def __setattr__(self, name: str, value: object, /) -> None: - if hasattr(self, "__name__"): + if hasattr(self, "__name__") and name != "__module__": self._raise_attribute_error(name) super().__setattr__(name, value) @@ -3744,7 +3744,7 @@ def _raise_attribute_error(self, name: str) -> Never: # Match the Python 3.12 error messages exactly if name == "__name__": raise AttributeError("readonly attribute") - elif name in {"__value__", "__type_params__", "__parameters__", "__module__"}: + elif name in {"__value__", "__type_params__", "__parameters__"}: raise AttributeError( f"attribute '{name}' of 'typing.TypeAliasType' objects " "is not writable" From a1d42373df142761977583819809dc0e7434486e Mon Sep 17 00:00:00 2001 From: Eric Mark Martin Date: Thu, 30 Apr 2026 13:16:14 -0400 Subject: [PATCH 2/3] add changelog entry --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 733505a5..80a1775e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Unreleased +- Make `typing_extensions.TypeAliasType`'s `__module__` attribute writable. + Backport of CPython PR + [#149172](https://github.com/python/cpython/pull/149172). - Fix incorrect behaviour on Python 3.9 and Python 3.10 that meant that calling `isinstance` with `typing_extensions.Concatenate[...]` or `typing_extensions.Unpack[...]` as the first argument could have a different From 21ae3906da24a97e74c1c706cc3cff103aa325e3 Mon Sep 17 00:00:00 2001 From: Eric Mark Martin Date: Thu, 30 Apr 2026 13:17:22 -0400 Subject: [PATCH 3/3] bump TypeAliasType re-export guard --- src/test_typing_extensions.py | 2 +- src/typing_extensions.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py index 34469068..2719ec80 100644 --- a/src/test_typing_extensions.py +++ b/src/test_typing_extensions.py @@ -7072,7 +7072,7 @@ def test_typing_extensions_defers_when_possible(self): 'AsyncGenerator', 'ContextManager', 'AsyncContextManager', 'ParamSpec', 'TypeVar', 'TypeVarTuple', 'get_type_hints', } - if sys.version_info < (3, 14): + if sys.version_info < (3, 15): exclude |= { 'TypeAliasType' } diff --git a/src/typing_extensions.py b/src/typing_extensions.py index 4c042ac8..d4a95678 100644 --- a/src/typing_extensions.py +++ b/src/typing_extensions.py @@ -3613,14 +3613,14 @@ def __ror__(self, other): return typing.Union[other, self] -# Breakpoint: https://github.com/python/cpython/pull/124795 -if sys.version_info >= (3, 14): +# Breakpoint: https://github.com/python/cpython/pull/149172 +if sys.version_info >= (3, 15): TypeAliasType = typing.TypeAliasType -# <=3.13 +# <=3.14 else: # Breakpoint: https://github.com/python/cpython/pull/103764 if sys.version_info >= (3, 12): - # 3.12-3.13 + # 3.12-3.14 def _is_unionable(obj): """Corresponds to is_unionable() in unionobject.c in CPython.""" return obj is None or isinstance(obj, (