Mercurial > public > mercurial-scm > hg
comparison mercurial/parser.py @ 34131:0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Our code transformer can't rewrite string literals in docstrings, and I
don't want to make the transformer more complex.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sun, 03 Sep 2017 14:32:11 +0900 |
parents | 7bbc4e113e5f |
children | a8994d08e4a2 |
comparison
equal
deleted
inserted
replaced
34130:ada8a19672ab | 34131:0fa781320203 |
---|---|
95 return t | 95 return t |
96 | 96 |
97 def splitargspec(spec): | 97 def splitargspec(spec): |
98 """Parse spec of function arguments into (poskeys, varkey, keys, optkey) | 98 """Parse spec of function arguments into (poskeys, varkey, keys, optkey) |
99 | 99 |
100 >>> splitargspec('') | 100 >>> splitargspec(b'') |
101 ([], None, [], None) | 101 ([], None, [], None) |
102 >>> splitargspec('foo bar') | 102 >>> splitargspec(b'foo bar') |
103 ([], None, ['foo', 'bar'], None) | 103 ([], None, ['foo', 'bar'], None) |
104 >>> splitargspec('foo *bar baz **qux') | 104 >>> splitargspec(b'foo *bar baz **qux') |
105 (['foo'], 'bar', ['baz'], 'qux') | 105 (['foo'], 'bar', ['baz'], 'qux') |
106 >>> splitargspec('*foo') | 106 >>> splitargspec(b'*foo') |
107 ([], 'foo', [], None) | 107 ([], 'foo', [], None) |
108 >>> splitargspec('**foo') | 108 >>> splitargspec(b'**foo') |
109 ([], None, [], 'foo') | 109 ([], None, [], 'foo') |
110 """ | 110 """ |
111 optkey = None | 111 optkey = None |
112 pre, sep, post = spec.partition('**') | 112 pre, sep, post = spec.partition('**') |
113 if sep: | 113 if sep: |
219 | 219 |
220 def simplifyinfixops(tree, targetnodes): | 220 def simplifyinfixops(tree, targetnodes): |
221 """Flatten chained infix operations to reduce usage of Python stack | 221 """Flatten chained infix operations to reduce usage of Python stack |
222 | 222 |
223 >>> def f(tree): | 223 >>> def f(tree): |
224 ... print prettyformat(simplifyinfixops(tree, ('or',)), ('symbol',)) | 224 ... print prettyformat(simplifyinfixops(tree, (b'or',)), (b'symbol',)) |
225 >>> f(('or', | 225 >>> f((b'or', |
226 ... ('or', | 226 ... (b'or', |
227 ... ('symbol', '1'), | 227 ... (b'symbol', b'1'), |
228 ... ('symbol', '2')), | 228 ... (b'symbol', b'2')), |
229 ... ('symbol', '3'))) | 229 ... (b'symbol', b'3'))) |
230 (or | 230 (or |
231 (symbol '1') | 231 (symbol '1') |
232 (symbol '2') | 232 (symbol '2') |
233 (symbol '3')) | 233 (symbol '3')) |
234 >>> f(('func', | 234 >>> f((b'func', |
235 ... ('symbol', 'p1'), | 235 ... (b'symbol', b'p1'), |
236 ... ('or', | 236 ... (b'or', |
237 ... ('or', | 237 ... (b'or', |
238 ... ('func', | 238 ... (b'func', |
239 ... ('symbol', 'sort'), | 239 ... (b'symbol', b'sort'), |
240 ... ('list', | 240 ... (b'list', |
241 ... ('or', | 241 ... (b'or', |
242 ... ('or', | 242 ... (b'or', |
243 ... ('symbol', '1'), | 243 ... (b'symbol', b'1'), |
244 ... ('symbol', '2')), | 244 ... (b'symbol', b'2')), |
245 ... ('symbol', '3')), | 245 ... (b'symbol', b'3')), |
246 ... ('negate', | 246 ... (b'negate', |
247 ... ('symbol', 'rev')))), | 247 ... (b'symbol', b'rev')))), |
248 ... ('and', | 248 ... (b'and', |
249 ... ('symbol', '4'), | 249 ... (b'symbol', b'4'), |
250 ... ('group', | 250 ... (b'group', |
251 ... ('or', | 251 ... (b'or', |
252 ... ('or', | 252 ... (b'or', |
253 ... ('symbol', '5'), | 253 ... (b'symbol', b'5'), |
254 ... ('symbol', '6')), | 254 ... (b'symbol', b'6')), |
255 ... ('symbol', '7'))))), | 255 ... (b'symbol', b'7'))))), |
256 ... ('symbol', '8')))) | 256 ... (b'symbol', b'8')))) |
257 (func | 257 (func |
258 (symbol 'p1') | 258 (symbol 'p1') |
259 (or | 259 (or |
260 (func | 260 (func |
261 (symbol 'sort') | 261 (symbol 'sort') |
302 return tuple(_buildtree(x, placeholder, replstack) for x in template) | 302 return tuple(_buildtree(x, placeholder, replstack) for x in template) |
303 | 303 |
304 def buildtree(template, placeholder, *repls): | 304 def buildtree(template, placeholder, *repls): |
305 """Create new tree by substituting placeholders by replacements | 305 """Create new tree by substituting placeholders by replacements |
306 | 306 |
307 >>> _ = ('symbol', '_') | 307 >>> _ = (b'symbol', b'_') |
308 >>> def f(template, *repls): | 308 >>> def f(template, *repls): |
309 ... return buildtree(template, _, *repls) | 309 ... return buildtree(template, _, *repls) |
310 >>> f(('func', ('symbol', 'only'), ('list', _, _)), | 310 >>> f((b'func', (b'symbol', b'only'), (b'list', _, _)), |
311 ... ('symbol', '1'), ('symbol', '2')) | 311 ... ('symbol', '1'), ('symbol', '2')) |
312 ('func', ('symbol', 'only'), ('list', ('symbol', '1'), ('symbol', '2'))) | 312 ('func', ('symbol', 'only'), ('list', ('symbol', '1'), ('symbol', '2'))) |
313 >>> f(('and', _, ('not', _)), ('symbol', '1'), ('symbol', '2')) | 313 >>> f((b'and', _, (b'not', _)), (b'symbol', b'1'), (b'symbol', b'2')) |
314 ('and', ('symbol', '1'), ('not', ('symbol', '2'))) | 314 ('and', ('symbol', '1'), ('not', ('symbol', '2'))) |
315 """ | 315 """ |
316 if not isinstance(placeholder, tuple): | 316 if not isinstance(placeholder, tuple): |
317 raise error.ProgrammingError('placeholder must be a node tuple') | 317 raise error.ProgrammingError('placeholder must be a node tuple') |
318 replstack = list(reversed(repls)) | 318 replstack = list(reversed(repls)) |
337 def matchtree(pattern, tree, placeholder=None, incompletenodes=()): | 337 def matchtree(pattern, tree, placeholder=None, incompletenodes=()): |
338 """If a tree matches the pattern, return a list of the tree and nodes | 338 """If a tree matches the pattern, return a list of the tree and nodes |
339 matched with the placeholder; Otherwise None | 339 matched with the placeholder; Otherwise None |
340 | 340 |
341 >>> def f(pattern, tree): | 341 >>> def f(pattern, tree): |
342 ... m = matchtree(pattern, tree, _, {'keyvalue', 'list'}) | 342 ... m = matchtree(pattern, tree, _, {b'keyvalue', b'list'}) |
343 ... if m: | 343 ... if m: |
344 ... return m[1:] | 344 ... return m[1:] |
345 | 345 |
346 >>> _ = ('symbol', '_') | 346 >>> _ = (b'symbol', b'_') |
347 >>> f(('func', ('symbol', 'ancestors'), _), | 347 >>> f((b'func', (b'symbol', b'ancestors'), _), |
348 ... ('func', ('symbol', 'ancestors'), ('symbol', '1'))) | 348 ... (b'func', (b'symbol', b'ancestors'), (b'symbol', b'1'))) |
349 [('symbol', '1')] | 349 [('symbol', '1')] |
350 >>> f(('func', ('symbol', 'ancestors'), _), | 350 >>> f((b'func', (b'symbol', b'ancestors'), _), |
351 ... ('func', ('symbol', 'ancestors'), None)) | 351 ... (b'func', (b'symbol', b'ancestors'), None)) |
352 >>> f(('range', ('dagrange', _, _), _), | 352 >>> f((b'range', (b'dagrange', _, _), _), |
353 ... ('range', | 353 ... (b'range', |
354 ... ('dagrange', ('symbol', '1'), ('symbol', '2')), | 354 ... (b'dagrange', (b'symbol', b'1'), (b'symbol', b'2')), |
355 ... ('symbol', '3'))) | 355 ... (b'symbol', b'3'))) |
356 [('symbol', '1'), ('symbol', '2'), ('symbol', '3')] | 356 [('symbol', '1'), ('symbol', '2'), ('symbol', '3')] |
357 | 357 |
358 The placeholder does not match the specified incomplete nodes because | 358 The placeholder does not match the specified incomplete nodes because |
359 an incomplete node (e.g. argument list) cannot construct an expression. | 359 an incomplete node (e.g. argument list) cannot construct an expression. |
360 | 360 |
361 >>> f(('func', ('symbol', 'ancestors'), _), | 361 >>> f((b'func', (b'symbol', b'ancestors'), _), |
362 ... ('func', ('symbol', 'ancestors'), | 362 ... (b'func', (b'symbol', b'ancestors'), |
363 ... ('list', ('symbol', '1'), ('symbol', '2')))) | 363 ... (b'list', (b'symbol', b'1'), (b'symbol', b'2')))) |
364 | 364 |
365 The placeholder may be omitted, but which shouldn't match a None node. | 365 The placeholder may be omitted, but which shouldn't match a None node. |
366 | 366 |
367 >>> _ = None | 367 >>> _ = None |
368 >>> f(('func', ('symbol', 'ancestors'), None), | 368 >>> f((b'func', (b'symbol', b'ancestors'), None), |
369 ... ('func', ('symbol', 'ancestors'), ('symbol', '0'))) | 369 ... (b'func', (b'symbol', b'ancestors'), (b'symbol', b'0'))) |
370 """ | 370 """ |
371 if placeholder is not None and not isinstance(placeholder, tuple): | 371 if placeholder is not None and not isinstance(placeholder, tuple): |
372 raise error.ProgrammingError('placeholder must be a node tuple') | 372 raise error.ProgrammingError('placeholder must be a node tuple') |
373 matches = [tree] | 373 matches = [tree] |
374 if _matchtree(pattern, tree, placeholder, incompletenodes, matches): | 374 if _matchtree(pattern, tree, placeholder, incompletenodes, matches): |
434 | 434 |
435 - ``name``: of declared alias (may be ``decl`` itself at error) | 435 - ``name``: of declared alias (may be ``decl`` itself at error) |
436 - ``args``: list of argument names (or None for symbol declaration) | 436 - ``args``: list of argument names (or None for symbol declaration) |
437 - ``errorstr``: detail about detected error (or None) | 437 - ``errorstr``: detail about detected error (or None) |
438 | 438 |
439 >>> sym = lambda x: ('symbol', x) | 439 >>> sym = lambda x: (b'symbol', x) |
440 >>> symlist = lambda *xs: ('list',) + tuple(sym(x) for x in xs) | 440 >>> symlist = lambda *xs: (b'list',) + tuple(sym(x) for x in xs) |
441 >>> func = lambda n, a: ('func', sym(n), a) | 441 >>> func = lambda n, a: (b'func', sym(n), a) |
442 >>> parsemap = { | 442 >>> parsemap = { |
443 ... 'foo': sym('foo'), | 443 ... b'foo': sym(b'foo'), |
444 ... '$foo': sym('$foo'), | 444 ... b'$foo': sym(b'$foo'), |
445 ... 'foo::bar': ('dagrange', sym('foo'), sym('bar')), | 445 ... b'foo::bar': (b'dagrange', sym(b'foo'), sym(b'bar')), |
446 ... 'foo()': func('foo', None), | 446 ... b'foo()': func(b'foo', None), |
447 ... '$foo()': func('$foo', None), | 447 ... b'$foo()': func(b'$foo', None), |
448 ... 'foo($1, $2)': func('foo', symlist('$1', '$2')), | 448 ... b'foo($1, $2)': func(b'foo', symlist(b'$1', b'$2')), |
449 ... 'foo(bar_bar, baz.baz)': | 449 ... b'foo(bar_bar, baz.baz)': |
450 ... func('foo', symlist('bar_bar', 'baz.baz')), | 450 ... func(b'foo', symlist(b'bar_bar', b'baz.baz')), |
451 ... 'foo(bar($1, $2))': | 451 ... b'foo(bar($1, $2))': |
452 ... func('foo', func('bar', symlist('$1', '$2'))), | 452 ... func(b'foo', func(b'bar', symlist(b'$1', b'$2'))), |
453 ... 'foo($1, $2, nested($1, $2))': | 453 ... b'foo($1, $2, nested($1, $2))': |
454 ... func('foo', (symlist('$1', '$2') + | 454 ... func(b'foo', (symlist(b'$1', b'$2') + |
455 ... (func('nested', symlist('$1', '$2')),))), | 455 ... (func(b'nested', symlist(b'$1', b'$2')),))), |
456 ... 'foo("bar")': func('foo', ('string', 'bar')), | 456 ... b'foo("bar")': func(b'foo', (b'string', b'bar')), |
457 ... 'foo($1, $2': error.ParseError('unexpected token: end', 10), | 457 ... b'foo($1, $2': error.ParseError(b'unexpected token: end', 10), |
458 ... 'foo("bar': error.ParseError('unterminated string', 5), | 458 ... b'foo("bar': error.ParseError(b'unterminated string', 5), |
459 ... 'foo($1, $2, $1)': func('foo', symlist('$1', '$2', '$1')), | 459 ... b'foo($1, $2, $1)': func(b'foo', symlist(b'$1', b'$2', b'$1')), |
460 ... } | 460 ... } |
461 >>> def parse(expr): | 461 >>> def parse(expr): |
462 ... x = parsemap[expr] | 462 ... x = parsemap[expr] |
463 ... if isinstance(x, Exception): | 463 ... if isinstance(x, Exception): |
464 ... raise x | 464 ... raise x |
465 ... return x | 465 ... return x |
466 >>> def trygetfunc(tree): | 466 >>> def trygetfunc(tree): |
467 ... if not tree or tree[0] != 'func' or tree[1][0] != 'symbol': | 467 ... if not tree or tree[0] != b'func' or tree[1][0] != b'symbol': |
468 ... return None | 468 ... return None |
469 ... if not tree[2]: | 469 ... if not tree[2]: |
470 ... return tree[1][1], [] | 470 ... return tree[1][1], [] |
471 ... if tree[2][0] == 'list': | 471 ... if tree[2][0] == b'list': |
472 ... return tree[1][1], list(tree[2][1:]) | 472 ... return tree[1][1], list(tree[2][1:]) |
473 ... return tree[1][1], [tree[2]] | 473 ... return tree[1][1], [tree[2]] |
474 >>> class aliasrules(basealiasrules): | 474 >>> class aliasrules(basealiasrules): |
475 ... _parse = staticmethod(parse) | 475 ... _parse = staticmethod(parse) |
476 ... _trygetfunc = staticmethod(trygetfunc) | 476 ... _trygetfunc = staticmethod(trygetfunc) |
477 >>> builddecl = aliasrules._builddecl | 477 >>> builddecl = aliasrules._builddecl |
478 >>> builddecl('foo') | 478 >>> builddecl(b'foo') |
479 ('foo', None, None) | 479 ('foo', None, None) |
480 >>> builddecl('$foo') | 480 >>> builddecl(b'$foo') |
481 ('$foo', None, "invalid symbol '$foo'") | 481 ('$foo', None, "invalid symbol '$foo'") |
482 >>> builddecl('foo::bar') | 482 >>> builddecl(b'foo::bar') |
483 ('foo::bar', None, 'invalid format') | 483 ('foo::bar', None, 'invalid format') |
484 >>> builddecl('foo()') | 484 >>> builddecl(b'foo()') |
485 ('foo', [], None) | 485 ('foo', [], None) |
486 >>> builddecl('$foo()') | 486 >>> builddecl(b'$foo()') |
487 ('$foo()', None, "invalid function '$foo'") | 487 ('$foo()', None, "invalid function '$foo'") |
488 >>> builddecl('foo($1, $2)') | 488 >>> builddecl(b'foo($1, $2)') |
489 ('foo', ['$1', '$2'], None) | 489 ('foo', ['$1', '$2'], None) |
490 >>> builddecl('foo(bar_bar, baz.baz)') | 490 >>> builddecl(b'foo(bar_bar, baz.baz)') |
491 ('foo', ['bar_bar', 'baz.baz'], None) | 491 ('foo', ['bar_bar', 'baz.baz'], None) |
492 >>> builddecl('foo($1, $2, nested($1, $2))') | 492 >>> builddecl(b'foo($1, $2, nested($1, $2))') |
493 ('foo($1, $2, nested($1, $2))', None, 'invalid argument list') | 493 ('foo($1, $2, nested($1, $2))', None, 'invalid argument list') |
494 >>> builddecl('foo(bar($1, $2))') | 494 >>> builddecl(b'foo(bar($1, $2))') |
495 ('foo(bar($1, $2))', None, 'invalid argument list') | 495 ('foo(bar($1, $2))', None, 'invalid argument list') |
496 >>> builddecl('foo("bar")') | 496 >>> builddecl(b'foo("bar")') |
497 ('foo("bar")', None, 'invalid argument list') | 497 ('foo("bar")', None, 'invalid argument list') |
498 >>> builddecl('foo($1, $2') | 498 >>> builddecl(b'foo($1, $2') |
499 ('foo($1, $2', None, 'at 10: unexpected token: end') | 499 ('foo($1, $2', None, 'at 10: unexpected token: end') |
500 >>> builddecl('foo("bar') | 500 >>> builddecl(b'foo("bar') |
501 ('foo("bar', None, 'at 5: unterminated string') | 501 ('foo("bar', None, 'at 5: unterminated string') |
502 >>> builddecl('foo($1, $2, $1)') | 502 >>> builddecl(b'foo($1, $2, $1)') |
503 ('foo', None, 'argument names collide with each other') | 503 ('foo', None, 'argument names collide with each other') |
504 """ | 504 """ |
505 try: | 505 try: |
506 tree = cls._parse(decl) | 506 tree = cls._parse(decl) |
507 except error.ParseError as inst: | 507 except error.ParseError as inst: |
554 | 554 |
555 ``args`` is a list of alias argument names, or None if the alias | 555 ``args`` is a list of alias argument names, or None if the alias |
556 is declared as a symbol. | 556 is declared as a symbol. |
557 | 557 |
558 >>> parsemap = { | 558 >>> parsemap = { |
559 ... '$1 or foo': ('or', ('symbol', '$1'), ('symbol', 'foo')), | 559 ... b'$1 or foo': (b'or', (b'symbol', b'$1'), (b'symbol', b'foo')), |
560 ... '$1 or $bar': ('or', ('symbol', '$1'), ('symbol', '$bar')), | 560 ... b'$1 or $bar': |
561 ... '$10 or baz': ('or', ('symbol', '$10'), ('symbol', 'baz')), | 561 ... (b'or', (b'symbol', b'$1'), (b'symbol', b'$bar')), |
562 ... '"$1" or "foo"': ('or', ('string', '$1'), ('string', 'foo')), | 562 ... b'$10 or baz': |
563 ... (b'or', (b'symbol', b'$10'), (b'symbol', b'baz')), | |
564 ... b'"$1" or "foo"': | |
565 ... (b'or', (b'string', b'$1'), (b'string', b'foo')), | |
563 ... } | 566 ... } |
564 >>> class aliasrules(basealiasrules): | 567 >>> class aliasrules(basealiasrules): |
565 ... _parse = staticmethod(parsemap.__getitem__) | 568 ... _parse = staticmethod(parsemap.__getitem__) |
566 ... _trygetfunc = staticmethod(lambda x: None) | 569 ... _trygetfunc = staticmethod(lambda x: None) |
567 >>> builddefn = aliasrules._builddefn | 570 >>> builddefn = aliasrules._builddefn |
568 >>> def pprint(tree): | 571 >>> def pprint(tree): |
569 ... print prettyformat(tree, ('_aliasarg', 'string', 'symbol')) | 572 ... print prettyformat(tree, (b'_aliasarg', b'string', b'symbol')) |
570 >>> args = ['$1', '$2', 'foo'] | 573 >>> args = [b'$1', b'$2', b'foo'] |
571 >>> pprint(builddefn('$1 or foo', args)) | 574 >>> pprint(builddefn(b'$1 or foo', args)) |
572 (or | 575 (or |
573 (_aliasarg '$1') | 576 (_aliasarg '$1') |
574 (_aliasarg 'foo')) | 577 (_aliasarg 'foo')) |
575 >>> try: | 578 >>> try: |
576 ... builddefn('$1 or $bar', args) | 579 ... builddefn(b'$1 or $bar', args) |
577 ... except error.ParseError as inst: | 580 ... except error.ParseError as inst: |
578 ... print parseerrordetail(inst) | 581 ... print parseerrordetail(inst) |
579 invalid symbol '$bar' | 582 invalid symbol '$bar' |
580 >>> args = ['$1', '$10', 'foo'] | 583 >>> args = [b'$1', b'$10', b'foo'] |
581 >>> pprint(builddefn('$10 or baz', args)) | 584 >>> pprint(builddefn(b'$10 or baz', args)) |
582 (or | 585 (or |
583 (_aliasarg '$10') | 586 (_aliasarg '$10') |
584 (symbol 'baz')) | 587 (symbol 'baz')) |
585 >>> pprint(builddefn('"$1" or "foo"', args)) | 588 >>> pprint(builddefn(b'"$1" or "foo"', args)) |
586 (or | 589 (or |
587 (string '$1') | 590 (string '$1') |
588 (string 'foo')) | 591 (string 'foo')) |
589 """ | 592 """ |
590 tree = cls._parse(defn) | 593 tree = cls._parse(defn) |