[Python-checkins] gh-102324: Improve tests of `typing.override` (#102325)

JelleZijlstra webhook-mailer at python.org
Thu Mar 2 22:59:44 EST 2023


https://github.com/python/cpython/commit/12011dd8bafa6867f2b4a8a9e8e54cb0fbf006e4
commit: 12011dd8bafa6867f2b4a8a9e8e54cb0fbf006e4
branch: main
author: Nikita Sobolev <mail at sobolevn.me>
committer: JelleZijlstra <jelle.zijlstra at gmail.com>
date: 2023-03-02T19:59:05-08:00
summary:

gh-102324: Improve tests of `typing.override` (#102325)

Fixes #101564

files:
M Lib/test/test_typing.py

diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index d61dc6e2fbd7..96496ec9279e 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -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):
 



More information about the Python-checkins mailing list