Skip to content

Commit 2912585

Browse files
Fix @deprecated on classes with only __new__ (#193)
1 parent e7fe63f commit 2912585

File tree

3 files changed

+28
-5
lines changed

3 files changed

+28
-5
lines changed

CHANGELOG.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# Unreleased
22

3-
- Fix regression in version 4.6.1 where comparing a generic class against a
3+
- Fix use of `@deprecated` on classes with `__new__` but no `__init__`.
4+
Patch by Jelle Zijlstra.
5+
- Fix regression in version 4.6.1 where comparing a generic class against a
46
runtime-checkable protocol using `isinstance()` would cause `AttributeError`
5-
to be raised if using Python 3.7
7+
to be raised if using Python 3.7.
68

79
# Release 4.6.1 (May 23, 2023)
810

src/test_typing_extensions.py

+21
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ class A:
357357
with self.assertRaises(TypeError):
358358
A(42)
359359

360+
def test_class_with_init(self):
360361
@deprecated("HasInit will go away soon")
361362
class HasInit:
362363
def __init__(self, x):
@@ -366,6 +367,7 @@ def __init__(self, x):
366367
instance = HasInit(42)
367368
self.assertEqual(instance.x, 42)
368369

370+
def test_class_with_new(self):
369371
has_new_called = False
370372

371373
@deprecated("HasNew will go away soon")
@@ -382,6 +384,8 @@ def __init__(self, x) -> None:
382384
instance = HasNew(42)
383385
self.assertEqual(instance.x, 42)
384386
self.assertTrue(has_new_called)
387+
388+
def test_class_with_inherited_new(self):
385389
new_base_called = False
386390

387391
class NewBase:
@@ -402,6 +406,23 @@ class HasInheritedNew(NewBase):
402406
self.assertEqual(instance.x, 42)
403407
self.assertTrue(new_base_called)
404408

409+
def test_class_with_new_but_no_init(self):
410+
new_called = False
411+
412+
@deprecated("HasNewNoInit will go away soon")
413+
class HasNewNoInit:
414+
def __new__(cls, x):
415+
nonlocal new_called
416+
new_called = True
417+
obj = super().__new__(cls)
418+
obj.x = x
419+
return obj
420+
421+
with self.assertWarnsRegex(DeprecationWarning, "HasNewNoInit will go away soon"):
422+
instance = HasNewNoInit(42)
423+
self.assertEqual(instance.x, 42)
424+
self.assertTrue(new_called)
425+
405426
def test_function(self):
406427
@deprecated("b will go away soon")
407428
def b():

src/typing_extensions.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -2497,11 +2497,11 @@ def decorator(__arg: _T) -> _T:
24972497
@functools.wraps(original_new)
24982498
def __new__(cls, *args, **kwargs):
24992499
warnings.warn(__msg, category=category, stacklevel=stacklevel + 1)
2500-
# Mirrors a similar check in object.__new__.
2501-
if not has_init and (args or kwargs):
2502-
raise TypeError(f"{cls.__name__}() takes no arguments")
25032500
if original_new is not object.__new__:
25042501
return original_new(cls, *args, **kwargs)
2502+
# Mirrors a similar check in object.__new__.
2503+
elif not has_init and (args or kwargs):
2504+
raise TypeError(f"{cls.__name__}() takes no arguments")
25052505
else:
25062506
return original_new(cls)
25072507

0 commit comments

Comments
 (0)