Hide keyboard shortcuts

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 -- 

4import types 

5from typing import List 

6 

7# -- third party -- 

8# -- own -- 

9 

10 

11# -- code -- 

12class 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 

35def check(cond): 

36 if not cond: 

37 raise CheckFailed 

38 

39 

40def _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 

50def 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''' 

118def 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 

126check_type = check_type_exc