# Coverage for utils/check.py : 11%

## 76 statements 13 run 63 missing 0 excluded 0 partial

Hot-keys on this page

r m x p toggle line displays

j k next/prev highlighted chunk

0 (zero) top of page

1 (one) first highlighted chunk

1# -*- coding: utf-8 -*-

2

3# -- stdlib --

4 import types

5 from typing import List

6

7# -- third party --

8# -- own --

9

10

11# -- code --

12 class CheckFailed(Exception):

13 path: List[str]

14

15 def __init__(self):

16 Exception.__init__(self)

17 self.path = []

18

19 def path_string(self):

20 return ''.join([

21 self._path_fragment(v)

22 for v in self.path

23 ])

24

25 def _path_fragment(self, v):

26 if isinstance(v, int):

27 return '[%s]' % v

28 elif isinstance(v, str):

29 return '.%s' % v

30

31 def finalize(self):

32 self.args = (self.path_string(), )

33

34

35 def check(cond):

36 if not cond:

37 raise CheckFailed

38

39

40 def _check_isinstance(obj, cls):

41 try:

42 check(isinstance(obj, cls))

43 except TypeError as e:

44 raise CheckFailed from e

45

46

47_check_key_not_exists = object()

48

49

50 def check_type_exc(pattern, obj, path=None):

51 try:

52 if isinstance(pattern, (list, tuple)):

53 _check_isinstance(obj, (list, tuple))

54 if len(pattern) == 2 and pattern[-1] is ...:

55 cls = pattern[0]

56 for i, v in enumerate(obj):

57 check_type_exc(cls, v, i)

58 else:

59 check(len(pattern) == len(obj))

60 for i, (cls, v) in enumerate(zip(pattern, obj)):

61 check_type_exc(cls, v, i)

62

63 elif isinstance(pattern, dict):

64 _check_isinstance(obj, dict)

65 if ... in pattern:

66 pattern = dict(pattern)

67 match = pattern.pop(...)

68 else:

69 match = '!'

70

71 if match in set('?!='):

72 lkeys = set(pattern.keys())

73 rkeys = set(obj.keys())

74

75 if match == '!':

76 iterkeys = lkeys

77 elif match == '?':

78 iterkeys = lkeys & rkeys

79 elif match == '=':

80 check(lkeys == rkeys)

81 iterkeys = lkeys

82 else:

83 assert False, 'WTF?!'

84

85 for k in iterkeys:

86 check_type_exc(pattern[k], obj.get(k, _check_key_not_exists), k)

87

88 elif match is ...:

89 assert len(pattern) == 1, 'Invalid dict pattern'

90 kt, vt = list(pattern.items())[0]

91 for k in obj:

92 check_type_exc(kt, k, '<%s>' % kt.__name__)

93 check_type_exc(vt, obj[k], k)

94 else:

95 assert False, 'Invalid dict match type'

96

97 else:

98 if issubclass(type(pattern), types.FunctionType):

99 try:

100 check(pattern(obj))

101 except Exception as e:

102 raise CheckFailed from e

103 elif issubclass(type(pattern), (int, str, bytes, tuple)):

104 check(obj == pattern)

105 else:

106 _check_isinstance(obj, pattern)

107

108 except CheckFailed as e:

109 if path is not None:

110 e.path.insert(0, path)

111 else:

112 e.finalize()

113

114 raise

115

116

117'''

118 def check_type(pattern, obj):

119 try:

120 check_type_exc(pattern, obj)

121 return None

122 except CheckFailed as e:

123 return e.path_string()

124'''

125

126 check_type = check_type_exc