mercurial/revsetlang.py
changeset 34131 0fa781320203
parent 34069 e18119b1ad5d
child 34272 53fb09c73ba8
equal deleted inserted replaced
34130:ada8a19672ab 34131:0fa781320203
    76 
    76 
    77     By default, character ``c`` is recognized as valid for non-initial
    77     By default, character ``c`` is recognized as valid for non-initial
    78     letters of symbols, if ``c.isalnum() or c in '-._/@' or ord(c) > 127``.
    78     letters of symbols, if ``c.isalnum() or c in '-._/@' or ord(c) > 127``.
    79 
    79 
    80     Check that @ is a valid unquoted token character (issue3686):
    80     Check that @ is a valid unquoted token character (issue3686):
    81     >>> list(tokenize("@::"))
    81     >>> list(tokenize(b"@::"))
    82     [('symbol', '@', 0), ('::', None, 1), ('end', None, 3)]
    82     [('symbol', '@', 0), ('::', None, 1), ('end', None, 3)]
    83 
    83 
    84     '''
    84     '''
    85     program = pycompat.bytestr(program)
    85     program = pycompat.bytestr(program)
    86     if syminitletters is None:
    86     if syminitletters is None:
   250     return tree
   250     return tree
   251 
   251 
   252 def _build(tmplspec, *repls):
   252 def _build(tmplspec, *repls):
   253     """Create raw parsed tree from a template revset statement
   253     """Create raw parsed tree from a template revset statement
   254 
   254 
   255     >>> _build('f(_) and _', ('string', '1'), ('symbol', '2'))
   255     >>> _build(b'f(_) and _', (b'string', b'1'), (b'symbol', b'2'))
   256     ('and', ('func', ('symbol', 'f'), ('string', '1')), ('symbol', '2'))
   256     ('and', ('func', ('symbol', 'f'), ('string', '1')), ('symbol', '2'))
   257     """
   257     """
   258     template = _cachedtree(tmplspec)
   258     template = _cachedtree(tmplspec)
   259     return parser.buildtree(template, ('symbol', '_'), *repls)
   259     return parser.buildtree(template, ('symbol', '_'), *repls)
   260 
   260 
   261 def _match(patspec, tree):
   261 def _match(patspec, tree):
   262     """Test if a tree matches the given pattern statement; return the matches
   262     """Test if a tree matches the given pattern statement; return the matches
   263 
   263 
   264     >>> _match('f(_)', parse('f()'))
   264     >>> _match(b'f(_)', parse(b'f()'))
   265     >>> _match('f(_)', parse('f(1)'))
   265     >>> _match(b'f(_)', parse(b'f(1)'))
   266     [('func', ('symbol', 'f'), ('symbol', '1')), ('symbol', '1')]
   266     [('func', ('symbol', 'f'), ('symbol', '1')), ('symbol', '1')]
   267     >>> _match('f(_)', parse('f(1, 2)'))
   267     >>> _match(b'f(_)', parse(b'f(1, 2)'))
   268     """
   268     """
   269     pattern = _cachedtree(patspec)
   269     pattern = _cachedtree(patspec)
   270     return parser.matchtree(pattern, tree, ('symbol', '_'),
   270     return parser.matchtree(pattern, tree, ('symbol', '_'),
   271                             {'keyvalue', 'list'})
   271                             {'keyvalue', 'list'})
   272 
   272 
   476 _aliassyminitletters = _syminitletters | {'$'}
   476 _aliassyminitletters = _syminitletters | {'$'}
   477 
   477 
   478 def _parsewith(spec, lookup=None, syminitletters=None):
   478 def _parsewith(spec, lookup=None, syminitletters=None):
   479     """Generate a parse tree of given spec with given tokenizing options
   479     """Generate a parse tree of given spec with given tokenizing options
   480 
   480 
   481     >>> _parsewith('foo($1)', syminitletters=_aliassyminitletters)
   481     >>> _parsewith(b'foo($1)', syminitletters=_aliassyminitletters)
   482     ('func', ('symbol', 'foo'), ('symbol', '$1'))
   482     ('func', ('symbol', 'foo'), ('symbol', '$1'))
   483     >>> _parsewith('$1')
   483     >>> _parsewith(b'$1')
   484     Traceback (most recent call last):
   484     Traceback (most recent call last):
   485       ...
   485       ...
   486     ParseError: ("syntax error in revset '$1'", 0)
   486     ParseError: ("syntax error in revset '$1'", 0)
   487     >>> _parsewith('foo bar')
   487     >>> _parsewith(b'foo bar')
   488     Traceback (most recent call last):
   488     Traceback (most recent call last):
   489       ...
   489       ...
   490     ParseError: ('invalid token', 4)
   490     ParseError: ('invalid token', 4)
   491     """
   491     """
   492     p = parser.parser(elements)
   492     p = parser.parser(elements)
   552     return _parsewith(spec, lookup=lookup)
   552     return _parsewith(spec, lookup=lookup)
   553 
   553 
   554 def _quote(s):
   554 def _quote(s):
   555     r"""Quote a value in order to make it safe for the revset engine.
   555     r"""Quote a value in order to make it safe for the revset engine.
   556 
   556 
   557     >>> _quote('asdf')
   557     >>> _quote(b'asdf')
   558     "'asdf'"
   558     "'asdf'"
   559     >>> _quote("asdf'\"")
   559     >>> _quote(b"asdf'\"")
   560     '\'asdf\\\'"\''
   560     '\'asdf\\\'"\''
   561     >>> _quote('asdf\'')
   561     >>> _quote(b'asdf\'')
   562     "'asdf\\''"
   562     "'asdf\\''"
   563     >>> _quote(1)
   563     >>> _quote(1)
   564     "'1'"
   564     "'1'"
   565     """
   565     """
   566     return "'%s'" % util.escapestr(pycompat.bytestr(s))
   566     return "'%s'" % util.escapestr(pycompat.bytestr(s))
   580     %n = hex(arg), single-quoted
   580     %n = hex(arg), single-quoted
   581     %% = a literal '%'
   581     %% = a literal '%'
   582 
   582 
   583     Prefixing the type with 'l' specifies a parenthesized list of that type.
   583     Prefixing the type with 'l' specifies a parenthesized list of that type.
   584 
   584 
   585     >>> formatspec('%r:: and %lr', '10 or 11', ("this()", "that()"))
   585     >>> formatspec(b'%r:: and %lr', b'10 or 11', (b"this()", b"that()"))
   586     '(10 or 11):: and ((this()) or (that()))'
   586     '(10 or 11):: and ((this()) or (that()))'
   587     >>> formatspec('%d:: and not %d::', 10, 20)
   587     >>> formatspec(b'%d:: and not %d::', 10, 20)
   588     '10:: and not 20::'
   588     '10:: and not 20::'
   589     >>> formatspec('%ld or %ld', [], [1])
   589     >>> formatspec(b'%ld or %ld', [], [1])
   590     "_list('') or 1"
   590     "_list('') or 1"
   591     >>> formatspec('keyword(%s)', 'foo\\xe9')
   591     >>> formatspec(b'keyword(%s)', b'foo\\xe9')
   592     "keyword('foo\\\\xe9')"
   592     "keyword('foo\\\\xe9')"
   593     >>> b = lambda: 'default'
   593     >>> b = lambda: b'default'
   594     >>> b.branch = b
   594     >>> b.branch = b
   595     >>> formatspec('branch(%b)', b)
   595     >>> formatspec(b'branch(%b)', b)
   596     "branch('default')"
   596     "branch('default')"
   597     >>> formatspec('root(%ls)', ['a', 'b', 'c', 'd'])
   597     >>> formatspec(b'root(%ls)', [b'a', b'b', b'c', b'd'])
   598     "root(_list('a\\x00b\\x00c\\x00d'))"
   598     "root(_list('a\\x00b\\x00c\\x00d'))"
   599     '''
   599     '''
   600 
   600 
   601     def argtype(c, arg):
   601     def argtype(c, arg):
   602         if c == 'd':
   602         if c == 'd':