bpo-46342: make @typing.final introspectable (GH-30530) · python/cpython@0bbf30e (original) (raw)
1
1
`import contextlib
`
2
2
`import collections
`
``
3
`+
from functools import lru_cache
`
``
4
`+
import inspect
`
3
5
`import pickle
`
4
6
`import re
`
5
7
`import sys
`
`@@ -2536,10 +2538,80 @@ def test_no_isinstance(self):
`
2536
2538
`with self.assertRaises(TypeError):
`
2537
2539
`issubclass(int, Final)
`
2538
2540
``
``
2541
+
``
2542
`+
class FinalDecoratorTests(BaseTestCase):
`
2539
2543
`def test_final_unmodified(self):
`
2540
2544
`def func(x): ...
`
2541
2545
`self.assertIs(func, final(func))
`
2542
2546
``
``
2547
`+
def test_dunder_final(self):
`
``
2548
`+
@final
`
``
2549
`+
def func(): ...
`
``
2550
`+
@final
`
``
2551
`+
class Cls: ...
`
``
2552
`+
self.assertIs(True, func.final)
`
``
2553
`+
self.assertIs(True, Cls.final)
`
``
2554
+
``
2555
`+
class Wrapper:
`
``
2556
`+
slots = ("func",)
`
``
2557
`+
def init(self, func):
`
``
2558
`+
self.func = func
`
``
2559
`+
def call(self, *args, **kwargs):
`
``
2560
`+
return self.func(*args, **kwargs)
`
``
2561
+
``
2562
`+
Check that no error is thrown if the attribute
`
``
2563
`+
is not writable.
`
``
2564
`+
@final
`
``
2565
`+
@Wrapper
`
``
2566
`+
def wrapped(): ...
`
``
2567
`+
self.assertIsInstance(wrapped, Wrapper)
`
``
2568
`+
self.assertIs(False, hasattr(wrapped, "final"))
`
``
2569
+
``
2570
`+
class Meta(type):
`
``
2571
`+
@property
`
``
2572
`+
def final(self): return "can't set me"
`
``
2573
`+
@final
`
``
2574
`+
class WithMeta(metaclass=Meta): ...
`
``
2575
`+
self.assertEqual(WithMeta.final, "can't set me")
`
``
2576
+
``
2577
`+
Builtin classes throw TypeError if you try to set an
`
``
2578
`+
attribute.
`
``
2579
`+
final(int)
`
``
2580
`+
self.assertIs(False, hasattr(int, "final"))
`
``
2581
+
``
2582
`+
Make sure it works with common builtin decorators
`
``
2583
`+
class Methods:
`
``
2584
`+
@final
`
``
2585
`+
@classmethod
`
``
2586
`+
def clsmethod(cls): ...
`
``
2587
+
``
2588
`+
@final
`
``
2589
`+
@staticmethod
`
``
2590
`+
def stmethod(): ...
`
``
2591
+
``
2592
`+
The other order doesn't work because property objects
`
``
2593
`+
don't allow attribute assignment.
`
``
2594
`+
@property
`
``
2595
`+
@final
`
``
2596
`+
def prop(self): ...
`
``
2597
+
``
2598
`+
@final
`
``
2599
`+
@lru_cache()
`
``
2600
`+
def cached(self): ...
`
``
2601
+
``
2602
`+
Use getattr_static because the descriptor returns the
`
``
2603
`+
underlying function, which doesn't have final.
`
``
2604
`+
self.assertIs(
`
``
2605
`+
True,
`
``
2606
`+
inspect.getattr_static(Methods, "clsmethod").final
`
``
2607
`+
)
`
``
2608
`+
self.assertIs(
`
``
2609
`+
True,
`
``
2610
`+
inspect.getattr_static(Methods, "stmethod").final
`
``
2611
`+
)
`
``
2612
`+
self.assertIs(True, Methods.prop.fget.final)
`
``
2613
`+
self.assertIs(True, Methods.cached.final)
`
``
2614
+
2543
2615
``
2544
2616
`class CastTests(BaseTestCase):
`
2545
2617
``