Open
Description
Bug Report
Trying to combine function attributes (a la #2087) where we add the attribute with a decorator fails to apply the decorator and the attribute is dropped on the ground.
To Reproduce
from __future__ import annotations
from typing import overload, Callable, TypeVar, Protocol
from typing_extensions import ParamSpec, reveal_type
P = ParamSpec("P")
R = TypeVar("R", covariant=True)
class WithExtra(Protocol[P, R]):
extra: str
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R: ...
def add_extra(func: Callable[P, R]) -> WithExtra[P, R]:
func.extra = "added" # type: ignore
return func # type: ignore
@overload
@add_extra
def foo(x: int) -> str: ...
@overload
@add_extra
def foo(x: str) -> str: ...
@add_extra
def foo(x: int | str) -> str:
return str(x)
assert foo.extra # type: ignore[attr-defined]
reveal_type(foo) # Revealed type is "Overload(def (x: builtins.int) -> builtins.str, def (x: builtins.str) -> builtins.str)"
This works in pyright.
I feel like it should be possible to work around it with a callable class, but I've yet to figure out the proper incantation.
Real-life use: https://github.com/pytest-dev/pytest/blob/b0caf3d7adc45f773177424593431869fd2f82d8/src/_pytest/python_api.py#L1025
Your Environment
- Mypy version used: 1.14.1
- Mypy command-line flags: none
- Mypy configuration options from
mypy.ini
(and other config files): none - Python version used: python 3.13.1