diff mercurial/revsetlang.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
line wrap: on
line diff
--- a/mercurial/revsetlang.py	Sun Oct 06 09:45:02 2019 -0400
+++ b/mercurial/revsetlang.py	Sun Oct 06 09:48:39 2019 -0400
@@ -22,63 +22,63 @@
 
 elements = {
     # token-type: binding-strength, primary, prefix, infix, suffix
-    "(": (21, None, ("group", 1, ")"), ("func", 1, ")"), None),
-    "[": (21, None, None, ("subscript", 1, "]"), None),
-    "#": (21, None, None, ("relation", 21), None),
-    "##": (20, None, None, ("_concat", 20), None),
-    "~": (18, None, None, ("ancestor", 18), None),
-    "^": (18, None, None, ("parent", 18), "parentpost"),
-    "-": (5, None, ("negate", 19), ("minus", 5), None),
-    "::": (
+    b"(": (21, None, (b"group", 1, b")"), (b"func", 1, b")"), None),
+    b"[": (21, None, None, (b"subscript", 1, b"]"), None),
+    b"#": (21, None, None, (b"relation", 21), None),
+    b"##": (20, None, None, (b"_concat", 20), None),
+    b"~": (18, None, None, (b"ancestor", 18), None),
+    b"^": (18, None, None, (b"parent", 18), b"parentpost"),
+    b"-": (5, None, (b"negate", 19), (b"minus", 5), None),
+    b"::": (
         17,
-        "dagrangeall",
-        ("dagrangepre", 17),
-        ("dagrange", 17),
-        "dagrangepost",
+        b"dagrangeall",
+        (b"dagrangepre", 17),
+        (b"dagrange", 17),
+        b"dagrangepost",
     ),
-    "..": (
+    b"..": (
         17,
-        "dagrangeall",
-        ("dagrangepre", 17),
-        ("dagrange", 17),
-        "dagrangepost",
+        b"dagrangeall",
+        (b"dagrangepre", 17),
+        (b"dagrange", 17),
+        b"dagrangepost",
     ),
-    ":": (15, "rangeall", ("rangepre", 15), ("range", 15), "rangepost"),
-    "not": (10, None, ("not", 10), None, None),
-    "!": (10, None, ("not", 10), None, None),
-    "and": (5, None, None, ("and", 5), None),
-    "&": (5, None, None, ("and", 5), None),
-    "%": (5, None, None, ("only", 5), "onlypost"),
-    "or": (4, None, None, ("or", 4), None),
-    "|": (4, None, None, ("or", 4), None),
-    "+": (4, None, None, ("or", 4), None),
-    "=": (3, None, None, ("keyvalue", 3), None),
-    ",": (2, None, None, ("list", 2), None),
-    ")": (0, None, None, None, None),
-    "]": (0, None, None, None, None),
-    "symbol": (0, "symbol", None, None, None),
-    "string": (0, "string", None, None, None),
-    "end": (0, None, None, None, None),
+    b":": (15, b"rangeall", (b"rangepre", 15), (b"range", 15), b"rangepost"),
+    b"not": (10, None, (b"not", 10), None, None),
+    b"!": (10, None, (b"not", 10), None, None),
+    b"and": (5, None, None, (b"and", 5), None),
+    b"&": (5, None, None, (b"and", 5), None),
+    b"%": (5, None, None, (b"only", 5), b"onlypost"),
+    b"or": (4, None, None, (b"or", 4), None),
+    b"|": (4, None, None, (b"or", 4), None),
+    b"+": (4, None, None, (b"or", 4), None),
+    b"=": (3, None, None, (b"keyvalue", 3), None),
+    b",": (2, None, None, (b"list", 2), None),
+    b")": (0, None, None, None, None),
+    b"]": (0, None, None, None, None),
+    b"symbol": (0, b"symbol", None, None, None),
+    b"string": (0, b"string", None, None, None),
+    b"end": (0, None, None, None, None),
 }
 
-keywords = {'and', 'or', 'not'}
+keywords = {b'and', b'or', b'not'}
 
 symbols = {}
 
-_quoteletters = {'"', "'"}
-_simpleopletters = set(pycompat.iterbytestr("()[]#:=,-|&+!~^%"))
+_quoteletters = {b'"', b"'"}
+_simpleopletters = set(pycompat.iterbytestr(b"()[]#:=,-|&+!~^%"))
 
 # default set of valid characters for the initial letter of symbols
 _syminitletters = set(
     pycompat.iterbytestr(
         pycompat.sysbytes(string.ascii_letters)
         + pycompat.sysbytes(string.digits)
-        + '._@'
+        + b'._@'
     )
 ) | set(map(pycompat.bytechr, pycompat.xrange(128, 256)))
 
 # default set of valid characters for non-initial letters of symbols
-_symletters = _syminitletters | set(pycompat.iterbytestr('-/'))
+_symletters = _syminitletters | set(pycompat.iterbytestr(b'-/'))
 
 
 def tokenize(program, lookup=None, syminitletters=None, symletters=None):
@@ -104,7 +104,7 @@
     '''
     if not isinstance(program, bytes):
         raise error.ProgrammingError(
-            'revset statement must be bytes, got %r' % program
+            b'revset statement must be bytes, got %r' % program
         )
     program = pycompat.bytestr(program)
     if syminitletters is None:
@@ -115,16 +115,16 @@
     if program and lookup:
         # attempt to parse old-style ranges first to deal with
         # things like old-tag which contain query metacharacters
-        parts = program.split(':', 1)
+        parts = program.split(b':', 1)
         if all(lookup(sym) for sym in parts if sym):
             if parts[0]:
-                yield ('symbol', parts[0], 0)
+                yield (b'symbol', parts[0], 0)
             if len(parts) > 1:
                 s = len(parts[0])
-                yield (':', None, s)
+                yield (b':', None, s)
                 if parts[1]:
-                    yield ('symbol', parts[1], s + 1)
-            yield ('end', None, len(program))
+                    yield (b'symbol', parts[1], s + 1)
+            yield (b'end', None, len(program))
             return
 
     pos, l = 0, len(program)
@@ -133,28 +133,28 @@
         if c.isspace():  # skip inter-token whitespace
             pass
         elif (
-            c == ':' and program[pos : pos + 2] == '::'
+            c == b':' and program[pos : pos + 2] == b'::'
         ):  # look ahead carefully
-            yield ('::', None, pos)
+            yield (b'::', None, pos)
             pos += 1  # skip ahead
         elif (
-            c == '.' and program[pos : pos + 2] == '..'
+            c == b'.' and program[pos : pos + 2] == b'..'
         ):  # look ahead carefully
-            yield ('..', None, pos)
+            yield (b'..', None, pos)
             pos += 1  # skip ahead
         elif (
-            c == '#' and program[pos : pos + 2] == '##'
+            c == b'#' and program[pos : pos + 2] == b'##'
         ):  # look ahead carefully
-            yield ('##', None, pos)
+            yield (b'##', None, pos)
             pos += 1  # skip ahead
         elif c in _simpleopletters:  # handle simple operators
             yield (c, None, pos)
         elif (
             c in _quoteletters
-            or c == 'r'
-            and program[pos : pos + 2] in ("r'", 'r"')
+            or c == b'r'
+            and program[pos : pos + 2] in (b"r'", b'r"')
         ):  # handle quoted strings
-            if c == 'r':
+            if c == b'r':
                 pos += 1
                 c = program[pos]
                 decode = lambda x: x
@@ -164,15 +164,15 @@
             s = pos
             while pos < l:  # find closing quote
                 d = program[pos]
-                if d == '\\':  # skip over escaped characters
+                if d == b'\\':  # skip over escaped characters
                     pos += 2
                     continue
                 if d == c:
-                    yield ('string', decode(program[s:pos]), s)
+                    yield (b'string', decode(program[s:pos]), s)
                     break
                 pos += 1
             else:
-                raise error.ParseError(_("unterminated string"), s)
+                raise error.ParseError(_(b"unterminated string"), s)
         # gather up a symbol/keyword
         elif c in syminitletters:
             s = pos
@@ -181,38 +181,40 @@
                 d = program[pos]
                 if d not in symletters:
                     break
-                if d == '.' and program[pos - 1] == '.':  # special case for ..
+                if (
+                    d == b'.' and program[pos - 1] == b'.'
+                ):  # special case for ..
                     pos -= 1
                     break
                 pos += 1
             sym = program[s:pos]
             if sym in keywords:  # operator keywords
                 yield (sym, None, s)
-            elif '-' in sym:
+            elif b'-' in sym:
                 # some jerk gave us foo-bar-baz, try to check if it's a symbol
                 if lookup and lookup(sym):
                     # looks like a real symbol
-                    yield ('symbol', sym, s)
+                    yield (b'symbol', sym, s)
                 else:
                     # looks like an expression
-                    parts = sym.split('-')
+                    parts = sym.split(b'-')
                     for p in parts[:-1]:
                         if p:  # possible consecutive -
-                            yield ('symbol', p, s)
+                            yield (b'symbol', p, s)
                         s += len(p)
-                        yield ('-', None, s)
+                        yield (b'-', None, s)
                         s += 1
                     if parts[-1]:  # possible trailing -
-                        yield ('symbol', parts[-1], s)
+                        yield (b'symbol', parts[-1], s)
             else:
-                yield ('symbol', sym, s)
+                yield (b'symbol', sym, s)
             pos -= 1
         else:
             raise error.ParseError(
-                _("syntax error in revset '%s'") % program, pos
+                _(b"syntax error in revset '%s'") % program, pos
             )
         pos += 1
-    yield ('end', None, pos)
+    yield (b'end', None, pos)
 
 
 # helpers
@@ -221,13 +223,13 @@
 
 
 def getsymbol(x):
-    if x and x[0] == 'symbol':
+    if x and x[0] == b'symbol':
         return x[1]
-    raise error.ParseError(_('not a symbol'))
+    raise error.ParseError(_(b'not a symbol'))
 
 
 def getstring(x, err):
-    if x and (x[0] == 'string' or x[0] == 'symbol'):
+    if x and (x[0] == b'string' or x[0] == b'symbol'):
         return x[1]
     raise error.ParseError(err)
 
@@ -251,7 +253,7 @@
 def getlist(x):
     if not x:
         return []
-    if x[0] == 'list':
+    if x[0] == b'list':
         return list(x[1:])
     return [x]
 
@@ -260,13 +262,13 @@
     if not x:
         raise error.ParseError(err)
     op = x[0]
-    if op == 'range':
+    if op == b'range':
         return x[1], x[2]
-    elif op == 'rangepre':
+    elif op == b'rangepre':
         return None, x[1]
-    elif op == 'rangepost':
+    elif op == b'rangepost':
         return x[1], None
-    elif op == 'rangeall':
+    elif op == b'rangeall':
         return None, None
     raise error.ParseError(err)
 
@@ -277,7 +279,7 @@
     If any of the sides omitted, and if no default provided, ParseError will
     be raised.
     """
-    if x and (x[0] == 'string' or x[0] == 'symbol'):
+    if x and (x[0] == b'string' or x[0] == b'symbol'):
         n = getinteger(x, err1)
         return n, n
     a, b = getrange(x, err1)
@@ -296,8 +298,8 @@
         getlist(x),
         funcname,
         parser.splitargspec(keys),
-        keyvaluenode='keyvalue',
-        keynode='symbol',
+        keyvaluenode=b'keyvalue',
+        keynode=b'symbol',
     )
 
 
@@ -320,7 +322,7 @@
     ('and', ('func', ('symbol', 'f'), ('string', '1')), ('symbol', '2'))
     """
     template = _cachedtree(tmplspec)
-    return parser.buildtree(template, ('symbol', '_'), *repls)
+    return parser.buildtree(template, (b'symbol', b'_'), *repls)
 
 
 def _match(patspec, tree):
@@ -333,12 +335,12 @@
     """
     pattern = _cachedtree(patspec)
     return parser.matchtree(
-        pattern, tree, ('symbol', '_'), {'keyvalue', 'list'}
+        pattern, tree, (b'symbol', b'_'), {b'keyvalue', b'list'}
     )
 
 
 def _matchonly(revs, bases):
-    return _match('ancestors(_) and not ancestors(_)', ('and', revs, bases))
+    return _match(b'ancestors(_) and not ancestors(_)', (b'and', revs, bases))
 
 
 def _fixops(x):
@@ -348,25 +350,25 @@
         return x
 
     op = x[0]
-    if op == 'parent':
+    if op == b'parent':
         # x^:y means (x^) : y, not x ^ (:y)
         # x^:  means (x^) :,   not x ^ (:)
-        post = ('parentpost', x[1])
-        if x[2][0] == 'dagrangepre':
-            return _fixops(('dagrange', post, x[2][1]))
-        elif x[2][0] == 'dagrangeall':
-            return _fixops(('dagrangepost', post))
-        elif x[2][0] == 'rangepre':
-            return _fixops(('range', post, x[2][1]))
-        elif x[2][0] == 'rangeall':
-            return _fixops(('rangepost', post))
-    elif op == 'or':
+        post = (b'parentpost', x[1])
+        if x[2][0] == b'dagrangepre':
+            return _fixops((b'dagrange', post, x[2][1]))
+        elif x[2][0] == b'dagrangeall':
+            return _fixops((b'dagrangepost', post))
+        elif x[2][0] == b'rangepre':
+            return _fixops((b'range', post, x[2][1]))
+        elif x[2][0] == b'rangeall':
+            return _fixops((b'rangepost', post))
+    elif op == b'or':
         # make number of arguments deterministic:
         # x + y + z -> (or x y z) -> (or (list x y z))
-        return (op, _fixops(('list',) + x[1:]))
-    elif op == 'subscript' and x[1][0] == 'relation':
+        return (op, _fixops((b'list',) + x[1:]))
+    elif op == b'subscript' and x[1][0] == b'relation':
         # x#y[z] ternary
-        return _fixops(('relsubscript', x[1][1], x[1][2], x[2]))
+        return _fixops((b'relsubscript', x[1][1], x[1][2], x[2]))
 
     return (op,) + tuple(_fixops(y) for y in x[1:])
 
@@ -376,53 +378,53 @@
         return x
 
     op = x[0]
-    if op == 'minus':
-        return _analyze(_build('_ and not _', *x[1:]))
-    elif op == 'only':
-        return _analyze(_build('only(_, _)', *x[1:]))
-    elif op == 'onlypost':
-        return _analyze(_build('only(_)', x[1]))
-    elif op == 'dagrangeall':
-        raise error.ParseError(_("can't use '::' in this context"))
-    elif op == 'dagrangepre':
-        return _analyze(_build('ancestors(_)', x[1]))
-    elif op == 'dagrangepost':
-        return _analyze(_build('descendants(_)', x[1]))
-    elif op == 'negate':
-        s = getstring(x[1], _("can't negate that"))
-        return _analyze(('string', '-' + s))
-    elif op in ('string', 'symbol', 'smartset'):
+    if op == b'minus':
+        return _analyze(_build(b'_ and not _', *x[1:]))
+    elif op == b'only':
+        return _analyze(_build(b'only(_, _)', *x[1:]))
+    elif op == b'onlypost':
+        return _analyze(_build(b'only(_)', x[1]))
+    elif op == b'dagrangeall':
+        raise error.ParseError(_(b"can't use '::' in this context"))
+    elif op == b'dagrangepre':
+        return _analyze(_build(b'ancestors(_)', x[1]))
+    elif op == b'dagrangepost':
+        return _analyze(_build(b'descendants(_)', x[1]))
+    elif op == b'negate':
+        s = getstring(x[1], _(b"can't negate that"))
+        return _analyze((b'string', b'-' + s))
+    elif op in (b'string', b'symbol', b'smartset'):
         return x
-    elif op == 'rangeall':
+    elif op == b'rangeall':
         return (op, None)
-    elif op in {'or', 'not', 'rangepre', 'rangepost', 'parentpost'}:
+    elif op in {b'or', b'not', b'rangepre', b'rangepost', b'parentpost'}:
         return (op, _analyze(x[1]))
-    elif op == 'group':
+    elif op == b'group':
         return _analyze(x[1])
     elif op in {
-        'and',
-        'dagrange',
-        'range',
-        'parent',
-        'ancestor',
-        'relation',
-        'subscript',
+        b'and',
+        b'dagrange',
+        b'range',
+        b'parent',
+        b'ancestor',
+        b'relation',
+        b'subscript',
     }:
         ta = _analyze(x[1])
         tb = _analyze(x[2])
         return (op, ta, tb)
-    elif op == 'relsubscript':
+    elif op == b'relsubscript':
         ta = _analyze(x[1])
         tb = _analyze(x[2])
         tc = _analyze(x[3])
         return (op, ta, tb, tc)
-    elif op == 'list':
+    elif op == b'list':
         return (op,) + tuple(_analyze(y) for y in x[1:])
-    elif op == 'keyvalue':
+    elif op == b'keyvalue':
         return (op, x[1], _analyze(x[2]))
-    elif op == 'func':
+    elif op == b'func':
         return (op, x[1], _analyze(x[2]))
-    raise ValueError('invalid operator %r' % op)
+    raise ValueError(b'invalid operator %r' % op)
 
 
 def analyze(x):
@@ -440,30 +442,30 @@
         return 0, x
 
     op = x[0]
-    if op in ('string', 'symbol', 'smartset'):
+    if op in (b'string', b'symbol', b'smartset'):
         return 0.5, x  # single revisions are small
-    elif op == 'and':
+    elif op == b'and':
         wa, ta = _optimize(x[1])
         wb, tb = _optimize(x[2])
         w = min(wa, wb)
 
         # (draft/secret/_notpublic() & ::x) have a fast path
-        m = _match('_() & ancestors(_)', ('and', ta, tb))
-        if m and getsymbol(m[1]) in {'draft', 'secret', '_notpublic'}:
-            return w, _build('_phaseandancestors(_, _)', m[1], m[2])
+        m = _match(b'_() & ancestors(_)', (b'and', ta, tb))
+        if m and getsymbol(m[1]) in {b'draft', b'secret', b'_notpublic'}:
+            return w, _build(b'_phaseandancestors(_, _)', m[1], m[2])
 
         # (::x and not ::y)/(not ::y and ::x) have a fast path
         m = _matchonly(ta, tb) or _matchonly(tb, ta)
         if m:
-            return w, _build('only(_, _)', *m[1:])
+            return w, _build(b'only(_, _)', *m[1:])
 
-        m = _match('not _', tb)
+        m = _match(b'not _', tb)
         if m:
-            return wa, ('difference', ta, m[1])
+            return wa, (b'difference', ta, m[1])
         if wa > wb:
-            op = 'andsmally'
+            op = b'andsmally'
         return w, (op, ta, tb)
-    elif op == 'or':
+    elif op == b'or':
         # fast path for machine-generated expression, that is likely to have
         # lots of trivial revisions: 'a + b + c()' to '_list(a b) + c()'
         ws, ts, ss = [], [], []
@@ -474,8 +476,8 @@
             if len(ss) == 1:
                 w, t = ss[0]
             else:
-                s = '\0'.join(t[1] for w, t in ss)
-                y = _build('_list(_)', ('string', s))
+                s = b'\0'.join(t[1] for w, t in ss)
+                y = _build(b'_list(_)', (b'string', s))
                 w, t = _optimize(y)
             ws.append(w)
             ts.append(t)
@@ -483,7 +485,7 @@
 
         for y in getlist(x[1]):
             w, t = _optimize(y)
-            if t is not None and (t[0] == 'string' or t[0] == 'symbol'):
+            if t is not None and (t[0] == b'string' or t[0] == b'symbol'):
                 ss.append((w, t))
                 continue
             flushss()
@@ -492,48 +494,48 @@
         flushss()
         if len(ts) == 1:
             return ws[0], ts[0]  # 'or' operation is fully optimized out
-        return max(ws), (op, ('list',) + tuple(ts))
-    elif op == 'not':
+        return max(ws), (op, (b'list',) + tuple(ts))
+    elif op == b'not':
         # Optimize not public() to _notpublic() because we have a fast version
-        if _match('public()', x[1]):
-            o = _optimize(_build('_notpublic()'))
+        if _match(b'public()', x[1]):
+            o = _optimize(_build(b'_notpublic()'))
             return o[0], o[1]
         else:
             o = _optimize(x[1])
             return o[0], (op, o[1])
-    elif op == 'rangeall':
+    elif op == b'rangeall':
         return 1, x
-    elif op in ('rangepre', 'rangepost', 'parentpost'):
+    elif op in (b'rangepre', b'rangepost', b'parentpost'):
         o = _optimize(x[1])
         return o[0], (op, o[1])
-    elif op in ('dagrange', 'range'):
+    elif op in (b'dagrange', b'range'):
         wa, ta = _optimize(x[1])
         wb, tb = _optimize(x[2])
         return wa + wb, (op, ta, tb)
-    elif op in ('parent', 'ancestor', 'relation', 'subscript'):
+    elif op in (b'parent', b'ancestor', b'relation', b'subscript'):
         w, t = _optimize(x[1])
         return w, (op, t, x[2])
-    elif op == 'relsubscript':
+    elif op == b'relsubscript':
         w, t = _optimize(x[1])
         return w, (op, t, x[2], x[3])
-    elif op == 'list':
+    elif op == b'list':
         ws, ts = zip(*(_optimize(y) for y in x[1:]))
         return sum(ws), (op,) + ts
-    elif op == 'keyvalue':
+    elif op == b'keyvalue':
         w, t = _optimize(x[2])
         return w, (op, x[1], t)
-    elif op == 'func':
+    elif op == b'func':
         f = getsymbol(x[1])
         wa, ta = _optimize(x[2])
         w = getattr(symbols.get(f), '_weight', 1)
-        m = _match('commonancestors(_)', ta)
+        m = _match(b'commonancestors(_)', ta)
 
         # Optimize heads(commonancestors(_)) because we have a fast version
-        if f == 'heads' and m:
-            return w + wa, _build('_commonancestorheads(_)', m[1])
+        if f == b'heads' and m:
+            return w + wa, _build(b'_commonancestorheads(_)', m[1])
 
         return w + wa, (op, x[1], ta)
-    raise ValueError('invalid operator %r' % op)
+    raise ValueError(b'invalid operator %r' % op)
 
 
 def optimize(tree):
@@ -547,7 +549,7 @@
 
 # the set of valid characters for the initial letter of symbols in
 # alias declarations and definitions
-_aliassyminitletters = _syminitletters | {'$'}
+_aliassyminitletters = _syminitletters | {b'$'}
 
 
 def _parsewith(spec, lookup=None, syminitletters=None):
@@ -564,21 +566,21 @@
       ...
     ParseError: ('invalid token', 4)
     """
-    if lookup and spec.startswith('revset(') and spec.endswith(')'):
+    if lookup and spec.startswith(b'revset(') and spec.endswith(b')'):
         lookup = None
     p = parser.parser(elements)
     tree, pos = p.parse(
         tokenize(spec, lookup=lookup, syminitletters=syminitletters)
     )
     if pos != len(spec):
-        raise error.ParseError(_('invalid token'), pos)
-    return _fixops(parser.simplifyinfixops(tree, ('list', 'or')))
+        raise error.ParseError(_(b'invalid token'), pos)
+    return _fixops(parser.simplifyinfixops(tree, (b'list', b'or')))
 
 
 class _aliasrules(parser.basealiasrules):
     """Parsing and expansion rule set of revset aliases"""
 
-    _section = _('revset alias')
+    _section = _(b'revset alias')
 
     @staticmethod
     def _parse(spec):
@@ -592,7 +594,7 @@
 
     @staticmethod
     def _trygetfunc(tree):
-        if tree[0] == 'func' and tree[1][0] == 'symbol':
+        if tree[0] == b'func' and tree[1][0] == b'symbol':
             return tree[1][1], getlist(tree[2])
 
 
@@ -604,7 +606,7 @@
     if warn is not None:
         for name, alias in sorted(aliases.iteritems()):
             if alias.error and not alias.warned:
-                warn(_('warning: %s\n') % (alias.error))
+                warn(_(b'warning: %s\n') % (alias.error))
                 alias.warned = True
     return tree
 
@@ -613,24 +615,24 @@
     """Fold elements to be concatenated by `##`
     """
     if not isinstance(tree, tuple) or tree[0] in (
-        'string',
-        'symbol',
-        'smartset',
+        b'string',
+        b'symbol',
+        b'smartset',
     ):
         return tree
-    if tree[0] == '_concat':
+    if tree[0] == b'_concat':
         pending = [tree]
         l = []
         while pending:
             e = pending.pop()
-            if e[0] == '_concat':
+            if e[0] == b'_concat':
                 pending.extend(reversed(e[1:]))
-            elif e[0] in ('string', 'symbol'):
+            elif e[0] in (b'string', b'symbol'):
                 l.append(e[1])
             else:
-                msg = _("\"##\" can't concatenate \"%s\" element") % (e[0])
+                msg = _(b"\"##\" can't concatenate \"%s\" element") % (e[0])
                 raise error.ParseError(msg)
-        return ('string', ''.join(l))
+        return (b'string', b''.join(l))
     else:
         return tuple(foldconcat(t) for t in tree)
 
@@ -642,12 +644,12 @@
         if len(inst.args) > 1:  # has location
             loc = inst.args[1]
             # Remove newlines -- spaces are equivalent whitespace.
-            spec = spec.replace('\n', ' ')
+            spec = spec.replace(b'\n', b' ')
             # We want the caret to point to the place in the template that
             # failed to parse, but in a hint we get a open paren at the
             # start. Therefore, we print "loc + 1" spaces (instead of "loc")
             # to line up the caret with the location of the error.
-            inst.hint = spec + '\n' + ' ' * (loc + 1) + '^ ' + _('here')
+            inst.hint = spec + b'\n' + b' ' * (loc + 1) + b'^ ' + _(b'here')
         raise
 
 
@@ -663,70 +665,70 @@
     >>> _quote(1)
     "'1'"
     """
-    return "'%s'" % stringutil.escapestr(pycompat.bytestr(s))
+    return b"'%s'" % stringutil.escapestr(pycompat.bytestr(s))
 
 
 def _formatargtype(c, arg):
-    if c == 'd':
-        return '_rev(%d)' % int(arg)
-    elif c == 's':
+    if c == b'd':
+        return b'_rev(%d)' % int(arg)
+    elif c == b's':
         return _quote(arg)
-    elif c == 'r':
+    elif c == b'r':
         if not isinstance(arg, bytes):
             raise TypeError
         parse(arg)  # make sure syntax errors are confined
-        return '(%s)' % arg
-    elif c == 'n':
+        return b'(%s)' % arg
+    elif c == b'n':
         return _quote(node.hex(arg))
-    elif c == 'b':
+    elif c == b'b':
         try:
             return _quote(arg.branch())
         except AttributeError:
             raise TypeError
-    raise error.ParseError(_('unexpected revspec format character %s') % c)
+    raise error.ParseError(_(b'unexpected revspec format character %s') % c)
 
 
 def _formatlistexp(s, t):
     l = len(s)
     if l == 0:
-        return "_list('')"
+        return b"_list('')"
     elif l == 1:
         return _formatargtype(t, s[0])
-    elif t == 'd':
+    elif t == b'd':
         return _formatintlist(s)
-    elif t == 's':
-        return "_list(%s)" % _quote("\0".join(s))
-    elif t == 'n':
-        return "_hexlist('%s')" % "\0".join(node.hex(a) for a in s)
-    elif t == 'b':
+    elif t == b's':
+        return b"_list(%s)" % _quote(b"\0".join(s))
+    elif t == b'n':
+        return b"_hexlist('%s')" % b"\0".join(node.hex(a) for a in s)
+    elif t == b'b':
         try:
-            return "_list('%s')" % "\0".join(a.branch() for a in s)
+            return b"_list('%s')" % b"\0".join(a.branch() for a in s)
         except AttributeError:
             raise TypeError
 
     m = l // 2
-    return '(%s or %s)' % (_formatlistexp(s[:m], t), _formatlistexp(s[m:], t))
+    return b'(%s or %s)' % (_formatlistexp(s[:m], t), _formatlistexp(s[m:], t))
 
 
 def _formatintlist(data):
     try:
         l = len(data)
         if l == 0:
-            return "_list('')"
+            return b"_list('')"
         elif l == 1:
-            return _formatargtype('d', data[0])
-        return "_intlist('%s')" % "\0".join('%d' % int(a) for a in data)
+            return _formatargtype(b'd', data[0])
+        return b"_intlist('%s')" % b"\0".join(b'%d' % int(a) for a in data)
     except (TypeError, ValueError):
-        raise error.ParseError(_('invalid argument for revspec'))
+        raise error.ParseError(_(b'invalid argument for revspec'))
 
 
 def _formatparamexp(args, t):
-    return ', '.join(_formatargtype(t, a) for a in args)
+    return b', '.join(_formatargtype(t, a) for a in args)
 
 
 _formatlistfuncs = {
-    'l': _formatlistexp,
-    'p': _formatparamexp,
+    b'l': _formatlistexp,
+    b'p': _formatparamexp,
 }
 
 
@@ -772,12 +774,12 @@
     for t, arg in parsed:
         if t is None:
             ret.append(arg)
-        elif t == 'baseset':
+        elif t == b'baseset':
             if isinstance(arg, set):
                 arg = sorted(arg)
             ret.append(_formatintlist(list(arg)))
         else:
-            raise error.ProgrammingError("unknown revspec item type: %r" % t)
+            raise error.ProgrammingError(b"unknown revspec item type: %r" % t)
     return b''.join(ret)
 
 
@@ -789,15 +791,15 @@
     for t, arg in parsed:
         if t is None:
             ret.append(arg)
-        elif t == 'baseset':
-            newtree = ('smartset', smartset.baseset(arg))
+        elif t == b'baseset':
+            newtree = (b'smartset', smartset.baseset(arg))
             inputs.append(newtree)
-            ret.append("$")
+            ret.append(b"$")
         else:
-            raise error.ProgrammingError("unknown revspec item type: %r" % t)
+            raise error.ProgrammingError(b"unknown revspec item type: %r" % t)
     expr = b''.join(ret)
     tree = _parsewith(expr, syminitletters=_aliassyminitletters)
-    tree = parser.buildtree(tree, ('symbol', '$'), *inputs)
+    tree = parser.buildtree(tree, (b'symbol', b'$'), *inputs)
     tree = foldconcat(tree)
     tree = analyze(tree)
     tree = optimize(tree)
@@ -818,7 +820,7 @@
     ret = []
     pos = 0
     while pos < len(expr):
-        q = expr.find('%', pos)
+        q = expr.find(b'%', pos)
         if q < 0:
             ret.append((None, expr[pos:]))
             break
@@ -827,8 +829,8 @@
         try:
             d = expr[pos]
         except IndexError:
-            raise error.ParseError(_('incomplete revspec format character'))
-        if d == '%':
+            raise error.ParseError(_(b'incomplete revspec format character'))
+        if d == b'%':
             ret.append((None, d))
             pos += 1
             continue
@@ -836,45 +838,47 @@
         try:
             arg = next(argiter)
         except StopIteration:
-            raise error.ParseError(_('missing argument for revspec'))
+            raise error.ParseError(_(b'missing argument for revspec'))
         f = _formatlistfuncs.get(d)
         if f:
             # a list of some type, might be expensive, do not replace
             pos += 1
-            islist = d == 'l'
+            islist = d == b'l'
             try:
                 d = expr[pos]
             except IndexError:
-                raise error.ParseError(_('incomplete revspec format character'))
-            if islist and d == 'd' and arg:
+                raise error.ParseError(
+                    _(b'incomplete revspec format character')
+                )
+            if islist and d == b'd' and arg:
                 # we don't create a baseset yet, because it come with an
                 # extra cost. If we are going to serialize it we better
                 # skip it.
-                ret.append(('baseset', arg))
+                ret.append((b'baseset', arg))
                 pos += 1
                 continue
             try:
                 ret.append((None, f(list(arg), d)))
             except (TypeError, ValueError):
-                raise error.ParseError(_('invalid argument for revspec'))
+                raise error.ParseError(_(b'invalid argument for revspec'))
         else:
             # a single entry, not expensive, replace
             try:
                 ret.append((None, _formatargtype(d, arg)))
             except (TypeError, ValueError):
-                raise error.ParseError(_('invalid argument for revspec'))
+                raise error.ParseError(_(b'invalid argument for revspec'))
         pos += 1
 
     try:
         next(argiter)
-        raise error.ParseError(_('too many revspec arguments specified'))
+        raise error.ParseError(_(b'too many revspec arguments specified'))
     except StopIteration:
         pass
     return ret
 
 
 def prettyformat(tree):
-    return parser.prettyformat(tree, ('string', 'symbol'))
+    return parser.prettyformat(tree, (b'string', b'symbol'))
 
 
 def depth(tree):
@@ -885,18 +889,18 @@
 
 
 def funcsused(tree):
-    if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
+    if not isinstance(tree, tuple) or tree[0] in (b'string', b'symbol'):
         return set()
     else:
         funcs = set()
         for s in tree[1:]:
             funcs |= funcsused(s)
-        if tree[0] == 'func':
+        if tree[0] == b'func':
             funcs.add(tree[1][1])
         return funcs
 
 
-_hashre = util.re.compile('[0-9a-fA-F]{1,40}$')
+_hashre = util.re.compile(b'[0-9a-fA-F]{1,40}$')
 
 
 def _ishashlikesymbol(symbol):
@@ -919,7 +923,7 @@
     if not tree:
         return []
 
-    if tree[0] == "symbol":
+    if tree[0] == b"symbol":
         if _ishashlikesymbol(tree[1]):
             return [tree[1]]
     elif len(tree) >= 3: