25def _check_instance(value, typevar):
26 base = typing.get_origin(typevar)
28 return isinstance(value, typevar)
29 arg_types = typing.get_args(typevar)
30 if base == collections.abc.Mapping
or base == typing.Mapping:
31 if not isinstance(value, collections.abc.Mapping):
33 assert len(arg_types) == 2
34 (keytype, valuetype) = arg_types
36 _check_instance(k, keytype)
and _check_instance(v, valuetype)
37 for k, v
in value.items()
39 elif base == collections.abc.Sequence
or base == typing.Sequence:
41 if not isinstance(value, base):
43 if len(arg_types) == 0:
45 assert len(arg_types) == 1
46 arg_type = arg_types[0]
47 return all(_check_instance(item, arg_type)
for item
in value)
48 elif base == typing.Union:
49 return any(_check_instance(value, arg_type)
for arg_type
in arg_types)
50 raise TypeError(
"unsupported type variable '" + str(typevar) +
"'")
54 """A decorator that checks FUNC's argument types at runtime."""
59 if not hasattr(typing,
"get_origin"):
62 hints = typing.get_type_hints(func)
71 @functools.wraps(func)
72 def check_arguments(**kwargs):
78 if key
in kwargs
and not _check_instance(kwargs[key], hints[key]):
82 +
"' does not have expected type '"
88 return check_arguments
void(* func)(remote_target *remote, char *)