pylint icon indicating copy to clipboard operation
pylint copied to clipboard

Pylint doesn't complain on Protocol callback argument-type / return-type mismatch

Open manuel-koch opened this issue 8 months ago • 1 comments

Bug description

from typing import Protocol


class Handler(Protocol):
    def __call__(self, value: int, name: str) -> int:
        pass


def invalid_func_arg_type_mismatch(value: str, name: str) -> int:
    return value * 2


def invalid_func_return_type_mismatch(value: int, name: str) -> str:
    return value * 2


class AsyncHandler(Protocol):
    async def __call__(self, value: int, name: str) -> int:
        pass


async def invalid_async_func_arg_type_mismatch(value: str, name: str) -> int:
    return value * 2


async def invalid_async_func_return_type_mismatch(value: int, name: str) -> str:
    return value * 2



# None of the following lines triggers a pylint issue regarding
# mismatch of the return-type or argument-type from the defined Protocol.
# My IntelliJ IDE complains on all 4 lines, because either an argument-type
# or the return-type of the function will not match the `Protocol` I try to assign
# to.

# Expected type 'Handler', got '(value: str, name: str) -> int' instead
my_handler_a: Handler = invalid_func_arg_type_mismatch

# Expected type 'Handler', got '(value: int, name: str) -> str' instead
my_handler_b: Handler = invalid_func_return_type_mismatch

# Expected type 'AsyncHandler', got '(value: str, name: str) -> Coroutine[Any, Any, int]' instead
my_handler_c: AsyncHandler = invalid_async_func_arg_type_mismatch

# Expected type 'AsyncHandler', got '(value: int, name: str) -> Coroutine[Any, Any, str]' instead 
my_handler_d: AsyncHandler = invalid_async_func_return_type_mismatch

Configuration


Command used

pylint scratch.py

Pylint output

************* Module src.tests.scratch
src/tests/scratch.py:1:0: C0114: Missing module docstring (missing-module-docstring)
src/tests/scratch.py:4:0: C0115: Missing class docstring (missing-class-docstring)
src/tests/scratch.py:4:0: R0903: Too few public methods (1/2) (too-few-public-methods)
src/tests/scratch.py:9:0: C0116: Missing function or method docstring (missing-function-docstring)
src/tests/scratch.py:9:47: W0613: Unused argument 'name' (unused-argument)
src/tests/scratch.py:13:0: C0116: Missing function or method docstring (missing-function-docstring)
src/tests/scratch.py:13:50: W0613: Unused argument 'name' (unused-argument)
src/tests/scratch.py:17:0: C0115: Missing class docstring (missing-class-docstring)
src/tests/scratch.py:17:0: R0903: Too few public methods (1/2) (too-few-public-methods)
src/tests/scratch.py:22:0: C0116: Missing function or method docstring (missing-function-docstring)
src/tests/scratch.py:22:59: W0613: Unused argument 'name' (unused-argument)
src/tests/scratch.py:26:0: C0116: Missing function or method docstring (missing-function-docstring)
src/tests/scratch.py:26:62: W0613: Unused argument 'name' (unused-argument)

------------------------------------------------------------------
Your code has been rated at 3.16/10 (previous run: 3.16/10, +0.00)

Expected behavior

Assignment with mismatched types should result in output of pylint complaining about the mismatch with the given Protocol.

Pylint version

pylint 3.3.4
astroid 3.3.8
Python 3.12.9 (main, Feb  4 2025, 14:38:38) [Clang 16.0.0 (clang-1600.0.26.6)]

OS / Environment

MacOS, 15.3.1 (24D70), Apple M1 Pro

Additional dependencies


manuel-koch avatar Mar 04 '25 12:03 manuel-koch

Thank you for bringing this up. This would be a new check/message, as I don't think pylint currently checks for such cases. A type checker like mypy should be able to pick up these type mismatches.

zenlyj avatar Mar 08 '25 06:03 zenlyj