Mercurial > public > mercurial-scm > hg
comparison mercurial/parser.py @ 34073:7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
The format of leaf nodes is slightly changed so they look more similar to
internal nodes.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sun, 03 Sep 2017 21:17:25 +0900 |
parents | 79681d8ee587 |
children | 0fa781320203 |
comparison
equal
deleted
inserted
replaced
34072:30535fe47e78 | 34073:7bbc4e113e5f |
---|---|
18 | 18 |
19 from __future__ import absolute_import | 19 from __future__ import absolute_import |
20 | 20 |
21 from .i18n import _ | 21 from .i18n import _ |
22 from . import ( | 22 from . import ( |
23 encoding, | |
23 error, | 24 error, |
24 util, | 25 util, |
25 ) | 26 ) |
26 | 27 |
27 class parser(object): | 28 class parser(object): |
191 return util.unescapestr(s) | 192 return util.unescapestr(s) |
192 except ValueError as e: | 193 except ValueError as e: |
193 # mangle Python's exception into our format | 194 # mangle Python's exception into our format |
194 raise error.ParseError(str(e).lower()) | 195 raise error.ParseError(str(e).lower()) |
195 | 196 |
197 def _brepr(obj): | |
198 if isinstance(obj, bytes): | |
199 return b"'%s'" % util.escapestr(obj) | |
200 return encoding.strtolocal(repr(obj)) | |
201 | |
196 def _prettyformat(tree, leafnodes, level, lines): | 202 def _prettyformat(tree, leafnodes, level, lines): |
197 if not isinstance(tree, tuple) or tree[0] in leafnodes: | 203 if not isinstance(tree, tuple): |
198 lines.append((level, str(tree))) | 204 lines.append((level, _brepr(tree))) |
205 elif tree[0] in leafnodes: | |
206 rs = map(_brepr, tree[1:]) | |
207 lines.append((level, '(%s %s)' % (tree[0], ' '.join(rs)))) | |
199 else: | 208 else: |
200 lines.append((level, '(%s' % tree[0])) | 209 lines.append((level, '(%s' % tree[0])) |
201 for s in tree[1:]: | 210 for s in tree[1:]: |
202 _prettyformat(s, leafnodes, level + 1, lines) | 211 _prettyformat(s, leafnodes, level + 1, lines) |
203 lines[-1:] = [(lines[-1][0], lines[-1][1] + ')')] | 212 lines[-1:] = [(lines[-1][0], lines[-1][1] + ')')] |
217 ... ('or', | 226 ... ('or', |
218 ... ('symbol', '1'), | 227 ... ('symbol', '1'), |
219 ... ('symbol', '2')), | 228 ... ('symbol', '2')), |
220 ... ('symbol', '3'))) | 229 ... ('symbol', '3'))) |
221 (or | 230 (or |
222 ('symbol', '1') | 231 (symbol '1') |
223 ('symbol', '2') | 232 (symbol '2') |
224 ('symbol', '3')) | 233 (symbol '3')) |
225 >>> f(('func', | 234 >>> f(('func', |
226 ... ('symbol', 'p1'), | 235 ... ('symbol', 'p1'), |
227 ... ('or', | 236 ... ('or', |
228 ... ('or', | 237 ... ('or', |
229 ... ('func', | 238 ... ('func', |
244 ... ('symbol', '5'), | 253 ... ('symbol', '5'), |
245 ... ('symbol', '6')), | 254 ... ('symbol', '6')), |
246 ... ('symbol', '7'))))), | 255 ... ('symbol', '7'))))), |
247 ... ('symbol', '8')))) | 256 ... ('symbol', '8')))) |
248 (func | 257 (func |
249 ('symbol', 'p1') | 258 (symbol 'p1') |
250 (or | 259 (or |
251 (func | 260 (func |
252 ('symbol', 'sort') | 261 (symbol 'sort') |
253 (list | 262 (list |
254 (or | 263 (or |
255 ('symbol', '1') | 264 (symbol '1') |
256 ('symbol', '2') | 265 (symbol '2') |
257 ('symbol', '3')) | 266 (symbol '3')) |
258 (negate | 267 (negate |
259 ('symbol', 'rev')))) | 268 (symbol 'rev')))) |
260 (and | 269 (and |
261 ('symbol', '4') | 270 (symbol '4') |
262 (group | 271 (group |
263 (or | 272 (or |
264 ('symbol', '5') | 273 (symbol '5') |
265 ('symbol', '6') | 274 (symbol '6') |
266 ('symbol', '7')))) | 275 (symbol '7')))) |
267 ('symbol', '8'))) | 276 (symbol '8'))) |
268 """ | 277 """ |
269 if not isinstance(tree, tuple): | 278 if not isinstance(tree, tuple): |
270 return tree | 279 return tree |
271 op = tree[0] | 280 op = tree[0] |
272 if op not in targetnodes: | 281 if op not in targetnodes: |
559 >>> def pprint(tree): | 568 >>> def pprint(tree): |
560 ... print prettyformat(tree, ('_aliasarg', 'string', 'symbol')) | 569 ... print prettyformat(tree, ('_aliasarg', 'string', 'symbol')) |
561 >>> args = ['$1', '$2', 'foo'] | 570 >>> args = ['$1', '$2', 'foo'] |
562 >>> pprint(builddefn('$1 or foo', args)) | 571 >>> pprint(builddefn('$1 or foo', args)) |
563 (or | 572 (or |
564 ('_aliasarg', '$1') | 573 (_aliasarg '$1') |
565 ('_aliasarg', 'foo')) | 574 (_aliasarg 'foo')) |
566 >>> try: | 575 >>> try: |
567 ... builddefn('$1 or $bar', args) | 576 ... builddefn('$1 or $bar', args) |
568 ... except error.ParseError as inst: | 577 ... except error.ParseError as inst: |
569 ... print parseerrordetail(inst) | 578 ... print parseerrordetail(inst) |
570 invalid symbol '$bar' | 579 invalid symbol '$bar' |
571 >>> args = ['$1', '$10', 'foo'] | 580 >>> args = ['$1', '$10', 'foo'] |
572 >>> pprint(builddefn('$10 or baz', args)) | 581 >>> pprint(builddefn('$10 or baz', args)) |
573 (or | 582 (or |
574 ('_aliasarg', '$10') | 583 (_aliasarg '$10') |
575 ('symbol', 'baz')) | 584 (symbol 'baz')) |
576 >>> pprint(builddefn('"$1" or "foo"', args)) | 585 >>> pprint(builddefn('"$1" or "foo"', args)) |
577 (or | 586 (or |
578 ('string', '$1') | 587 (string '$1') |
579 ('string', 'foo')) | 588 (string 'foo')) |
580 """ | 589 """ |
581 tree = cls._parse(defn) | 590 tree = cls._parse(defn) |
582 if args: | 591 if args: |
583 args = set(args) | 592 args = set(args) |
584 else: | 593 else: |