typelets.funcs

Typing useful for defining and calling functions.

Added in version 1.0.

Module Attributes

TParams

Standard type for referencing a callable's parameters.

TReturn_co

Standard type for referencing a function's return value.

TOwner

Standard type for the owner of a method.

KwargsDict

A type indicating a dictionary used for keyword arguments.

Functions

type_func_params_as(params_from, *[, ...])

Decorator for typing a function signature based on another function.

type_method_params_as(params_from, *[, ...])

Decorator for typing a function signature based on another method.

Classes

BaseParamsFromFunc(func)

Base class for defining a signature based on a function.

BaseParamsFromMethod(func)

Base class for defining a signature based on a method.

MethodDirective(*args, **kwargs)

A representation of a method on a class.

OnlyParamsFromFunc(func)

Defines a signature for inheriting all parameters from a function.

OnlyParamsFromMethod(func)

Defines a signature for inheriting all parameters from a method.

typelets.funcs.TParams = ~TParams[source]

Standard type for referencing a callable’s parameters.

Added in version 1.1.

class typelets.funcs.TReturn_co[source]

Standard type for referencing a function’s return value.

Added in version 1.1.

alias of TypeVar(‘TReturn_co’, covariant=True)

__bound__ = None[source]
__constraints__ = ()[source]
__contravariant__ = False[source]
__covariant__ = True[source]
__default__ = typing_extensions.NoDefault[source]
__infer_variance__ = False[source]
__name__ = 'TReturn_co'[source]
__typing_prepare_subst__(args)[source]
has_default()[source]
class typelets.funcs.TOwner[source]

Standard type for the owner of a method.

This would generally be a class.

alias of TypeVar(‘TOwner’, bound=object)

__bound__[source]

alias of object

__constraints__ = ()[source]
__contravariant__ = False[source]
__covariant__ = False[source]
__default__ = typing_extensions.NoDefault[source]
__infer_variance__ = False[source]
__name__ = 'TOwner'[source]
__typing_prepare_subst__(args)[source]
has_default()[source]
typelets.funcs.KwargsDict

A type indicating a dictionary used for keyword arguments.

Added in version 1.0.

alias of Dict[str, Any]

class typelets.funcs.MethodDirective(*args, **kwargs)[source]

Bases: Protocol[TOwner, TParams, TReturn_co]

A representation of a method on a class.

This works as a directive for converting an unbound method to a bound method. It can be returned in place of a Callable[] to ensure proper typing when returning a type for a method.

Added in version 1.1.

__self__: TOwner

The owner of the method.

__get__(instance: None, owner: type[TOwner]) Callable[Concatenate[TOwner, TParams], TReturn_co][source]
__get__(instance: TOwner, owner: type[TOwner]) Callable[TParams, TReturn_co]
__init__(*args, **kwargs)
class typelets.funcs.BaseParamsFromFunc(func: Callable[TParams, Any])[source]

Bases: Generic[TParams]

Base class for defining a signature based on a function.

This is built to be used with the type_func_params_as() or type_method_params_as() decorators. It references another function, classmethod, or staticmethod, providing access to its ParamSpec and allows its use in a __call__() method.

Subclasses must implement __call__(), taking in the parameters needed by the decorated function, and returns Any specifically.

Note

There are some things to be aware of when writing your __call__() method:

  1. Because this is defined in a class, it must contain self, even if your decorated function does not. This won’t affect the final type of your function.

  2. typing.Any must always be returned from the signature, regardless of the referenced or decorated functions.

  3. If your decorated function uses *, /, those must be present.

  4. You must include both TParams.args and TParams.kwargs at the end of the signature, even if the wrapped function doesn’t use either *args or **kwargs.

    This is necessary for the type checkers.

  5. Using / to indicate positional-only arguments may trigger a type error when decorating a class. This should not affect the resulting type.

    We recommend using # type: ignore on the decorator line in this situation.

If your decorated function simply takes *args and/or **kwargs and passes them to the referenced without taking any additional parameters, you can use:

Added in version 1.1.

Examples

A simple function with *args and **kwargs.
from typelets.funcs import BaseParamsFromFunc, TParams


