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

``