I have many functions and I want to add a stringify option on each function: if stringify=True, the functions returns str(result) instead of result.
Instead of adding the optional argument and refactoring each function (which would force me to duplicate the stringify logic across all my functions) I used a decorator:
from typing import Callable, Union
def WithStringifyOption(func: Callable[[int], int]) -> Callable[[int, bool], Union[int, str]]:
def wrapper(value: int, stringify: bool = False) -> Union[int, str]:
result = func(value)
return str(result) if stringify else result
return wrapper
# my old function
def func0(value: int) -> int:
return value * 2
# How it looks now
@WithStringifyOption
def func1(value: int) -> int:
return value * 2
func0(value=2)
func1(value=3, stringify=True)
The code works, but by doing this, I get typing error (and I lose autocomplete for keyword arguments): Unexpected keyword argument "value" for "func1"mypy(error) and Unexpected keyword argument "stringify" for "func1"mypy(error)
According to typing documentation about typing.Callable:
There is no syntax to indicate optional or keyword arguments; such function types are rarely used as callback types.
So how can I fix this typing error ?
Note: this is a simplified example on my real project; i want to add a much more complex logic on each one of my functions, so refactoring all my functions by adding and duplicating this complex logic is not an option. I also don't want to add type: ignore everywhere on the project and i don't want to replace all keyword arguments by positional arguments everywhere on the project