# This would provide typing for any of the following functions.
#
# def my_function(
#     name: str,
#     age: int,
#     *args,
#     **kwargs,
# ) -> str:
#
# def my_function(
#     name: str,
#     *args,
#     age: int,
#     **kwargs,
# ) -> str:
#
# def my_function(
#     name: str,
#     age: int,
#     *args,
# ) -> str:
#
# def my_function(
#     name: str,
#     age: int,
#     **kwargs,
# ) -> str:
#
# def my_function(
#     *,
#     name: str,
#     age: int,
#     **kwargs,
# ) -> str:
class MyFunctionParamsFrom(BaseParamsFromFunc[TParams]):
    def __call__(
        self,
        name: str,
        age: int,
        *args: TParams.args,
        **kwargs: TParams.kwargs,
    ): ...
__init__(func: Callable[TParams, Any]) None[source]

Construct the signature based on a function.

Parameters:

func (callable) – The function to pass the signature off of.

class typelets.funcs.BaseParamsFromMethod(func: Callable[Concatenate[TOwner, TParams], Any])[source]

Bases: Generic[TParams, TOwner]

Base class for defining a signature based on a method.

This is built to be used with the type_func_params_as() or type_method_params_as() decorators. It references an unbound method on a class, providing access to its ParamSpec and allows its use in a __call__() method.

Subclasses must implement __call__(), taking in the parameters needed by the decorated function, and returns Any specifically.

Note

There are some things to be aware of when writing your __call__() method:

  1. Because this is defined in a class, it must contain self, even if your decorated function does not. This won’t affect the final type of your function.

  2. typing.Any must always be returned from the signature, regardless of the referenced or decorated functions.

  3. If your decorated function uses *, /, those must be present.

  4. You must include both TParams.args and TParams.kwargs at the end of the signature, even if the wrapped function doesn’t use either *args or **kwargs.

    This is necessary for the type checkers.

  5. Using / to indicate positional-only arguments may trigger a type error when decorating a class. This should not affect the resulting type.

    We recommend using # type: ignore on the decorator line in this situation.

If your decorated function simply takes *args and/or **kwargs and passes them to the referenced without taking any additional parameters, you can use:

Added in version 1.1.

Examples

A simple function with *args and **kwargs.
from typelets.funcs import BaseParamsFromMethod, TOwner, TParams


# This would provide typing for any of the following functions.
#
# def my_function(
#     self,
#     name: str,
#     age: int,
#     *args,
#     **kwargs,
# ) -> str:
#
# def my_function(
#     self,
#     name: str,
#     *args,
#     age: int,
#     **kwargs,
# ) -> str:
#
# def my_function(
#     self,
#     name: str,
#     age: int,
#     *args,
# ) -> str:
#
# def my_function(
#     self,
#     name: str,
#     age: int,
#     **kwargs,
# ) -> str:
#
# def my_function(
#     self,
#     *,
#     name: str,
#     age: int,
#     **kwargs,
# ) -> str:
class MyFunctionParamsFrom(BaseParamsFromMethod[TParams, TOwner]):
    def __call__(
        self,
        name: str,
        age: int,
        *args: TParams.args,
        **kwargs: TParams.kwargs,
    ): ...
__init__(func: Callable[Concatenate[TOwner, TParams], Any]) None[source]

Construct the signature based on a method.

Parameters:

func (callable) – The method to pass the signature off of.

class typelets.funcs.OnlyParamsFromFunc(func: Callable[TParams, Any])[source]

Bases: BaseParamsFromFunc[TParams]

Defines a signature for inheriting all parameters from a function.

This is used whenever you have a function or method that takes in a *args and/or **kwargs (but no other parameters) and passes them to another function.

The *args and/or **kwargs will inherit the signature and types from the referenced function.

This can be used with either type_func_params_as() or type_method_params_as().

Example

from typelets.funcs import (OnlyParamsFromFunc,
                            type_func_params_as,
                            type_method_params_as)


def wrapped_func(
    a: int,
    b: str,
    /,
    c: int,
    *,
    d: bool,
) -> int:
    return a + c


# Apply to a function:
@type_func_params_as(OnlyParamsFromFunc(wrapped_func))
def my_wrapper_func(*args, **kwargs) -> str:
    return str(wrapped_func(*args, **kwargs))


# Or apply to a method:
class MyClass:
    @type_method_params_as(OnlyParamsFromFunc(wrapped_func))
    def my_wrapper_func(self, *args, **kwargs) -> str:
        return str(wrapped_func(*args, **kwargs))

Added in version 1.1.

__call__(*args: ~typing.~TParams, **kwargs: ~typing.~TParams) Any[source]

Call self as a function.

class typelets.funcs.OnlyParamsFromMethod(func: Callable[Concatenate[TOwner, TParams], Any])[source]

