Skip to content

F811 (redefinition of unused variable) incorrectly triggered with @overload decorator #320

Closed

Description

@bartvm

PEP 484 introduced the @overload decorator for type annotations.

[...] a series of @overload-decorated definitions must be followed by exactly one non-@overload-decorated definition (for the same function/method). The @overload-decorated definitions are for the benefit of the type checker only, since they will be overwritten by the non-@overload-decorated definition, while the latter is used at runtime but should be ignored by a type checker.

The following should pass PyFlakes without errors, but currently triggers F811 errors:

from typing import overload


@overload
def utf8(value: None) -> None:
    pass


@overload
def utf8(value: bytes) -> bytes:
    pass


@overload
def utf8(value: str) -> bytes:
    pass


def utf8(value):
    pass  # actual implementation
test.py:9:1: F811 redefinition of unused 'utf8' from line 4
test.py:14:1: F811 redefinition of unused 'utf8' from line 9
test.py:19:1: F811 redefinition of unused 'utf8' from line 14

Activity

  1. tscholak commented on Feb 13, 2018

    @tscholak

    facing the same issue. do you have a workaround?

  2. bartvm commented on Feb 13, 2018

    @bartvm
    Author

    Added this to .pydocstyle

    [pydocstyle]
    ignore-decorators = overload
    
    We ended up adding `# noqa: F811` comments.
  3. sigmavirus24 commented on Feb 13, 2018

    @sigmavirus24
    Member

    How does pydocstyle config fix a pyflakes bug?

  4. asottile commented on Oct 14, 2018

    @asottile
    Member

    I took a stab at this: #371

  5. feisuzhu commented on Mar 4, 2019

    @feisuzhu

    Hi, it's good to see #371 solved this partially, but overloads on classes is still incorrectly triggered

    import typing
    from typing import overload
    
    
    class Foo:
        @overload
        def f(self, s):  # type: (None) -> None
            pass
    
        @overload
        def f(self, s):  # type: (int) -> int
            pass
    
        def f(self, s):
            return s
    
        @typing.overload
        def g(self, s):  # type: (None) -> None
            pass
    
        @typing.overload
        def g(self, s):  # type: (int) -> int
            pass
    
        def g(self, s):
            return s
    ☁  shm  pyflakes a.py 
    a.py:11: redefinition of unused 'f' from line 6
    a.py:16: redefinition of unused 'f' from line 10
    ☁  shm  pyflakes --version
    2.1.1 Python 3.6.7 on Linux
    

    I'm now working around this by using full typing.overload name

  6. asottile commented on Mar 4, 2019

    @asottile
    Member

    @feisuzhu try master, I've already fixed this: #435

  7. eellison commented on Aug 6, 2019

    @eellison

    I still have this issue when the overload decorator is wrapped by another decorator.

    def my_decorator(func):
        return typing.overload(func)
    
    @my_decorator
    def utf8(value: None) -> None:
        pass
    
    @my_decorator
    def utf8(value: bytes) -> bytes:
        pass
    
    def utf8(value):
        pass  # actual implementation
    
  8. asottile commented on Aug 6, 2019

    @asottile
    Member

    that's not possible to detect statically -- I'd suggest not doing that (I don't think mypy can detect that either)

    I'd suggest explicitly using the overload decorator

  9. eellison commented on Aug 6, 2019

    @eellison

    Gotcha. I don't think this works either.

    from typing import overload
    
    def my_decorator(func):
        return func
    
    @overload
    @my_decorator
    def utf8(value: None) -> None:
        pass
    
    @overload
    @my_decorator
    def utf8(value: bytes) -> bytes:
        pass
    
    def utf8(value):
        pass  # actual implementation
    
    
  10. asottile commented on Aug 6, 2019

    @asottile
    Member

    Have you tried on master? it works for me

  11. asottile commented on Aug 6, 2019

    @asottile
    Member

    actually, it even works with the released version of pyflakes so you're probably on an old one

  12. eellison commented on Aug 6, 2019

    @eellison

    This is my version info that doesn't work:

    3.7.8 (flake8-comprehensions: 2.1.0, flake8-mypy: 17.8.0, mccabe: 0.6.1, pycodestyle: 2.5.0, pyflakes: 2.1.1) CPython 3.6.8 on Linux

    What do you think about counting a decorator as a use of a function? Edit: the redefinition error would still exist even if the unused wouldn't

  13. asottile commented on Aug 6, 2019

    @asottile
    Member

    actually, I'm wrong about it being already released -- it is fixed on master though, please try that and confirm

  14. asottile commented on Aug 6, 2019

    @asottile
    Member

    see #435

  15. eellison commented on Aug 6, 2019

    @eellison

    yea works on master, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions