def test_nullable_validator_invalid_value_should_return_false(self): """==> nullable validator invalid value should return False""" for item in self.nullable_fixtures: # Any is always valid if item.get('annotation') is not typing.Any: self.assertFalse( NullableValidator(TypeHint(item.get('annotation')), 'invalid_value')) self.assertFalse( NullableValidator(TypeHint(item.get('annotation')), 666)) self.assertFalse( NullableValidator(TypeHint(item.get('annotation')), True))
def is_valid(self) -> bool: if not self.is_supported: return False # value does not match alias type if self.value is not self.hint.origin and not isinstance( self.value, self.valid_types): return False # Alias inconsitently returns TypeVar object or None when no parameters given ... stupid python # will not validate recursively, still value does match alias type though if len(self.hint.types) == 0 or isinstance(self.hint.types[0], TypeVar): return True # validate keys hint = TypeHint(self.hint.types[0]) nullablevalidator = NullableValidator(hint) stdtypevalidator = StdtypeValidator(hint) unionvalidator = UnionValidator(hint) for value in self.value.keys(): if not (nullablevalidator.validate(value) or stdtypevalidator.validate(value) or unionvalidator.validate(value)): return False # validate values hint = TypeHint(self.hint.types[1]) # Any is always valid if AnyValidator().supports(hint): return True nullablevalidator = NullableValidator(hint) stdtypevalidator = StdtypeValidator(hint) classvalidator = ClassValidator(hint) callablevalidator = CallableValidator(hint) aliasvalidator = AliasValidator(hint) listvalidator = ListValidator(hint) dictvalidator = DictValidator(hint) unionvalidator = UnionValidator(hint) for value in self.value.values(): if not (nullablevalidator.validate(value) or stdtypevalidator.validate(value) or classvalidator.validate(value) or callablevalidator.validate(value) or aliasvalidator.validate(value) or listvalidator.validate(value) or dictvalidator.validate(value) or unionvalidator.validate(value)): return False return True
def test_nested_any_in_dict_should_return_true(self): """==> nested any in dict should return True""" hint = TypeHint(typing.Dict[int, typing.Any]) validator = DictValidator(hint, self.nested_union_expected_valid) self.assertTrue(validator) validator = DictValidator(hint, self.nested_union_expected_invalid) self.assertTrue(validator)
def test_union_validator_nested_any_should_return_true(self): """==> union validator nested Any should return True""" hint = TypeHint(typing.Union[int, typing.Any]) validator = UnionValidator(hint, b'valid') self.assertTrue(validator) validator = UnionValidator(hint, 666) self.assertTrue(validator)
def test_nested_any_in_list_should_return_true(self): """==> nested any in list should return true""" hint = TypeHint(typing.List[typing.Any]) validator = ListValidator(hint, self.list_expected_valid) self.assertTrue(validator) validator = ListValidator(hint, self.list_expected_invalid) self.assertTrue(validator)
def test_hint_setter(self): """==> abstract validator value in setter should not raise TypeError""" try: abstractvalidator = AbstractValidator() abstractvalidator.hint = TypeHint(str) except Exception as e: self.fail(e)
def test_alias_validator_invalid_value_should_return_false(self): """==> alias validator invalid value should return False""" for item in self.alias_no_argument_fixtures: # seems like every object is hashable ... stupid python if item.get('alias') != 'Hashable': hint = TypeHint(item.get('annotation')) validator = AliasValidator(hint, None) self.assertFalse(validator)
def test_union_validator_valid_value_should_return_true(self): """==> union validator valid value should return True""" for item in self.union_fixtures: hint = TypeHint(item.get('annotation')) validator = UnionValidator(hint, 'valid') self.assertTrue(validator.is_valid) validator = UnionValidator(hint, 666) self.assertTrue(validator.is_valid)
def is_valid(self) -> bool: if self.is_supported: for annotation in self.hint.types: hint = TypeHint(annotation) if AnyValidator(hint, self.value) or \ NullableValidator(hint, self.value) or \ StdtypeValidator(hint, self.value) or \ ClassValidator(hint, self.value) or \ CallableValidator(hint, self.value) or \ AliasValidator(hint, self.value) or \ ListValidator(hint, self.value) or \ DictValidator(hint, self.value) or \ UnionValidator(hint, self.value): return True return False
def _not_blank(function: Callable, fixed_kwargs: Dict[str, Any]) -> None: if not callable(function): raise TypeError('_type_check: function must be callable') if not isinstance(fixed_kwargs, dict): raise TypeError( '_type_check: fixed_kwargs must be set to a dictionary') # get type hints (typing.get_type_hints method requires to import unnecessary module) for arg_name, arg_hint in function.__annotations__.items(): # ignore "return" (will raise "KeyError" when accessing "fixed_kwargs[arg_name]") if arg_name == 'return': continue hint = TypeHint(arg_hint) # there is no way to validate custom property if hint.category == 'property': continue value = fixed_kwargs[arg_name] if not NotBlankValidator(hint, value): raise ValueError('{} cannot be blank'.format( function.__qualname__))
def _type_check(function: Callable, fixed_kwargs: Dict[str, Any]) -> None: if not callable(function): raise TypeError('_type_check: function must be callable') if not isinstance(fixed_kwargs, dict): raise TypeError( '_type_check: fixed_kwargs must be set to a dictionary') # get type hints (typing.get_type_hints method requires to import unnecessary module) for arg_name, arg_hint in function.__annotations__.items(): # ignore "return" (will raise "KeyError" when accessing "fixed_kwargs[arg_name]") if arg_name == 'return': continue hint = TypeHint(arg_hint) # there is no way to validate custom property if hint.category == 'property': continue value = fixed_kwargs[arg_name] if not (NullableValidator(hint, value) or StdtypeValidator( hint, value) or ClassValidator(hint, value) or CallableValidator(hint, value) or AliasValidator(hint, value) or ListValidator(hint, value) or DictValidator(hint, value) or UnionValidator(hint, value)): raise TypeError('{} must be set to {}, {} given'.format( function.__qualname__, hint.types, type(value)))
def test_stdtype_validator_valid_value_should_return_true(self): """==> stdtype validator valid value should return True""" for item in self.stdtype_fixtures: self.assertTrue( StdtypeValidator(TypeHint(item.get('type')), item.get('valid')))
def test_nested_union_should_return_true(self): """==> nested union should return True""" for item in self.nested_union_fixtures: hint = TypeHint(item.get('annotation')) validator = DictValidator(hint, self.nested_union_expected_valid) self.assertTrue(validator)
def test_nested_dict_validator_should_return_true(self): """==> nested dict validator should return True""" for item in self.nested_dict_fixtures: self.assertTrue( DictValidator(TypeHint(item.get('annotation')), self.nested_dict_expected_valid))
def test_dict_validator_alias_with_no_parameter_should_return_true(self): """==> dict validator alias with no parameter should return True""" for item in self.dict_no_parameter_fixtures: hint = TypeHint(item.get('annotation')) validator = DictValidator(hint, self.dict_expected_valid) self.assertTrue(validator)
def test_dict_validator_should_return_false(self): """==> dict validator should return false""" for item in self.dict_fixtures: self.assertFalse( DictValidator(TypeHint(item.get('annotation')), self.dict_expected_invalid))
def test_nullable_validator_valid_value_should_return_true(self): """==> nullable validator valid value should return True""" for item in self.nullable_fixtures: self.assertTrue( NullableValidator(TypeHint(item.get('annotation')), None))
def test_list_validator_should_return_true(self): """==> list validator should return true""" for item in self.list_fixtures: self.assertTrue( ListValidator(TypeHint(item.get('annotation')), self.list_expected_valid))
def test_callable_validator_invalid_value_should_return_false(self): """==> callable validator invalid value should return False""" for item in self.callable_fixtures: self.assertFalse( CallableValidator(TypeHint(item.get('annotation')), 'invalid_value'))
def test_nested_list_validator_should_return_true(self): """==> nested list validator should return true""" for item in self.nested_list_fixtures: hint = TypeHint(item.get('annotation')) validator = ListValidator(hint, self.nested_list_expected_valid) self.assertTrue(validator)
def test_not_blank_validator_valid_value_should_return_true(self): """==> not_blank validator valid value should return True""" for item in self.stdtype_fixtures: self.assertTrue( NotBlankValidator(TypeHint(item.get('type')), item.get('valid')))
def test_stdtype_validator_invalid_value_should_return_false(self): """==> stdtype validator invalid value should return False""" for item in self.stdtype_fixtures: self.assertFalse( StdtypeValidator(TypeHint(item.get('type')), item.get('invalid')))
def test_union_validator_invalid_value_should_return_false(self): """==> union validator invalid value should return False""" for item in self.union_fixtures: hint = TypeHint(item.get('annotation')) validator = UnionValidator(hint, b'invalid') self.assertFalse(validator.is_valid)
def test_nested_union_should_return_false(self): """==> nested union should return false""" for item in self.nested_union_fixtures: hint = TypeHint(item.get('annotation')) validator = ListValidator(hint, self.nested_union_expected_invalid) self.assertFalse(validator)
def test_alias_validator_invalid_value_should_return_false(self): """==> alias validator invalid value should return False""" for item in self.alias_fixtures: hint = TypeHint(item.get('annotation')) validator = AliasValidator(hint, None) self.assertFalse(validator)
def test_any_validator_should_return_false(self): """==> Any should always return False""" for value in self.expected_valid: self.assertFalse(AnyValidator(TypeHint(int), value))
def test_alias_validator_valid_value_should_return_true(self): """==> alias validator valid value should return True""" for item in self.alias_no_argument_fixtures: hint = TypeHint(item.get('annotation')) validator = AliasValidator(hint, item.get('origin')) self.assertTrue(validator)
def test_any_validator_should_return_true(self): """==> Any should always return True""" for value in self.expected_valid: self.assertTrue(AnyValidator(TypeHint(Any), value))
def test_callable_validator_valid_value_should_return_true(self): """==> callable validator valid value should return True""" for item in self.callable_fixtures: hint = TypeHint(item.get('annotation')) validator = CallableValidator(hint, lambda: True) self.assertTrue(validator.is_valid)
def test_constructor_typehint(self): """==> abstract validator valid value in constructor should not raise TypeError""" try: AbstractValidator(TypeHint(str), 'value') except Exception as e: self.fail(e)