Bases: BaseParamsFromMethod[TParams, TOwner]

Defines a signature for inheriting all parameters from a method.

This is used whenever you have a function or method that takes in a *args and/or **kwargs (but no other parameters) and passes them to another method.

The *args and/or **kwargs will inherit the signature and types from the referenced function.

This can be used with either type_func_params_as() or type_method_params_as().

Example

from typelets.funcs import (OnlyParamsFromMethod,
                            type_func_params_as,
                            type_method_params_as)


class OtherClass:
    def wrapped_func(
        self,
        a: int,
        b: str,
        /,
        c: int,
        *,
        d: bool,
    ) -> int:
        return a + c


# Apply to a function:
@type_func_params_as(OnlyParamsFromMethod(OtherClass.wrapped_func))
def my_wrapper_func(*args, **kwargs) -> str:
    return str(OtherClass().wrapped_func(*args, **kwargs))


# Or apply to a method:
class MyClass:
    @type_method_params_as(OnlyParamsFromMethod(
        OtherClass.wrapped_func
    ))
    def my_wrapper_func(self, *args, **kwargs) -> str:
        return str(OtherClass().wrapped_func(*args, **kwargs))

Added in version 1.1.

__call__(*args: ~typing.~TParams, **kwargs: ~typing.~TParams) Any[source]

Call self as a function.

typelets.funcs.type_func_params_as(params_from: Callable[TParams, Any], *, args_name: str | None = 'args', kwargs_name: str | None = 'kwargs') Callable[[Callable[TParams, TReturn_co]], Callable[TParams, TReturn_co]][source]

Decorator for typing a function signature based on another function.

This can be used with standard functions, classmethods, and staticmethods to type *args and/or **kwargs based on the arguments defined in a referenced function.

It’s built for functions that take in arguments for the purpose of passing to another function or method, which normally would mean either duplicating the arguments in the signature or losing out on typing altogether.

This works as a decorator that takes a function signature definition (an instance of a BaseParamsFromFunc subclass) or method signature (an instance of a BaseParamsFromMethod), and retypes the decorated function using that signature. The definition is able to use the ParamSpec of a referenced function.

You can craft your own definition by creating a subclass of either of these base classes. See the documentation for examples.

For simple cases, you can use the built-in OnlyParamsFromFunc or OnlyParamsFromMethod.

There is minimal impact to function setup, and no impact when calling the function at runtime. The decorated function’s __annotations__ and __signature__ will be patched at decoration time. There are no costs to calling the function, and no changes to function behavior.

Warning

This may affect docstrings in Visual Studio Code or in other editors using PyLance, due to the way that docstrings are inferred from the first-provided callable. See https://github.com/microsoft/pylance-release/issues/5840.

Added in version 1.1.

Parameters:
  • params_from (callable) –

    The callable function signature to base parameters off of.

    This is generally going to be an instance of a BaseParamsFromFunc subclass.

  • args_name (str, optional) –

    Optional name of the *args argument.

    By default, the name will be auto-detected if "args" isn’t the correct name. Consumers can set this to a name explicitly, or set it to None to avoid looking for this argument.

  • kwargs_name (str, optional) –

    Optional name of the *kwargs argument.

    By default, the name will be auto-detected if "kwargs" isn’t the correct name. Consumers can set this to a name explicitly, or set it to None to avoid looking for this argument.

Examples

Type a function based fully on a function
from typelets.funcs import (OnlyParamsFromFunc,
                            type_func_params_as,
                            type_method_params_as)


def wrapped_func(
    a: int,
    b: str,
    /,
    c: int,
    *,
    d: bool,
) -> int:
    return a + c

@type_func_params_as(OnlyParamsFromFunc(wrapped_func))
def my_wrapper_func(*args, **kwargs) -> str:
    return str(wrapped_func(*args, **kwargs))
Type a function based fully on a method
from typelets.funcs import (OnlyParamsFromMethod,
                            type_method_params_as)


class MyClass:
    def wrapped_func(
        self,
        a: int,
        b: str,
        /,
        c: int,
        *,
        d: bool,
    ) -> int:
        return a + c


@type_func_params_as(OnlyParamsFromMethod(MyClass.wrapped_func))
def my_wrapper_func(*args, **kwargs) -> str:
    return str(wrapped_func(*args, **kwargs))
Type a method using a custom signature
from typing import Any

from typelets.funcs import (BaseParamsFromFunc,
                            TParams,
                            type_method_params_as)


