I have a function that takes a callback
function as a parameter:
def function(arg1: int, callback):
...
I am trying to add a type hint for the callback
function. Now, the callback functions that are passed to this function have the same positional args but the kwargs can be completely different (both in type and name).
def function1(arg1: int, arg2: str, **kwargs1):
...
def function2(arg1: int, arg2: str, **kwargs2):
...
I am trying to write a Callback Protocol that fits these 2 functions, but so far I don't see a way to make this work when the kwargs are different. Is there a way to create a unified Callback protocol in this case?
You can create this Callback protocol:
and type hint
callback
asCallback
:Now, among these three function calls:
mypy
will report success for the first two, but report an error for the third one because of the missingarg2
.The key thing to realize here is that the name of the keyword-arguments parameter does not actually matter. If I take
function2
and renamearg1
toarg_1
,mypy
would complain about that. This is because the public interface offunction2
has changed in a backwards-incompatible way. For example, I would have to modifyarg1=0
at any call site toarg_1=0
.But if I take the same function and rename
kwargs2
tokwargs_2
, the public interface does not actually change! This is because it was impossible to ever explicitly refer to thekwargs
/kwargs1
/kwargs2
parameter at a call site in the first place. Take this example:If I were to dump
kwargs2
from inside the function, it would actually have the key"kwargs2"
mapped to{}
, instead of being an empty dictionary itself. This shows that it is impossible to rely on the name of the keyword-arguments parameter.mypy
can therefore allow different names when checking if the public interface offunction2
matches that of aCallback
.As for the type,
kwargs
,kwargs1
andkwargs2
all have a type ofDict[str, Any]
left annotated. Since you're consistent across all 3,mypy
reports success here, while also enabling you to take advantage ofAny
for keyword arguments specific tofunction1
orfunction2
.