GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-101561: Add typing.override decorator by stroxler · Pull Request #101564 · python/cpython

gh-101561: Add typing.override decorator #101564

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Sign up for GitHub

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
JelleZijlstra merged 10 commits into python:main from stroxler:gh-101561-typing-override
Feb 27, 2023

Uh oh!

There was an error while loading. Please reload this page.

Merged

gh-101561: Add typing.override decorator #101564

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
10 commits
Select commit Hold shift + click to select a range
e2349bb
PEP 698: Add typing.override decorator
stroxler Feb 3, 2023
bd3b6ac
Add missing `For example::` in the rst doc
stroxler Feb 4, 2023
c3b9b7f
📜🤖 Added by blurb_it.
blurb-it[bot] Feb 4, 2023
c7cecf8
Update Doc/library/typing.rst
stroxler Feb 4, 2023
2acf32f
Add whatsnew entry, as per Alex Waygood's suggestion
stroxler Feb 4, 2023
6bd3356
Add ACKS entry, fix rst errors
stroxler Feb 4, 2023
42277cb
Fix title underline length in whatisnew doc.
stroxler Feb 4, 2023
afb74de
Update Misc/NEWS.d/next/Library/2023-02-04-16-35-46.gh-issue-101561.X…
stroxler Feb 4, 2023
090d9d2
Use a positional-only argument named `method`
stroxler Feb 4, 2023
f6c00e5
Apply suggestions from code review
stroxler Feb 27, 2023
File filter
Filter by extension

Clear filters
Conversations
Failed to load comments.
Loading

Uh oh!

There was an error while loading. Please reload this page.

Jump to
Jump to file
Failed to load files.
Loading

Uh oh!

There was an error while loading. Please reload this page.

Diff view
Diff view

There are no files selected for viewing

38 changes: 38 additions & 0 deletions 38 Doc/library/typing.rst
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ annotations. These include:
*Introducing* :data:`LiteralString`
* :pep:`681`: Data Class Transforms
*Introducing* the :func:`@dataclass_transform<dataclass_transform>` decorator
* :pep:`698`: Adding an override decorator to typing
*Introducing* the :func:`@override<override>` decorator

.. _type-aliases:

Expand Down Expand Up @@ -2722,6 +2724,42 @@ Functions and decorators
This wraps the decorator with something that wraps the decorated
function in :func:`no_type_check`.


.. decorator:: override

A decorator for methods that indicates to type checkers that this method
should override a method or attribute 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.

For example::

class Base:
def log_status(self)

class Sub(Base):
@override
def log_status(self) -> None: # Okay: overrides Base.log_status
...

@override
def done(self) -> None: # Error reported by type checker
...

There is no runtime checking of this property.

The decorator will set the ``__override__`` attribute to ``True`` on
the decorated object. Thus, a check like
``if getattr(obj, "__override__", False)`` can be used at runtime to determine
whether an object ``obj`` has been marked as an override. If the decorated object
does not support setting attributes, the decorator returns the object unchanged
without raising an exception.

See :pep:`698` for more details.

.. versionadded:: 3.12


.. decorator:: type_check_only

Decorator to mark a class or function to be unavailable at runtime.
Expand Down
8 changes: 8 additions & 0 deletions 8 Doc/whatsnew/3.12.rst
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,14 @@ tempfile
The :class:`tempfile.NamedTemporaryFile` function has a new optional parameter
*delete_on_close* (Contributed by Evgeny Zorin in :gh:`58451`.)

typing
------

* Add :func:`typing.override`, an override decorator telling to static type
checkers to verify that a method overrides some method or attribute of the
same name on a base class, as per :pep:`698`. (Contributed by Steven Troxler in
:gh:`101564`.)

sys
---

Expand Down
38 changes: 38 additions & 0 deletions 38 Lib/test/test_typing.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from typing import assert_type, cast, runtime_checkable
from typing import get_type_hints
from typing import get_origin, get_args
from typing import override
from typing import is_typeddict
from typing import reveal_type
from typing import dataclass_transform
Expand Down Expand Up @@ -4166,6 +4167,43 @@ def cached(self): ...
self.assertIs(True, Methods.cached.__final__)


class OverrideDecoratorTests(BaseTestCase):
def test_override(self):
class Base:
def normal_method(self): ...
@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

@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, instance.normal_method.__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__"))


class CastTests(BaseTestCase):

def test_basics(self):
Expand Down
41 changes: 41 additions & 0 deletions 41 Lib/typing.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ def _idfunc(_, x):
'NoReturn',
'NotRequired',
'overload',
'override',
'ParamSpecArgs',
'ParamSpecKwargs',
'Required',
Expand Down Expand Up @@ -2657,6 +2658,7 @@ class Other(Leaf): # Error reported by type checker
# Internal type variable used for Type[].
CT_co = TypeVar('CT_co', covariant=True, bound=type)


# A useful type variable with constraints. This represents string types.
# (This one *is* for export!)
AnyStr = TypeVar('AnyStr', bytes, str)
Expand Down Expand Up @@ -2748,6 +2750,8 @@ def new_user(user_class: Type[U]) -> U:
At this point the type checker knows that joe has type BasicUser.
"""

# Internal type variable for callables. Not for export.
F = TypeVar("F", bound=Callable[..., Any])

@runtime_checkable
class SupportsInt(Protocol):
Expand Down Expand Up @@ -3448,3 +3452,40 @@ def decorator(cls_or_fn):
}
return cls_or_fn
return decorator



def override(method: 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 or attribute 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.

There is no runtime checking of this property. The decorator sets the
``__override__`` attribute to ``True`` on the decorated object to allow
runtime introspection.

See PEP 698 for details.

"""
try:
method.__override__ = True
except (AttributeError, TypeError):
# Skip the attribute silently if it is not writable.
# AttributeError happens if the object has __slots__ or a
# read-only property, TypeError if it's a builtin class.
pass
return method
1 change: 1 addition & 0 deletions 1 Misc/ACKS
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -1848,6 +1848,7 @@ Tom Tromey
John Tromp
Diane Trout
Jason Trowbridge
Steven Troxler
Brent Tubbs
Anthony Tuininga
Erno Tukia
Expand Down
1 change: 1 addition & 0 deletions 1 Misc/NEWS.d/next/Library/2023-02-04-16-35-46.gh-issue-101561.Xo6pIZ.rst
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add a new decorator :func:`typing.override`. See :pep:`698` for details. Patch by Steven Troxler.
Add this suggestion to a batch that can be applied as a single commit. This suggestion is invalid because no changes were made to the code. Suggestions cannot be applied while the pull request is closed. Suggestions cannot be applied while viewing a subset of changes. Only one suggestion per line can be applied in a batch. Add this suggestion to a batch that can be applied as a single commit. Applying suggestions on deleted lines is not supported. You must change the existing code in this line in order to create a valid suggestion. Outdated suggestions cannot be applied. This suggestion has been applied or marked resolved. Suggestions cannot be applied from pending reviews. Suggestions cannot be applied on multi-line comments. Suggestions cannot be applied while the pull request is queued to merge. Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.