Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Annotate function that passes parameters to another function

def foo(myarg, **other_args):
    # do something
    return bar(**other_args)

Is it possible to annotate this function in a way that would make it clear to IDEs that other_args are the arguments of function bar()? So that the IDE would provide a helpful code completion in this case.

like image 806
BlindDriver Avatar asked Sep 07 '25 21:09

BlindDriver


1 Answers

Combine this answer with Concatenate:

(playgrounds: Mypy, Pyright)

def same_signature_with_one_leading_extra[**P, T, E](
    _origin: Callable[P, T]
) -> Callable[
    [Callable[Concatenate[E, ...], Any]],
    Callable[Concatenate[E, P], T]
]:
    def decorator(target: Callable[Concatenate[E, ...], Any]) -> Callable[Concatenate[E, P], T]:
        return cast(Callable[Concatenate[E, P], T], target)
    
    return decorator
def bar(*, lorem: bool, ipsum: float = 3.14) -> None:
    ...

@same_signature_with_one_leading_extra(bar)
def foo(myarg: Foo, *args: Any, **kwargs: Any) -> Any:
    return bar(**kwargs)

reveal_type(foo)  # (Foo, *, lorem: bool, ipsum: float = 3.14) -> None

Note that Mypy requires myarg to be positional-only (the /):

@same_signature_with_one_leading_extra(bar)
def foo(myarg: Foo, /, *args: Any, **kwargs: Any) -> Any:
    return bar(**kwargs)

Concatenate prepends a type variable E to the parameter specification P. In context:

  • E refers to the type of myarg, which is Foo
  • P refers to the signature of _origin, which is (*, lorem: bool, ipsum: float = 3.14)

Concatenate[E, P] is thus resolved to (Foo, *, lorem: bool, ipsum: float = 3.14). This, wrapped in Callable[<>, T], is used as the return type of the decorator and becomes the new type of foo.

IDE support

VSCode/Pylance has good support for this (since this data is taken directly from Pyright):

(Foo, *, lorem: bool, ipsum: float = 3.14) -> None

PyCharm, not so much:

foo(Foo(), lorem = True); Parameter(s) unfilled

like image 101
InSync Avatar answered Sep 09 '25 10:09

InSync