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
callbackasCallback:Now, among these three function calls:
mypywill 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
function2and renamearg1toarg_1,mypywould complain about that. This is because the public interface offunction2has changed in a backwards-incompatible way. For example, I would have to modifyarg1=0at any call site toarg_1=0.But if I take the same function and rename
kwargs2tokwargs_2, the public interface does not actually change! This is because it was impossible to ever explicitly refer to thekwargs/kwargs1/kwargs2parameter at a call site in the first place. Take this example:If I were to dump
kwargs2from 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.mypycan therefore allow different names when checking if the public interface offunction2matches that of aCallback.As for the type,
kwargs,kwargs1andkwargs2all have a type ofDict[str, Any]left annotated. Since you're consistent across all 3,mypyreports success here, while also enabling you to take advantage ofAnyfor keyword arguments specific tofunction1orfunction2.