Description
Bug description
Hi from Ruff!
We recently received a bug report at Ruff stating that our reimplementation of E1520 was recommending an invalid combination of @functools.singledispatch
and @staticmethod
. For example, this code runs fine, but ruff's PLE1520 rule was telling the issue reporter that they should use @singledispatch
here instead of @singledispatchmethod
. If you do so, the code raises an exception at runtime, as @staticmethod
is a descriptor, and @singledispatch
isn't designed to be stacked on top of descriptor instances (that's what @singledispatchmethod
is for). The Python docs also state that @singledispatchmethod
should be used for static methods: https://docs.python.org/3/library/functools.html#functools.singledispatchmethod.
from functools import singledispatch, singledispatchmethod
class Foo:
@singledispatchmethod
@staticmethod
def bar(value):
raise NotImplementedError()
@bar.register
@staticmethod
def _(value: int) -> int:
return 42 * value
def method(self) -> int:
return self.bar(2)
print(Foo().method())
After investigating the bug, we decided to change our PLE1520 rule so that it no longer complained about @singledispatchmethod
on top of @staticmethod
. It looks like pylint has the same incorrect behaviour here in the original PLE1520 rule, though, so I thought I'd open an issue to give you a heads-up as well!
In case it's helpful, here's the fix that was contributed to Ruff to fix the bug: astral-sh/ruff#10637. The fix also involved some small changes to PLE1519 (E1519 at pylint) as well as PLE1520 (E1520 at pylint).
Command used
pylint demo.py
Pylint output
************* Module demo
demo.py:7:35: C0303: Trailing whitespace (trailing-whitespace)
demo.py:1:0: C0114: Missing module docstring (missing-module-docstring)
demo.py:3:0: C0115: Missing class docstring (missing-class-docstring)
demo.py:6:4: C0116: Missing function or method docstring (missing-function-docstring)
demo.py:6:4: C0104: Disallowed name "bar" (disallowed-name)
demo.py:4:5: E1520: singledispatchmethod decorator should not be used with functions, use singledispatch instead. (singledispatchmethod-function)
demo.py:9:5: E1520: singledispatchmethod decorator should not be used with functions, use singledispatch instead. (singledispatchmethod-function)
demo.py:14:4: C0116: Missing function or method docstring (missing-function-docstring)
demo.py:1:0: W0611: Unused singledispatch imported from functools (unused-import)
------------------------------------------------------------------
Your code has been rated at 0.00/10 (previous run: 0.00/10, +0.00)
Expected behavior
************* Module demo
demo.py:7:35: C0303: Trailing whitespace (trailing-whitespace)
demo.py:1:0: C0114: Missing module docstring (missing-module-docstring)
demo.py:3:0: C0115: Missing class docstring (missing-class-docstring)
demo.py:6:4: C0116: Missing function or method docstring (missing-function-docstring)
demo.py:6:4: C0104: Disallowed name "bar" (disallowed-name)
demo.py:14:4: C0116: Missing function or method docstring (missing-function-docstring)
demo.py:1:0: W0611: Unused singledispatch imported from functools (unused-import)
------------------------------------------------------------------
Your code has been rated at 10.00/10 (previous run: 0.00/10, +0.00)
Pylint version
pylint 3.1.0
astroid 3.1.0
Python 3.12.2 (main, Feb 15 2024, 19:30:27) [Clang 15.0.0 (clang-1500.1.0.2.5)]
OS / Environment
MacOS; Python 3.12.2
Additional dependencies
None