def test_instance_of_callable(self): def func1(x: int, y: str) -> object: pass def func2() -> int: pass def func3(x: int): pass def func4(): pass def func5(x): pass def func6(l: List[List[List[int]]]): pass self.assertTrue(instance_of(func1, Callable[[int, str], object])) self.assertTrue(instance_of(func1, Callable[[object, str], object])) self.assertTrue(not instance_of(func1, Callable[[str, str], object])) self.assertTrue(not instance_of(func1, Callable[[str, str], int])) self.assertTrue(instance_of(func2, Callable[[], int])) self.assertTrue(instance_of(func3, Callable[[int], Any])) self.assertTrue(instance_of(func4, Callable)) self.assertTrue(instance_of(func5, Callable[[Any], Any])) self.assertTrue( instance_of(func6, Callable[[List[List[List[int]]]], Any]))
def __init__(self, body: Union[ClsDict, dict, Iterable[Callable]]): if isinstance(body, ClsDict): self.body = body elif isinstance(body, dict): self.body = ClsDict(body) elif instance_of(body, Iterable[Callable]): list_of_tuples = [] for func in body: signature = inspect.signature(func) params = list(signature.parameters.keys()) if not params: raise TypeError('ClsFunction expects callables that take ' 'at least one parameter, {} does not.' .format(func.__name__)) first_param = signature.parameters[params[0]] hint = first_param.annotation key = Any if hint == Empty else hint list_of_tuples.append((key, func)) self.body = ClsDict(OrderedDict(list_of_tuples)) else: raise TypeError('ClsFunction expects a ClsDict or a dict that can ' 'be turned to a ClsDict or an iterable of ' 'callables.') if not all(isinstance(value, Callable) for value in self.body.values()): raise TypeError('ClsFunction expects a dict or ClsDict with only ' 'callables as values.')
def __instancecheck__(self, instance: object) -> bool: # Check if all attributes from self.signature are also present in # instance and also check that their types correspond. sig = self.signature() for key in sig: attr = getattr(instance, key, None) if not attr or not instance_of(attr, sig[key]): return False return True
def _wrapper(*args, **kwargs): for i, arg in enumerate(args): param = sig.parameters[param_names[i]] param_type = _map_empty(param.annotation) if not instance_of(arg, param_type): raise TypeError( 'Value {} for \'{}\' is not of type \'{}\''.format( arg, param.name, param_type)) return decorated(*args, **kwargs)
def test_lambda_instance_of_callable(self): self.assertTrue(instance_of(lambda x, y: 42, Callable[[int, str], str])) self.assertTrue(instance_of(lambda: 42, Callable[[], str]))
def test_instance_of_union(self): self.assertTrue(instance_of(F(), Union[int, A])) self.assertTrue(instance_of(F(), Union[A, int])) self.assertTrue(instance_of(F(), Union[A, str])) self.assertTrue(instance_of(F(), Optional[str])) self.assertTrue(instance_of(None, Optional[str]))
def test_instance_of_multiple(self): self.assertTrue(instance_of(F(), A)) self.assertTrue(instance_of(F(), str)) self.assertTrue(instance_of(F(), A, str)) self.assertTrue(not instance_of(F(), A, str, int))
def test_instance_of(self): self.assertTrue(instance_of([[[1], [2]]], List[List[List[int]]])) self.assertTrue(instance_of([[[1], ['2']]], List[List[List[object]]])) self.assertTrue(instance_of([], List[int])) self.assertTrue(instance_of({}, Dict[int, int]))
def test_instance_of_tuple(self): self.assertTrue(instance_of((1, ), Tuple[int])) self.assertTrue(instance_of((1, 2, 3), Tuple[int, ...]))
def test_instance_of_type(self): self.assertTrue(instance_of(int, Type)) self.assertTrue(instance_of(int, Type[int])) self.assertTrue(not instance_of(str, Type[int]))