Overrides Library
The `overrides` library (v7.7.0) provides a Python decorator `@override` to ensure that a method in a subclass correctly overrides a method from its superclass. It also includes `EnforceOverrides` for metaclass-level checks and `@final` to prevent methods from being overridden. The library focuses on improving the safety and experience of creating class hierarchies by catching common errors at class creation time, such as signature mismatches or accidental non-overrides. It has a regular release cadence, with several minor and patch releases in the past year.
Warnings
- breaking In version 7.0.0, the library changed how it handles `final` magic methods and assertion failures. Magic methods (e.g., `__eq__`, `__init__`) marked as `@final` that are accidentally overridden now raise `TypeError` instead of `AssertionError`. Similarly, assertion errors originating from the `EnforceOverrides` metaclass have been changed to `TypeErrors`. This may break existing tests or error handling code that specifically caught `AssertionError`.
- gotcha Versions prior to 7.6.0 might experience issues with Python 3.12 due to changes in bytecode handling. This could lead to unexpected behavior or runtime errors on Python 3.12 environments.
- gotcha When combining `@override` with other method decorators like `@classmethod` or `@staticmethod`, the `@classmethod` or `@staticmethod` decorator must always be applied *before* `@override`. Incorrect order will lead to unexpected behavior or errors.
- deprecated The original decorator name `@overrides` (plural) is still functional, but `@override` (singular) was introduced in version 7.3.0 as an alias and is now the officially recommended decorator name, aligning with common usage and `typing.override`.
- gotcha If a base class inherits from `EnforceOverrides`, any method in a subclass that is intended to override a superclass method *must* be explicitly decorated with `@override` (or `@overrides`). Failing to do so will result in a `TypeError` at class definition time, preventing subtle bugs caused by method signature changes in parent classes.
- gotcha Python 3.12 introduced a standard `typing.override` decorator (PEP 698) for static type checkers. The `overrides` library's `@override` provides *runtime* validation and docstring inheritance, which is distinct from `typing.override`'s static analysis purpose. Using both might be confusing but they serve different roles.
Install
-
pip install overrides
Imports
- override
from overrides import override
- overrides
from overrides import overrides
- EnforceOverrides
from overrides import EnforceOverrides
- final
from overrides import final
Quickstart
from overrides import override, EnforceOverrides
class Animal(EnforceOverrides):
def make_sound(self) -> str:
raise NotImplementedError
def eat(self) -> str:
return "Eating generic food"
class Dog(Animal):
@override
def make_sound(self) -> str:
return "Woof!"
# No @override needed if not overriding a method, or if EnforceOverrides is not used.
def fetch(self) -> str:
return "Fetching the ball"
# Example of usage
dog = Dog()
print(dog.make_sound())
print(dog.eat())
# This would raise TypeError if @override was missing on make_sound and EnforceOverrides was used.
# class Cat(Animal):
# def make_sound(self) -> str: # Missing @override, would fail with EnforceOverrides
# return "Meow!"