mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
[3.12] gh-115165: Fix typing.Annotated
for immutable types (GH-115213) (#115227)
gh-115165: Fix `typing.Annotated` for immutable types (GH-115213)
The return value from an annotated callable can raise any exception from
__setattr__ for the `__orig_class__` property.
(cherry picked from commit 564385612c
)
Co-authored-by: dave-shawley <daveshawley@gmail.com>
This commit is contained in:
parent
3539b02873
commit
321ec5e0fe
3 changed files with 28 additions and 1 deletions
|
@ -4181,6 +4181,16 @@ class GenericTests(BaseTestCase):
|
||||||
c.bar = 'abc'
|
c.bar = 'abc'
|
||||||
self.assertEqual(c.__dict__, {'bar': 'abc'})
|
self.assertEqual(c.__dict__, {'bar': 'abc'})
|
||||||
|
|
||||||
|
def test_setattr_exceptions(self):
|
||||||
|
class Immutable[T]:
|
||||||
|
def __setattr__(self, key, value):
|
||||||
|
raise RuntimeError("immutable")
|
||||||
|
|
||||||
|
# gh-115165: This used to cause RuntimeError to be raised
|
||||||
|
# when we tried to set `__orig_class__` on the `Immutable` instance
|
||||||
|
# returned by the `Immutable[int]()` call
|
||||||
|
self.assertIsInstance(Immutable[int](), Immutable)
|
||||||
|
|
||||||
def test_subscripted_generics_as_proxies(self):
|
def test_subscripted_generics_as_proxies(self):
|
||||||
T = TypeVar('T')
|
T = TypeVar('T')
|
||||||
class C(Generic[T]):
|
class C(Generic[T]):
|
||||||
|
@ -8207,6 +8217,17 @@ class AnnotatedTests(BaseTestCase):
|
||||||
self.assertEqual(MyCount([4, 4, 5]), {4: 2, 5: 1})
|
self.assertEqual(MyCount([4, 4, 5]), {4: 2, 5: 1})
|
||||||
self.assertEqual(MyCount[int]([4, 4, 5]), {4: 2, 5: 1})
|
self.assertEqual(MyCount[int]([4, 4, 5]), {4: 2, 5: 1})
|
||||||
|
|
||||||
|
def test_instantiate_immutable(self):
|
||||||
|
class C:
|
||||||
|
def __setattr__(self, key, value):
|
||||||
|
raise Exception("should be ignored")
|
||||||
|
|
||||||
|
A = Annotated[C, "a decoration"]
|
||||||
|
# gh-115165: This used to cause RuntimeError to be raised
|
||||||
|
# when we tried to set `__orig_class__` on the `C` instance
|
||||||
|
# returned by the `A()` call
|
||||||
|
self.assertIsInstance(A(), C)
|
||||||
|
|
||||||
def test_cannot_instantiate_forward(self):
|
def test_cannot_instantiate_forward(self):
|
||||||
A = Annotated["int", (5, 6)]
|
A = Annotated["int", (5, 6)]
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
|
|
|
@ -1140,7 +1140,9 @@ class _BaseGenericAlias(_Final, _root=True):
|
||||||
result = self.__origin__(*args, **kwargs)
|
result = self.__origin__(*args, **kwargs)
|
||||||
try:
|
try:
|
||||||
result.__orig_class__ = self
|
result.__orig_class__ = self
|
||||||
except AttributeError:
|
# Some objects raise TypeError (or something even more exotic)
|
||||||
|
# if you try to set attributes on them; we guard against that here
|
||||||
|
except Exception:
|
||||||
pass
|
pass
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Most exceptions are now ignored when attempting to set the ``__orig_class__``
|
||||||
|
attribute on objects returned when calling :mod:`typing` generic aliases
|
||||||
|
(including generic aliases created using :data:`typing.Annotated`).
|
||||||
|
Previously only :exc:`AttributeError`` was ignored. Patch by Dave Shawley.
|
Loading…
Add table
Add a link
Reference in a new issue