Skip to content

Commit 88a0c20

Browse files
authored
Do not shadow user arguments in generated __new__ by @deprecated (#581)
Backport of: python/cpython#132160
1 parent 281d7b0 commit 88a0c20

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
- Fix `TypeError` when taking the union of `typing_extensions.TypeAliasType` and a
44
`typing.TypeAliasType` on Python 3.12 and 3.13.
55
Patch by [Joren Hammudoglu](https://github.com/jorenham).
6+
- Backport from CPython PR [#132160](https://github.com/python/cpython/pull/132160)
7+
to avoid having user arguments shadowed in generated `__new__` by
8+
`@typing_extensions.deprecated`.
9+
Patch by [Victorien Plot](https://github.com/Viicos).
610

711
# Release 4.13.1 (April 3, 2025)
812

src/test_typing_extensions.py

+19
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,25 @@ class Child(Base, Mixin):
707707
instance = Child(42)
708708
self.assertEqual(instance.a, 42)
709709

710+
def test_do_not_shadow_user_arguments(self):
711+
new_called = False
712+
new_called_cls = None
713+
714+
@deprecated("MyMeta will go away soon")
715+
class MyMeta(type):
716+
def __new__(mcs, name, bases, attrs, cls=None):
717+
nonlocal new_called, new_called_cls
718+
new_called = True
719+
new_called_cls = cls
720+
return super().__new__(mcs, name, bases, attrs)
721+
722+
with self.assertWarnsRegex(DeprecationWarning, "MyMeta will go away soon"):
723+
class Foo(metaclass=MyMeta, cls='haha'):
724+
pass
725+
726+
self.assertTrue(new_called)
727+
self.assertEqual(new_called_cls, 'haha')
728+
710729
def test_existing_init_subclass(self):
711730
@deprecated("C will go away soon")
712731
class C:

src/typing_extensions.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -3123,7 +3123,8 @@ def method(self) -> None:
31233123
return arg
31243124

31253125

3126-
if hasattr(warnings, "deprecated"):
3126+
# Python 3.13.3+ contains a fix for the wrapped __new__
3127+
if sys.version_info >= (3, 13, 3):
31273128
deprecated = warnings.deprecated
31283129
else:
31293130
_T = typing.TypeVar("_T")
@@ -3203,7 +3204,7 @@ def __call__(self, arg: _T, /) -> _T:
32033204
original_new = arg.__new__
32043205

32053206
@functools.wraps(original_new)
3206-
def __new__(cls, *args, **kwargs):
3207+
def __new__(cls, /, *args, **kwargs):
32073208
if cls is arg:
32083209
warnings.warn(msg, category=category, stacklevel=stacklevel + 1)
32093210
if original_new is not object.__new__:

0 commit comments

Comments
 (0)