comparison mercurial/filesetlang.py @ 43077:687b865b95ad

formatting: byteify all mercurial/ and hgext/ string literals Done with python3.7 contrib/byteify-strings.py -i $(hg files 'set:mercurial/**.py - mercurial/thirdparty/** + hgext/**.py - hgext/fsmonitor/pywatchman/** - mercurial/__init__.py') black -l 80 -t py33 -S $(hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**" - hgext/fsmonitor/pywatchman/**') # skip-blame mass-reformatting only Differential Revision: https://phab.mercurial-scm.org/D6972
author Augie Fackler <augie@google.com>
date Sun, 06 Oct 2019 09:48:39 -0400
parents 2372284d9457
children c59eb1560c44
comparison
equal deleted inserted replaced
43076:2372284d9457 43077:687b865b95ad
21 WEIGHT_STATUS = 10 21 WEIGHT_STATUS = 10
22 WEIGHT_STATUS_THOROUGH = 50 22 WEIGHT_STATUS_THOROUGH = 50
23 23
24 elements = { 24 elements = {
25 # token-type: binding-strength, primary, prefix, infix, suffix 25 # token-type: binding-strength, primary, prefix, infix, suffix
26 "(": (20, None, ("group", 1, ")"), ("func", 1, ")"), None), 26 b"(": (20, None, (b"group", 1, b")"), (b"func", 1, b")"), None),
27 ":": (15, None, None, ("kindpat", 15), None), 27 b":": (15, None, None, (b"kindpat", 15), None),
28 "-": (5, None, ("negate", 19), ("minus", 5), None), 28 b"-": (5, None, (b"negate", 19), (b"minus", 5), None),
29 "not": (10, None, ("not", 10), None, None), 29 b"not": (10, None, (b"not", 10), None, None),
30 "!": (10, None, ("not", 10), None, None), 30 b"!": (10, None, (b"not", 10), None, None),
31 "and": (5, None, None, ("and", 5), None), 31 b"and": (5, None, None, (b"and", 5), None),
32 "&": (5, None, None, ("and", 5), None), 32 b"&": (5, None, None, (b"and", 5), None),
33 "or": (4, None, None, ("or", 4), None), 33 b"or": (4, None, None, (b"or", 4), None),
34 "|": (4, None, None, ("or", 4), None), 34 b"|": (4, None, None, (b"or", 4), None),
35 "+": (4, None, None, ("or", 4), None), 35 b"+": (4, None, None, (b"or", 4), None),
36 ",": (2, None, None, ("list", 2), None), 36 b",": (2, None, None, (b"list", 2), None),
37 ")": (0, None, None, None, None), 37 b")": (0, None, None, None, None),
38 "symbol": (0, "symbol", None, None, None), 38 b"symbol": (0, b"symbol", None, None, None),
39 "string": (0, "string", None, None, None), 39 b"string": (0, b"string", None, None, None),
40 "end": (0, None, None, None, None), 40 b"end": (0, None, None, None, None),
41 } 41 }
42 42
43 keywords = {'and', 'or', 'not'} 43 keywords = {b'and', b'or', b'not'}
44 44
45 symbols = {} 45 symbols = {}
46 46
47 globchars = ".*{}[]?/\\_" 47 globchars = b".*{}[]?/\\_"
48 48
49 49
50 def tokenize(program): 50 def tokenize(program):
51 pos, l = 0, len(program) 51 pos, l = 0, len(program)
52 program = pycompat.bytestr(program) 52 program = pycompat.bytestr(program)
53 while pos < l: 53 while pos < l:
54 c = program[pos] 54 c = program[pos]
55 if c.isspace(): # skip inter-token whitespace 55 if c.isspace(): # skip inter-token whitespace
56 pass 56 pass
57 elif c in "(),-:|&+!": # handle simple operators 57 elif c in b"(),-:|&+!": # handle simple operators
58 yield (c, None, pos) 58 yield (c, None, pos)
59 elif ( 59 elif (
60 c in '"\'' or c == 'r' and program[pos : pos + 2] in ("r'", 'r"') 60 c in b'"\''
61 or c == b'r'
62 and program[pos : pos + 2] in (b"r'", b'r"')
61 ): # handle quoted strings 63 ): # handle quoted strings
62 if c == 'r': 64 if c == b'r':
63 pos += 1 65 pos += 1
64 c = program[pos] 66 c = program[pos]
65 decode = lambda x: x 67 decode = lambda x: x
66 else: 68 else:
67 decode = parser.unescapestr 69 decode = parser.unescapestr
68 pos += 1 70 pos += 1
69 s = pos 71 s = pos
70 while pos < l: # find closing quote 72 while pos < l: # find closing quote
71 d = program[pos] 73 d = program[pos]
72 if d == '\\': # skip over escaped characters 74 if d == b'\\': # skip over escaped characters
73 pos += 2 75 pos += 2
74 continue 76 continue
75 if d == c: 77 if d == c:
76 yield ('string', decode(program[s:pos]), s) 78 yield (b'string', decode(program[s:pos]), s)
77 break 79 break
78 pos += 1 80 pos += 1
79 else: 81 else:
80 raise error.ParseError(_("unterminated string"), s) 82 raise error.ParseError(_(b"unterminated string"), s)
81 elif c.isalnum() or c in globchars or ord(c) > 127: 83 elif c.isalnum() or c in globchars or ord(c) > 127:
82 # gather up a symbol/keyword 84 # gather up a symbol/keyword
83 s = pos 85 s = pos
84 pos += 1 86 pos += 1
85 while pos < l: # find end of symbol 87 while pos < l: # find end of symbol
89 pos += 1 91 pos += 1
90 sym = program[s:pos] 92 sym = program[s:pos]
91 if sym in keywords: # operator keywords 93 if sym in keywords: # operator keywords
92 yield (sym, None, s) 94 yield (sym, None, s)
93 else: 95 else:
94 yield ('symbol', sym, s) 96 yield (b'symbol', sym, s)
95 pos -= 1 97 pos -= 1
96 else: 98 else:
97 raise error.ParseError(_("syntax error"), pos) 99 raise error.ParseError(_(b"syntax error"), pos)
98 pos += 1 100 pos += 1
99 yield ('end', None, pos) 101 yield (b'end', None, pos)
100 102
101 103
102 def parse(expr): 104 def parse(expr):
103 p = parser.parser(elements) 105 p = parser.parser(elements)
104 tree, pos = p.parse(tokenize(expr)) 106 tree, pos = p.parse(tokenize(expr))
105 if pos != len(expr): 107 if pos != len(expr):
106 raise error.ParseError(_("invalid token"), pos) 108 raise error.ParseError(_(b"invalid token"), pos)
107 return parser.simplifyinfixops(tree, {'list', 'or'}) 109 return parser.simplifyinfixops(tree, {b'list', b'or'})
108 110
109 111
110 def getsymbol(x): 112 def getsymbol(x):
111 if x and x[0] == 'symbol': 113 if x and x[0] == b'symbol':
112 return x[1] 114 return x[1]
113 raise error.ParseError(_('not a symbol')) 115 raise error.ParseError(_(b'not a symbol'))
114 116
115 117
116 def getstring(x, err): 118 def getstring(x, err):
117 if x and (x[0] == 'string' or x[0] == 'symbol'): 119 if x and (x[0] == b'string' or x[0] == b'symbol'):
118 return x[1] 120 return x[1]
119 raise error.ParseError(err) 121 raise error.ParseError(err)
120 122
121 123
122 def getkindpat(x, y, allkinds, err): 124 def getkindpat(x, y, allkinds, err):
123 kind = getsymbol(x) 125 kind = getsymbol(x)
124 pat = getstring(y, err) 126 pat = getstring(y, err)
125 if kind not in allkinds: 127 if kind not in allkinds:
126 raise error.ParseError(_("invalid pattern kind: %s") % kind) 128 raise error.ParseError(_(b"invalid pattern kind: %s") % kind)
127 return '%s:%s' % (kind, pat) 129 return b'%s:%s' % (kind, pat)
128 130
129 131
130 def getpattern(x, allkinds, err): 132 def getpattern(x, allkinds, err):
131 if x and x[0] == 'kindpat': 133 if x and x[0] == b'kindpat':
132 return getkindpat(x[1], x[2], allkinds, err) 134 return getkindpat(x[1], x[2], allkinds, err)
133 return getstring(x, err) 135 return getstring(x, err)
134 136
135 137
136 def getlist(x): 138 def getlist(x):
137 if not x: 139 if not x:
138 return [] 140 return []
139 if x[0] == 'list': 141 if x[0] == b'list':
140 return list(x[1:]) 142 return list(x[1:])
141 return [x] 143 return [x]
142 144
143 145
144 def getargs(x, min, max, err): 146 def getargs(x, min, max, err):
151 def _analyze(x): 153 def _analyze(x):
152 if x is None: 154 if x is None:
153 return x 155 return x
154 156
155 op = x[0] 157 op = x[0]
156 if op in {'string', 'symbol'}: 158 if op in {b'string', b'symbol'}:
157 return x 159 return x
158 if op == 'kindpat': 160 if op == b'kindpat':
159 getsymbol(x[1]) # kind must be a symbol 161 getsymbol(x[1]) # kind must be a symbol
160 t = _analyze(x[2]) 162 t = _analyze(x[2])
161 return (op, x[1], t) 163 return (op, x[1], t)
162 if op == 'group': 164 if op == b'group':
163 return _analyze(x[1]) 165 return _analyze(x[1])
164 if op == 'negate': 166 if op == b'negate':
165 raise error.ParseError(_("can't use negate operator in this context")) 167 raise error.ParseError(_(b"can't use negate operator in this context"))
166 if op == 'not': 168 if op == b'not':
167 t = _analyze(x[1]) 169 t = _analyze(x[1])
168 return (op, t) 170 return (op, t)
169 if op == 'and': 171 if op == b'and':
170 ta = _analyze(x[1]) 172 ta = _analyze(x[1])
171 tb = _analyze(x[2]) 173 tb = _analyze(x[2])
172 return (op, ta, tb) 174 return (op, ta, tb)
173 if op == 'minus': 175 if op == b'minus':
174 return _analyze(('and', x[1], ('not', x[2]))) 176 return _analyze((b'and', x[1], (b'not', x[2])))
175 if op in {'list', 'or'}: 177 if op in {b'list', b'or'}:
176 ts = tuple(_analyze(y) for y in x[1:]) 178 ts = tuple(_analyze(y) for y in x[1:])
177 return (op,) + ts 179 return (op,) + ts
178 if op == 'func': 180 if op == b'func':
179 getsymbol(x[1]) # function name must be a symbol 181 getsymbol(x[1]) # function name must be a symbol
180 ta = _analyze(x[2]) 182 ta = _analyze(x[2])
181 return (op, x[1], ta) 183 return (op, x[1], ta)
182 raise error.ProgrammingError('invalid operator %r' % op) 184 raise error.ProgrammingError(b'invalid operator %r' % op)
183 185
184 186
185 def _insertstatushints(x): 187 def _insertstatushints(x):
186 """Insert hint nodes where status should be calculated (first path) 188 """Insert hint nodes where status should be calculated (first path)
187 189
193 """ 195 """
194 if x is None: 196 if x is None:
195 return (), x 197 return (), x
196 198
197 op = x[0] 199 op = x[0]
198 if op in {'string', 'symbol', 'kindpat'}: 200 if op in {b'string', b'symbol', b'kindpat'}:
199 return (), x 201 return (), x
200 if op == 'not': 202 if op == b'not':
201 h, t = _insertstatushints(x[1]) 203 h, t = _insertstatushints(x[1])
202 return h, (op, t) 204 return h, (op, t)
203 if op == 'and': 205 if op == b'and':
204 ha, ta = _insertstatushints(x[1]) 206 ha, ta = _insertstatushints(x[1])
205 hb, tb = _insertstatushints(x[2]) 207 hb, tb = _insertstatushints(x[2])
206 hr = ha + hb 208 hr = ha + hb
207 if ha and hb: 209 if ha and hb:
208 return hr, ('withstatus', (op, ta, tb), ('string', ' '.join(hr))) 210 return hr, (b'withstatus', (op, ta, tb), (b'string', b' '.join(hr)))
209 return hr, (op, ta, tb) 211 return hr, (op, ta, tb)
210 if op == 'or': 212 if op == b'or':
211 hs, ts = zip(*(_insertstatushints(y) for y in x[1:])) 213 hs, ts = zip(*(_insertstatushints(y) for y in x[1:]))
212 hr = sum(hs, ()) 214 hr = sum(hs, ())
213 if sum(bool(h) for h in hs) > 1: 215 if sum(bool(h) for h in hs) > 1:
214 return hr, ('withstatus', (op,) + ts, ('string', ' '.join(hr))) 216 return hr, (b'withstatus', (op,) + ts, (b'string', b' '.join(hr)))
215 return hr, (op,) + ts 217 return hr, (op,) + ts
216 if op == 'list': 218 if op == b'list':
217 hs, ts = zip(*(_insertstatushints(y) for y in x[1:])) 219 hs, ts = zip(*(_insertstatushints(y) for y in x[1:]))
218 return sum(hs, ()), (op,) + ts 220 return sum(hs, ()), (op,) + ts
219 if op == 'func': 221 if op == b'func':
220 f = getsymbol(x[1]) 222 f = getsymbol(x[1])
221 # don't propagate 'ha' crossing a function boundary 223 # don't propagate 'ha' crossing a function boundary
222 ha, ta = _insertstatushints(x[2]) 224 ha, ta = _insertstatushints(x[2])
223 if getattr(symbols.get(f), '_callstatus', False): 225 if getattr(symbols.get(f), '_callstatus', False):
224 return (f,), ('withstatus', (op, x[1], ta), ('string', f)) 226 return (f,), (b'withstatus', (op, x[1], ta), (b'string', f))
225 return (), (op, x[1], ta) 227 return (), (op, x[1], ta)
226 raise error.ProgrammingError('invalid operator %r' % op) 228 raise error.ProgrammingError(b'invalid operator %r' % op)
227 229
228 230
229 def _mergestatushints(x, instatus): 231 def _mergestatushints(x, instatus):
230 """Remove redundant status hint nodes (second path) 232 """Remove redundant status hint nodes (second path)
231 233
233 """ 235 """
234 if x is None: 236 if x is None:
235 return x 237 return x
236 238
237 op = x[0] 239 op = x[0]
238 if op == 'withstatus': 240 if op == b'withstatus':
239 if instatus: 241 if instatus:
240 # drop redundant hint node 242 # drop redundant hint node
241 return _mergestatushints(x[1], instatus) 243 return _mergestatushints(x[1], instatus)
242 t = _mergestatushints(x[1], instatus=True) 244 t = _mergestatushints(x[1], instatus=True)
243 return (op, t, x[2]) 245 return (op, t, x[2])
244 if op in {'string', 'symbol', 'kindpat'}: 246 if op in {b'string', b'symbol', b'kindpat'}:
245 return x 247 return x
246 if op == 'not': 248 if op == b'not':
247 t = _mergestatushints(x[1], instatus) 249 t = _mergestatushints(x[1], instatus)
248 return (op, t) 250 return (op, t)
249 if op == 'and': 251 if op == b'and':
250 ta = _mergestatushints(x[1], instatus) 252 ta = _mergestatushints(x[1], instatus)
251 tb = _mergestatushints(x[2], instatus) 253 tb = _mergestatushints(x[2], instatus)
252 return (op, ta, tb) 254 return (op, ta, tb)
253 if op in {'list', 'or'}: 255 if op in {b'list', b'or'}:
254 ts = tuple(_mergestatushints(y, instatus) for y in x[1:]) 256 ts = tuple(_mergestatushints(y, instatus) for y in x[1:])
255 return (op,) + ts 257 return (op,) + ts
256 if op == 'func': 258 if op == b'func':
257 # don't propagate 'instatus' crossing a function boundary 259 # don't propagate 'instatus' crossing a function boundary
258 ta = _mergestatushints(x[2], instatus=False) 260 ta = _mergestatushints(x[2], instatus=False)
259 return (op, x[1], ta) 261 return (op, x[1], ta)
260 raise error.ProgrammingError('invalid operator %r' % op) 262 raise error.ProgrammingError(b'invalid operator %r' % op)
261 263
262 264
263 def analyze(x): 265 def analyze(x):
264 """Transform raw parsed tree to evaluatable tree which can be fed to 266 """Transform raw parsed tree to evaluatable tree which can be fed to
265 optimize() or getmatch() 267 optimize() or getmatch()
271 _h, t = _insertstatushints(t) 273 _h, t = _insertstatushints(t)
272 return _mergestatushints(t, instatus=False) 274 return _mergestatushints(t, instatus=False)
273 275
274 276
275 def _optimizeandops(op, ta, tb): 277 def _optimizeandops(op, ta, tb):
276 if tb is not None and tb[0] == 'not': 278 if tb is not None and tb[0] == b'not':
277 return ('minus', ta, tb[1]) 279 return (b'minus', ta, tb[1])
278 return (op, ta, tb) 280 return (op, ta, tb)
279 281
280 282
281 def _optimizeunion(xs): 283 def _optimizeunion(xs):
282 # collect string patterns so they can be compiled into a single regexp 284 # collect string patterns so they can be compiled into a single regexp
283 ws, ts, ss = [], [], [] 285 ws, ts, ss = [], [], []
284 for x in xs: 286 for x in xs:
285 w, t = _optimize(x) 287 w, t = _optimize(x)
286 if t is not None and t[0] in {'string', 'symbol', 'kindpat'}: 288 if t is not None and t[0] in {b'string', b'symbol', b'kindpat'}:
287 ss.append(t) 289 ss.append(t)
288 continue 290 continue
289 ws.append(w) 291 ws.append(w)
290 ts.append(t) 292 ts.append(t)
291 if ss: 293 if ss:
292 ws.append(WEIGHT_CHECK_FILENAME) 294 ws.append(WEIGHT_CHECK_FILENAME)
293 ts.append(('patterns',) + tuple(ss)) 295 ts.append((b'patterns',) + tuple(ss))
294 return ws, ts 296 return ws, ts
295 297
296 298
297 def _optimize(x): 299 def _optimize(x):
298 if x is None: 300 if x is None:
299 return 0, x 301 return 0, x
300 302
301 op = x[0] 303 op = x[0]
302 if op == 'withstatus': 304 if op == b'withstatus':
303 w, t = _optimize(x[1]) 305 w, t = _optimize(x[1])
304 return w, (op, t, x[2]) 306 return w, (op, t, x[2])
305 if op in {'string', 'symbol'}: 307 if op in {b'string', b'symbol'}:
306 return WEIGHT_CHECK_FILENAME, x 308 return WEIGHT_CHECK_FILENAME, x
307 if op == 'kindpat': 309 if op == b'kindpat':
308 w, t = _optimize(x[2]) 310 w, t = _optimize(x[2])
309 return w, (op, x[1], t) 311 return w, (op, x[1], t)
310 if op == 'not': 312 if op == b'not':
311 w, t = _optimize(x[1]) 313 w, t = _optimize(x[1])
312 return w, (op, t) 314 return w, (op, t)
313 if op == 'and': 315 if op == b'and':
314 wa, ta = _optimize(x[1]) 316 wa, ta = _optimize(x[1])
315 wb, tb = _optimize(x[2]) 317 wb, tb = _optimize(x[2])
316 if wa <= wb: 318 if wa <= wb:
317 return wa, _optimizeandops(op, ta, tb) 319 return wa, _optimizeandops(op, ta, tb)
318 else: 320 else:
319 return wb, _optimizeandops(op, tb, ta) 321 return wb, _optimizeandops(op, tb, ta)
320 if op == 'or': 322 if op == b'or':
321 ws, ts = _optimizeunion(x[1:]) 323 ws, ts = _optimizeunion(x[1:])
322 if len(ts) == 1: 324 if len(ts) == 1:
323 return ws[0], ts[0] # 'or' operation is fully optimized out 325 return ws[0], ts[0] # 'or' operation is fully optimized out
324 ts = tuple( 326 ts = tuple(
325 it[1] for it in sorted(enumerate(ts), key=lambda it: ws[it[0]]) 327 it[1] for it in sorted(enumerate(ts), key=lambda it: ws[it[0]])
326 ) 328 )
327 return max(ws), (op,) + ts 329 return max(ws), (op,) + ts
328 if op == 'list': 330 if op == b'list':
329 ws, ts = zip(*(_optimize(y) for y in x[1:])) 331 ws, ts = zip(*(_optimize(y) for y in x[1:]))
330 return sum(ws), (op,) + ts 332 return sum(ws), (op,) + ts
331 if op == 'func': 333 if op == b'func':
332 f = getsymbol(x[1]) 334 f = getsymbol(x[1])
333 w = getattr(symbols.get(f), '_weight', 1) 335 w = getattr(symbols.get(f), '_weight', 1)
334 wa, ta = _optimize(x[2]) 336 wa, ta = _optimize(x[2])
335 return w + wa, (op, x[1], ta) 337 return w + wa, (op, x[1], ta)
336 raise error.ProgrammingError('invalid operator %r' % op) 338 raise error.ProgrammingError(b'invalid operator %r' % op)
337 339
338 340
339 def optimize(x): 341 def optimize(x):
340 """Reorder/rewrite evaluatable tree for optimization 342 """Reorder/rewrite evaluatable tree for optimization
341 343
344 _w, t = _optimize(x) 346 _w, t = _optimize(x)
345 return t 347 return t
346 348
347 349
348 def prettyformat(tree): 350 def prettyformat(tree):
349 return parser.prettyformat(tree, ('string', 'symbol')) 351 return parser.prettyformat(tree, (b'string', b'symbol'))