Skip to content

Variadic Callback Protocols for Non-Variadic Functions (I think?) #10657

Closed
@akern40

Description

@akern40

Feature

Currently, a function with multiple typed arguments does not match a protocol that defines typed variadic arguments. I think many people have a use for typing these functions with a variadic callback protocol, especially when writing wrappers. I believe this is related to #5876, but extends the use of Any to other types.

Pitch

Many times it is useful to define a wrapper function with the signature wrapper(*args: T, **kwargs: Any) -> T, or something similar. This allows you to create a wrapper that is agnostic to the number of positional arguments, as long as they are all of the same type, with optional keyword arguments. This wrapper can then be applied to any number of functions that take in multiple positional arguments of the same type. For example:

from functools import wraps
from typing import Any, Protocol


class IntTransformer(Protocol):
    def __call__(self, *args: int, **kwargs: Any) -> int:
        ...


def incrementer(func: IntTransformer) -> IntTransformer:
    @wraps(func)
    def wrapper(*args: int, **kwargs: Any) -> int:
        for a in args:
            a += 1
        return func(*args, **kwargs)

    return wrapper

# Argument 1 to "incrementer" has incompatible type "Callable[[int, int], int]";  expected "IntTransformer"
@incrementer
def summation(a: int, b: int) -> int:
    return a + b

This capability would extend the proposal in #5876 to still check for the argument types of the non-variadic functions, instead of just looking for Any. I think this would help alleviate typing headaches when trying to implement general wrappers and decorators.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions