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: