Skip to content

Commit

Permalink
gh-102324: Improve tests of typing.override (#102325)
Browse files Browse the repository at this point in the history
Fixes #101564
  • Loading branch information
sobolevn authored Mar 3, 2023
1 parent 71db5db commit 12011dd
Showing 1 changed file with 95 additions and 4 deletions.
99 changes: 95 additions & 4 deletions Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -4171,38 +4171,129 @@ class OverrideDecoratorTests(BaseTestCase):
def test_override(self):
class Base:
def normal_method(self): ...
@classmethod
def class_method_good_order(cls): ...
@classmethod
def class_method_bad_order(cls): ...
@staticmethod
def static_method_good_order(): ...
@staticmethod
def static_method_bad_order(): ...
@staticmethod
def decorator_with_slots(): ...

class Derived(Base):
@override
def normal_method(self):
return 42

@classmethod
@override
def class_method_good_order(cls):
return 42
@override
@classmethod
def class_method_bad_order(cls):
return 42

@staticmethod
@override
def static_method_good_order():
return 42

@override
@staticmethod
def static_method_bad_order():
return 42


self.assertIsSubclass(Derived, Base)
instance = Derived()
self.assertEqual(instance.normal_method(), 42)
self.assertIs(True, Derived.normal_method.__override__)
self.assertIs(True, instance.normal_method.__override__)

self.assertEqual(Derived.class_method_good_order(), 42)
self.assertIs(True, Derived.class_method_good_order.__override__)
self.assertEqual(Derived.class_method_bad_order(), 42)
self.assertIs(False, hasattr(Derived.class_method_bad_order, "__override__"))

self.assertEqual(Derived.static_method_good_order(), 42)
self.assertIs(True, Derived.static_method_good_order.__override__)
self.assertEqual(Derived.static_method_bad_order(), 42)
self.assertIs(False, hasattr(Derived.static_method_bad_order, "__override__"))

# Base object is not changed:
self.assertIs(False, hasattr(Base.normal_method, "__override__"))
self.assertIs(False, hasattr(Base.class_method_good_order, "__override__"))
self.assertIs(False, hasattr(Base.class_method_bad_order, "__override__"))
self.assertIs(False, hasattr(Base.static_method_good_order, "__override__"))
self.assertIs(False, hasattr(Base.static_method_bad_order, "__override__"))

def test_property(self):
class Base:
@property
def correct(self) -> int:
return 1
@property
def wrong(self) -> int:
return 1

class Child(Base):
@property
@override
def correct(self) -> int:
return 2
@override
@property
def wrong(self) -> int:
return 2

instance = Child()
self.assertEqual(instance.correct, 2)
self.assertTrue(Child.correct.fget.__override__)
self.assertEqual(instance.wrong, 2)
self.assertFalse(hasattr(Child.wrong, "__override__"))
self.assertFalse(hasattr(Child.wrong.fset, "__override__"))

def test_silent_failure(self):
class CustomProp:
__slots__ = ('fget',)
def __init__(self, fget):
self.fget = fget
def __get__(self, obj, objtype=None):
return self.fget(obj)

class WithOverride:
@override # must not fail on object with `__slots__`
@CustomProp
def some(self):
return 1

self.assertEqual(WithOverride.some, 1)
self.assertFalse(hasattr(WithOverride.some, "__override__"))

def test_multiple_decorators(self):
import functools

def with_wraps(f): # similar to `lru_cache` definition
@functools.wraps(f)
def wrapper(*args, **kwargs):
return f(*args, **kwargs)
return wrapper

class WithOverride:
@override
@with_wraps
def on_top(self, a: int) -> int:
return a + 1
@with_wraps
@override
def on_bottom(self, a: int) -> int:
return a + 2

instance = WithOverride()
self.assertEqual(instance.on_top(1), 2)
self.assertTrue(instance.on_top.__override__)
self.assertEqual(instance.on_bottom(1), 3)
self.assertTrue(instance.on_bottom.__override__)


class CastTests(BaseTestCase):

Expand Down

0 comments on commit 12011dd

Please sign in to comment.