diff --git a/CHANGELOG.md b/CHANGELOG.md index f35c4827..77b27dda 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 setting of `__required_keys__` and `__optional_keys__` when inheriting keys with the same name. - Fix incorrect behaviour on Python 3.9 and Python 3.10 that meant that diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py index c7025321..c3aede8c 100644 --- a/src/test_typing_extensions.py +++ b/src/test_typing_extensions.py @@ -7114,7 +7114,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' } @@ -8286,11 +8286,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 05d4522c..e3704756 100644 --- a/src/typing_extensions.py +++ b/src/typing_extensions.py @@ -3677,14 +3677,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, ( @@ -3797,7 +3797,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) @@ -3808,7 +3808,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"