Skip to content

How to type a decorator which also injects an attribute? #1509

Answered by erictraut
BrandonNav asked this question in Q&A
Discussion options

You must be logged in to vote

You're modifying the value in a way that's not type safe, so you'd need to use a cast call.

Code sample in pyright playground

from functools import wraps
from typing import Callable, Literal, ParamSpec, Protocol, TypeVar, cast

_R = TypeVar("_R", covariant=True)
_P = ParamSpec("_P")

class CallableExemptForCSRF(Protocol[_P, _R]):
    exempt: Literal[True]

    def __call__(self, *args: _P.args, **kwds: _P.kwargs) -> _R:
        ...

def mark_exempt(func: Callable[_P, _R]) -> CallableExemptForCSRF[_P, _R]:
    @wraps(func)
    def wrapped(*args: _P.args, **kwargs: _P.kwargs) -> _R:
        return func(*args, **kwargs)

    setattr(wrapped, "exempt", True)
    return cast(CallableExemptForCSRF

Replies: 1 comment 1 reply

Comment options

You must be logged in to vote
1 reply
@BrandonNav
Comment options

Answer selected by BrandonNav
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet
2 participants