Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pyparsing/util.py: 47%

134 statements  

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

1# util.py 

2import warnings 

3import types 

4import collections 

5import itertools 

6from functools import lru_cache 

7from typing import List, Union, Iterable 

8 

9_bslash = chr(92) 

10 

11 

12class __config_flags: 

13 """Internal class for defining compatibility and debugging flags""" 

14 

15 _all_names: List[str] = [] 

16 _fixed_names: List[str] = [] 

17 _type_desc = "configuration" 

18 

19 @classmethod 

20 def _set(cls, dname, value): 

21 if dname in cls._fixed_names: 

22 warnings.warn( 

23 "{}.{} {} is {} and cannot be overridden".format( 

24 cls.__name__, 

25 dname, 

26 cls._type_desc, 

27 str(getattr(cls, dname)).upper(), 

28 ) 

29 ) 

30 return 

31 if dname in cls._all_names: 

32 setattr(cls, dname, value) 

33 else: 

34 raise ValueError("no such {} {!r}".format(cls._type_desc, dname)) 

35 

36 enable = classmethod(lambda cls, name: cls._set(name, True)) 

37 disable = classmethod(lambda cls, name: cls._set(name, False)) 

38 

39 

40@lru_cache(maxsize=128) 

41def col(loc: int, strg: str) -> int: 

42 """ 

43 Returns current column within a string, counting newlines as line separators. 

44 The first column is number 1. 

45 

46 Note: the default parsing behavior is to expand tabs in the input string 

47 before starting the parsing process. See 

48 :class:`ParserElement.parseString` for more 

49 information on parsing strings containing ``<TAB>`` s, and suggested 

50 methods to maintain a consistent view of the parsed string, the parse 

51 location, and line and column positions within the parsed string. 

52 """ 

53 s = strg 

54 return 1 if 0 < loc < len(s) and s[loc - 1] == "\n" else loc - s.rfind("\n", 0, loc) 

55 

56 

57@lru_cache(maxsize=128) 

58def lineno(loc: int, strg: str) -> int: 

59 """Returns current line number within a string, counting newlines as line separators. 

60 The first line is number 1. 

61 

62 Note - the default parsing behavior is to expand tabs in the input string 

63 before starting the parsing process. See :class:`ParserElement.parseString` 

64 for more information on parsing strings containing ``<TAB>`` s, and 

65 suggested methods to maintain a consistent view of the parsed string, the 

66 parse location, and line and column positions within the parsed string. 

67 """ 

68 return strg.count("\n", 0, loc) + 1 

69 

70 

71@lru_cache(maxsize=128) 

72def line(loc: int, strg: str) -> str: 

73 """ 

74 Returns the line of text containing loc within a string, counting newlines as line separators. 

75 """ 

76 last_cr = strg.rfind("\n", 0, loc) 

77 next_cr = strg.find("\n", loc) 

78 return strg[last_cr + 1 : next_cr] if next_cr >= 0 else strg[last_cr + 1 :] 

79 

80 

81class _UnboundedCache: 

82 def __init__(self): 

83 cache = {} 

84 cache_get = cache.get 

85 self.not_in_cache = not_in_cache = object() 

86 

87 def get(_, key): 

88 return cache_get(key, not_in_cache) 

89 

90 def set_(_, key, value): 

91 cache[key] = value 

92 

93 def clear(_): 

94 cache.clear() 

95 

96 self.size = None 

97 self.get = types.MethodType(get, self) 

98 self.set = types.MethodType(set_, self) 

99 self.clear = types.MethodType(clear, self) 

100 

101 

102class _FifoCache: 

103 def __init__(self, size): 

104 self.not_in_cache = not_in_cache = object() 

105 cache = collections.OrderedDict() 

106 cache_get = cache.get 

107 

108 def get(_, key): 

109 return cache_get(key, not_in_cache) 

110 

111 def set_(_, key, value): 

112 cache[key] = value 

113 while len(cache) > size: 

114 cache.popitem(last=False) 

115 

116 def clear(_): 

117 cache.clear() 

118 

119 self.size = size 

120 self.get = types.MethodType(get, self) 

121 self.set = types.MethodType(set_, self) 

122 self.clear = types.MethodType(clear, self) 

123 

124 

125class LRUMemo: 

126 """ 

127 A memoizing mapping that retains `capacity` deleted items 

128 

129 The memo tracks retained items by their access order; once `capacity` items 

130 are retained, the least recently used item is discarded. 

131 """ 

132 

133 def __init__(self, capacity): 

134 self._capacity = capacity 

135 self._active = {} 

136 self._memory = collections.OrderedDict() 

137 

138 def __getitem__(self, key): 

139 try: 

140 return self._active[key] 

141 except KeyError: 

142 self._memory.move_to_end(key) 

143 return self._memory[key] 

144 

145 def __setitem__(self, key, value): 

146 self._memory.pop(key, None) 

147 self._active[key] = value 

148 

149 def __delitem__(self, key): 

150 try: 

151 value = self._active.pop(key) 

152 except KeyError: 

153 pass 

154 else: 

155 while len(self._memory) >= self._capacity: 

156 self._memory.popitem(last=False) 

157 self._memory[key] = value 

158 

159 def clear(self): 

160 self._active.clear() 

161 self._memory.clear() 

162 

163 

164class UnboundedMemo(dict): 

165 """ 

166 A memoizing mapping that retains all deleted items 

167 """ 

168 

169 def __delitem__(self, key): 

170 pass 

171 

172 

173def _escape_regex_range_chars(s: str) -> str: 

174 # escape these chars: ^-[] 

175 for c in r"\^-[]": 

176 s = s.replace(c, _bslash + c) 

177 s = s.replace("\n", r"\n") 

178 s = s.replace("\t", r"\t") 

179 return str(s) 

180 

181 

182def _collapse_string_to_ranges( 

183 s: Union[str, Iterable[str]], re_escape: bool = True 

184) -> str: 

185 def is_consecutive(c): 

186 c_int = ord(c) 

187 is_consecutive.prev, prev = c_int, is_consecutive.prev 

188 if c_int - prev > 1: 

189 is_consecutive.value = next(is_consecutive.counter) 

190 return is_consecutive.value 

191 

192 is_consecutive.prev = 0 

193 is_consecutive.counter = itertools.count() 

194 is_consecutive.value = -1 

195 

196 def escape_re_range_char(c): 

197 return "\\" + c if c in r"\^-][" else c 

198 

199 def no_escape_re_range_char(c): 

200 return c 

201 

202 if not re_escape: 

203 escape_re_range_char = no_escape_re_range_char 

204 

205 ret = [] 

206 s = "".join(sorted(set(s))) 

207 if len(s) > 3: 

208 for _, chars in itertools.groupby(s, key=is_consecutive): 

209 first = last = next(chars) 

210 last = collections.deque( 

211 itertools.chain(iter([last]), chars), maxlen=1 

212 ).pop() 

213 if first == last: 

214 ret.append(escape_re_range_char(first)) 

215 else: 

216 sep = "" if ord(last) == ord(first) + 1 else "-" 

217 ret.append( 

218 "{}{}{}".format( 

219 escape_re_range_char(first), sep, escape_re_range_char(last) 

220 ) 

221 ) 

222 else: 

223 ret = [escape_re_range_char(c) for c in s] 

224 

225 return "".join(ret) 

226 

227 

228def _flatten(ll: list) -> list: 

229 ret = [] 

230 for i in ll: 

231 if isinstance(i, list): 

232 ret.extend(_flatten(i)) 

233 else: 

234 ret.append(i) 

235 return ret