Для произвольной функции вы вообще не можете этого сделать - здесь даже нет синтаксиса. Вот я составляю некоторый синтаксис для этого.

отрим следующий код:

from typing import Callable, Any

TFunc = Callable[..., Any]

def get_authenticated_user(): return "John"

def require_auth() -> Callable[TFunc, TFunc]:
    def decorator(func: TFunc) -> TFunc:
        def wrapper(*args, **kwargs) -> Any:
            user = get_authenticated_user()
            if user is None:
                raise Exception("Don't!")
            return func(*args, **kwargs)
        return wrapper
    return decorator

@require_auth()
def foo(a: int) -> bool:
    return bool(a % 2)

foo(2)      # Type check OK
foo("no!")  # Type check failing as intended

Этот кусок кода работает как задумано. Теперь представьте, что я хочу расширить это, а не просто выполнятьfunc(*args, **kwargs) Я хочу ввести имя пользователя в аргументах. Поэтому я изменяю сигнатуру функции.

from typing import Callable, Any

TFunc = Callable[..., Any]

def get_authenticated_user(): return "John"

def inject_user() -> Callable[TFunc, TFunc]:
    def decorator(func: TFunc) -> TFunc:
        def wrapper(*args, **kwargs) -> Any:
            user = get_authenticated_user()
            if user is None:
                raise Exception("Don't!")
            return func(*args, user, **kwargs)  # <- call signature modified

        return wrapper

    return decorator


@inject_user()
def foo(a: int, username: str) -> bool:
    print(username)
    return bool(a % 2)


foo(2)      # Type check OK
foo("no!")  # Type check OK <---- UNEXPECTED

Я не могу найти правильный способ напечатать это. Я знаю, что в этом примере оформленная функция и возвращаемая функция должны технически иметь одинаковую подпись (но даже это не определяется).

Ответы на вопрос(1)

Ваш ответ на вопрос