python / mypy

Optional static typing for Python
https://www.mypy-lang.org/
Other
17.85k stars 2.74k forks source link

Staticmethod's generated by closures are not recognized as being static #17438

Open rpbeltran opened 1 week ago

rpbeltran commented 1 week ago

When using a closure to generate static methods, the resulting static method is not properly identified by mypy as being a static method. This causes mypy to complain about using the static method decorator for the inner function, and also about resulting calls to the function when using self.my_static_method

This code reproduces the issue:

from typing import Callable

class Foo:

    @staticmethod
    def add_to(num: int) -> Callable[[int], int]:
        @staticmethod
        def add_to_inner(x: int) -> int:
            return x + num
        return add_to_inner

    add1 = add_to(1)

    def __init__(self, value: int):
        self.value = value
        self.value_plus_1 = self.add1(value)

if __name__ == "__main__":
    f = Foo(10)
    print(f.value)
    print(f.value_plus_1)

When evaluated with mypy I get the errors:

$ mypy mypy-nested-static.py
mypy-nested-static.py:7: error: "staticmethod" used with a non-method  [misc]
mypy-nested-static.py:16: error: Invalid self argument "Foo" to attribute function "add1" with type "Callable[[int], int]"  [misc]
mypy-nested-static.py:16: error: Too many arguments  [call-arg]

This pattern is admittedly a bit strange but I believe it should be valid. I bumped into this when using a library that abuses static methods a little bit so my hands were a bit tied to this design.

Version info: mypy 1.10.0 (compiled: yes)