Skip to content
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.

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

Add typing.override decorator #101561

Closed
stroxler opened this issue Feb 4, 2023 · 1 comment
Closed

Add typing.override decorator #101561

stroxler opened this issue Feb 4, 2023 · 1 comment
Labels
3.12 bugs and security fixes stdlib Python modules in the Lib dir topic-typing type-feature A feature request or enhancement

Comments

@stroxler
Copy link
Contributor

stroxler commented Feb 4, 2023

Feature or enhancement

See PEP 698 for details.

The typing.override decorator should, at runtime, attempt to set the __override__ attribute on its argument to True and then return the argument. If it cannot set the __override__ flag it should return its argument unchanged.

Pitch

The purpose of typing.override is to inform static type checkers that we expect this method to override some attribute of an ancestor class. By having this decorator in place, a developer can ensure that static type checkers will warn them if a base class method name changes.

To quote the PEP consider a code change where we rename a parent class method.

The original code looks like this:

class Parent:
    def foo(self, x: int) -> int:
        return x

class Child(Parent):
    def foo(self, x: int) -> int:
        return x + 1

def parent_callsite(parent: Parent) -> None:
    parent.foo(1)

def child_callsite(child: Child) -> None:
    child.foo(1)

And after our rename it looks like this:

class Parent:
    # Rename this method
    def new_foo(self, x: int) -> int:
        return x

class Child(Parent):
    # This (unchanged) method used to override `foo` but is unrelated to `new_foo`
    def foo(self, x: int) -> int:
        return x + 1

def parent_callsite(parent: Parent) -> None:
    # If we pass a Child instance we’ll now run Parent.new_foo - likely a bug
    parent.new_foo(1)

def child_callsite(child: Child) -> None:
    # We probably wanted to invoke new_foo here. Instead, we forked the method
    child.foo(1)

In the code snippet above, renaming foo to new_foo in Parent invalidated the override foo of Child. But type checkers have no way of knowing this, because they only see a snapshot of the code.

If we mark Child.foo as an override, then static type checkers will catch the mistake when we rename only Parent.foo:

from typing import override

class Parent:
    def new_foo(self) -> int:
        return 1

    def bar(self, x: str) -> str:
        return x

class Child(Parent):
    @override
    def foo(self) -> int:   # Type Error: foo does not override an attribute of any ancestor
        return 2

Previous discussion

PEP 698 has details about the proposal itself.

Discussion on this proposal has happened on typing-sig and on [discuss.python.org)[https://discuss.python.org/t/pep-698-a-typing-override-decorator/20839].

Linked PRs

@stroxler stroxler added the type-feature A feature request or enhancement label Feb 4, 2023
@AlexWaygood AlexWaygood added stdlib Python modules in the Lib dir 3.12 bugs and security fixes labels Feb 4, 2023
@JelleZijlstra
Copy link
Member

Merged, thanks @stroxler!

JelleZijlstra added a commit that referenced this issue Feb 27, 2023
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
carljm added a commit to carljm/cpython that referenced this issue Feb 28, 2023
* main: (67 commits)
  pythongh-99108: Add missing md5/sha1 defines to Modules/Setup (python#102308)
  pythongh-100227: Move _str_replace_inf to PyInterpreterState (pythongh-102333)
  pythongh-100227: Move the dtoa State to PyInterpreterState (pythongh-102331)
  pythonGH-102305: Expand some macros in generated_cases.c.h (python#102309)
  Migrate to new PSF mailgun account (python#102284)
  pythongh-102192: Replace PyErr_Fetch/Restore etc by more efficient alternatives (in Python/) (python#102193)
  pythonGH-90744: Fix erroneous doc links in the sys module (python#101319)
  pythongh-87092: Make jump target label equal to the offset of the target in the instructions sequence (python#102093)
  pythongh-101101: Unstable C API tier (PEP 689) (pythonGH-101102)
  IDLE: Simplify DynOptionsMenu __init__code (python#101371)
  pythongh-101561: Add typing.override decorator (python#101564)
  pythongh-101825: Clarify that as_integer_ratio() output is always normalized (python#101843)
  pythongh-101773: Optimize creation of Fractions in private methods (python#101780)
  pythongh-102251: Updates to test_imp Toward Fixing Some Refleaks (pythongh-102254)
  pythongh-102296 Document that inspect.Parameter kinds support ordering (pythonGH-102297)
  pythongh-102250: Fix double-decref in COMPARE_AND_BRANCH error case (pythonGH-102287)
  pythongh-101100: Fix sphinx warnings in `types` module (python#102274)
  pythongh-91038: Change default argument value to `False` instead of `0` (python#31621)
  pythongh-101765: unicodeobject: use Py_XDECREF correctly (python#102283)
  [doc] Improve grammar/fix missing word (pythonGH-102060)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.12 bugs and security fixes stdlib Python modules in the Lib dir topic-typing type-feature A feature request or enhancement
Projects
None yet
Development

No branches or pull requests

3 participants