Skip to content

Spurious error with partial and ParamSpec #15215

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
sterliakov opened this issue May 10, 2023 · 0 comments · Fixed by #18954
Closed

Spurious error with partial and ParamSpec #15215

sterliakov opened this issue May 10, 2023 · 0 comments · Fixed by #18954
Labels
bug mypy got something wrong topic-paramspec PEP 612, ParamSpec, Concatenate

Comments

@sterliakov
Copy link
Collaborator

Bug Report

When type checking the code below mypy produces a bunch of weird errors, most interesting one being

Argument 1 to "partial" has incompatible type "Callable[[Callable[_P, _T], NamedArg(str, 'name')], Task[_P, _T]]"; expected "Callable[..., Task[_P, _T]]"  [arg-type]

I'm not sure, but isn't Callable[[Something], Task[_P, _T]] always compatible with Callable[..., Task[_P, _T]]?

To Reproduce

You can also see this in playground.

from __future__ import annotations

from dataclasses import dataclass
from functools import partial
from typing import Any, TypeVar, ParamSpec, Generic, Protocol, Callable


_T = TypeVar("_T")
_P = ParamSpec("_P")


@dataclass(kw_only=True, repr=True)
class Task(Generic[_P, _T]):
    name: str
    function: Callable[_P, _T]


class _TaskRegistrator(Protocol):
    def __call__(self, func: Callable[_P, _T], /, *, name: str = ...) -> Task[_P, _T]:
        ...


class TaskQueue:
    def _register_task(self, func: Callable[_P, _T], *, name: str) -> Task[_P, _T]:
        # Actual implementation omitted
        return Task(name=name, function=func)

    def task(self, name: str) -> _TaskRegistrator:
        return partial(self._register_task, name=name)  # E: see below (L29)
        
    def task2(self, name: str) -> Callable[[Callable[_P, _T]], Task[_P, _T]]:
        return partial(self._register_task, name=name)  # E: see below (L32)


# And now we see that the problem is even unrelated to `self`:

def _register_task(func: Callable[_P, _T], *, name: str) -> Task[_P, _T]:
    # Actual implementation omitted
    return Task(name=name, function=func)

def task(name: str) -> _TaskRegistrator:
    return partial(_register_task, name=name)  # E: see below (L42)

Expected Behavior

From my understanding, no mypy errors should be pointed out. pyright agrees with me (just to test on another typechecker) - all green - but I'm not ready to switch from convenient mypy to pyright (I personally dislike that project for being non-python in python ecosystem, plus my current project relies heavily on Django plugin).

Actual Behavior

Several errors, all located on lines with partial(...) calls.

main.py:29: error: Argument 1 to "partial" has incompatible type "Callable[[Callable[_P, _T], NamedArg(str, 'name')], Task[_P, _T]]"; expected "Callable[..., Task[_P, _T]]"  [arg-type]
main.py:32: error: Incompatible return value type (got "partial[Task[_P, _T]]", expected "Callable[[Callable[_P, _T]], Task[_P, _T]]")  [return-value]
main.py:32: note: "partial[Task[_P, _T]].__call__" has type "Callable[[VarArg(Any), KwArg(Any)], Task[_P, _T]]"
main.py:32: error: Argument 1 to "partial" has incompatible type "Callable[[Callable[_P, _T], NamedArg(str, 'name')], Task[_P, _T]]"; expected "Callable[..., Task[_P, _T]]"  [arg-type]
main.py:42: error: Argument 1 to "partial" has incompatible type "Callable[[Callable[_P, _T], NamedArg(str, 'name')], Task[_P, _T]]"; expected "Callable[..., Task[_P, _T]]"  [arg-type]
Found 4 errors in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: 1.2.0, then master and all versions since 0.990.
  • Mypy command-line flags: none (with and without --strict result is the same)
  • Mypy configuration options from mypy.ini (and other config files): none
  • Python version used: 3.10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-paramspec PEP 612, ParamSpec, Concatenate
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants