Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/validators/utils.py: 92%

26 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:08 +0000

1"""Utils.""" 

2# -*- coding: utf-8 -*- 

3 

4# standard 

5from typing import Callable, Dict, Any 

6from inspect import getfullargspec 

7from itertools import chain 

8from functools import wraps 

9 

10 

11class ValidationFailure(Exception): 

12 """Exception class when validation failure occurs.""" 

13 

14 def __init__(self, function: Callable[..., Any], arg_dict: Dict[str, Any], message: str = ""): 

15 """Initialize Validation Failure.""" 

16 if message: 

17 self.reason = message 

18 self.func = function 

19 self.__dict__.update(arg_dict) 

20 

21 def __repr__(self): 

22 """Repr Validation Failure.""" 

23 return ( 

24 f"ValidationFailure(func={self.func.__name__}, " 

25 + f"args={({k: v for (k, v) in self.__dict__.items() if k != 'func'})})" 

26 ) 

27 

28 def __str__(self): 

29 """Str Validation Failure.""" 

30 return repr(self) 

31 

32 def __bool__(self): 

33 """Bool Validation Failure.""" 

34 return False 

35 

36 

37def _func_args_as_dict(func: Callable[..., Any], *args: Any, **kwargs: Any): 

38 """Return function's positional and key value arguments as an ordered dictionary.""" 

39 return dict( 

40 list(zip(dict.fromkeys(chain(getfullargspec(func)[0], kwargs.keys())), args)) 

41 + list(kwargs.items()) 

42 ) 

43 

44 

45def validator(func: Callable[..., Any]): 

46 """A decorator that makes given function validator. 

47 

48 Whenever the given `func` returns `False` this 

49 decorator returns `ValidationFailure` object. 

50 

51 Examples: 

52 >>> @validator 

53 ... def even(value): 

54 ... return not (value % 2) 

55 >>> even(4) 

56 # Output: True 

57 >>> even(5) 

58 # Output: ValidationFailure(func=even, args={'value': 5}) 

59 

60 Args: 

61 func: 

62 Function which is to be decorated. 

63 

64 Returns: 

65 (Callable[..., ValidationFailure | Literal[True]]): 

66 A decorator which returns either `ValidationFailure` 

67 or `Literal[True]`. 

68 

69 > *New in version 2013.10.21*. 

70 """ 

71 

72 @wraps(func) 

73 def wrapper(*args: Any, **kwargs: Any): 

74 try: 

75 return ( 

76 True 

77 if func(*args, **kwargs) 

78 else ValidationFailure(func, _func_args_as_dict(func, *args, **kwargs)) 

79 ) 

80 except Exception as exp: 

81 return ValidationFailure(func, _func_args_as_dict(func, *args, **kwargs), str(exp)) 

82 

83 return wrapper