Skip to content

Commit

Permalink
Add @typing.override (#78)
Browse files Browse the repository at this point in the history
Co-authored-by: Steven Troxler <steven.troxler@gmail.com>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
  • Loading branch information
3 people committed Oct 6, 2022
1 parent ba776ea commit 3c21f33
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
and Jelle Zijlstra). Patch by James Hilton-Balfe (@Gobot1234).
- Add initial support for TypeVarLike `default` parameter, PEP 696.
Patch by Marc Mueller (@cdce8p).
- Runtime support for PEP 698, adding `typing_extensions.override`. Patch by
Jelle Zijlstra.
- Add the `infer_variance` parameter to `TypeVar`, as specified in PEP 695.
Patch by Jelle Zijlstra.

Expand Down
16 changes: 16 additions & 0 deletions src/test_typing_extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from typing_extensions import assert_type, get_type_hints, get_origin, get_args
from typing_extensions import clear_overloads, get_overloads, overload
from typing_extensions import NamedTuple
from typing_extensions import override
from _typed_dict_test_helper import FooGeneric

# Flags used to mark tests that only apply after a specific
Expand Down Expand Up @@ -160,6 +161,21 @@ def test_exception(self):
assert_never(None)


class OverrideTests(BaseTestCase):
def test_override(self):
class Base:
def foo(self): ...

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

self.assertIsSubclass(Derived, Base)
self.assertEqual(Derived().foo(), 42)
self.assertEqual(dir(Base.foo), dir(Derived.foo))


class AnyTests(BaseTestCase):
def test_can_subclass(self):
class Mock(Any): pass
Expand Down
31 changes: 31 additions & 0 deletions src/typing_extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
'Literal',
'NewType',
'overload',
'override',
'Protocol',
'reveal_type',
'runtime',
Expand Down Expand Up @@ -2078,6 +2079,36 @@ def decorator(cls_or_fn):
return decorator


if hasattr(typing, "override"):
override = typing.override
else:
_F = typing.TypeVar("_F", bound=typing.Callable[..., typing.Any])

def override(__arg: _F) -> _F:
"""Indicate that a method is intended to override a method in a base class.
Usage:
class Base:
def method(self) -> None: ...
pass
class Child(Base):
@override
def method(self) -> None:
super().method()
When this decorator is applied to a method, the type checker will
validate that it overrides a method with the same name on a base class.
This helps prevent bugs that may occur when a base class is changed
without an equivalent change to a child class.
See PEP 698 for details.
"""
return __arg


# We have to do some monkey patching to deal with the dual nature of
# Unpack/TypeVarTuple:
# - We want Unpack to be a kind of TypeVar so it gets accepted in
Expand Down

0 comments on commit 3c21f33

Please sign in to comment.