class MyParamsFrom(BaseParamsFromFunc[TParams]):
    def __call__(
        self,
        x: int,
        y: bool = True,
        *args: TParams.args,
        **kwargs: TParams.kwargs,
    ) -> Any:
        ...


def wrapped_func(
    a: int,
    b: str,
    /,
    c: int,
    *,
    d: bool,
) -> int:
    return a + c


@type_func_params_as(MyParamsFrom(wrapped_func))
def my_wrapper_func(
    x: int,
    y: bool = True,
    *args,
    **kwargs,
) -> str:
    return str(wrapped_func(*args, **kwargs))
typelets.funcs.type_method_params_as(params_from: Callable[TParams, Any], *, args_name: str | None = 'args', kwargs_name: str | None = 'kwargs') Callable[[Callable[Concatenate[TOwner, TParams], TReturn_co]], MethodDirective[TOwner, TParams, TReturn_co]][source]

Decorator for typing a function signature based on another method.

This can be used with unbound methods on classes to type *args and/or **kwargs based on the arguments defined in a referenced function.

It’s built for methods that take in arguments for the purpose of passing to another function or method, which normally would mean either duplicating the arguments in the signature or losing out on typing altogether.

This works as a decorator that takes a function signature definition (an instance of a BaseParamsFromFunc subclass) or method signature (an instance of a BaseParamsFromMethod), and retypes the decorated method using that signature. The definition is able to use the ParamSpec of a referenced function.

Both the unbound method and bound method will have the correct signature.

You can craft your own definition by creating a subclass of either of these base classes. See the documentation for examples.

For simple cases, you can use the built-in OnlyParamsFromFunc or OnlyParamsFromMethod.

There is minimal impact to function setup, and no impact when calling the function at runtime. The decorated function’s __annotations__ and __signature__ will be patched at decoration time. There are no costs to calling the function, and no changes to function behavior.

Warning

This may affect docstrings in Visual Studio Code or in other editors using PyLance, due to the way that docstrings are inferred from the first-provided callable. See https://github.com/microsoft/pylance-release/issues/5840.

Added in version 1.1.

Parameters:
  • params_from (callable) –

    The callable function signature to base parameters off of.

    This is generally going to be an instance of a BaseParamsFromFunc subclass.

  • args_name (str, optional) –

    Optional name of the *args argument.

    By default, the name will be auto-detected if "args" isn’t the correct name. Consumers can set this to a name explicitly, or set it to None to avoid looking for this argument.

  • kwargs_name (str, optional) –

    Optional name of the *kwargs argument.

    By default, the name will be auto-detected if "kwargs" isn’t the correct name. Consumers can set this to a name explicitly, or set it to None to avoid looking for this argument.

Examples

Type a method based fully on a function
from typelets.funcs import (OnlyParamsFromFunc,
                            type_method_params_as)


def wrapped_func(
    a: int,
    b: str,
    /,
    c: int,
    *,
    d: bool,
) -> int:
    return a + c

class MyClass:
    @type_method_params_as(OnlyParamsFromFunc(wrapped_func))
    def my_wrapper_func(self, *args, **kwargs) -> str:
        return str(wrapped_func(*args, **kwargs))
Type a method based fully on a method
from typelets.funcs import (OnlyParamsFromMethod,
                            type_method_params_as)


class MyClass:
    def wrapped_func(
        self,
        a: int,
        b: str,
        /,
        c: int,
        *,
        d: bool,
    ) -> int:
        return a + c

    @type_method_params_as(OnlyParamsFromMethod(wrapped_func))
    def my_wrapper_func(self, *args, **kwargs) -> str:
        return str(self.wrapped_func(*args, **kwargs))
Type a method using a custom signature
from typing import Any

from typelets.funcs import (BaseParamsFromMethod,
                            TParams,
                            TOwner,
                            type_method_params_as)


class MyParamsFrom(BaseParamsFromMethod[TParams, TOwner]):
    def __call__(
        self,
        x: int,
        y: bool = True,
        *args: TParams.args,
        **kwargs: TParams.kwargs,
    ) -> Any:
        ...


class MyClass:
    def wrapped_func(
        self,
        a: int,
        b: str,
        /,
        c: int,
        *,
        d: bool,
    ) -> int:
        return a + c

    @type_method_params_as(MyParamsFrom(wrapped_func))
    def my_wrapper_func(
        self,
        x: int,
        y: bool = True,
        *args,
        **kwargs,
    ) -> str:
        return str(self.wrapped_func(*args, **kwargs))