overrides


Nameoverrides JSON
Version 7.7.0 PyPI version JSON
download
home_pagehttps://github.com/mkorpela/overrides
SummaryA decorator to automatically detect mismatch when overriding a method.
upload_time2024-01-27 21:01:33
maintainer
docs_urlNone
authorMikko Korpela
requires_python>=3.6
licenseApache License, Version 2.0
keywords override inheritence oop
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            overrides
=========

.. image:: https://img.shields.io/pypi/v/overrides.svg
  :target: https://pypi.python.org/pypi/overrides

.. image:: http://pepy.tech/badge/overrides
  :target: http://pepy.tech/project/overrides

A decorator ``@override`` that verifies that a method that should override an inherited method actually does it.

Copies the docstring of the inherited method to the overridden method.

Since signature validation and docstring inheritance are performed on class creation and not on class instantiation,
this library significantly improves the safety and experience of creating class hierarchies in 
Python without significantly impacting performance. See https://stackoverflow.com/q/1167617 for the
initial inspiration for this library.

Motivation
----------

Python has no standard mechanism by which to guarantee that (1) a method that previously overrode an inherited method
continues to do so, and (2) a method that previously did not override an inherited will not override now.
This opens the door for subtle problems as class hierarchies evolve over time. For example,

1. A method that is added to a superclass is shadowed by an existing method with the same name in a 
   subclass.

2. A method of a superclass that is overridden by a subclass is renamed in the superclass but not in 
   the subclass.

3. A method of a superclass that is overridden by a subclass is removed in the superclass but not in
   the subclass.

4. A method of a superclass that is overridden by a subclass but the signature of the overridden
   method is incompatible with that of the inherited one.

These can be only checked by explicitly marking method override in the code.

Python also has no standard mechanism by which to inherit docstrings in overridden methods. Because 
most standard linters (e.g., flake8) have rules that require all public methods to have a docstring, 
this inevitably leads to a proliferation of ``See parent class for usage`` docstrings on overridden
methods, or, worse, to a disabling of these rules altogether. In addition, mediocre or missing
docstrings degrade the quality of tooltips and completions that can be provided by an editor.

Installation
------------

Compatible with Python 3.6+.

.. code-block:: bash

    $ pip install overrides

Usage
-----

Use ``@override`` to indicate that a subclass method should override a superclass method.

.. code-block:: python

    from overrides import override

    class SuperClass:

        def foo(self):
            """This docstring will be inherited by any method that overrides this!"""
            return 1

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

    class SubClass(SuperClass):

        @override
        def foo(self):
            return 2

        @override
        def bar(self, y) -> int: # Raises, because the signature is not compatible.
            return y
            
        @override
        def zoo(self): # Raises, because does not exist in the super class.
            return "foobarzoo"

Use ``EnforceOverrides`` to require subclass methods that shadow superclass methods to be decorated 
with ``@override``.

.. code-block:: python
 
    from overrides import EnforceOverrides

    class SuperClass(EnforceOverrides):

        def foo(self):
            return 1

    class SubClass(SuperClass):

        def foo(self): # Raises, because @override is missing.
            return 2

Use ``@final`` to indicate that a superclass method cannot be overriden.
With Python 3.11 and above ``@final`` is directly `typing.final <https://docs.python.org/3.11/library/typing.html#typing.final>`_.

.. code-block:: python

    from overrides import EnforceOverrides, final, override

    class SuperClass(EnforceOverrides):

        @final
        def foo(self):
            return 1

    class SubClass(SuperClass):

        @override
        def foo(self): # Raises, because overriding a final method is forbidden.
            return 2

Note that ``@classmethod`` and ``@staticmethod`` must be declared before ``@override``.

.. code-block:: python

    from overrides import override

    class SuperClass:

        @staticmethod
        def foo(x):
            return 1

    class SubClass(SuperClass):

        @staticmethod
        @override
        def foo(x):
            return 2


Flags of control
----------------

.. code-block:: python

    # To prevent all signature checks do:
    @override(check_signature=False)
    def some_method(self, now_this_can_be_funny_and_wrong: str, what_ever: int) -> "Dictirux":
        pass

    # To do the check only at runtime and solve some forward reference problems
    @override(check_at_runtime=True)
    def some_other_method(self, ..) -> "SomethingDefinedLater":
        pass

    a.some_other_method() # Kaboom if not SomethingDefinedLater


Contributors
------------

This project exists only through the work of all the people who contribute.

mkorpela, drorasaf, ngoodman90, TylerYep, leeopop, donpatrice, jayvdb, joelgrus, lisyarus, 
soulmerge, rkr-at-dbx, ashwin153, brentyi,  jobh, tjsmart, bersbersbers, LysanderGG, mgorny.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/mkorpela/overrides",
    "name": "overrides",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.6",
    "maintainer_email": "",
    "keywords": "override,inheritence,OOP",
    "author": "Mikko Korpela",
    "author_email": "mikko.korpela@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/36/86/b585f53236dec60aba864e050778b25045f857e17f6e5ea0ae95fe80edd2/overrides-7.7.0.tar.gz",
    "platform": null,
    "description": "overrides\n=========\n\n.. image:: https://img.shields.io/pypi/v/overrides.svg\n  :target: https://pypi.python.org/pypi/overrides\n\n.. image:: http://pepy.tech/badge/overrides\n  :target: http://pepy.tech/project/overrides\n\nA decorator ``@override`` that verifies that a method that should override an inherited method actually does it.\n\nCopies the docstring of the inherited method to the overridden method.\n\nSince signature validation and docstring inheritance are performed on class creation and not on class instantiation,\nthis library significantly improves the safety and experience of creating class hierarchies in \nPython without significantly impacting performance. See https://stackoverflow.com/q/1167617 for the\ninitial inspiration for this library.\n\nMotivation\n----------\n\nPython has no standard mechanism by which to guarantee that (1) a method that previously overrode an inherited method\ncontinues to do so, and (2) a method that previously did not override an inherited will not override now.\nThis opens the door for subtle problems as class hierarchies evolve over time. For example,\n\n1. A method that is added to a superclass is shadowed by an existing method with the same name in a \n   subclass.\n\n2. A method of a superclass that is overridden by a subclass is renamed in the superclass but not in \n   the subclass.\n\n3. A method of a superclass that is overridden by a subclass is removed in the superclass but not in\n   the subclass.\n\n4. A method of a superclass that is overridden by a subclass but the signature of the overridden\n   method is incompatible with that of the inherited one.\n\nThese can be only checked by explicitly marking method override in the code.\n\nPython also has no standard mechanism by which to inherit docstrings in overridden methods. Because \nmost standard linters (e.g., flake8) have rules that require all public methods to have a docstring, \nthis inevitably leads to a proliferation of ``See parent class for usage`` docstrings on overridden\nmethods, or, worse, to a disabling of these rules altogether. In addition, mediocre or missing\ndocstrings degrade the quality of tooltips and completions that can be provided by an editor.\n\nInstallation\n------------\n\nCompatible with Python 3.6+.\n\n.. code-block:: bash\n\n    $ pip install overrides\n\nUsage\n-----\n\nUse ``@override`` to indicate that a subclass method should override a superclass method.\n\n.. code-block:: python\n\n    from overrides import override\n\n    class SuperClass:\n\n        def foo(self):\n            \"\"\"This docstring will be inherited by any method that overrides this!\"\"\"\n            return 1\n\n        def bar(self, x) -> str:\n            return x\n\n    class SubClass(SuperClass):\n\n        @override\n        def foo(self):\n            return 2\n\n        @override\n        def bar(self, y) -> int: # Raises, because the signature is not compatible.\n            return y\n            \n        @override\n        def zoo(self): # Raises, because does not exist in the super class.\n            return \"foobarzoo\"\n\nUse ``EnforceOverrides`` to require subclass methods that shadow superclass methods to be decorated \nwith ``@override``.\n\n.. code-block:: python\n \n    from overrides import EnforceOverrides\n\n    class SuperClass(EnforceOverrides):\n\n        def foo(self):\n            return 1\n\n    class SubClass(SuperClass):\n\n        def foo(self): # Raises, because @override is missing.\n            return 2\n\nUse ``@final`` to indicate that a superclass method cannot be overriden.\nWith Python 3.11 and above ``@final`` is directly `typing.final <https://docs.python.org/3.11/library/typing.html#typing.final>`_.\n\n.. code-block:: python\n\n    from overrides import EnforceOverrides, final, override\n\n    class SuperClass(EnforceOverrides):\n\n        @final\n        def foo(self):\n            return 1\n\n    class SubClass(SuperClass):\n\n        @override\n        def foo(self): # Raises, because overriding a final method is forbidden.\n            return 2\n\nNote that ``@classmethod`` and ``@staticmethod`` must be declared before ``@override``.\n\n.. code-block:: python\n\n    from overrides import override\n\n    class SuperClass:\n\n        @staticmethod\n        def foo(x):\n            return 1\n\n    class SubClass(SuperClass):\n\n        @staticmethod\n        @override\n        def foo(x):\n            return 2\n\n\nFlags of control\n----------------\n\n.. code-block:: python\n\n    # To prevent all signature checks do:\n    @override(check_signature=False)\n    def some_method(self, now_this_can_be_funny_and_wrong: str, what_ever: int) -> \"Dictirux\":\n        pass\n\n    # To do the check only at runtime and solve some forward reference problems\n    @override(check_at_runtime=True)\n    def some_other_method(self, ..) -> \"SomethingDefinedLater\":\n        pass\n\n    a.some_other_method() # Kaboom if not SomethingDefinedLater\n\n\nContributors\n------------\n\nThis project exists only through the work of all the people who contribute.\n\nmkorpela, drorasaf, ngoodman90, TylerYep, leeopop, donpatrice, jayvdb, joelgrus, lisyarus, \nsoulmerge, rkr-at-dbx, ashwin153, brentyi,  jobh, tjsmart, bersbersbers, LysanderGG, mgorny.\n",
    "bugtrack_url": null,
    "license": "Apache License, Version 2.0",
    "summary": "A decorator to automatically detect mismatch when overriding a method.",
    "version": "7.7.0",
    "project_urls": {
        "Homepage": "https://github.com/mkorpela/overrides"
    },
    "split_keywords": [
        "override",
        "inheritence",
        "oop"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "2cabfc8290c6a4c722e5514d80f62b2dc4c4df1a68a41d1364e625c35990fcf3",
                "md5": "e2085e15aab27f255ebae2916092c4f5",
                "sha256": "c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49"
            },
            "downloads": -1,
            "filename": "overrides-7.7.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "e2085e15aab27f255ebae2916092c4f5",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6",
            "size": 17832,
            "upload_time": "2024-01-27T21:01:31",
            "upload_time_iso_8601": "2024-01-27T21:01:31.393624Z",
            "url": "https://files.pythonhosted.org/packages/2c/ab/fc8290c6a4c722e5514d80f62b2dc4c4df1a68a41d1364e625c35990fcf3/overrides-7.7.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "3686b585f53236dec60aba864e050778b25045f857e17f6e5ea0ae95fe80edd2",
                "md5": "a95b152a6d0c14ed9d8b331ca35c2183",
                "sha256": "55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a"
            },
            "downloads": -1,
            "filename": "overrides-7.7.0.tar.gz",
            "has_sig": false,
            "md5_digest": "a95b152a6d0c14ed9d8b331ca35c2183",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.6",
            "size": 22812,
            "upload_time": "2024-01-27T21:01:33",
            "upload_time_iso_8601": "2024-01-27T21:01:33.423462Z",
            "url": "https://files.pythonhosted.org/packages/36/86/b585f53236dec60aba864e050778b25045f857e17f6e5ea0ae95fe80edd2/overrides-7.7.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-01-27 21:01:33",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "mkorpela",
    "github_project": "overrides",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "overrides"
}
        
Elapsed time: 0.24858s