Mercurial > public > mercurial-scm > hg-stable
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')) |