Patchwork [evolve-ext] py3: broad pass for python3 compatibility

login
register
mail settings
Submitter Ludovic Chabant
Date May 24, 2019, 3:57 p.m.
Message ID <3af350fa12d4dbf69d5c.1558713473@devahi>
Download mbox | patch
Permalink /patch/40230/
State Superseded
Headers show

Comments

Ludovic Chabant - May 24, 2019, 3:57 p.m.
# HG changeset patch
# User Ludovic Chabant <ludovic@chabant.com>
# Date 1558677189 0
#      Fri May 24 05:53:09 2019 +0000
# Node ID 3af350fa12d4dbf69d5cbbaf5ca679067472f9ee
# Parent  0b231ea2124baf74fee5e325922a57fb0d89bbe3
# EXP-Topic py3
py3: broad pass for python3 compatibility

- ran mercurial's bytify-strings script
- excluded some places where we use strings to pass to setattr()
Pulkit Goyal - May 24, 2019, 6:24 p.m.
On Fri, May 24, 2019 at 7:02 PM Ludovic Chabant <ludovic@chabant.com> wrote:

> # HG changeset patch
> # User Ludovic Chabant <ludovic@chabant.com>
> # Date 1558677189 0
> #      Fri May 24 05:53:09 2019 +0000
> # Node ID 3af350fa12d4dbf69d5cbbaf5ca679067472f9ee
> # Parent  0b231ea2124baf74fee5e325922a57fb0d89bbe3
> # EXP-Topic py3
> py3: broad pass for python3 compatibility
>

I didn't review the patch but thanks a lot for working on this.

>
>
>      with patchcontext as metadata:
>          # store the metadata from the patch to variables
> -        parents = (metadata.get('p1'), metadata.get('p2'))
> -        date = metadata.get('date') or old.date()
> -        branch = metadata.get('branch') or old.branch()
> -        user = metadata.get('user') or old.user()
> +        parents = (metadata.get(b'p1'), metadata.get(b'p2'))
> +        date = metadata.get(b'date') or old.date()
> +        branch = metadata.get(b'branch') or old.branch()
> +        user = metadata.get(b'user') or old.user()
>          # XXX: we must extract extras from the patchfile too
>          extra = old.extra()
> -        message = metadata.get('message') or old.description()
> +        message = metadata.get(b'message') or old.description()
>          store = patch.filestore()
>          fp.seek(0)
>          try:
>              files = set()
>              # beware: next line may raise a PatchError to be handled by
> the caller
>              # of this function
> -            patch.patchrepo(ui, repo, pold, store, fp, 1, '',
> +            patch.patchrepo(ui, repo, pold, store, fp, 1, b'',
>                              files=files, eolmode=None)
>
>              memctx = context.memctx(repo, parents, message, files=files,
> @@ -280,23 +280,23 @@
>      else:
>          prev = node.nullid
>
> -    fp.write("# HG changeset patch\n")
> -    fp.write("# User %s\n" % ctx.user())
> -    fp.write("# Date %d %d\n" % ctx.date())
> -    fp.write("#      %s\n" % datestr(ctx.date()))
> -    if branch and branch != 'default':
> -        fp.write("# Branch %s\n" % branch)
> -    fp.write("# Node ID %s\n" % node.hex(nodeval))
> -    fp.write("# Parent  %s\n" % node.hex(prev))
> +    fp.write(b"# HG changeset patch\n")
> +    fp.write(b"# User %s\n" % ctx.user())
> +    fp.write(b"# Date %d %d\n" % ctx.date())
> +    fp.write(b"#      %s\n" % datestr(ctx.date()))
> +    if branch and branch != b'default':
> +        fp.write(b"# Branch %s\n" % branch)
> +    fp.write(b"# Node ID %s\n" % node.hex(nodeval))
> +    fp.write(b"# Parent  %s\n" % node.hex(prev))
>      if len(parents) > 1:
> -        fp.write("# Parent  %s\n" % node.hex(parents[1]))
> +        fp.write(b"# Parent  %s\n" % node.hex(parents[1]))
>
>      for headerid in cmdutil.extraexport:
>          header = cmdutil.extraexportmap[headerid](1, ctx)
>          if header is not None:
> -            fp.write('# %s\n' % header)
> +            fp.write(b'# %s\n' % header)
>      fp.write(ctx.description().rstrip())
> -    fp.write("\n\n")
> +    fp.write(b"\n\n")
>
>  def _touchedbetween(repo, source, dest, match=None):
>      touched = set()
> @@ -329,7 +329,7 @@
>
>      # Filter copies
>      copied = copies.pathcopies(target, ctx)
> -    copied = dict((dst, src) for dst, src in copied.iteritems()
> +    copied = dict((dst, src) for dst, src in copied.items()
>                    if dst in files)
>
>      def filectxfn(repo, memctx, path, contentctx=ctx,
> redirect=newcontent):
> @@ -365,7 +365,7 @@
>      oldctx to a copy of oldctx not containing changed files matched by
>      match.
>      """
> -    ctx = repo['.']
> +    ctx = repo[b'.']
>      ds = repo.dirstate
>      copies = dict(ds.copies())
>      if interactive:
> @@ -384,7 +384,7 @@
>              # Also any modifications to a removed file will result the
> status as
>              # added, so we have only two cases. So in either of the
> cases, the
>              # resulting status can be modified or clean.
> -            if ds[f] == 'r':
> +            if ds[f] == b'r':
>                  # But the file is removed in the working directory,
> leaving that
>                  # as removed
>                  continue
> @@ -398,7 +398,7 @@
>              # does not adds it back. If it's adds it back, we do a
> normallookup.
>              # The file can't be removed in working directory, because it
> was
>              # removed in oldctx
> -            if ds[f] == 'a':
> +            if ds[f] == b'a':
>                  ds.normallookup(f)
>                  continue
>              ds.remove(f)
> @@ -410,7 +410,7 @@
>              # would have resulted in modified status, not removed.
>              # So a file added in a commit, and uncommitting that addition
> must
>              # result in file being stated as unknown.
> -            if ds[f] == 'r':
> +            if ds[f] == b'r':
>                  # The working directory say it's removed, so lets make
> the file
>                  # unknown
>                  ds.drop(f)
> @@ -419,23 +419,23 @@
>      else:
>          m, a, r = repo.status(oldctx.p1(), oldctx, match=match)[:3]
>          for f in m:
> -            if ds[f] == 'r':
> +            if ds[f] == b'r':
>                  # modified + removed -> removed
>                  continue
>              ds.normallookup(f)
>
>          for f in a:
> -            if ds[f] == 'r':
> +            if ds[f] == b'r':
>                  # added + removed -> unknown
>                  ds.drop(f)
> -            elif ds[f] != 'a':
> +            elif ds[f] != b'a':
>                  ds.add(f)
>
>          for f in r:
> -            if ds[f] == 'a':
> +            if ds[f] == b'a':
>                  # removed + added -> normal
>                  ds.normallookup(f)
> -            elif ds[f] != 'r':
> +            elif ds[f] != b'r':
>                  ds.remove(f)
>
>      # Merge old parent and old working dir copies
> @@ -450,22 +450,22 @@
>              oldcopies[f] = src[0]
>      oldcopies.update(copies)
>      copies = dict((dst, oldcopies.get(src, src))
> -                  for dst, src in oldcopies.iteritems())
> +                  for dst, src in oldcopies.items())
>      # Adjust the dirstate copies
> -    for dst, src in copies.iteritems():
> -        if (src not in ctx or dst in ctx or ds[dst] != 'a'):
> +    for dst, src in copies.items():
> +        if (src not in ctx or dst in ctx or ds[dst] != b'a'):
>              src = None
>          ds.copy(src, dst)
>
>  @eh.command(
> -    'uncommit',
> -    [('a', 'all', None, _('uncommit all changes when no arguments
> given')),
> -     ('i', 'interactive', False, _('interactive mode to uncommit
> (EXPERIMENTAL)')),
> -     ('r', 'rev', '', _('revert commit content to REV instead'),
> _('REV')),
> -     ('', 'revert', False, _('discard working directory changes after
> uncommit')),
> -     ('n', 'note', '', _('store a note on uncommit'), _('TEXT')),
> +    b'uncommit',
> +    [(b'a', b'all', None, _(b'uncommit all changes when no arguments
> given')),
> +     (b'i', b'interactive', False, _(b'interactive mode to uncommit
> (EXPERIMENTAL)')),
> +     (b'r', b'rev', b'', _(b'revert commit content to REV instead'),
> _(b'REV')),
> +     (b'', b'revert', False, _(b'discard working directory changes after
> uncommit')),
> +     (b'n', b'note', b'', _(b'store a note on uncommit'), _(b'TEXT')),
>       ] + commands.walkopts + commitopts + commitopts2 + commitopts3,
> -    _('[OPTION]... [NAME]'))
> +    _(b'[OPTION]... [NAME]'))
>  def uncommit(ui, repo, *pats, **opts):
>      """move changes from parent revision to working directory
>
> @@ -491,34 +491,34 @@
>
>      _checknotesize(ui, opts)
>      _resolveoptions(ui, opts) # process commitopts3
> -    interactive = opts.get('interactive')
> +    interactive = opts.get(b'interactive')
>      wlock = lock = tr = None
>      try:
>          wlock = repo.wlock()
>          lock = repo.lock()
>          wctx = repo[None]
>          if len(wctx.parents()) <= 0:
> -            raise error.Abort(_("cannot uncommit null changeset"))
> +            raise error.Abort(_(b"cannot uncommit null changeset"))
>          if len(wctx.parents()) > 1:
> -            raise error.Abort(_("cannot uncommit while merging"))
> -        old = repo['.']
> -        rewriteutil.precheck(repo, [repo['.'].rev()], action='uncommit')
> +            raise error.Abort(_(b"cannot uncommit while merging"))
> +        old = repo[b'.']
> +        rewriteutil.precheck(repo, [repo[b'.'].rev()], action=b'uncommit')
>          if len(old.parents()) > 1:
> -            raise error.Abort(_("cannot uncommit merge changeset"))
> +            raise error.Abort(_(b"cannot uncommit merge changeset"))
>          oldphase = old.phase()
>
>          rev = None
> -        if opts.get('rev'):
> -            rev = scmutil.revsingle(repo, opts.get('rev'))
> +        if opts.get(b'rev'):
> +            rev = scmutil.revsingle(repo, opts.get(b'rev'))
>              ctx = repo[None]
>              if ctx.p1() == rev or ctx.p2() == rev:
> -                raise error.Abort(_("cannot uncommit to parent
> changeset"))
> +                raise error.Abort(_(b"cannot uncommit to parent
> changeset"))
>
>          onahead = old.rev() in repo.changelog.headrevs()
>          disallowunstable = not obsolete.isenabled(repo,
>
>  obsolete.allowunstableopt)
>          if disallowunstable and not onahead:
> -            raise error.Abort(_("cannot uncommit in the middle of a
> stack"))
> +            raise error.Abort(_(b"cannot uncommit in the middle of a
> stack"))
>
>          match = scmutil.match(old, pats, opts)
>
> @@ -553,42 +553,42 @@
>                                    % uipathfn(f), hint=hint)
>
>          # Recommit the filtered changeset
> -        tr = repo.transaction('uncommit')
> +        tr = repo.transaction(b'uncommit')
>          if interactive:
> -            opts['all'] = True
> +            opts[b'all'] = True
>              newid = _interactiveuncommit(ui, repo, old, match)
>          else:
>              newid = None
> -            includeorexclude = opts.get('include') or opts.get('exclude')
> -            if (pats or includeorexclude or opts.get('all')):
> -                if not (opts['message'] or opts['logfile']):
> -                    opts['message'] = old.description()
> +            includeorexclude = opts.get(b'include') or
> opts.get(b'exclude')
> +            if (pats or includeorexclude or opts.get(b'all')):
> +                if not (opts[b'message'] or opts[b'logfile']):
> +                    opts[b'message'] = old.description()
>                  message = cmdutil.logmessage(ui, opts)
>                  newid = _commitfiltered(repo, old, match, target=rev,
> -                                        message=message,
> user=opts.get('user'),
> -                                        date=opts.get('date'))
> +                                        message=message,
> user=opts.get(b'user'),
> +                                        date=opts.get(b'date'))
>              if newid is None:
> -                raise error.Abort(_('nothing to uncommit'),
> -                                  hint=_("use --all to uncommit all
> files"))
> +                raise error.Abort(_(b'nothing to uncommit'),
> +                                  hint=_(b"use --all to uncommit all
> files"))
>
>          # metadata to be stored in obsmarker
>          metadata = {}
> -        if opts.get('note'):
> -            metadata['note'] = opts['note']
> +        if opts.get(b'note'):
> +            metadata[b'note'] = opts[b'note']
>
>          replacements = {old.node(): [newid]}
> -        scmutil.cleanupnodes(repo, replacements, operation="uncommit",
> +        scmutil.cleanupnodes(repo, replacements, operation=b"uncommit",
>                               metadata=metadata)
>          phases.retractboundary(repo, tr, oldphase, [newid])
> -        if opts.get('revert'):
> +        if opts.get(b'revert'):
>              hg.updaterepo(repo, newid, True)
>          else:
>              with repo.dirstate.parentchange():
>                  repo.dirstate.setparents(newid, node.nullid)
>                  _uncommitdirstate(repo, old, match, interactive)
>          if not repo[newid].files():
> -            ui.warn(_("new changeset is empty\n"))
> -            ui.status(_("(use 'hg prune .' to remove it)\n"))
> +            ui.warn(_(b"new changeset is empty\n"))
> +            ui.status(_(b"(use 'hg prune .' to remove it)\n"))
>          tr.close()
>      finally:
>          lockmod.release(tr, lock, wlock)
> @@ -615,7 +615,7 @@
>      fp.seek(0)
>      newnode = _patchtocommit(ui, repo, old, fp)
>      # creating obs marker temp -> ()
> -    obsolete.createmarkers(repo, [(repo[tempnode], ())],
> operation="uncommit")
> +    obsolete.createmarkers(repo, [(repo[tempnode], ())],
> operation=b"uncommit")
>      return newnode
>
>  def _createtempcommit(ui, repo, old, match):
> @@ -637,20 +637,20 @@
>      # to add uncommit as an operation taking care of BC.
>      try:
>          chunks, opts = cmdutil.recordfilter(repo.ui, originalchunks,
> match,
> -                                            operation='discard')
> +                                            operation=b'discard')
>      except TypeError:
>          # hg <= 4.9 (db72f9f6580e)
>          chunks, opts = cmdutil.recordfilter(repo.ui, originalchunks,
> -                                            operation='discard')
> +                                            operation=b'discard')
>      if not chunks:
> -        raise error.Abort(_("nothing selected to uncommit"))
> +        raise error.Abort(_(b"nothing selected to uncommit"))
>      fp = stringio()
>      for c in chunks:
>          c.write(fp)
>
>      fp.seek(0)
>      oldnode = node.hex(old.node())[:12]
> -    message = 'temporary commit for uncommiting %s' % oldnode
> +    message = b'temporary commit for uncommiting %s' % oldnode
>      tempnode = _patchtocommit(ui, repo, old, fp, message, oldnode)
>      return tempnode
>
> @@ -667,14 +667,14 @@
>      user = old.user()
>      extra = old.extra()
>      if extras:
> -        extra['uncommit_source'] = extras
> +        extra[b'uncommit_source'] = extras
>      if not message:
>          message = old.description()
>      store = patch.filestore()
>      try:
>          files = set()
>          try:
> -            patch.patchrepo(ui, repo, pold, store, fp, 1, '',
> +            patch.patchrepo(ui, repo, pold, store, fp, 1, b'',
>                              files=files, eolmode=None)
>          except patch.PatchError as err:
>              raise error.Abort(str(err))
> @@ -694,13 +694,13 @@
>      return newcm
>
>  @eh.command(
> -    'fold|squash',
> -    [('r', 'rev', [], _("revision to fold"), _('REV')),
> -     ('', 'exact', None, _("only fold specified revisions")),
> -     ('', 'from', None, _("fold revisions linearly to working copy
> parent")),
> -     ('n', 'note', '', _('store a note on fold'), _('TEXT')),
> -    ] + commitopts + commitopts2 + commitopts3,
> -    _('hg fold [OPTION]... [-r] REV'),
> +    b'fold|squash',
> +    [(b'r', b'rev', [], _(b"revision to fold"), _(b'REV')),
> +     (b'', b'exact', None, _(b"only fold specified revisions")),
> +     (b'', b'from', None, _(b"fold revisions linearly to working copy
> parent")),
> +     (b'n', b'note', b'', _(b'store a note on fold'), _(b'TEXT')),
> +     ] + commitopts + commitopts2 + commitopts3,
> +    _(b'hg fold [OPTION]... [-r] REV'),
>      helpbasic=True)
>  def fold(ui, repo, *revs, **opts):
>      """fold multiple revisions into a single one
> @@ -742,35 +742,35 @@
>      _checknotesize(ui, opts)
>      _resolveoptions(ui, opts)
>      revs = list(revs)
> -    revs.extend(opts['rev'])
> +    revs.extend(opts[b'rev'])
>      if not revs:
> -        raise error.Abort(_('no revisions specified'))
> +        raise error.Abort(_(b'no revisions specified'))
>
>      revs = scmutil.revrange(repo, revs)
>
> -    if opts['from'] and opts['exact']:
> -        raise error.Abort(_('cannot use both --from and --exact'))
> -    elif opts['from']:
> +    if opts[b'from'] and opts[b'exact']:
> +        raise error.Abort(_(b'cannot use both --from and --exact'))
> +    elif opts[b'from']:
>          # Try to extend given revision starting from the working directory
> -        extrevs = repo.revs('(%ld::.) or (.::%ld)', revs, revs)
> +        extrevs = repo.revs(b'(%ld::.) or (.::%ld)', revs, revs)
>          discardedrevs = [r for r in revs if r not in extrevs]
>          if discardedrevs:
> -            msg = _("cannot fold non-linear revisions")
> -            hint = _("given revisions are unrelated to parent of working"
> -                     " directory")
> +            msg = _(b"cannot fold non-linear revisions")
> +            hint = _(b"given revisions are unrelated to parent of working"
> +                     b" directory")
>              raise error.Abort(msg, hint=hint)
>          revs = extrevs
> -    elif opts['exact']:
> +    elif opts[b'exact']:
>          # Nothing to do; "revs" is already set correctly
>          pass
>      else:
> -        raise error.Abort(_('must specify either --from or --exact'))
> +        raise error.Abort(_(b'must specify either --from or --exact'))
>
>      if not revs:
> -        raise error.Abort(_('specified revisions evaluate to an empty
> set'),
> -                          hint=_('use different revision arguments'))
> +        raise error.Abort(_(b'specified revisions evaluate to an empty
> set'),
> +                          hint=_(b'use different revision arguments'))
>      elif len(revs) == 1:
> -        ui.write_err(_('single revision specified, nothing to fold\n'))
> +        ui.write_err(_(b'single revision specified, nothing to fold\n'))
>          return 1
>
>      # Sort so combined commit message of `hg fold --exact -r . -r .^` is
> @@ -784,24 +784,24 @@
>
>          root, head = rewriteutil.foldcheck(repo, revs)
>
> -        tr = repo.transaction('fold')
> +        tr = repo.transaction(b'fold')
>          try:
>              commitopts = opts.copy()
>              allctx = [repo[r] for r in revs]
>              targetphase = max(c.phase() for c in allctx)
>
> -            if commitopts.get('message') or commitopts.get('logfile'):
> -                commitopts['edit'] = False
> +            if commitopts.get(b'message') or commitopts.get(b'logfile'):
> +                commitopts[b'edit'] = False
>              else:
> -                msgs = ["HG: This is a fold of %d changesets." %
> len(allctx)]
> -                msgs += ["HG: Commit message of changeset %s.\n\n%s\n" %
> +                msgs = [b"HG: This is a fold of %d changesets." %
> len(allctx)]
> +                msgs += [b"HG: Commit message of changeset %s.\n\n%s\n" %
>                           (c.rev(), c.description()) for c in allctx]
> -                commitopts['message'] = "\n".join(msgs)
> -                commitopts['edit'] = True
> +                commitopts[b'message'] = b"\n".join(msgs)
> +                commitopts[b'edit'] = True
>
>              metadata = {}
> -            if opts.get('note'):
> -                metadata['note'] = opts['note']
> +            if opts.get(b'note'):
> +                metadata[b'note'] = opts[b'note']
>
>              newid, unusedvariable = rewriteutil.rewrite(repo, root,
> allctx,
>                                                          head,
> @@ -810,24 +810,24 @@
>
>  commitopts=commitopts)
>              phases.retractboundary(repo, tr, targetphase, [newid])
>              replacements = {ctx.node(): [newid] for ctx in allctx}
> -            scmutil.cleanupnodes(repo, replacements, operation="fold",
> +            scmutil.cleanupnodes(repo, replacements, operation=b"fold",
>                                   metadata=metadata)
>              tr.close()
>          finally:
>              tr.release()
> -        ui.status('%i changesets folded\n' % len(revs))
> -        if repo['.'].rev() in revs:
> +        ui.status(b'%i changesets folded\n' % len(revs))
> +        if repo[b'.'].rev() in revs:
>              hg.update(repo, newid)
>      finally:
>          lockmod.release(lock, wlock)
>
>  @eh.command(
> -    'metaedit',
> -    [('r', 'rev', [], _("revision to edit"), _('REV')),
> -     ('', 'fold', None, _("also fold specified revisions into one")),
> -     ('n', 'note', '', _('store a note on metaedit'), _('TEXT')),
> -    ] + commitopts + commitopts2 + commitopts3,
> -    _('hg metaedit [OPTION]... [-r] [REV]'))
> +    b'metaedit',
> +    [(b'r', b'rev', [], _(b"revision to edit"), _(b'REV')),
> +     (b'', b'fold', None, _(b"also fold specified revisions into one")),
> +     (b'n', b'note', b'', _(b'store a note on metaedit'), _(b'TEXT')),
> +     ] + commitopts + commitopts2 + commitopts3,
> +    _(b'hg metaedit [OPTION]... [-r] [REV]'))
>  def metaedit(ui, repo, *revs, **opts):
>      """edit commit information
>
> @@ -860,11 +860,11 @@
>      _checknotesize(ui, opts)
>      _resolveoptions(ui, opts)
>      revs = list(revs)
> -    revs.extend(opts['rev'])
> +    revs.extend(opts[b'rev'])
>      if not revs:
> -        if opts['fold']:
> -            raise error.Abort(_('revisions must be specified with
> --fold'))
> -        revs = ['.']
> +        if opts[b'fold']:
> +            raise error.Abort(_(b'revisions must be specified with
> --fold'))
> +        revs = [b'.']
>
>      wlock = lock = None
>      try:
> @@ -872,7 +872,7 @@
>          lock = repo.lock()
>
>          revs = scmutil.revrange(repo, revs)
> -        if not opts['fold'] and len(revs) > 1:
> +        if not opts[b'fold'] and len(revs) > 1:
>              # TODO: handle multiple revisions. This is somewhat tricky
> because
>              # if we want to edit a series of commits:
>              #
> @@ -881,45 +881,45 @@
>              # we need to rewrite a first, then directly rewrite b on top
> of the
>              # new a, then rewrite c on top of the new b. So we need to
> handle
>              # revisions in topological order.
> -            raise error.Abort(_('editing multiple revisions without
> --fold is '
> -                                'not currently supported'))
> +            raise error.Abort(_(b'editing multiple revisions without
> --fold is '
> +                                b'not currently supported'))
>
> -        if opts['fold']:
> +        if opts[b'fold']:
>              root, head = rewriteutil.foldcheck(repo, revs)
>          else:
> -            if repo.revs("%ld and public()", revs):
> -                raise error.Abort(_('cannot edit commit information for
> public '
> -                                    'revisions'))
> +            if repo.revs(b"%ld and public()", revs):
> +                raise error.Abort(_(b'cannot edit commit information for
> public '
> +                                    b'revisions'))
>              newunstable = rewriteutil.disallowednewunstable(repo, revs)
>              if newunstable:
> -                msg = _('cannot edit commit information in the middle'
> -                        ' of a stack')
> -                hint = _('%s will become unstable and new unstable
> changes'
> -                         ' are not allowed')
> +                msg = _(b'cannot edit commit information in the middle'
> +                        b' of a stack')
> +                hint = _(b'%s will become unstable and new unstable
> changes'
> +                         b' are not allowed')
>                  hint %= repo[newunstable.first()]
>                  raise error.Abort(msg, hint=hint)
>              root = head = repo[revs.first()]
>
>          wctx = repo[None]
>          p1 = wctx.p1()
> -        tr = repo.transaction('metaedit')
> +        tr = repo.transaction(b'metaedit')
>          newp1 = None
>          try:
>              commitopts = opts.copy()
>              allctx = [repo[r] for r in revs]
>              targetphase = max(c.phase() for c in allctx)
>
> -            if commitopts.get('message') or commitopts.get('logfile'):
> -                commitopts['edit'] = False
> +            if commitopts.get(b'message') or commitopts.get(b'logfile'):
> +                commitopts[b'edit'] = False
>              else:
> -                if opts['fold']:
> -                    msgs = ["HG: This is a fold of %d changesets." %
> len(allctx)]
> -                    msgs += ["HG: Commit message of changeset
> %s.\n\n%s\n" %
> +                if opts[b'fold']:
> +                    msgs = [b"HG: This is a fold of %d changesets." %
> len(allctx)]
> +                    msgs += [b"HG: Commit message of changeset
> %s.\n\n%s\n" %
>                               (c.rev(), c.description()) for c in allctx]
>                  else:
>                      msgs = [head.description()]
> -                commitopts['message'] = "\n".join(msgs)
> -                commitopts['edit'] = True
> +                commitopts[b'message'] = b"\n".join(msgs)
> +                commitopts[b'edit'] = True
>
>              # TODO: if the author and message are the same, don't create
> a new
>              # hash. Right now we create a new hash because the date can be
> @@ -933,60 +933,60 @@
>                      newp1 = newid
>                  # metadata to be stored on obsmarker
>                  metadata = {}
> -                if opts.get('note'):
> -                    metadata['note'] = opts['note']
> +                if opts.get(b'note'):
> +                    metadata[b'note'] = opts[b'note']
>
>                  phases.retractboundary(repo, tr, targetphase, [newid])
>                  obsolete.createmarkers(repo, [(ctx, (repo[newid],))
>                                                for ctx in allctx],
> -                                       metadata=metadata,
> operation="metaedit")
> +                                       metadata=metadata,
> operation=b"metaedit")
>              else:
> -                ui.status(_("nothing changed\n"))
> +                ui.status(_(b"nothing changed\n"))
>              tr.close()
>          finally:
>              tr.release()
>
> -        if opts['fold']:
> -            ui.status('%i changesets folded\n' % len(revs))
> +        if opts[b'fold']:
> +            ui.status(b'%i changesets folded\n' % len(revs))
>          if newp1 is not None:
>              hg.update(repo, newp1)
>      finally:
>          lockmod.release(lock, wlock)
>
>  metadataopts = [
> -    ('d', 'date', '',
> -     _('record the specified date in metadata'), _('DATE')),
> -    ('u', 'user', '',
> -     _('record the specified user in metadata'), _('USER')),
> +    (b'd', b'date', b'',
> +     _(b'record the specified date in metadata'), _(b'DATE')),
> +    (b'u', b'user', b'',
> +     _(b'record the specified user in metadata'), _(b'USER')),
>  ]
>
>  def _getmetadata(**opts):
>      metadata = {}
> -    date = opts.get('date')
> -    user = opts.get('user')
> +    date = opts.get(b'date')
> +    user = opts.get(b'user')
>      if date:
> -        metadata['date'] = '%i %i' % compat.parsedate(date)
> +        metadata[b'date'] = b'%i %i' % compat.parsedate(date)
>      if user:
> -        metadata['user'] = user
> +        metadata[b'user'] = user
>      return metadata
>
>  @eh.command(
> -    'prune|obsolete',
> -    [('n', 'new', [], _("successor changeset (DEPRECATED)")),
> -     ('s', 'succ', [], _("successor changeset"), _('REV')),
> -     ('r', 'rev', [], _("revisions to prune"), _('REV')),
> -     ('k', 'keep', None, _("does not modify working copy during prune")),
> -     ('n', 'note', '', _('store a note on prune'), _('TEXT')),
> -     ('', 'pair', False, _("record a pairing, such as a rebase or
> divergence resolution "
> -                           "(pairing multiple precursors to multiple
> successors)")),
> -     ('', 'biject', False, _("alias to --pair (DEPRECATED)")),
> -     ('', 'fold', False,
> -      _("record a fold (multiple precursors, one successors)")),
> -     ('', 'split', False,
> -      _("record a split (on precursor, multiple successors)")),
> -     ('B', 'bookmark', [], _("remove revs only reachable from given"
> -                             " bookmark"), _('BOOKMARK'))] + metadataopts,
> -    _('[OPTION] [-r] REV...'),
> +    b'prune|obsolete',
> +    [(b'n', b'new', [], _(b"successor changeset (DEPRECATED)")),
> +     (b's', b'succ', [], _(b"successor changeset"), _(b'REV')),
> +     (b'r', b'rev', [], _(b"revisions to prune"), _(b'REV')),
> +     (b'k', b'keep', None, _(b"does not modify working copy during
> prune")),
> +     (b'n', b'note', b'', _(b'store a note on prune'), _(b'TEXT')),
> +     (b'', b'pair', False, _(b"record a pairing, such as a rebase or
> divergence resolution "
> +                             b"(pairing multiple precursors to multiple
> successors)")),
> +     (b'', b'biject', False, _(b"alias to --pair (DEPRECATED)")),
> +     (b'', b'fold', False,
> +      _(b"record a fold (multiple precursors, one successors)")),
> +     (b'', b'split', False,
> +      _(b"record a split (on precursor, multiple successors)")),
> +     (b'B', b'bookmark', [], _(b"remove revs only reachable from given"
> +                               b" bookmark"), _(b'BOOKMARK'))] +
> metadataopts,
> +    _(b'[OPTION] [-r] REV...'),
>      helpbasic=True)
>  # XXX -U  --noupdate option to prevent wc update and or bookmarks update ?
>  def cmdprune(ui, repo, *revs, **opts):
> @@ -1015,17 +1015,17 @@
>      else does edits history without obsolescence enabled.
>      """
>      _checknotesize(ui, opts)
> -    revs = scmutil.revrange(repo, list(revs) + opts.get('rev'))
> -    succs = opts['new'] + opts['succ']
> -    bookmarks = set(opts.get('bookmark'))
> +    revs = scmutil.revrange(repo, list(revs) + opts.get(b'rev'))
> +    succs = opts[b'new'] + opts[b'succ']
> +    bookmarks = set(opts.get(b'bookmark'))
>      metadata = _getmetadata(**opts)
> -    biject = opts.get('pair') or opts.get('biject')
> -    fold = opts.get('fold')
> -    split = opts.get('split')
> +    biject = opts.get(b'pair') or opts.get(b'biject')
> +    fold = opts.get(b'fold')
> +    split = opts.get(b'split')
>
> -    options = [o for o in ('pair', 'fold', 'split') if opts.get(o)]
> +    options = [o for o in (b'pair', b'fold', b'split') if opts.get(o)]
>      if 1 < len(options):
> -        raise error.Abort(_("can only specify one of %s") % ',
> '.join(options))
> +        raise error.Abort(_(b"can only specify one of %s") % b',
> '.join(options))
>
>      if bookmarks:
>          reachablefrombookmark = rewriteutil.reachablefrombookmark
> @@ -1035,14 +1035,14 @@
>              rewriteutil.deletebookmark(repo, repomarks, bookmarks)
>
>      if not revs:
> -        raise error.Abort(_('nothing to prune'))
> +        raise error.Abort(_(b'nothing to prune'))
>
>      wlock = lock = tr = None
>      try:
>          wlock = repo.wlock()
>          lock = repo.lock()
> -        rewriteutil.precheck(repo, revs, 'prune')
> -        tr = repo.transaction('prune')
> +        rewriteutil.precheck(repo, revs, b'prune')
> +        tr = repo.transaction(b'prune')
>          # defines pruned changesets
>          precs = []
>          revs.sort()
> @@ -1050,33 +1050,33 @@
>              cp = repo[p]
>              precs.append(cp)
>          if not precs:
> -            raise error.Abort('nothing to prune')
> +            raise error.Abort(b'nothing to prune')
>
>          # defines successors changesets
>          sucs = scmutil.revrange(repo, succs)
>          sucs.sort()
>          sucs = tuple(repo[n] for n in sucs)
>          if not biject and len(sucs) > 1 and len(precs) > 1:
> -            msg = "Can't use multiple successors for multiple precursors"
> -            hint = _("use --pair to mark a series as a replacement"
> -                     " for another")
> +            msg = b"Can't use multiple successors for multiple precursors"
> +            hint = _(b"use --pair to mark a series as a replacement"
> +                     b" for another")
>              raise error.Abort(msg, hint=hint)
>          elif biject and len(sucs) != len(precs):
> -            msg = "Can't use %d successors for %d precursors" \
> +            msg = b"Can't use %d successors for %d precursors"\
>                  % (len(sucs), len(precs))
>              raise error.Abort(msg)
>          elif (len(precs) == 1 and len(sucs) > 1) and not split:
> -            msg = "please add --split if you want to do a split"
> +            msg = b"please add --split if you want to do a split"
>              raise error.Abort(msg)
>          elif len(sucs) == 1 and len(precs) > 1 and not fold:
> -            msg = "please add --fold if you want to do a fold"
> +            msg = b"please add --fold if you want to do a fold"
>              raise error.Abort(msg)
>          elif biject:
>              replacements = {p.node(): [s.node()] for p, s in zip(precs,
> sucs)}
>          else:
>              replacements = {p.node(): [s.node() for s in sucs] for p in
> precs}
>
> -        wdp = repo['.']
> +        wdp = repo[b'.']
>
>          if len(sucs) == 1 and len(precs) == 1 and wdp in precs:
>              # '.' killed, so update to the successor
> @@ -1089,14 +1089,14 @@
>                  newnode = newnode.parents()[0]
>
>          if newnode.node() != wdp.node():
> -            if opts.get('keep', False):
> +            if opts.get(b'keep', False):
>                  # This is largely the same as the implementation in
>                  # strip.stripcmd(). We might want to refactor this
> somewhere
>                  # common at some point.
>
>                  # only reset the dirstate for files that would actually
> change
>                  # between the working context and uctx
> -                descendantrevs = repo.revs("%d::." % newnode.rev())
> +                descendantrevs = repo.revs(b"%d::." % newnode.rev())
>                  changedfiles = []
>                  for rev in descendantrevs:
>                      # blindly reset the files, regardless of what actually
> @@ -1105,7 +1105,7 @@
>
>                  # reset files that only changed in the dirstate too
>                  dirstate = repo.dirstate
> -                dirchanges = [f for f in dirstate if dirstate[f] != 'n']
> +                dirchanges = [f for f in dirstate if dirstate[f] != b'n']
>                  changedfiles.extend(dirchanges)
>                  repo.dirstate.rebuild(newnode.node(), newnode.manifest(),
>                                        changedfiles)
> @@ -1121,8 +1121,8 @@
>                      bmchanges = [(bookactive, newnode.node())]
>                      repo._bookmarks.applychanges(repo, tr, bmchanges)
>                  commands.update(ui, repo, newnode.hex())
> -                ui.status(_('working directory is now at %s\n')
> -                          % ui.label(str(newnode), 'evolve.node'))
> +                ui.status(_(b'working directory is now at %s\n')
> +                          % ui.label(str(newnode), b'evolve.node'))
>                  if movebookmark:
>                      bookmarksmod.activate(repo, bookactive)
>
> @@ -1131,12 +1131,12 @@
>              rewriteutil.deletebookmark(repo, repomarks, bookmarks)
>
>          # store note in metadata
> -        if opts.get('note'):
> -            metadata['note'] = opts['note']
> +        if opts.get(b'note'):
> +            metadata[b'note'] = opts[b'note']
>
>          precrevs = (precursor.rev() for precursor in precs)
>          moves = {}
> -        for ctx in repo.unfiltered().set('bookmark() and %ld', precrevs):
> +        for ctx in repo.unfiltered().set(b'bookmark() and %ld', precrevs):
>              # used to be:
>              #
>              #   ldest = list(repo.set('max((::%d) - obsolete())', ctx))
> @@ -1149,23 +1149,23 @@
>                  if not dest.obsolete() and dest.node() not in
> replacements:
>                      moves[ctx.node()] = dest.node()
>                      break
> -        scmutil.cleanupnodes(repo, replacements, operation="prune",
> moves=moves,
> +        scmutil.cleanupnodes(repo, replacements, operation=b"prune",
> moves=moves,
>                               metadata=metadata)
>
>          # informs that changeset have been pruned
> -        ui.status(_('%i changesets pruned\n') % len(precs))
> +        ui.status(_(b'%i changesets pruned\n') % len(precs))
>
>          tr.close()
>      finally:
>          lockmod.release(tr, lock, wlock)
>
>  @eh.command(
> -    'split',
> -    [('i', 'interactive', True, _('use interactive mode')),
> -     ('r', 'rev', [], _("revision to split"), _('REV')),
> -     ('n', 'note', '', _("store a note on split"), _('TEXT')),
> -    ] + commitopts + commitopts2 + commitopts3,
> -    _('hg split [OPTION] [-r REV] [FILES]'),
> +    b'split',
> +    [(b'i', b'interactive', True, _(b'use interactive mode')),
> +     (b'r', b'rev', [], _(b"revision to split"), _(b'REV')),
> +     (b'n', b'note', b'', _(b"store a note on split"), _(b'TEXT')),
> +     ] + commitopts + commitopts2 + commitopts3,
> +    _(b'hg split [OPTION] [-r REV] [FILES]'),
>      helpbasic=True)
>  def cmdsplit(ui, repo, *pats, **opts):
>      """split a changeset into smaller changesets
> @@ -1183,17 +1183,17 @@
>      _resolveoptions(ui, opts)
>      tr = wlock = lock = None
>      newcommits = []
> -    iselect = opts.pop('interactive')
> +    iselect = opts.pop(b'interactive')
>
> -    revs = opts.get('rev') or '.'
> +    revs = opts.get(b'rev') or b'.'
>      if not revs:
> -        revarg = '.'
> +        revarg = b'.'
>      elif len(revs) == 1:
>          revarg = revs[0]
>      else:
>          # XXX --rev often accept multiple value, it seems safer to
> explicitly
>          # complains here instead of just taking the last value.
> -        raise error.Abort(_('more than one revset is given'))
> +        raise error.Abort(_(b'more than one revset is given'))
>
>      # Save the current branch to restore it in the end
>      savedbranch = repo.dirstate.branch()
> @@ -1204,18 +1204,18 @@
>          ctx = scmutil.revsingle(repo, revarg)
>          rev = ctx.rev()
>          cmdutil.bailifchanged(repo)
> -        rewriteutil.precheck(repo, [rev], action='split')
> -        tr = repo.transaction('split')
> +        rewriteutil.precheck(repo, [rev], action=b'split')
> +        tr = repo.transaction(b'split')
>          # make sure we respect the phase while splitting
> -        overrides = {('phases', 'new-commit'): ctx.phase()}
> +        overrides = {(b'phases', b'new-commit'): ctx.phase()}
>
>          if len(ctx.parents()) > 1:
> -            raise error.Abort(_("cannot split merge commits"))
> +            raise error.Abort(_(b"cannot split merge commits"))
>          prev = ctx.p1()
>          bmupdate = rewriteutil.bookmarksupdater(repo, ctx.node(), tr)
>          bookactive = repo._activebookmark
>          if bookactive is not None:
> -            repo.ui.status(_("(leaving bookmark %s)\n") %
> repo._activebookmark)
> +            repo.ui.status(_(b"(leaving bookmark %s)\n") %
> repo._activebookmark)
>          bookmarksmod.deactivate(repo)
>
>          # Prepare the working directory
> @@ -1224,13 +1224,13 @@
>          def haschanges(matcher=None):
>              modified, added, removed, deleted =
> repo.status(match=matcher)[:4]
>              return modified or added or removed or deleted
> -        msg = ("HG: This is the original pre-split commit message. "
> -               "Edit it as appropriate.\n\n")
> +        msg = (b"HG: This is the original pre-split commit message. "
> +               b"Edit it as appropriate.\n\n")
>          msg += ctx.description()
> -        opts['message'] = msg
> -        opts['edit'] = True
> -        if not opts['user']:
> -            opts['user'] = ctx.user()
> +        opts[b'message'] = msg
> +        opts[b'edit'] = True
> +        if not opts[b'user']:
> +            opts[b'user'] = ctx.user()
>
>          # Set the right branch
>          # XXX-TODO: Find a way to set the branch without altering the
> dirstate
> @@ -1246,21 +1246,21 @@
>
>              if haschanges(matcher):
>                  if iselect:
> -                    with repo.ui.configoverride(overrides, 'split'):
> -                        cmdutil.dorecord(ui, repo, commands.commit,
> 'commit',
> +                    with repo.ui.configoverride(overrides, b'split'):
> +                        cmdutil.dorecord(ui, repo, commands.commit,
> b'commit',
>                                           False, cmdutil.recordfilter,
> *pats,
>                                           **opts)
>                      # TODO: Does no seem like the best way to do this
>                      # We should make dorecord return the newly created
> commit
> -                    newcommits.append(repo['.'])
> +                    newcommits.append(repo[b'.'])
>                  elif not pats:
> -                    msg = _("no files of directories specified")
> -                    hint = _("do you want --interactive")
> +                    msg = _(b"no files of directories specified")
> +                    hint = _(b"do you want --interactive")
>                      raise error.Abort(msg, hint=hint)
>                  else:
> -                    with repo.ui.configoverride(overrides, 'split'):
> +                    with repo.ui.configoverride(overrides, b'split'):
>                          commands.commit(ui, repo, *pats, **opts)
> -                    newcommits.append(repo['.'])
> +                    newcommits.append(repo[b'.'])
>              if pats:
>                  # refresh the wctx used for the matcher
>                  matcher = scmutil.match(repo[None], pats)
> @@ -1270,20 +1270,20 @@
>              if haschanges(matcher):
>                  nextaction = None
>                  while nextaction is None:
> -                    nextaction = ui.prompt('continue splitting? [Ycdq?]',
> default='y')
> -                    if nextaction == 'c':
> -                        with repo.ui.configoverride(overrides, 'split'):
> +                    nextaction = ui.prompt(b'continue splitting?
> [Ycdq?]', default=b'y')
> +                    if nextaction == b'c':
> +                        with repo.ui.configoverride(overrides, b'split'):
>                              commands.commit(ui, repo, **opts)
> -                        newcommits.append(repo['.'])
> +                        newcommits.append(repo[b'.'])
>                          break
> -                    elif nextaction == 'q':
> -                        raise error.Abort(_('user quit'))
> -                    elif nextaction == 'd':
> +                    elif nextaction == b'q':
> +                        raise error.Abort(_(b'user quit'))
> +                    elif nextaction == b'd':
>                          # TODO: We should offer a way for the user to
> confirm
>                          # what is the remaining changes, either via a
> separate
>                          # diff action or by showing the remaining and
>                          # prompting for confirmation
> -                        ui.status(_('discarding remaining changes\n'))
> +                        ui.status(_(b'discarding remaining changes\n'))
>                          target = newcommits[0]
>                          if pats:
>                              status = repo.status(match=matcher)[:4]
> @@ -1296,34 +1296,34 @@
>                          else:
>                              cmdutil.revert(ui, repo, repo[target],
>                                             (target, node.nullid),
> all=True)
> -                    elif nextaction == '?':
> +                    elif nextaction == b'?':
>                          nextaction = None
> -                        ui.write(_("y - yes, continue selection\n"))
> -                        ui.write(_("c - commit, select all remaining
> changes\n"))
> -                        ui.write(_("d - discard, discard remaining
> changes\n"))
> -                        ui.write(_("q - quit, abort the split\n"))
> -                        ui.write(_("? - ?, display help\n"))
> +                        ui.write(_(b"y - yes, continue selection\n"))
> +                        ui.write(_(b"c - commit, select all remaining
> changes\n"))
> +                        ui.write(_(b"d - discard, discard remaining
> changes\n"))
> +                        ui.write(_(b"q - quit, abort the split\n"))
> +                        ui.write(_(b"? - ?, display help\n"))
>                  else:
>                      continue
>                  break # propagate the previous break
>              else:
> -                ui.status(_("no more change to split\n"))
> +                ui.status(_(b"no more change to split\n"))
>                  if haschanges():
>                      # XXX: Should we show a message for informing the user
>                      # that we create another commit with remaining
> changes?
> -                    with repo.ui.configoverride(overrides, 'split'):
> +                    with repo.ui.configoverride(overrides, b'split'):
>                          commands.commit(ui, repo, **opts)
> -                    newcommits.append(repo['.'])
> +                    newcommits.append(repo[b'.'])
>          if newcommits:
>              tip = repo[newcommits[-1]]
>              bmupdate(tip.node())
>              if bookactive is not None:
>                  bookmarksmod.activate(repo, bookactive)
>              metadata = {}
> -            if opts.get('note'):
> -                metadata['note'] = opts['note']
> +            if opts.get(b'note'):
> +                metadata[b'note'] = opts[b'note']
>              obsolete.createmarkers(repo, [(repo[rev], newcommits)],
> -                                   metadata=metadata, operation="split")
> +                                   metadata=metadata, operation=b"split")
>          tr.close()
>      finally:
>          # Restore the old branch
> @@ -1332,47 +1332,47 @@
>          lockmod.release(tr, lock, wlock)
>
>  @eh.command(
> -    'touch',
> -    [('r', 'rev', [], _('revision to update'), _('REV')),
> -     ('n', 'note', '', _('store a note on touch'), _('TEXT')),
> -     ('D', 'duplicate', False,
> -      'do not mark the new revision as successor of the old one'),
> -     ('A', 'allowdivergence', False,
> -      'mark the new revision as successor of the old one potentially
> creating '
> -      'divergence')],
> +    b'touch',
> +    [(b'r', b'rev', [], _(b'revision to update'), _(b'REV')),
> +     (b'n', b'note', b'', _(b'store a note on touch'), _(b'TEXT')),
> +     (b'D', b'duplicate', False,
> +      b'do not mark the new revision as successor of the old one'),
> +     (b'A', b'allowdivergence', False,
> +      b'mark the new revision as successor of the old one potentially
> creating '
> +      b'divergence')],
>      # allow to choose the seed ?
> -    _('[-r] revs'))
> +    _(b'[-r] revs'))
>  def touch(ui, repo, *revs, **opts):
>      """create successors identical to their predecessors but the
> changeset ID
>
>      This is used to "resurrect" changesets
>      """
>      _checknotesize(ui, opts)
> -    duplicate = opts['duplicate']
> -    allowdivergence = opts['allowdivergence']
> +    duplicate = opts[b'duplicate']
> +    allowdivergence = opts[b'allowdivergence']
>      revs = list(revs)
> -    revs.extend(opts['rev'])
> +    revs.extend(opts[b'rev'])
>      if not revs:
> -        revs = ['.']
> +        revs = [b'.']
>      revs = scmutil.revrange(repo, revs)
>      if not revs:
> -        ui.write_err('no revision to touch\n')
> +        ui.write_err(b'no revision to touch\n')
>          return 1
>      if not duplicate:
> -        rewriteutil.precheck(repo, revs, 'touch')
> +        rewriteutil.precheck(repo, revs, b'touch')
>      tmpl = utility.shorttemplate
> -    displayer = compat.changesetdisplayer(ui, repo, {'template': tmpl})
> +    displayer = compat.changesetdisplayer(ui, repo, {b'template': tmpl})
>      wlock = lock = tr = None
>      try:
>          wlock = repo.wlock()
>          lock = repo.lock()
> -        tr = repo.transaction('touch')
> +        tr = repo.transaction(b'touch')
>          revs.sort() # ensure parent are run first
>          newmapping = {}
>          for r in revs:
>              ctx = repo[r]
>              extra = ctx.extra().copy()
> -            extra['__touch-noise__'] = random.randint(0, 0xffffffff)
> +            extra[b'__touch-noise__'] = random.randint(0, 0xffffffff)
>              # search for touched parent
>              p1 = ctx.p1().node()
>              p2 = ctx.p2().node()
> @@ -1393,17 +1393,17 @@
>                  else:
>                      displayer.show(ctx)
>                      index = ui.promptchoice(
> -                        _("reviving this changeset will create divergence"
> -                          " unless you make a duplicate.\n(a)llow
> divergence or"
> -                          " (d)uplicate the changeset? $$
> &Allowdivergence $$ "
> -                          "&Duplicate"), 0)
> -                    choice = ['allowdivergence', 'duplicate'][index]
> -                    if choice == 'allowdivergence':
> +                        _(b"reviving this changeset will create
> divergence"
> +                          b" unless you make a duplicate.\n(a)llow
> divergence or"
> +                          b" (d)uplicate the changeset? $$
> &Allowdivergence $$ "
> +                          b"&Duplicate"), 0)
> +                    choice = [b'allowdivergence', b'duplicate'][index]
> +                    if choice == b'allowdivergence':
>                          duplicate = False
>                      else:
>                          duplicate = True
>
> -            extradict = {'extra': extra}
> +            extradict = {b'extra': extra}
>              new, unusedvariable = rewriteutil.rewrite(repo, ctx, [], ctx,
>                                                        [p1, p2],
>
>  commitopts=extradict)
> @@ -1412,10 +1412,10 @@
>
>              if not duplicate:
>                  metadata = {}
> -                if opts.get('note'):
> -                    metadata['note'] = opts['note']
> +                if opts.get(b'note'):
> +                    metadata[b'note'] = opts[b'note']
>                  obsolete.createmarkers(repo, [(ctx, (repo[new],))],
> -                                       metadata=metadata,
> operation="touch")
> +                                       metadata=metadata,
> operation=b"touch")
>              phases.retractboundary(repo, tr, ctx.phase(), [new])
>              if ctx in repo[None].parents():
>                  with repo.dirstate.parentchange():
> @@ -1425,80 +1425,80 @@
>          lockmod.release(tr, lock, wlock)
>
>  @eh.command(
> -    'pick|grab',
> -    [('r', 'rev', '', _('revision to pick'), _('REV')),
> -     ('c', 'continue', False, 'continue interrupted pick'),
> -     ('a', 'abort', False, 'abort interrupted pick'),
> -    ] + mergetoolopts,
> -    _('[-r] rev'))
> +    b'pick|grab',
> +    [(b'r', b'rev', b'', _(b'revision to pick'), _(b'REV')),
> +     (b'c', b'continue', False, b'continue interrupted pick'),
> +     (b'a', b'abort', False, b'abort interrupted pick'),
> +     ] + mergetoolopts,
> +    _(b'[-r] rev'))
>  def cmdpick(ui, repo, *revs, **opts):
>      """move a commit on the top of working directory parent and updates
> to it."""
>
> -    cont = opts.get('continue')
> -    abort = opts.get('abort')
> +    cont = opts.get(b'continue')
> +    abort = opts.get(b'abort')
>
>      if cont and abort:
> -        raise error.Abort(_("cannot specify both --continue and --abort"))
> +        raise error.Abort(_(b"cannot specify both --continue and
> --abort"))
>
>      revs = list(revs)
> -    if opts.get('rev'):
> -        revs.append(opts['rev'])
> +    if opts.get(b'rev'):
> +        revs.append(opts[b'rev'])
>
> -    overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
> -    with repo.wlock(), repo.lock(), repo.transaction('pick'),
> ui.configoverride(overrides, 'pick'):
> -        pickstate = state.cmdstate(repo, path='pickstate')
> -        pctx = repo['.']
> +    overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
> +    with repo.wlock(), repo.lock(), repo.transaction(b'pick'),
> ui.configoverride(overrides, b'pick'):
> +        pickstate = state.cmdstate(repo, path=b'pickstate')
> +        pctx = repo[b'.']
>
>          if not cont and not abort:
>              cmdutil.bailifchanged(repo)
>              revs = scmutil.revrange(repo, revs)
>              if len(revs) > 1:
> -                raise error.Abort(_("specify just one revision"))
> +                raise error.Abort(_(b"specify just one revision"))
>              elif not revs:
> -                raise error.Abort(_("empty revision set"))
> +                raise error.Abort(_(b"empty revision set"))
>
>              origctx = repo[revs.first()]
>
>              if origctx in pctx.ancestors() or origctx.node() ==
> pctx.node():
> -                raise error.Abort(_("cannot pick an ancestor revision"))
> +                raise error.Abort(_(b"cannot pick an ancestor revision"))
>
> -            rewriteutil.precheck(repo, [origctx.rev()], 'pick')
> +            rewriteutil.precheck(repo, [origctx.rev()], b'pick')
>
> -            ui.status(_('picking %d:%s "%s"\n') %
> +            ui.status(_(b'picking %d:%s "%s"\n') %
>                        (origctx.rev(), origctx,
> -                       origctx.description().split("\n", 1)[0]))
> -            stats = merge.graft(repo, origctx, origctx.p1(), ['local',
> -
> 'destination'])
> +                       origctx.description().split(b"\n", 1)[0]))
> +            stats = merge.graft(repo, origctx, origctx.p1(), [b'local',
> +
> b'destination'])
>              if compat.hasconflict(stats):
> -                pickstate.addopts({'orignode': origctx.node(),
> -                                   'oldpctx': pctx.node()})
> +                pickstate.addopts({b'orignode': origctx.node(),
> +                                   b'oldpctx': pctx.node()})
>                  pickstate.save()
> -                raise error.InterventionRequired(_("unresolved merge
> conflicts"
> -                                                   " (see hg help
> resolve)"))
> +                raise error.InterventionRequired(_(b"unresolved merge
> conflicts"
> +                                                   b" (see hg help
> resolve)"))
>
>          elif abort:
>              if not pickstate:
> -                raise error.Abort(_("no interrupted pick state exists"))
> +                raise error.Abort(_(b"no interrupted pick state exists"))
>              pickstate.load()
> -            pctxnode = pickstate['oldpctx']
> -            ui.status(_("aborting pick, updating to %s\n") %
> +            pctxnode = pickstate[b'oldpctx']
> +            ui.status(_(b"aborting pick, updating to %s\n") %
>                        node.hex(pctxnode)[:12])
>              hg.updaterepo(repo, pctxnode, True)
>              return 0
>
>          else:
>              if revs:
> -                raise error.Abort(_("cannot specify both --continue and "
> -                                    "revision"))
> +                raise error.Abort(_(b"cannot specify both --continue and "
> +                                    b"revision"))
>              if not pickstate:
> -                raise error.Abort(_("no interrupted pick state exists"))
> +                raise error.Abort(_(b"no interrupted pick state exists"))
>
>              pickstate.load()
> -            orignode = pickstate['orignode']
> +            orignode = pickstate[b'orignode']
>              origctx = repo[orignode]
>
> -        overrides = {('phases', 'new-commit'): origctx.phase()}
> -        with repo.ui.configoverride(overrides, 'pick'):
> +        overrides = {(b'phases', b'new-commit'): origctx.phase()}
> +        with repo.ui.configoverride(overrides, b'pick'):
>              newnode = repo.commit(text=origctx.description(),
>                                    user=origctx.user(),
>                                    date=origctx.date(),
> extra=origctx.extra())
> @@ -1508,10 +1508,10 @@
>              pickstate.delete()
>          newctx = repo[newnode] if newnode else pctx
>          replacements = {origctx.node(): [newctx.node()]}
> -        scmutil.cleanupnodes(repo, replacements, operation="pick")
> +        scmutil.cleanupnodes(repo, replacements, operation=b"pick")
>
>          if newnode is None:
> -            ui.warn(_("note: picking %d:%s created no changes to
> commit\n") %
> +            ui.warn(_(b"note: picking %d:%s created no changes to
> commit\n") %
>                      (origctx.rev(), origctx))
>              return 0
>
> diff --git a/hgext3rd/evolve/compat.py b/hgext3rd/evolve/compat.py
> --- a/hgext3rd/evolve/compat.py
> +++ b/hgext3rd/evolve/compat.py
> @@ -48,29 +48,29 @@
>      # check
>      if not obsutil:
>          return False
> -    return util.safehasattr(obsutil, 'obsfateprinter')
> +    return util.safehasattr(obsutil, b'obsfateprinter')
>
>  # Evolution renaming compat
>
>  TROUBLES = {
> -    'ORPHAN': 'orphan',
> -    'CONTENTDIVERGENT': 'content-divergent',
> -    'PHASEDIVERGENT': 'phase-divergent',
> +    b'ORPHAN': b'orphan',
> +    b'CONTENTDIVERGENT': b'content-divergent',
> +    b'PHASEDIVERGENT': b'phase-divergent',
>  }
>
> -if util.safehasattr(uimod.ui, 'makeprogress'):
> -    def progress(ui, topic, pos, item="", unit="", total=None):
> +if util.safehasattr(uimod.ui, b'makeprogress'):
> +    def progress(ui, topic, pos, item=b"", unit=b"", total=None):
>          progress = ui.makeprogress(topic, unit, total)
>          if pos is not None:
>              progress.update(pos, item=item)
>          else:
>              progress.complete()
>  else:
> -    def progress(ui, topic, pos, item="", unit="", total=None):
> +    def progress(ui, topic, pos, item=b"", unit=b"", total=None):
>          ui.progress(topic, pos, item, unit, total)
>
>  # XXX: Better detection of property cache
> -if 'predecessors' not in dir(obsolete.obsstore):
> +if b'predecessors' not in dir(obsolete.obsstore):
>      @property
>      def predecessors(self):
>          return self.precursors
> @@ -81,33 +81,33 @@
>      # XXX Would it be better at the module level?
>      varnames = context.memfilectx.__init__.__code__.co_varnames
>
> -    if "copysource" in varnames:
> +    if b"copysource" in varnames:
>          mctx = context.memfilectx(repo, ctx, fctx.path(), fctx.data(),
> -                                  islink='l' in flags,
> -                                  isexec='x' in flags,
> +                                  islink=b'l' in flags,
> +                                  isexec=b'x' in flags,
>                                    copysource=copied.get(path))
>      # compat with hg <- 4.9
> -    elif varnames[2] == "changectx":
> +    elif varnames[2] == b"changectx":
>          mctx = context.memfilectx(repo, ctx, fctx.path(), fctx.data(),
> -                                  islink='l' in flags,
> -                                  isexec='x' in flags,
> +                                  islink=b'l' in flags,
> +                                  isexec=b'x' in flags,
>                                    copied=copied.get(path))
>      else:
>          mctx = context.memfilectx(repo, fctx.path(), fctx.data(),
> -                                  islink='l' in flags,
> -                                  isexec='x' in flags,
> +                                  islink=b'l' in flags,
> +                                  isexec=b'x' in flags,
>                                    copied=copied.get(path))
>      return mctx
>
>  def strdiff(a, b, fn1, fn2):
>      """ A version of mdiff.unidiff for comparing two strings
>      """
> -    args = [a, '', b, '', fn1, fn2]
> +    args = [a, b'', b, b'', fn1, fn2]
>
>      # hg < 4.6 compat 8b6dd3922f70
>      argspec = inspect.getargspec(mdiff.unidiff)
>
> -    if 'binary' in argspec.args:
> +    if b'binary' in argspec.args:
>          args.append(False)
>
>      return mdiff.unidiff(*args)
> @@ -123,7 +123,7 @@
>      makedate = mercurial.util.makedate
>      parsedate = mercurial.util.parsedate
>
> -def wireprotocommand(exthelper, name, args='', permission='pull'):
> +def wireprotocommand(exthelper, name, args=b'', permission=b'pull'):
>      try:
>          # Since b4d85bc1
>          from mercurial.wireprotov1server import wireprotocommand
> @@ -161,7 +161,7 @@
>          return bool(upres[-1])
>      return bool(upres.unresolvedcount)
>
> -hg48 = util.safehasattr(copies, 'stringutil')
> +hg48 = util.safehasattr(copies, b'stringutil')
>  # code imported from Mercurial core at ae17555ef93f + patch
>  def fixedcopytracing(repo, c1, c2, base):
>      """A complete copy-patse of copies._fullcopytrace with a one line fix
> to
> @@ -185,7 +185,7 @@
>      # an endpoint is "dirty" if it isn't a descendant of the merge base
>      # if we have a dirty endpoint, we need to trigger graft logic, and
> also
>      # keep track of which endpoint is dirty
> -    if util.safehasattr(base, 'isancestorof'):
> +    if util.safehasattr(base, b'isancestorof'):
>          dirtyc1 = not base.isancestorof(_c1)
>          dirtyc2 = not base.isancestorof(_c2)
>      else: # hg <= 4.6
> @@ -204,7 +204,7 @@
>      if limit is None:
>          # no common ancestor, no copies
>          return {}, {}, {}, {}, {}
> -    repo.ui.debug("  searching for copies back to rev %d\n" % limit)
> +    repo.ui.debug(b"  searching for copies back to rev %d\n" % limit)
>
>      m1 = c1.manifest()
>      m2 = c2.manifest()
> @@ -218,18 +218,18 @@
>      # - incompletediverge = record divergent partial copies here
>      diverge = {} # divergence data is shared
>      incompletediverge = {}
> -    data1 = {'copy': {},
> -             'fullcopy': {},
> -             'incomplete': {},
> -             'diverge': diverge,
> -             'incompletediverge': incompletediverge,
> -            }
> -    data2 = {'copy': {},
> -             'fullcopy': {},
> -             'incomplete': {},
> -             'diverge': diverge,
> -             'incompletediverge': incompletediverge,
> -            }
> +    data1 = {b'copy': {},
> +             b'fullcopy': {},
> +             b'incomplete': {},
> +             b'diverge': diverge,
> +             b'incompletediverge': incompletediverge,
> +             }
> +    data2 = {b'copy': {},
> +             b'fullcopy': {},
> +             b'incomplete': {},
> +             b'diverge': diverge,
> +             b'incompletediverge': incompletediverge,
> +             }
>
>      # find interesting file sets from manifests
>      if hg48:
> @@ -246,20 +246,20 @@
>      else:
>          # unmatched file from base (DAG rotation in the graft case)
>          u1r, u2r = copies._computenonoverlap(repo, c1, c2, addedinm1,
> addedinm2,
> -                                             baselabel='base')
> +                                             baselabel=b'base')
>          # unmatched file from topological common ancestors (no DAG
> rotation)
>          # need to recompute this for directory move handling when grafting
>          mta = tca.manifest()
>          if hg48:
>              m1f = m1.filesnotin(mta, repo.narrowmatch())
>              m2f = m2.filesnotin(mta, repo.narrowmatch())
> -            baselabel = 'topological common ancestor'
> +            baselabel = b'topological common ancestor'
>              u1u, u2u = copies._computenonoverlap(repo, c1, c2, m1f, m2f,
>                                                   baselabel=baselabel)
>          else:
>              u1u, u2u = copies._computenonoverlap(repo, c1, c2,
> m1.filesnotin(mta),
>                                                   m2.filesnotin(mta),
> -                                                 baselabel='topological
> common ancestor')
> +                                                 baselabel=b'topological
> common ancestor')
>
>      for f in u1u:
>          copies._checkcopies(c1, c2, f, base, tca, dirtyc1, limit, data1)
> @@ -267,16 +267,16 @@
>      for f in u2u:
>          copies._checkcopies(c2, c1, f, base, tca, dirtyc2, limit, data2)
>
> -    copy = dict(data1['copy'])
> -    copy.update(data2['copy'])
> -    fullcopy = dict(data1['fullcopy'])
> -    fullcopy.update(data2['fullcopy'])
> +    copy = dict(data1[b'copy'])
> +    copy.update(data2[b'copy'])
> +    fullcopy = dict(data1[b'fullcopy'])
> +    fullcopy.update(data2[b'fullcopy'])
>
>      if dirtyc1:
> -        copies._combinecopies(data2['incomplete'], data1['incomplete'],
> copy, diverge,
> +        copies._combinecopies(data2[b'incomplete'], data1[b'incomplete'],
> copy, diverge,
>                                incompletediverge)
>      else:
> -        copies._combinecopies(data1['incomplete'], data2['incomplete'],
> copy, diverge,
> +        copies._combinecopies(data1[b'incomplete'], data2[b'incomplete'],
> copy, diverge,
>                                incompletediverge)
>
>      renamedelete = {}
> @@ -294,23 +294,23 @@
>              divergeset.update(fl) # reverse map for below
>
>      if bothnew:
> -        repo.ui.debug("  unmatched files new in both:\n   %s\n"
> -                      % "\n   ".join(bothnew))
> +        repo.ui.debug(b"  unmatched files new in both:\n   %s\n"
> +                      % b"\n   ".join(bothnew))
>      bothdiverge = {}
>      bothincompletediverge = {}
>      remainder = {}
> -    both1 = {'copy': {},
> -             'fullcopy': {},
> -             'incomplete': {},
> -             'diverge': bothdiverge,
> -             'incompletediverge': bothincompletediverge
> -            }
> -    both2 = {'copy': {},
> -             'fullcopy': {},
> -             'incomplete': {},
> -             'diverge': bothdiverge,
> -             'incompletediverge': bothincompletediverge
> -            }
> +    both1 = {b'copy': {},
> +             b'fullcopy': {},
> +             b'incomplete': {},
> +             b'diverge': bothdiverge,
> +             b'incompletediverge': bothincompletediverge
> +             }
> +    both2 = {b'copy': {},
> +             b'fullcopy': {},
> +             b'incomplete': {},
> +             b'diverge': bothdiverge,
> +             b'incompletediverge': bothincompletediverge
> +             }
>      for f in bothnew:
>          copies._checkcopies(c1, c2, f, base, tca, dirtyc1, limit, both1)
>          copies._checkcopies(c2, c1, f, base, tca, dirtyc2, limit, both2)
> @@ -319,17 +319,17 @@
>          pass
>      elif dirtyc1:
>          # incomplete copies may only be found on the "dirty" side for
> bothnew
> -        assert not both2['incomplete']
> -        remainder = copies._combinecopies({}, both1['incomplete'], copy,
> bothdiverge,
> +        assert not both2[b'incomplete']
> +        remainder = copies._combinecopies({}, both1[b'incomplete'], copy,
> bothdiverge,
>                                            bothincompletediverge)
>      elif dirtyc2:
> -        assert not both1['incomplete']
> -        remainder = copies._combinecopies({}, both2['incomplete'], copy,
> bothdiverge,
> +        assert not both1[b'incomplete']
> +        remainder = copies._combinecopies({}, both2[b'incomplete'], copy,
> bothdiverge,
>                                            bothincompletediverge)
>      else:
>          # incomplete copies and divergences can't happen outside grafts
> -        assert not both1['incomplete']
> -        assert not both2['incomplete']
> +        assert not both1[b'incomplete']
> +        assert not both2[b'incomplete']
>          assert not bothincompletediverge
>      for f in remainder:
>          assert f not in bothdiverge
> @@ -342,52 +342,52 @@
>              copy[fl[0]] = of # not actually divergent, just matching
> renames
>
>      if fullcopy and repo.ui.debugflag:
> -        repo.ui.debug("  all copies found (* = to merge, ! = divergent, "
> -                      "% = renamed and deleted):\n")
> +        repo.ui.debug(b"  all copies found (* = to merge, ! = divergent, "
> +                      b"% = renamed and deleted):\n")
>          for f in sorted(fullcopy):
> -            note = ""
> +            note = b""
>              if f in copy:
> -                note += "*"
> +                note += b"*"
>              if f in divergeset:
> -                note += "!"
> +                note += b"!"
>              if f in renamedeleteset:
> -                note += "%"
> -            repo.ui.debug("   src: '%s' -> dst: '%s' %s\n" %
> (fullcopy[f], f,
> -                                                              note))
> +                note += b"%"
> +            repo.ui.debug(b"   src: '%s' -> dst: '%s' %s\n" %
> (fullcopy[f], f,
> +                                                               note))
>      del divergeset
>
>      if not fullcopy:
>          return copy, {}, diverge, renamedelete, {}
>
> -    repo.ui.debug("  checking for directory renames\n")
> +    repo.ui.debug(b"  checking for directory renames\n")
>
>      # generate a directory move map
>      d1, d2 = c1.dirs(), c2.dirs()
>      # Hack for adding '', which is not otherwise added, to d1 and d2
> -    d1.addpath('/')
> -    d2.addpath('/')
> +    d1.addpath(b'/')
> +    d2.addpath(b'/')
>      invalid = set()
>      dirmove = {}
>
>      # examine each file copy for a potential directory move, which is
>      # when all the files in a directory are moved to a new directory
> -    for dst, src in fullcopy.iteritems():
> +    for dst, src in fullcopy.items():
>          dsrc, ddst = pathutil.dirname(src), pathutil.dirname(dst)
>          if dsrc in invalid:
>              # already seen to be uninteresting
>              continue
>          elif dsrc in d1 and ddst in d1:
>              # directory wasn't entirely moved locally
> -            invalid.add(dsrc + "/")
> +            invalid.add(dsrc + b"/")
>          elif dsrc in d2 and ddst in d2:
>              # directory wasn't entirely moved remotely
> -            invalid.add(dsrc + "/")
> -        elif dsrc + "/" in dirmove and dirmove[dsrc + "/"] != ddst + "/":
> +            invalid.add(dsrc + b"/")
> +        elif dsrc + b"/" in dirmove and dirmove[dsrc + b"/"] != ddst +
> b"/":
>              # files from the same directory moved to two different places
> -            invalid.add(dsrc + "/")
> +            invalid.add(dsrc + b"/")
>          else:
>              # looks good so far
> -            dirmove[dsrc + "/"] = ddst + "/"
> +            dirmove[dsrc + b"/"] = ddst + b"/"
>
>      for i in invalid:
>          if i in dirmove:
> @@ -398,7 +398,7 @@
>          return copy, {}, diverge, renamedelete, {}
>
>      for d in dirmove:
> -        repo.ui.debug("   discovered dir src: '%s' -> dst: '%s'\n" %
> +        repo.ui.debug(b"   discovered dir src: '%s' -> dst: '%s'\n" %
>                        (d, dirmove[d]))
>
>      movewithdir = {}
> @@ -411,18 +411,18 @@
>                      df = dirmove[d] + f[len(d):]
>                      if df not in copy:
>                          movewithdir[f] = df
> -                        repo.ui.debug(("   pending file src: '%s' -> "
> -                                       "dst: '%s'\n") % (f, df))
> +                        repo.ui.debug((b"   pending file src: '%s' -> "
> +                                       b"dst: '%s'\n") % (f, df))
>                      break
>
>      return copy, movewithdir, diverge, renamedelete, dirmove
>
>  # hg <= 4.9 compat (7694b685bb10)
> -fixupstreamed = util.safehasattr(scmutil, 'movedirstate')
> +fixupstreamed = util.safehasattr(scmutil, b'movedirstate')
>  if not fixupstreamed:
>      copies._fullcopytracing = fixedcopytracing
>
> -if not util.safehasattr(obsutil, "_succs"):
> +if not util.safehasattr(obsutil, b"_succs"):
>      class _succs(list):
>          """small class to represent a successors with some metadata about
> it"""
>
> @@ -450,12 +450,12 @@
>      _succs instance
>      """
>
> -    if not util.safehasattr(succs, "markers"):
> +    if not util.safehasattr(succs, b"markers"):
>          return _succs(succs)
>      else:
>          return succs
>
> -if not util.safehasattr(obsutil, "markersdates"):
> +if not util.safehasattr(obsutil, b"markersdates"):
>      MARKERS_DATE_COMPAT = True
>  else:
>      MARKERS_DATE_COMPAT = False
> @@ -468,7 +468,7 @@
>
>      return [m[4] for m in markers]
>
> -if not util.safehasattr(obsutil, "markersusers"):
> +if not util.safehasattr(obsutil, b"markersusers"):
>      MARKERS_USERS_COMPAT = True
>  else:
>      MARKERS_USERS_COMPAT = False
> @@ -480,12 +480,12 @@
>          return obsutil.markersusers(markers)
>
>      markersmeta = [dict(m[3]) for m in markers]
> -    users = set(encoding.tolocal(meta['user']) for meta in markersmeta
> -                if meta.get('user'))
> +    users = set(encoding.tolocal(meta[b'user']) for meta in markersmeta
> +                if meta.get(b'user'))
>
>      return sorted(users)
>
> -if not util.safehasattr(obsutil, "markersoperations"):
> +if not util.safehasattr(obsutil, b"markersoperations"):
>      MARKERS_OPERATIONS_COMPAT = True
>  else:
>      MARKERS_OPERATIONS_COMPAT = False
> @@ -497,7 +497,7 @@
>          return obsutil.markersoperations(markers)
>
>      markersmeta = [dict(m[3]) for m in markers]
> -    operations = set(meta.get('operation') for meta in markersmeta
> -                     if meta.get('operation'))
> +    operations = set(meta.get(b'operation') for meta in markersmeta
> +                     if meta.get(b'operation'))
>
>      return sorted(operations)
> diff --git a/hgext3rd/evolve/dagutil.py b/hgext3rd/evolve/dagutil.py
> --- a/hgext3rd/evolve/dagutil.py
> +++ b/hgext3rd/evolve/dagutil.py
> @@ -140,7 +140,7 @@
>      def _internalize(self, id):
>          ix = self._revlog.rev(id)
>          if ix == nullrev:
> -            raise LookupError(id, self._revlog.indexfile, _('nullid'))
> +            raise LookupError(id, self._revlog.indexfile, _(b'nullid'))
>          return ix
>
>      def _internalizeall(self, ids, filterunknown):
> diff --git a/hgext3rd/evolve/debugcmd.py b/hgext3rd/evolve/debugcmd.py
> --- a/hgext3rd/evolve/debugcmd.py
> +++ b/hgext3rd/evolve/debugcmd.py
> @@ -21,7 +21,7 @@
>
>  eh = exthelper.exthelper()
>
> -@eh.command('debugobsstorestat', [], '')
> +@eh.command(b'debugobsstorestat', [], b'')
>  def cmddebugobsstorestat(ui, repo):
>      """print statistics about obsolescence markers in the repo"""
>      def _updateclustermap(nodes, mark, clustersmap):
> @@ -45,7 +45,7 @@
>      unfi = repo.unfiltered()
>      nm = unfi.changelog.nodemap
>      nbmarkers = len(store._all)
> -    ui.write(_('markers total:              %9i\n') % nbmarkers)
> +    ui.write(_(b'markers total:              %9i\n') % nbmarkers)
>      sucscount = [0, 0, 0, 0]
>      known = 0
>      parentsdata = 0
> @@ -67,7 +67,7 @@
>              metakeys.setdefault(key, 0)
>              metakeys[key] += 1
>          meta = dict(meta)
> -        parents = [meta.get('p1'), meta.get('p2')]
> +        parents = [meta.get(b'p1'), meta.get(b'p2')]
>          parents = [node.bin(p) for p in parents if p is not None]
>          if parents:
>              parentsdata += 1
> @@ -91,71 +91,71 @@
>          fc = (frozenset(c[0]), frozenset(c[1]))
>          for n in fc[0]:
>              pclustersmap[n] = fc
> -    numobs = len(unfi.revs('obsolete()'))
> +    numobs = len(unfi.revs(b'obsolete()'))
>      numtotal = len(unfi)
> -    ui.write(('    for known precursors:   %9i' % known))
> -    ui.write((' (%i/%i obsolete changesets)\n' % (numobs, numtotal)))
> -    ui.write(('    with parents data:      %9i\n' % parentsdata))
> +    ui.write((b'    for known precursors:   %9i' % known))
> +    ui.write((b' (%i/%i obsolete changesets)\n' % (numobs, numtotal)))
> +    ui.write((b'    with parents data:      %9i\n' % parentsdata))
>      # successors data
> -    ui.write(('markers with no successors: %9i\n' % sucscount[0]))
> -    ui.write(('              1 successors: %9i\n' % sucscount[1]))
> -    ui.write(('              2 successors: %9i\n' % sucscount[2]))
> -    ui.write(('    more than 2 successors: %9i\n' % sucscount[3]))
> +    ui.write((b'markers with no successors: %9i\n' % sucscount[0]))
> +    ui.write((b'              1 successors: %9i\n' % sucscount[1]))
> +    ui.write((b'              2 successors: %9i\n' % sucscount[2]))
> +    ui.write((b'    more than 2 successors: %9i\n' % sucscount[3]))
>      # meta data info
> -    ui.write(('    available  keys:\n'))
> +    ui.write((b'    available  keys:\n'))
>      for key in sorted(metakeys):
> -        ui.write(('    %15s:        %9i\n' % (key, metakeys[key])))
> +        ui.write((b'    %15s:        %9i\n' % (key, metakeys[key])))
>
>      size_v0.sort()
>      size_v1.sort()
>      if size_v0:
> -        ui.write('marker size:\n')
> +        ui.write(b'marker size:\n')
>          # format v1
> -        ui.write('    format v1:\n')
> -        ui.write(('        smallest length:    %9i\n' % size_v1[0]))
> -        ui.write(('        longer length:      %9i\n' % size_v1[-1]))
> +        ui.write(b'    format v1:\n')
> +        ui.write((b'        smallest length:    %9i\n' % size_v1[0]))
> +        ui.write((b'        longer length:      %9i\n' % size_v1[-1]))
>          median = size_v1[nbmarkers // 2]
> -        ui.write(('        median length:      %9i\n' % median))
> +        ui.write((b'        median length:      %9i\n' % median))
>          mean = sum(size_v1) // nbmarkers
> -        ui.write(('        mean length:        %9i\n' % mean))
> +        ui.write((b'        mean length:        %9i\n' % mean))
>          # format v0
> -        ui.write('    format v0:\n')
> -        ui.write(('        smallest length:    %9i\n' % size_v0[0]))
> -        ui.write(('        longer length:      %9i\n' % size_v0[-1]))
> +        ui.write(b'    format v0:\n')
> +        ui.write((b'        smallest length:    %9i\n' % size_v0[0]))
> +        ui.write((b'        longer length:      %9i\n' % size_v0[-1]))
>          median = size_v0[nbmarkers // 2]
> -        ui.write(('        median length:      %9i\n' % median))
> +        ui.write((b'        median length:      %9i\n' % median))
>          mean = sum(size_v0) // nbmarkers
> -        ui.write(('        mean length:        %9i\n' % mean))
> +        ui.write((b'        mean length:        %9i\n' % mean))
>
>      allclusters = list(set(clustersmap.values()))
>      allclusters.sort(key=lambda x: len(x[1]))
> -    ui.write(('disconnected clusters:      %9i\n' % len(allclusters)))
> +    ui.write((b'disconnected clusters:      %9i\n' % len(allclusters)))
>
> -    ui.write('        any known node:     %9i\n'
> +    ui.write(b'        any known node:     %9i\n'
>               % len([c for c in allclusters
>                      if [n for n in c[0] if nm.get(n) is not None]]))
>      if allclusters:
>          nbcluster = len(allclusters)
> -        ui.write(('        smallest length:    %9i\n' %
> len(allclusters[0][1])))
> -        ui.write(('        longer length:      %9i\n'
> -                 % len(allclusters[-1][1])))
> +        ui.write((b'        smallest length:    %9i\n' %
> len(allclusters[0][1])))
> +        ui.write((b'        longer length:      %9i\n'
> +                  % len(allclusters[-1][1])))
>          median = len(allclusters[nbcluster // 2][1])
> -        ui.write(('        median length:      %9i\n' % median))
> +        ui.write((b'        median length:      %9i\n' % median))
>          mean = sum(len(x[1]) for x in allclusters) // nbcluster
> -        ui.write(('        mean length:        %9i\n' % mean))
> +        ui.write((b'        mean length:        %9i\n' % mean))
>      allpclusters = list(set(pclustersmap.values()))
>      allpclusters.sort(key=lambda x: len(x[1]))
> -    ui.write(('    using parents data:     %9i\n' % len(allpclusters)))
> -    ui.write('        any known node:     %9i\n'
> +    ui.write((b'    using parents data:     %9i\n' % len(allpclusters)))
> +    ui.write(b'        any known node:     %9i\n'
>               % len([c for c in allclusters
>                      if [n for n in c[0] if nm.get(n) is not None]]))
>      if allpclusters:
>          nbcluster = len(allpclusters)
> -        ui.write(('        smallest length:    %9i\n'
> -                 % len(allpclusters[0][1])))
> -        ui.write(('        longer length:      %9i\n'
> -                 % len(allpclusters[-1][1])))
> +        ui.write((b'        smallest length:    %9i\n'
> +                  % len(allpclusters[0][1])))
> +        ui.write((b'        longer length:      %9i\n'
> +                  % len(allpclusters[-1][1])))
>          median = len(allpclusters[nbcluster // 2][1])
> -        ui.write(('        median length:      %9i\n' % median))
> +        ui.write((b'        median length:      %9i\n' % median))
>          mean = sum(len(x[1]) for x in allpclusters) // nbcluster
> -        ui.write(('        mean length:        %9i\n' % mean))
> +        ui.write((b'        mean length:        %9i\n' % mean))
> diff --git a/hgext3rd/evolve/depthcache.py b/hgext3rd/evolve/depthcache.py
> --- a/hgext3rd/evolve/depthcache.py
> +++ b/hgext3rd/evolve/depthcache.py
> @@ -32,39 +32,39 @@
>
>  def simpledepth(repo, rev):
>      """simple but obviously right implementation of depth"""
> -    return len(repo.revs('::%d', rev))
> +    return len(repo.revs(b'::%d', rev))
>
>  @eh.command(
> -    'debugdepth',
> +    b'debugdepth',
>      [
> -        ('r', 'rev', [], 'revs to print depth for'),
> -        ('', 'method', 'cached', "one of 'simple', 'cached', 'compare'"),
> -    ],
> -    _('REVS'))
> +        (b'r', b'rev', [], b'revs to print depth for'),
> +        (b'', b'method', b'cached', b"one of 'simple', 'cached',
> 'compare'"),
> +     ],
> +    _(b'REVS'))
>  def debugdepth(ui, repo, **opts):
>      """display depth of REVS
>      """
> -    revs = scmutil.revrange(repo, opts['rev'])
> -    method = opts['method']
> -    if method in ('cached', 'compare'):
> +    revs = scmutil.revrange(repo, opts[b'rev'])
> +    method = opts[b'method']
> +    if method in (b'cached', b'compare'):
>          cache = repo.depthcache
>          cache.save(repo)
>      for r in revs:
>          ctx = repo[r]
> -        if method == 'simple':
> +        if method == b'simple':
>              depth = simpledepth(repo, r)
> -        elif method == 'cached':
> +        elif method == b'cached':
>              depth = cache.get(r)
> -        elif method == 'compare':
> +        elif method == b'compare':
>              simple = simpledepth(repo, r)
>              cached = cache.get(r)
>              if simple != cached:
> -                raise error.Abort('depth differ for revision %s: %d != %d'
> +                raise error.Abort(b'depth differ for revision %s: %d !=
> %d'
>                                    % (ctx, simple, cached))
>              depth = simple
>          else:
> -            raise error.Abort('unknown method "%s"' % method)
> -        ui.write('%s %d\n' % (ctx, depth))
> +            raise error.Abort(b'unknown method "%s"' % method)
> +        ui.write(b'%s %d\n' % (ctx, depth))
>
>  @eh.reposetup
>  def setupcache(ui, repo):
> @@ -79,7 +79,7 @@
>
>          @localrepo.unfilteredmethod
>          def destroyed(self):
> -            if 'depthcache' in vars(self):
> +            if b'depthcache' in vars(self):
>                  self.depthcache.clear()
>              super(depthcacherepo, self).destroyed()
>
> @@ -94,16 +94,16 @@
>
>  class depthcache(genericcaches.changelogsourcebase):
>
> -    _filepath = 'evoext-depthcache-00'
> -    _cachename = 'evo-ext-depthcache'
> +    _filepath = b'evoext-depthcache-00'
> +    _cachename = b'evo-ext-depthcache'
>
>      def __init__(self):
>          super(depthcache, self).__init__()
> -        self._data = array.array('l')
> +        self._data = array.array(b'l')
>
>      def get(self, rev):
>          if len(self._data) <= rev:
> -            raise error.ProgrammingError('depthcache must be warmed
> before use')
> +            raise error.ProgrammingError(b'depthcache must be warmed
> before use')
>          return self._data[rev]
>
>      def _updatefrom(self, repo, data):
> @@ -113,15 +113,15 @@
>          total = len(data)
>
>          def progress(pos, rev):
> -            compat.progress(repo.ui, 'updating depth cache',
> -                            pos, 'rev %s' % rev, unit='revision',
> total=total)
> -        progress(0, '')
> +            compat.progress(repo.ui, b'updating depth cache',
> +                            pos, b'rev %s' % rev, unit=b'revision',
> total=total)
> +        progress(0, b'')
>          for idx, rev in enumerate(data, 1):
>              assert rev == len(self._data), (rev, len(self._data))
>              self._data.append(self._depth(cl, rev))
>              if not (idx % 10000): # progress as a too high performance
> impact
>                  progress(idx, rev)
> -        progress(None, '')
> +        progress(None, b'')
>
>      def _depth(self, changelog, rev):
>          cl = changelog
> @@ -170,7 +170,7 @@
>          Subclasses MUST overide this method to actually affect the cache
> data.
>          """
>          super(depthcache, self).clear()
> -        self._data = array.array('l')
> +        self._data = array.array(b'l')
>
>      # crude version of a cache, to show the kind of information we have
> to store
>
> @@ -179,7 +179,7 @@
>          assert repo.filtername is None
>
>          data = repo.cachevfs.tryread(self._filepath)
> -        self._data = array.array('l')
> +        self._data = array.array(b'l')
>          if not data:
>              self._cachekey = self.emptykey
>          else:
> @@ -198,12 +198,12 @@
>              return
>
>          try:
> -            cachefile = repo.cachevfs(self._filepath, 'w',
> atomictemp=True)
> +            cachefile = repo.cachevfs(self._filepath, b'w',
> atomictemp=True)
>              headerdata = self._serializecachekey()
>              cachefile.write(headerdata)
>              cachefile.write(self._data.tostring())
>              cachefile.close()
>              self._ondiskkey = self._cachekey
>          except (IOError, OSError) as exc:
> -            repo.ui.log('depthcache', 'could not write update %s\n' % exc)
> -            repo.ui.debug('depthcache: could not write update %s\n' % exc)
> +            repo.ui.log(b'depthcache', b'could not write update %s\n' %
> exc)
> +            repo.ui.debug(b'depthcache: could not write update %s\n' %
> exc)
> diff --git a/hgext3rd/evolve/evolvecmd.py b/hgext3rd/evolve/evolvecmd.py
> --- a/hgext3rd/evolve/evolvecmd.py
> +++ b/hgext3rd/evolve/evolvecmd.py
> @@ -52,7 +52,7 @@
>  eh = exthelper.exthelper()
>  mergetoolopts = commands.mergetoolopts
>
> -abortmessage = _("see `hg help evolve.interrupted`\n")
> +abortmessage = _(b"see `hg help evolve.interrupted`\n")
>
>  def _solveone(ui, repo, ctx, evolvestate, dryrun, confirm,
>                progresscb, category, lastsolved=None, stacktmplt=False):
> @@ -69,23 +69,23 @@
>      displayer = None
>      if stacktmplt:
>          displayer = compat.changesetdisplayer(ui, repo,
> -                                              {'template': stacktemplate})
> +                                              {b'template':
> stacktemplate})
>      else:
>          displayer = compat.changesetdisplayer(ui, repo,
> -                                              {'template': shorttemplate})
> -    if 'orphan' == category:
> +                                              {b'template':
> shorttemplate})
> +    if b'orphan' == category:
>          result = _solveunstable(ui, repo, ctx, evolvestate, displayer,
>                                  dryrun, confirm, progresscb,
>                                  lastsolved=lastsolved)
> -    elif 'phasedivergent' == category:
> +    elif b'phasedivergent' == category:
>          result = _solvephasedivergence(ui, repo, ctx, evolvestate,
>                                         displayer, dryrun, confirm,
>                                         progresscb)
> -    elif 'contentdivergent' == category:
> +    elif b'contentdivergent' == category:
>          result = _solvedivergent(ui, repo, ctx, evolvestate, displayer,
>                                   dryrun, confirm, progresscb)
>      else:
> -        assert False, "unknown trouble category: %s" % (category)
> +        assert False, b"unknown trouble category: %s" % (category)
>      return result
>
>  def _solveunstable(ui, repo, orig, evolvestate, displayer, dryrun=False,
> @@ -111,7 +111,7 @@
>          else:
>              # store that we are resolving an orphan merge with both
> parents
>              # obsolete and proceed with first parent
> -            evolvestate['orphanmerge'] = True
> +            evolvestate[b'orphanmerge'] = True
>              # we should process the second parent first, so that in case
> of
>              # no-conflicts the first parent is processed later and
> preserved as
>              # first parent
> @@ -119,40 +119,40 @@
>              keepbranch = orig.p2().branch() != orig.branch()
>
>      if not pctx.obsolete():
> -        ui.warn(_("cannot solve instability of %s, skipping\n") % orig)
> -        return (False, ".")
> +        ui.warn(_(b"cannot solve instability of %s, skipping\n") % orig)
> +        return (False, b".")
>      obs = pctx
>      newer = obsutil.successorssets(repo, obs.node())
>      # search of a parent which is not killed
>      while not newer or newer == [()]:
> -        ui.debug("stabilize target %s is plain dead,"
> -                 " trying to stabilize on its parent\n" %
> +        ui.debug(b"stabilize target %s is plain dead,"
> +                 b" trying to stabilize on its parent\n" %
>                   obs)
>          obs = obs.parents()[0]
>          newer = obsutil.successorssets(repo, obs.node())
>      if len(newer) > 1:
> -        msg = _("skipping %s: divergent rewriting. can't choose "
> -                "destination\n") % obs
> +        msg = _(b"skipping %s: divergent rewriting. can't choose "
> +                b"destination\n") % obs
>          ui.write_err(msg)
> -        return (False, ".")
> +        return (False, b".")
>      targets = newer[0]
>      assert targets
>      if len(targets) > 1:
>          # split target, figure out which one to pick, are they all in
> line?
>          targetrevs = [repo[r].rev() for r in targets]
> -        roots = repo.revs('roots(%ld)', targetrevs)
> -        heads = repo.revs('heads(%ld)', targetrevs)
> +        roots = repo.revs(b'roots(%ld)', targetrevs)
> +        heads = repo.revs(b'heads(%ld)', targetrevs)
>          if len(roots) > 1 or len(heads) > 1:
> -            cheader = _("ancestor '%s' split over multiple topological"
> -                        " branches.\nchoose an evolve destination:") %
> orig
> +            cheader = _(b"ancestor '%s' split over multiple topological"
> +                        b" branches.\nchoose an evolve destination:") %
> orig
>              selectedrev = utility.revselectionprompt(ui, repo,
> list(heads),
>                                                       cheader)
>              if selectedrev is None:
> -                msg = _("could not solve instability, "
> -                        "ambiguous destination: "
> -                        "parent split across two branches\n")
> +                msg = _(b"could not solve instability, "
> +                        b"ambiguous destination: "
> +                        b"parent split across two branches\n")
>                  ui.write_err(msg)
> -                return (False, ".")
> +                return (False, b".")
>              target = repo[selectedrev]
>          else:
>              target = repo[heads.first()]
> @@ -160,29 +160,29 @@
>          target = targets[0]
>      target = repo[target]
>      if not ui.quiet or confirm:
> -        repo.ui.write(_('move:'), label='evolve.operation')
> +        repo.ui.write(_(b'move:'), label=b'evolve.operation')
>          displayer.show(orig)
>          if lastsolved is None or target != repo[lastsolved]:
> -            repo.ui.write(_('atop:'))
> +            repo.ui.write(_(b'atop:'))
>              displayer.show(target)
> -    if confirm and ui.prompt('perform evolve? [Ny]', 'n') != 'y':
> -        raise error.Abort(_('evolve aborted by user'))
> -    todo = 'hg rebase -r %s -d %s\n' % (orig, target)
> +    if confirm and ui.prompt(b'perform evolve? [Ny]', b'n') != b'y':
> +        raise error.Abort(_(b'evolve aborted by user'))
> +    todo = b'hg rebase -r %s -d %s\n' % (orig, target)
>      if dryrun:
>          if progresscb:
>              progresscb()
>          repo.ui.write(todo)
> -        return (False, ".")
> +        return (False, b".")
>      else:
>          repo.ui.note(todo)
>          if progresscb:
>              progresscb()
>          try:
>              newid = relocate(repo, orig, target, evolvestate, pctx,
> -                             keepbranch, 'orphan')
> +                             keepbranch, b'orphan')
>              return (True, newid)
>          except error.InterventionRequired:
> -            ops = {'current': orig.node()}
> +            ops = {b'current': orig.node()}
>              evolvestate.addopts(ops)
>              evolvestate.save()
>              raise
> @@ -201,32 +201,32 @@
>      bumped = repo[bumped.rev()]
>      # For now we deny bumped merge
>      if len(bumped.parents()) > 1:
> -        msg = _('skipping %s : we do not handle merge yet\n') % bumped
> +        msg = _(b'skipping %s : we do not handle merge yet\n') % bumped
>          ui.write_err(msg)
> -        return (False, ".")
> -    prec = repo.set('last(allpredecessors(%d) and public())',
> bumped.rev()).next()
> +        return (False, b".")
> +    prec = repo.set(b'last(allpredecessors(%d) and public())',
> bumped.rev()).next()
>      # For now we deny target merge
>      if len(prec.parents()) > 1:
> -        msg = _('skipping: %s: public version is a merge, '
> -                'this is not handled yet\n') % prec
> +        msg = _(b'skipping: %s: public version is a merge, '
> +                b'this is not handled yet\n') % prec
>          ui.write_err(msg)
> -        return (False, ".")
> +        return (False, b".")
>
>      if not ui.quiet or confirm:
> -        repo.ui.write(_('recreate:'), label='evolve.operation')
> +        repo.ui.write(_(b'recreate:'), label=b'evolve.operation')
>          displayer.show(bumped)
> -        repo.ui.write(_('atop:'))
> +        repo.ui.write(_(b'atop:'))
>          displayer.show(prec)
> -    if confirm and ui.prompt('perform evolve? [Ny]', 'n') != 'y':
> -        raise error.Abort(_('evolve aborted by user'))
> +    if confirm and ui.prompt(b'perform evolve? [Ny]', b'n') != b'y':
> +        raise error.Abort(_(b'evolve aborted by user'))
>      if dryrun:
> -        todo = 'hg rebase --rev %s --dest %s;\n' % (bumped, prec.p1())
> +        todo = b'hg rebase --rev %s --dest %s;\n' % (bumped, prec.p1())
>          repo.ui.write(todo)
> -        repo.ui.write(('hg update %s;\n' % prec))
> -        repo.ui.write(('hg revert --all --rev %s;\n' % bumped))
> -        repo.ui.write(('hg commit --msg "%s update to %s"\n' %
> -                       (TROUBLES['PHASEDIVERGENT'], bumped)))
> -        return (False, ".")
> +        repo.ui.write((b'hg update %s;\n' % prec))
> +        repo.ui.write((b'hg revert --all --rev %s;\n' % bumped))
> +        repo.ui.write((b'hg commit --msg "%s update to %s"\n' %
> +                       (TROUBLES[b'PHASEDIVERGENT'], bumped)))
> +        return (False, b".")
>      if progresscb:
>          progresscb()
>
> @@ -236,22 +236,22 @@
>      # evolved or any other operation which can change parent. In such
> cases,
>      # when parents are not same, we first rebase the divergent changeset
> onto
>      # parent or precursor and then perform later steps
> -    if not list(repo.set('parents(%d) and parents(%d)', bumped.rev(),
> prec.rev())):
> +    if not list(repo.set(b'parents(%d) and parents(%d)', bumped.rev(),
> prec.rev())):
>          # Need to rebase the changeset at the right place
>          repo.ui.status(
> -            _('rebasing to destination parent: %s\n') % prec.p1())
> +            _(b'rebasing to destination parent: %s\n') % prec.p1())
>          try:
>              newnode = relocate(repo, bumped, prec.p1(), evolvestate,
> -                               category='phasedivergent')
> +                               category=b'phasedivergent')
>              if newnode is not None:
>                  new = repo[newnode]
>                  obsolete.createmarkers(repo, [(bumped, (new,))],
> -                                       operation='evolve')
> +                                       operation=b'evolve')
>                  bumped = new
> -                evolvestate['temprevs'].append(newnode)
> +                evolvestate[b'temprevs'].append(newnode)
>          except error.InterventionRequired:
> -            evolvestate['current'] = bumped.hex()
> -            evolvestate['precursor'] = prec.hex()
> +            evolvestate[b'current'] = bumped.hex()
> +            evolvestate[b'precursor'] = prec.hex()
>              evolvestate.save()
>              raise
>
> @@ -283,7 +283,7 @@
>      merge.update(repo, bumped.node(), ancestor=prec, mergeancestor=True,
>                   branchmerge=True, force=False, wc=wctx)
>      if not wctx.isempty():
> -        text = '%s update to %s:\n\n' % (TROUBLES['PHASEDIVERGENT'], prec)
> +        text = b'%s update to %s:\n\n' % (TROUBLES[b'PHASEDIVERGENT'],
> prec)
>          text += bumped.description()
>          memctx = wctx.tomemctx(text,
>                                 parents=(prec.node(), nodemod.nullid),
> @@ -293,14 +293,14 @@
>          newid = repo.commitctx(memctx)
>          replacementnode = newid
>      if newid is None:
> -        repo.ui.status(_('no changes to commit\n'))
> -        obsolete.createmarkers(repo, [(bumped, ())], operation='evolve')
> +        repo.ui.status(_(b'no changes to commit\n'))
> +        obsolete.createmarkers(repo, [(bumped, ())], operation=b'evolve')
>          newid = prec.node()
>      else:
> -        repo.ui.status(_('committed as %s\n') % nodemod.short(newid))
> +        repo.ui.status(_(b'committed as %s\n') % nodemod.short(newid))
>          phases.retractboundary(repo, tr, bumped.phase(), [newid])
>          obsolete.createmarkers(repo, [(bumped, (repo[newid],))],
> -                               flag=obsolete.bumpedfix,
> operation='evolve')
> +                               flag=obsolete.bumpedfix,
> operation=b'evolve')
>      bmupdate(newid)
>      # reroute the working copy parent to the new changeset
>      with repo.dirstate.parentchange():
> @@ -319,45 +319,45 @@
>      """
>      repo = repo.unfiltered()
>      divergent = repo[divergent.rev()]
> -    evolvestate['divergent'] = divergent.node()
> -    evolvestate['orig-divergent'] = divergent.node()
> +    evolvestate[b'divergent'] = divergent.node()
> +    evolvestate[b'orig-divergent'] = divergent.node()
>      # sometimes we will relocate a node in case of different parents and
> we can
>      # encounter conflicts after relocation is done while solving
>      # content-divergence and if the user calls `hg evolve --stop`, we
> need to
>      # strip that relocated commit. However if `--all` is passed, we need
> to
>      # reset this value for each content-divergence resolution which we
> are doing
>      # below.
> -    evolvestate['relocated'] = None
> -    evolvestate['relocating'] = False
> +    evolvestate[b'relocated'] = None
> +    evolvestate[b'relocating'] = False
>      # in case or relocation we get a new other node, we need to store the
> old
>      # other for purposes like `--abort` or `--stop`
> -    evolvestate['old-other'] = None
> +    evolvestate[b'old-other'] = None
>      base, others = divergentdata(divergent)
>
>      # we don't handle split in content-divergence yet
>      if len(others) > 1:
> -        othersstr = "[%s]" % (','.join([str(i) for i in others]))
> -        msg = _("skipping %s: %s with a changeset that got split"
> -                " into multiple ones:\n"
> -                "|[%s]\n"
> -                "| This is not handled by automatic evolution yet\n"
> -                "| You have to fallback to manual handling with commands "
> -                "such as:\n"
> -                "| - hg touch -D\n"
> -                "| - hg prune\n"
> -                "| \n"
> -                "| You should contact your local evolution Guru for
> help.\n"
> -                ) % (divergent, TROUBLES['CONTENTDIVERGENT'], othersstr)
> +        othersstr = b"[%s]" % (b','.join([str(i) for i in others]))
> +        msg = _(b"skipping %s: %s with a changeset that got split"
> +                b" into multiple ones:\n"
> +                b"|[%s]\n"
> +                b"| This is not handled by automatic evolution yet\n"
> +                b"| You have to fallback to manual handling with commands
> "
> +                b"such as:\n"
> +                b"| - hg touch -D\n"
> +                b"| - hg prune\n"
> +                b"| \n"
> +                b"| You should contact your local evolution Guru for
> help.\n"
> +                ) % (divergent, TROUBLES[b'CONTENTDIVERGENT'], othersstr)
>          ui.write_err(msg)
> -        return (False, ".")
> +        return (False, b".")
>      other = others[0]
> -    evolvestate['other-divergent'] = other.node()
> -    evolvestate['base'] = base.node()
> +    evolvestate[b'other-divergent'] = other.node()
> +    evolvestate[b'base'] = base.node()
>
>      def swapnodes(div, other):
>          div, other = other, div
> -        evolvestate['divergent'] = div.node()
> -        evolvestate['other-divergent'] = other.node()
> +        evolvestate[b'divergent'] = div.node()
> +        evolvestate[b'other-divergent'] = other.node()
>          return div, other
>      # haspubdiv: to keep track if we are solving public content-divergence
>      haspubdiv = False
> @@ -370,17 +370,17 @@
>              divergent, other = swapnodes(divergent, other)
>          else:
>              publicdiv = divergent
> -        evolvestate['public-divergent'] = publicdiv.node()
> +        evolvestate[b'public-divergent'] = publicdiv.node()
>      # we don't handle merge content-divergent changesets yet
>      if len(other.parents()) > 1:
> -        msg = _("skipping %s: %s changeset can't be "
> -                "a merge (yet)\n") % (divergent,
> TROUBLES['CONTENTDIVERGENT'])
> +        msg = _(b"skipping %s: %s changeset can't be "
> +                b"a merge (yet)\n") % (divergent,
> TROUBLES[b'CONTENTDIVERGENT'])
>          ui.write_err(msg)
> -        hint = _("You have to fallback to solving this by hand...\n"
> -                 "| This probably means redoing the merge and using \n"
> -                 "| `hg prune` to kill older version.\n")
> +        hint = _(b"You have to fallback to solving this by hand...\n"
> +                 b"| This probably means redoing the merge and using \n"
> +                 b"| `hg prune` to kill older version.\n")
>          ui.write_err(hint)
> -        return (False, ".")
> +        return (False, b".")
>
>      otherp1 = other.p1().rev()
>      divp1 = divergent.p1().rev()
> @@ -399,15 +399,15 @@
>      # the changeset on which resolution changeset will be based on
>      resolutionparent = repo[divp1].node()
>
> -    gca = repo.revs("ancestor(%d, %d)" % (otherp1, divp1))
> +    gca = repo.revs(b"ancestor(%d, %d)" % (otherp1, divp1))
>      # divonly: non-obsolete csets which are topological ancestor of
> "divergent"
>      # but not "other"
> -    divonly = repo.revs("only(%d, %d) - obsolete()" % (divergent.rev(),
> -                                                       other.rev()))
> +    divonly = repo.revs(b"only(%d, %d) - obsolete()" % (divergent.rev(),
> +                                                        other.rev()))
>      # otheronly: non-obsolete csets which are topological ancestor of
> "other"
>      # but not "div"
> -    otheronly = repo.revs("only(%d, %d) - obsolete()" % (other.rev(),
> -                                                         divergent.rev()))
> +    otheronly = repo.revs(b"only(%d, %d) - obsolete()" % (other.rev(),
> +
> divergent.rev()))
>      # make it exclusive set
>      divonly = set(divonly) - {divergent.rev()}
>      otheronly = set(otheronly) - {other.rev()}
> @@ -467,62 +467,62 @@
>              divergent, other = swapnodes(divergent, other)
>              resolutionparent = divergent.p1().node()
>      else:
> -        msg = _("skipping %s: have a different parent than %s "
> -                "(not handled yet)\n") % (divergent, other)
> -        hint = _("| %(d)s, %(o)s are not based on the same changeset.\n"
> -                 "| With the current state of its implementation, \n"
> -                 "| evolve does not work in that case.\n"
> -                 "| rebase one of them next to the other and run \n"
> -                 "| this command again.\n"
> -                 "| - either: hg rebase --dest 'p1(%(d)s)' -r %(o)s\n"
> -                 "| - or:     hg rebase --dest 'p1(%(o)s)' -r %(d)s\n"
> -                 ) % {'d': divergent, 'o': other}
> +        msg = _(b"skipping %s: have a different parent than %s "
> +                b"(not handled yet)\n") % (divergent, other)
> +        hint = _(b"| %(d)s, %(o)s are not based on the same changeset.\n"
> +                 b"| With the current state of its implementation, \n"
> +                 b"| evolve does not work in that case.\n"
> +                 b"| rebase one of them next to the other and run \n"
> +                 b"| this command again.\n"
> +                 b"| - either: hg rebase --dest 'p1(%(d)s)' -r %(o)s\n"
> +                 b"| - or:     hg rebase --dest 'p1(%(o)s)' -r %(d)s\n"
> +                 ) % {b'd': divergent, b'o': other}
>          ui.write_err(msg)
>          ui.write_err(hint)
> -        return (False, ".")
> +        return (False, b".")
>
>      if not ui.quiet or confirm:
> -        ui.write(_('merge:'), label='evolve.operation')
> +        ui.write(_(b'merge:'), label=b'evolve.operation')
>          displayer.show(divergent)
> -        ui.write(_('with: '))
> +        ui.write(_(b'with: '))
>          displayer.show(other)
> -        ui.write(_('base: '))
> +        ui.write(_(b'base: '))
>          displayer.show(base)
> -    if confirm and ui.prompt(_('perform evolve? [Ny]'), 'n') != 'y':
> -        raise error.Abort(_('evolve aborted by user'))
> +    if confirm and ui.prompt(_(b'perform evolve? [Ny]'), b'n') != b'y':
> +        raise error.Abort(_(b'evolve aborted by user'))
>      if dryrun:
> -        ui.write(('hg update -c %s &&\n' % divergent))
> -        ui.write(('hg merge %s &&\n' % other))
> -        ui.write(('hg commit -m "auto merge resolving conflict between '
> -                 '%s and %s"&&\n' % (divergent, other)))
> -        ui.write(('hg up -C %s &&\n' % base))
> -        ui.write(('hg revert --all --rev tip &&\n'))
> -        ui.write(('hg commit -m "`hg log -r %s --template={desc}`";\n'
> -                 % divergent))
> -        return (False, ".")
> +        ui.write((b'hg update -c %s &&\n' % divergent))
> +        ui.write((b'hg merge %s &&\n' % other))
> +        ui.write((b'hg commit -m "auto merge resolving conflict between '
> +                  b'%s and %s"&&\n' % (divergent, other)))
> +        ui.write((b'hg up -C %s &&\n' % base))
> +        ui.write((b'hg revert --all --rev tip &&\n'))
> +        ui.write((b'hg commit -m "`hg log -r %s --template={desc}`";\n'
> +                  % divergent))
> +        return (False, b".")
>
> -    evolvestate['resolutionparent'] = resolutionparent
> +    evolvestate[b'resolutionparent'] = resolutionparent
>      # relocate the other divergent if required
>      if relocatereq:
>          # relocating will help us understand during the time of conflicts
> that
>          # whether conflicts occur at reloacting or they occured at merging
>          # content divergent changesets
> -        evolvestate['relocating'] = True
> -        ui.status(_('rebasing "other" content-divergent changeset %s on'
> -                    ' %s\n' % (other, divergent.p1())))
> +        evolvestate[b'relocating'] = True
> +        ui.status(_(b'rebasing "other" content-divergent changeset %s on'
> +                    b' %s\n' % (other, divergent.p1())))
>          try:
>              newother = relocate(repo, other, divergent.p1(), evolvestate,
>                                  keepbranch=True)
>          except error.InterventionRequired:
> -            evolvestate['current'] = other.node()
> +            evolvestate[b'current'] = other.node()
>              evolvestate.save()
>              raise
> -        evolvestate['old-other'] = other.node()
> +        evolvestate[b'old-other'] = other.node()
>          other = repo[newother]
> -        evolvestate['relocating'] = False
> -        evolvestate['relocated'] = other.node()
> -        evolvestate['temprevs'].append(other.node())
> -        evolvestate['other-divergent'] = other.node()
> +        evolvestate[b'relocating'] = False
> +        evolvestate[b'relocated'] = other.node()
> +        evolvestate[b'temprevs'].append(other.node())
> +        evolvestate[b'other-divergent'] = other.node()
>
>      _mergecontentdivergents(repo, progresscb, divergent, other, base,
>                              evolvestate)
> @@ -544,9 +544,9 @@
>              # case 2)
>              pubstr = str(publicdiv)
>              othstr = str(other)
> -            msg = _('content divergence resolution between %s '
> -                    '(public) and %s has same content as %s, '
> -                    'discarding %s\n')
> +            msg = _(b'content divergence resolution between %s '
> +                    b'(public) and %s has same content as %s, '
> +                    b'discarding %s\n')
>              msg %= (pubstr, othstr, pubstr, othstr)
>              repo.ui.status(msg)
>              return (res, newnode)
> @@ -558,12 +558,12 @@
>  def _mergecontentdivergents(repo, progresscb, divergent, other, base,
>                              evolvestate):
>      if divergent not in repo[None].parents():
> -        repo.ui.note(_("updating to \"local\" side of the conflict:
> %s\n") %
> +        repo.ui.note(_(b"updating to \"local\" side of the conflict:
> %s\n") %
>                       divergent.hex()[:12])
>          hg.updaterepo(repo, divergent.node(), False)
>      # merging the two content-divergent changesets
> -    repo.ui.note(_("merging \"other\" %s changeset '%s'\n") %
> -                 (TROUBLES['CONTENTDIVERGENT'], other.hex()[:12]))
> +    repo.ui.note(_(b"merging \"other\" %s changeset '%s'\n") %
> +                 (TROUBLES[b'CONTENTDIVERGENT'], other.hex()[:12]))
>      if progresscb:
>          progresscb()
>      mergeancestor = repo.changelog.isancestor(divergent.node(),
> other.node())
> @@ -578,8 +578,8 @@
>      # conflicts while merging content-divergent changesets
>      if compat.hasconflict(stats):
>          evolvestate.save()
> -        raise error.InterventionRequired(_("fix conflicts and see `hg
> help "
> -                                           "evolve.interrupted`"))
> +        raise error.InterventionRequired(_(b"fix conflicts and see `hg
> help "
> +                                           b"evolve.interrupted`"))
>
>  def _completecontentdivergent(ui, repo, progresscb, divergent, other,
>                                base, evolvestate):
> @@ -588,20 +588,20 @@
>      # resume resolution
>      if progresscb:
>          progresscb()
> -    emtpycommitallowed = repo.ui.backupconfig('ui', 'allowemptycommit')
> +    emtpycommitallowed = repo.ui.backupconfig(b'ui', b'allowemptycommit')
>      tr = repo.currenttransaction()
>      assert tr is not None
>      # whether to store the obsmarker in the evolvestate
>      storemarker = False
> -    resparent = evolvestate['resolutionparent']
> +    resparent = evolvestate[b'resolutionparent']
>
>      # whether we are solving public divergence
>      haspubdiv = False
> -    if evolvestate.get('public-divergent'):
> +    if evolvestate.get(b'public-divergent'):
>          haspubdiv = True
> -        publicnode = evolvestate['public-divergent']
> +        publicnode = evolvestate[b'public-divergent']
>          publicdiv = repo[publicnode]
> -        othernode = evolvestate['other-divergent']
> +        othernode = evolvestate[b'other-divergent']
>          otherdiv = repo[othernode]
>
>          with repo.dirstate.parentchange():
> @@ -614,7 +614,7 @@
>              warnmetadataloss(repo, publicdiv, otherdiv)
>              # no changes, create markers to resolve divergence
>              obsolete.createmarkers(repo, [(otherdiv, (publicdiv,))],
> -                                   operation='evolve')
> +                                   operation=b'evolve')
>              return (True, publicnode)
>      try:
>          with repo.dirstate.parentchange():
> @@ -639,29 +639,29 @@
>              # no changes
>              new = divergent
>              storemarker = True
> -            repo.ui.status(_("nothing changed\n"))
> +            repo.ui.status(_(b"nothing changed\n"))
>              hg.updaterepo(repo, divergent.rev(), False)
>          else:
>              new = repo[newnode]
>              newnode = new.node()
>              hg.updaterepo(repo, new.rev(), False)
>              if haspubdiv and publicdiv == divergent:
> -                bypassphase(repo, (divergent, new), operation='evolve')
> +                bypassphase(repo, (divergent, new), operation=b'evolve')
>              else:
>                  obsolete.createmarkers(repo, [(divergent, (new,))],
> -                                       operation='evolve')
> +                                       operation=b'evolve')
>
>          # creating markers and moving phases post-resolution
>          if haspubdiv and publicdiv == other:
> -            bypassphase(repo, (other, new), operation='evolve')
> +            bypassphase(repo, (other, new), operation=b'evolve')
>          else:
> -            obsolete.createmarkers(repo, [(other, (new,))],
> operation='evolve')
> +            obsolete.createmarkers(repo, [(other, (new,))],
> operation=b'evolve')
>          if storemarker:
>              # storing the marker in the evolvestate
>              # we just store the precursors and successor pair for now, we
> might
>              # want to store more data and serialize obsmarker in a better
> way in
>              # future
> -            evolvestate['obsmarkers'].append((other.node(), new.node()))
> +            evolvestate[b'obsmarkers'].append((other.node(), new.node()))
>
>          phases.retractboundary(repo, tr, other.phase(), [new.node()])
>          return (True, newnode)
> @@ -673,7 +673,7 @@
>      public content-divergence"""
>
>      # needtowarn: aspects where we need to warn user
> -    needtowarn = ['branch', 'topic', 'close']
> +    needtowarn = [b'branch', b'topic', b'close']
>      aspects = set()
>      localextra = local.extra()
>      otherextra = other.extra()
> @@ -685,48 +685,48 @@
>              aspects.add(asp)
>
>      if other.description() != local.description():
> -        aspects.add('description')
> +        aspects.add(b'description')
>
>      if aspects:
>          # warn user
>          locstr = str(local)
>          othstr = str(other)
> -        if 'close' in aspects:
> -            filteredasp = aspects - {'close'}
> +        if b'close' in aspects:
> +            filteredasp = aspects - {b'close'}
>              if filteredasp:
> -                msg = _('other divergent changeset %s is a closed branch
> head '
> -                        'and differs from local %s by "%s" only,' %
> -                        (othstr, locstr, ', '.join(sorted(filteredasp))))
> +                msg = _(b'other divergent changeset %s is a closed branch
> head '
> +                        b'and differs from local %s by "%s" only,' %
> +                        (othstr, locstr, b', '.join(sorted(filteredasp))))
>              else:
> -                msg = _('other divergent changeset %s is a closed branch
> head '
> -                        'and has same content as local %s,' % (othstr,
> locstr))
> +                msg = _(b'other divergent changeset %s is a closed branch
> head '
> +                        b'and has same content as local %s,' % (othstr,
> locstr))
>          else:
> -            msg = _('other divergent changeset %s has same content as
> local %s'
> -                    ' and differs by "%s" only,' %
> -                    (othstr, locstr, ', '.join(sorted(aspects))))
> -        msg += _(' discarding %s\n' % othstr)
> +            msg = _(b'other divergent changeset %s has same content as
> local %s'
> +                    b' and differs by "%s" only,' %
> +                    (othstr, locstr, b', '.join(sorted(aspects))))
> +        msg += _(b' discarding %s\n' % othstr)
>          repo.ui.warn(msg)
>
> -def bypassphase(repo, relation, flag=0, metadata=None,
> operation='evolve'):
> +def bypassphase(repo, relation, flag=0, metadata=None,
> operation=b'evolve'):
>      """function to create a single obsmarker relation even for public
> csets
>      where relation should be a single pair (prec, succ)"""
>
>      # prepare metadata
>      if metadata is None:
>          metadata = {}
> -    if 'user' not in metadata:
> -        luser = repo.ui.config('devel', 'user.obsmarker') or
> repo.ui.username()
> -        metadata['user'] = encoding.fromlocal(luser)
> +    if b'user' not in metadata:
> +        luser = repo.ui.config(b'devel', b'user.obsmarker') or
> repo.ui.username()
> +        metadata[b'user'] = encoding.fromlocal(luser)
>      # Operation metadata handling
> -    useoperation = repo.ui.configbool('experimental',
> -                                      'evolution.track-operation')
> +    useoperation = repo.ui.configbool(b'experimental',
> +                                      b'evolution.track-operation')
>      if useoperation and operation:
> -        metadata['operation'] = operation
> +        metadata[b'operation'] = operation
>
>      # Effect flag metadata handling
> -    saveeffectflag = repo.ui.configbool('experimental',
> -                                        'evolution.effect-flags')
> -    with repo.transaction('add-obsolescence-marker') as tr:
> +    saveeffectflag = repo.ui.configbool(b'experimental',
> +                                        b'evolution.effect-flags')
> +    with repo.transaction(b'add-obsolescence-marker') as tr:
>          prec, succ = relation
>          nprec = prec.node()
>          npare = None
> @@ -734,7 +734,7 @@
>          if not nsucs:
>              npare = tuple(p.node() for p in prec.parents())
>          if nprec in nsucs:
> -            raise error.Abort(_("changeset %s cannot obsolete itself") %
> prec)
> +            raise error.Abort(_(b"changeset %s cannot obsolete itself") %
> prec)
>
>          if saveeffectflag:
>              # The effect flag is saved in a versioned field name for
> @@ -744,7 +744,7 @@
>              except TypeError:
>                  # hg <= 4.7
>                  effectflag = obsutil.geteffectflag((prec, (succ,)))
> -            metadata[obsutil.EFFECTFLAGFIELD] = "%d" % effectflag
> +            metadata[obsutil.EFFECTFLAGFIELD] = b"%d" % effectflag
>
>          # create markers
>          repo.obsstore.create(tr, nprec, nsucs, flag, parents=npare,
> @@ -846,11 +846,11 @@
>              repo.dirstate.setbranch(othbranch)
>          else:
>              # all the three branches are different
> -            index = repo.ui.promptchoice(_("content divergent changesets
> on "
> -                                           "different branches.\nchoose
> branch"
> -                                           " for the resolution
> changeset. (a) "
> -                                           "%s or (b) %s or (c) %s? $$ &a
> $$ &b"
> -                                           " $$ &c") %
> +            index = repo.ui.promptchoice(_(b"content divergent changesets
> on "
> +                                           b"different branches.\nchoose
> branch"
> +                                           b" for the resolution
> changeset. (a) "
> +                                           b"%s or (b) %s or (c) %s? $$
> &a $$ &b"
> +                                           b" $$ &c") %
>                                           (basebranch, divbranch,
> othbranch), 0)
>
>              if index == 0:
> @@ -867,20 +867,20 @@
>      merger = simplemerge.Merge3Text(basedesc, divdesc, othdesc)
>      mdesc = []
>      kwargs = {}
> -    kwargs['name_base'] = 'base'
> -    kwargs['base_marker'] = '|||||||'
> -    for line in merger.merge_lines(name_a='divergent', name_b='other',
> +    kwargs[b'name_base'] = b'base'
> +    kwargs[b'base_marker'] = b'|||||||'
> +    for line in merger.merge_lines(name_a=b'divergent', name_b=b'other',
>                                     **kwargs):
>          mdesc.append(line)
>
> -    desc = ''.join(mdesc)
> +    desc = b''.join(mdesc)
>      if merger.conflicts:
>
> -        prefixes = ("HG: Conflicts while merging changeset description of"
> -                    " content-divergent changesets.\nHG: Resolve
> conflicts"
> -                    " in commit messages to continue.\n\n")
> +        prefixes = (b"HG: Conflicts while merging changeset description
> of"
> +                    b" content-divergent changesets.\nHG: Resolve
> conflicts"
> +                    b" in commit messages to continue.\n\n")
>
> -        resolveddesc = ui.edit(prefixes + desc, ui.username(),
> action='desc')
> +        resolveddesc = ui.edit(prefixes + desc, ui.username(),
> action=b'desc')
>          # make sure we remove the prefixes part from final commit message
>          if prefixes in resolveddesc:
>              # hack, we should find something better
> @@ -931,17 +931,17 @@
>      returns the node of new commit which is formed
>      """
>      if orig.rev() == dest.rev():
> -        msg = _('tried to relocate a node on top of itself')
> -        hint = _("This shouldn't happen. If you still need to move
> changesets, "
> -                 "please do so manually with nothing to rebase - working "
> -                 "directory parent is also destination")
> +        msg = _(b'tried to relocate a node on top of itself')
> +        hint = _(b"This shouldn't happen. If you still need to move
> changesets, "
> +                 b"please do so manually with nothing to rebase - working
> "
> +                 b"directory parent is also destination")
>          raise error.ProgrammingError(msg, hint=hint)
>
>      if pctx is None:
>          if len(orig.parents()) == 2:
> -            msg = _("tried to relocate a merge commit without specifying
> which "
> -                    "parent should be moved")
> -            hint = _("Specify the parent by passing in pctx")
> +            msg = _(b"tried to relocate a merge commit without specifying
> which "
> +                    b"parent should be moved")
> +            hint = _(b"Specify the parent by passing in pctx")
>              raise error.ProgrammingError(msg, hint)
>          pctx = orig.p1()
>
> @@ -951,7 +951,7 @@
>      sha1s = re.findall(sha1re, commitmsg)
>      unfi = repo.unfiltered()
>      for sha1 in sha1s:
> -        if util.safehasattr(scmutil, 'resolvehexnodeidprefix'): # > hg-4.6
> +        if util.safehasattr(scmutil, b'resolvehexnodeidprefix'): # >
> hg-4.6
>              fullnode = scmutil.resolvehexnodeidprefix(unfi, sha1)
>          else:
>              fullnode = unfi.changelog.index.partialmatch(sha1)
> @@ -969,8 +969,8 @@
>              newsha1 = nodemod.hex(successors[0][0])
>              commitmsg = commitmsg.replace(sha1, newsha1[:len(sha1)])
>          else:
> -            repo.ui.note(_('The stale commit message reference to %s
> could '
> -                           'not be updated\n') % sha1)
> +            repo.ui.note(_(b'The stale commit message reference to %s
> could '
> +                           b'not be updated\n') % sha1)
>
>      tr = repo.currenttransaction()
>      assert tr is not None
> @@ -983,8 +983,8 @@
>              copies.duplicatecopies(repo, repo[None], dest.rev(),
>                                     orig.p1().rev())
>              dirstatedance(repo, dest, orig.node(), None)
> -        raise error.InterventionRequired(_("fix conflicts and see `hg
> help "
> -                                           "evolve.interrupted`"))
> +        raise error.InterventionRequired(_(b"fix conflicts and see `hg
> help "
> +                                           b"evolve.interrupted`"))
>      nodenew = _relocatecommit(repo, orig, commitmsg)
>      _finalizerelocate(repo, orig, dest, nodenew, tr, category,
> evolvestate)
>      return nodenew
> @@ -993,14 +993,14 @@
>      if commitmsg is None:
>          commitmsg = orig.description()
>      extra = dict(orig.extra())
> -    if 'branch' in extra:
> -        del extra['branch']
> -    extra['rebase_source'] = orig.hex()
> +    if b'branch' in extra:
> +        del extra[b'branch']
> +    extra[b'rebase_source'] = orig.hex()
>
> -    backup = repo.ui.backupconfig('phases', 'new-commit')
> +    backup = repo.ui.backupconfig(b'phases', b'new-commit')
>      try:
>          targetphase = max(orig.phase(), phases.draft)
> -        repo.ui.setconfig('phases', 'new-commit', targetphase, 'evolve')
> +        repo.ui.setconfig(b'phases', b'new-commit', targetphase,
> b'evolve')
>          # Commit might fail if unresolved files exist
>          nodenew = repo.commit(text=commitmsg, user=orig.user(),
>                                date=orig.date(), extra=extra)
> @@ -1016,18 +1016,18 @@
>
>      if nodenew is not None:
>          obsolete.createmarkers(repo, [(repo[nodesrc], (repo[nodenew],))],
> -                               operation='evolve')
> +                               operation=b'evolve')
>          for book in oldbookmarks:
>              bmchanges.append((book, nodenew))
> -            evolvestate['bookmarkchanges'].append((book, nodesrc))
> +            evolvestate[b'bookmarkchanges'].append((book, nodesrc))
>      else:
> -        if category == 'orphan':
> -            repo.ui.status(_("evolution of %d:%s created no changes "
> -                             "to commit\n") % (orig.rev(), orig))
> -        obsolete.createmarkers(repo, [(repo[nodesrc], ())],
> operation='evolve')
> +        if category == b'orphan':
> +            repo.ui.status(_(b"evolution of %d:%s created no changes "
> +                             b"to commit\n") % (orig.rev(), orig))
> +        obsolete.createmarkers(repo, [(repo[nodesrc], ())],
> operation=b'evolve')
>          # Behave like rebase, move bookmarks to dest
>          for book in oldbookmarks:
> -            evolvestate['bookmarkchanges'].append((book, nodesrc))
> +            evolvestate[b'bookmarkchanges'].append((book, nodesrc))
>              bmchanges.append((book, dest.node()))
>      for book in destbookmarks: # restore bookmark that rebase move
>          bmchanges.append((book, dest.node()))
> @@ -1037,61 +1037,61 @@
>  def _evolvemerge(repo, orig, dest, pctx, keepbranch):
>      """Used by the evolve function to merge dest on top of pctx.
>      return the same tuple as merge.graft"""
> -    if repo['.'].rev() != dest.rev():
> +    if repo[b'.'].rev() != dest.rev():
>          merge.update(repo,
>                       dest,
>                       branchmerge=False,
>                       force=True)
>      if repo._activebookmark:
> -        repo.ui.status(_("(leaving bookmark %s)\n") %
> repo._activebookmark)
> +        repo.ui.status(_(b"(leaving bookmark %s)\n") %
> repo._activebookmark)
>      bookmarksmod.deactivate(repo)
>      if keepbranch:
>          repo.dirstate.setbranch(orig.branch())
> -    if util.safehasattr(repo, 'currenttopic'):
> +    if util.safehasattr(repo, b'currenttopic'):
>          # uurrgs
>          # there no other topic setter yet
> -        if not orig.topic() and repo.vfs.exists('topic'):
> -            repo.vfs.unlink('topic')
> +        if not orig.topic() and repo.vfs.exists(b'topic'):
> +            repo.vfs.unlink(b'topic')
>          else:
> -            with repo.vfs.open('topic', 'w') as f:
> +            with repo.vfs.open(b'topic', b'w') as f:
>                  f.write(orig.topic())
>
> -    return merge.graft(repo, orig, pctx, ['destination', 'evolving'],
> True)
> +    return merge.graft(repo, orig, pctx, [b'destination', b'evolving'],
> True)
>
>  instabilities_map = {
> -    'contentdivergent': "content-divergent",
> -    'phasedivergent': "phase-divergent"
> +    b'contentdivergent': b"content-divergent",
> +    b'phasedivergent': b"phase-divergent"
>  }
>
>  def _selectrevs(repo, allopt, revopt, anyopt, targetcat):
>      """select troubles in repo matching according to given options"""
>      revs = set()
>      if allopt or revopt:
> -        revs = repo.revs("%s()" % targetcat)
> +        revs = repo.revs(b"%s()" % targetcat)
>          if revopt:
>              revs = scmutil.revrange(repo, revopt) & revs
>          elif not anyopt:
> -            topic = getattr(repo, 'currenttopic', '')
> +            topic = getattr(repo, 'currenttopic', b'')
>              if topic:
> -                revs = repo.revs('topic(%s)', topic) & revs
> -            elif targetcat == 'orphan':
> +                revs = repo.revs(b'topic(%s)', topic) & revs
> +            elif targetcat == b'orphan':
>                  revs = _aspiringdescendant(repo,
> -                                           repo.revs('(.::) -
> obsolete()::'))
> +                                           repo.revs(b'(.::) -
> obsolete()::'))
>                  revs = set(revs)
> -        if targetcat == 'contentdivergent':
> +        if targetcat == b'contentdivergent':
>              # Pick one divergent per group of divergents
>              revs = _dedupedivergents(repo, revs)
>      elif anyopt:
> -        revs = repo.revs('first(%s())' % (targetcat))
> -    elif targetcat == 'orphan':
> -        revs = set(_aspiringchildren(repo, repo.revs('(.::) -
> obsolete()::')))
> +        revs = repo.revs(b'first(%s())' % (targetcat))
> +    elif targetcat == b'orphan':
> +        revs = set(_aspiringchildren(repo, repo.revs(b'(.::) -
> obsolete()::')))
>          if 1 < len(revs):
> -            msg = "multiple evolve candidates"
> -            hint = (_("select one of %s with --rev")
> -                    % ', '.join([str(repo[r]) for r in sorted(revs)]))
> +            msg = b"multiple evolve candidates"
> +            hint = (_(b"select one of %s with --rev")
> +                    % b', '.join([str(repo[r]) for r in sorted(revs)]))
>              raise error.Abort(msg, hint=hint)
> -    elif instabilities_map.get(targetcat, targetcat) in
> repo['.'].instabilities():
> -        revs = set([repo['.'].rev()])
> +    elif instabilities_map.get(targetcat, targetcat) in
> repo[b'.'].instabilities():
> +        revs = set([repo[b'.'].rev()])
>      return revs
>
>  def _dedupedivergents(repo, revs):
> @@ -1120,14 +1120,14 @@
>      XXX this woobly function won't survive XXX
>      """
>      repo = ctx._repo.unfiltered()
> -    for base in repo.set('reverse(allpredecessors(%d))', ctx.rev()):
> +    for base in repo.set(b'reverse(allpredecessors(%d))', ctx.rev()):
>          newer = obsutil.successorssets(ctx._repo, base.node())
>          # drop filter and solution including the original ctx
>          newer = [n for n in newer if n and ctx.node() not in n]
>          if newer:
>              return base, tuple(ctx._repo[o] for o in newer[0])
> -    raise error.Abort(_("base of divergent changeset %s not found") % ctx,
> -                      hint=_('this case is not yet handled'))
> +    raise error.Abort(_(b"base of divergent changeset %s not found") %
> ctx,
> +                      hint=_(b'this case is not yet handled'))
>
>  def _aspiringdescendant(repo, revs):
>      """Return a list of changectx which can be stabilized on top of pctx
> or
> @@ -1135,7 +1135,7 @@
>      target = set(revs)
>      result = set(target)
>      paths = collections.defaultdict(set)
> -    for r in repo.revs('orphan() - %ld', revs):
> +    for r in repo.revs(b'orphan() - %ld', revs):
>          for d in _possibledestination(repo, r):
>              paths[d].add(r)
>
> @@ -1154,7 +1154,7 @@
>      one of its descendants. Empty list if none can be found."""
>      target = set(revs)
>      result = []
> -    for r in repo.revs('orphan() - %ld', revs):
> +    for r in repo.revs(b'orphan() - %ld', revs):
>          dest = _possibledestination(repo, r)
>          if target & dest:
>              result.append(r)
> @@ -1187,104 +1187,104 @@
>  def _handlenotrouble(ui, repo, allopt, revopt, anyopt, targetcat):
>      """Used by the evolve function to display an error message when
>      no troubles can be resolved"""
> -    troublecategories = ['phasedivergent', 'contentdivergent', 'orphan']
> +    troublecategories = [b'phasedivergent', b'contentdivergent',
> b'orphan']
>      unselectedcategories = [c for c in troublecategories if c !=
> targetcat]
>      msg = None
>      hint = None
>      retoverride = None
>
>      troubled = {
> -        "orphan": repo.revs("orphan()"),
> -        "contentdivergent": repo.revs("contentdivergent()"),
> -        "phasedivergent": repo.revs("phasedivergent()"),
> -        "all": repo.revs("unstable()"),
> +        b"orphan": repo.revs(b"orphan()"),
> +        b"contentdivergent": repo.revs(b"contentdivergent()"),
> +        b"phasedivergent": repo.revs(b"phasedivergent()"),
> +        b"all": repo.revs(b"unstable()"),
>      }
>
>      hintmap = {
> -        'phasedivergent': _("do you want to use --phase-divergent"),
> -        'phasedivergent+contentdivergent': _("do you want to use "
> -                                             "--phase-divergent or"
> -                                             " --content-divergent"),
> -        'phasedivergent+orphan': _("do you want to use --phase-divergent"
> -                                   " or --orphan"),
> -        'contentdivergent': _("do you want to use --content-divergent"),
> -        'contentdivergent+orphan': _("do you want to use
> --content-divergent"
> -                                     " or --orphan"),
> -        'orphan': _("do you want to use --orphan"),
> -        'any+phasedivergent': _("do you want to use --any (or --rev) and"
> -                                " --phase-divergent"),
> -        'any+phasedivergent+contentdivergent': _("do you want to use
> --any"
> -                                                 " (or --rev) and"
> -                                                 " --phase-divergent or"
> -                                                 " --content-divergent"),
> -        'any+phasedivergent+orphan': _("do you want to use --any (or
> --rev)"
> -                                       " and --phase-divergent or
> --orphan"),
> -        'any+contentdivergent': _("do you want to use --any (or --rev)
> and"
> -                                  " --content-divergent"),
> -        'any+contentdivergent+orphan': _("do you want to use --any (or
> --rev)"
> -                                         " and --content-divergent or "
> -                                         "--orphan"),
> -        'any+orphan': _("do you want to use --any (or --rev)"
> -                        "and --orphan"),
> +        b'phasedivergent': _(b"do you want to use --phase-divergent"),
> +        b'phasedivergent+contentdivergent': _(b"do you want to use "
> +                                              b"--phase-divergent or"
> +                                              b" --content-divergent"),
> +        b'phasedivergent+orphan': _(b"do you want to use
> --phase-divergent"
> +                                    b" or --orphan"),
> +        b'contentdivergent': _(b"do you want to use --content-divergent"),
> +        b'contentdivergent+orphan': _(b"do you want to use
> --content-divergent"
> +                                      b" or --orphan"),
> +        b'orphan': _(b"do you want to use --orphan"),
> +        b'any+phasedivergent': _(b"do you want to use --any (or --rev)
> and"
> +                                 b" --phase-divergent"),
> +        b'any+phasedivergent+contentdivergent': _(b"do you want to use
> --any"
> +                                                  b" (or --rev) and"
> +                                                  b" --phase-divergent or"
> +                                                  b"
> --content-divergent"),
> +        b'any+phasedivergent+orphan': _(b"do you want to use --any (or
> --rev)"
> +                                        b" and --phase-divergent or
> --orphan"),
> +        b'any+contentdivergent': _(b"do you want to use --any (or --rev)
> and"
> +                                   b" --content-divergent"),
> +        b'any+contentdivergent+orphan': _(b"do you want to use --any (or
> --rev)"
> +                                          b" and --content-divergent or "
> +                                          b"--orphan"),
> +        b'any+orphan': _(b"do you want to use --any (or --rev)"
> +                         b"and --orphan"),
>      }
>
>      if revopt:
>          revs = scmutil.revrange(repo, revopt)
>          if not revs:
> -            msg = _("set of specified revisions is empty")
> +            msg = _(b"set of specified revisions is empty")
>          else:
> -            msg = _("no %s changesets in specified revisions") % targetcat
> +            msg = _(b"no %s changesets in specified revisions") %
> targetcat
>              othertroubles = []
>              for cat in unselectedcategories:
>                  if revs & troubled[cat]:
>                      othertroubles.append(cat)
>              if othertroubles:
> -                hint = hintmap['+'.join(othertroubles)]
> +                hint = hintmap[b'+'.join(othertroubles)]
>
>      elif anyopt:
> -        msg = _("no %s changesets to evolve") % targetcat
> +        msg = _(b"no %s changesets to evolve") % targetcat
>          othertroubles = []
>          for cat in unselectedcategories:
>              if troubled[cat]:
>                  othertroubles.append(cat)
>          if othertroubles:
> -            hint = hintmap['+'.join(othertroubles)]
> +            hint = hintmap[b'+'.join(othertroubles)]
>
>      else:
>          # evolve without any option = relative to the current wdir
> -        if targetcat == 'orphan':
> -            msg = _("nothing to evolve on current working copy parent")
> +        if targetcat == b'orphan':
> +            msg = _(b"nothing to evolve on current working copy parent")
>          else:
> -            msg = _("current working copy parent is not %s") % targetcat
> +            msg = _(b"current working copy parent is not %s") % targetcat
>
> -        p1 = repo['.'].rev()
> +        p1 = repo[b'.'].rev()
>          othertroubles = []
>          for cat in unselectedcategories:
>              if p1 in troubled[cat]:
>                  othertroubles.append(cat)
>          if othertroubles:
> -            hint = hintmap['+'.join(othertroubles)]
> +            hint = hintmap[b'+'.join(othertroubles)]
>          else:
>              length = len(troubled[targetcat])
>              if length:
> -                hint = _("%d other %s in the repository, do you want
> --any "
> -                         "or --rev") % (length, targetcat)
> +                hint = _(b"%d other %s in the repository, do you want
> --any "
> +                         b"or --rev") % (length, targetcat)
>              else:
>                  othertroubles = []
>                  for cat in unselectedcategories:
>                      if troubled[cat]:
>                          othertroubles.append(cat)
>                  if othertroubles:
> -                    hint = hintmap['any+' + ('+'.join(othertroubles))]
> +                    hint = hintmap[b'any+' + (b'+'.join(othertroubles))]
>                  else:
> -                    msg = _("no troubled changesets")
> +                    msg = _(b"no troubled changesets")
>                      # Exit with a 0 (success) status in this case.
>                      retoverride = 0
>
>      assert msg is not None
> -    ui.write_err("%s\n" % msg)
> +    ui.write_err(b"%s\n" % msg)
>      if hint:
> -        ui.write_err("(%s)\n" % hint)
> +        ui.write_err(b"(%s)\n" % hint)
>          ret = 2
>      else:
>          ret = 1
> @@ -1304,21 +1304,21 @@
>
>  def listtroubles(ui, repo, troublecategories, **opts):
>      """Print all the troubles for the repo (or given revset)"""
> -    troublecategories = troublecategories or ['contentdivergent',
> 'orphan', 'phasedivergent']
> -    showunstable = 'orphan' in troublecategories
> -    showbumped = 'phasedivergent' in troublecategories
> -    showdivergent = 'contentdivergent' in troublecategories
> +    troublecategories = troublecategories or [b'contentdivergent',
> b'orphan', b'phasedivergent']
> +    showunstable = b'orphan' in troublecategories
> +    showbumped = b'phasedivergent' in troublecategories
> +    showdivergent = b'contentdivergent' in troublecategories
>
> -    revs = repo.revs('+'.join("%s()" % t for t in troublecategories))
> -    if opts.get('rev'):
> -        revs = scmutil.revrange(repo, opts.get('rev'))
> +    revs = repo.revs(b'+'.join(b"%s()" % t for t in troublecategories))
> +    if opts.get(b'rev'):
> +        revs = scmutil.revrange(repo, opts.get(b'rev'))
>
> -    fm = ui.formatter('evolvelist', opts)
> +    fm = ui.formatter(b'evolvelist', opts)
>      for rev in revs:
>          ctx = repo[rev]
>          unpars = _preparelistctxs(ctx.parents(), lambda p: p.orphan())
>          obspars = _preparelistctxs(ctx.parents(), lambda p: p.obsolete())
> -        imprecs = _preparelistctxs(repo.set("allpredecessors(%n)",
> ctx.node()),
> +        imprecs = _preparelistctxs(repo.set(b"allpredecessors(%n)",
> ctx.node()),
>                                     lambda p: not p.mutable())
>          dsets = divergentsets(repo, ctx)
>
> @@ -1328,55 +1328,55 @@
>          desc = ctx.description()
>          if desc:
>              desc = desc.splitlines()[0]
> -        desc = (desc[:desclen] + '...') if len(desc) > desclen else desc
> -        fm.plain('%s: ' % ctx.hex()[:hashlen])
> -        fm.plain('%s\n' % desc)
> +        desc = (desc[:desclen] + b'...') if len(desc) > desclen else desc
> +        fm.plain(b'%s: ' % ctx.hex()[:hashlen])
> +        fm.plain(b'%s\n' % desc)
>          fm.data(node=ctx.hex(), rev=ctx.rev(), desc=desc,
> phase=ctx.phasestr())
>
>          for unpar in unpars if showunstable else []:
> -            fm.plain('  %s: %s (%s parent)\n' % (TROUBLES['ORPHAN'],
> -                                                 unpar[:hashlen],
> -                                                 TROUBLES['ORPHAN']))
> +            fm.plain(b'  %s: %s (%s parent)\n' % (TROUBLES[b'ORPHAN'],
> +                                                  unpar[:hashlen],
> +                                                  TROUBLES[b'ORPHAN']))
>          for obspar in obspars if showunstable else []:
> -            fm.plain('  %s: %s (obsolete parent)\n' % (TROUBLES['ORPHAN'],
> -                                                       obspar[:hashlen]))
> +            fm.plain(b'  %s: %s (obsolete parent)\n' %
> (TROUBLES[b'ORPHAN'],
> +                                                        obspar[:hashlen]))
>          for imprec in imprecs if showbumped else []:
> -            fm.plain('  %s: %s (immutable precursor)\n' %
> -                     (TROUBLES['PHASEDIVERGENT'], imprec[:hashlen]))
> +            fm.plain(b'  %s: %s (immutable precursor)\n' %
> +                     (TROUBLES[b'PHASEDIVERGENT'], imprec[:hashlen]))
>
>          if dsets and showdivergent:
>              for dset in dsets:
> -                fm.plain('  %s: ' % TROUBLES['CONTENTDIVERGENT'])
> +                fm.plain(b'  %s: ' % TROUBLES[b'CONTENTDIVERGENT'])
>                  first = True
> -                for n in dset['divergentnodes']:
> -                    t = "%s (%s)" if first else " %s (%s)"
> +                for n in dset[b'divergentnodes']:
> +                    t = b"%s (%s)" if first else b" %s (%s)"
>                      first = False
>                      fm.plain(t % (nodemod.hex(n)[:hashlen],
> repo[n].phasestr()))
> -                comprec = nodemod.hex(dset['commonprecursor'])[:hashlen]
> -                fm.plain(" (precursor %s)\n" % comprec)
> -        fm.plain("\n")
> +                comprec = nodemod.hex(dset[b'commonprecursor'])[:hashlen]
> +                fm.plain(b" (precursor %s)\n" % comprec)
> +        fm.plain(b"\n")
>
>          # templater-friendly section
>          _formatctx(fm, ctx)
>          troubles = []
>          for unpar in unpars:
> -            troubles.append({'troubletype': TROUBLES['ORPHAN'],
> -                             'sourcenode': unpar, 'sourcetype':
> 'orphanparent'})
> +            troubles.append({b'troubletype': TROUBLES[b'ORPHAN'],
> +                             b'sourcenode': unpar, b'sourcetype':
> b'orphanparent'})
>          for obspar in obspars:
> -            troubles.append({'troubletype': TROUBLES['ORPHAN'],
> -                             'sourcenode': obspar,
> -                             'sourcetype': 'obsoleteparent'})
> +            troubles.append({b'troubletype': TROUBLES[b'ORPHAN'],
> +                             b'sourcenode': obspar,
> +                             b'sourcetype': b'obsoleteparent'})
>          for imprec in imprecs:
> -            troubles.append({'troubletype': TROUBLES['PHASEDIVERGENT'],
> -                             'sourcenode': imprec,
> -                             'sourcetype': 'immutableprecursor'})
> +            troubles.append({b'troubletype': TROUBLES[b'PHASEDIVERGENT'],
> +                             b'sourcenode': imprec,
> +                             b'sourcetype': b'immutableprecursor'})
>          for dset in dsets:
> -            divnodes = [{'node': nodemod.hex(n),
> -                         'phase': repo[n].phasestr(),
> -                        } for n in dset['divergentnodes']]
> -            troubles.append({'troubletype': TROUBLES['CONTENTDIVERGENT'],
> -                             'commonprecursor':
> nodemod.hex(dset['commonprecursor']),
> -                             'divergentnodes': divnodes})
> +            divnodes = [{b'node': nodemod.hex(n),
> +                         b'phase': repo[n].phasestr(),
> +                         } for n in dset[b'divergentnodes']]
> +            troubles.append({b'troubletype':
> TROUBLES[b'CONTENTDIVERGENT'],
> +                             b'commonprecursor':
> nodemod.hex(dset[b'commonprecursor']),
> +                             b'divergentnodes': divnodes})
>          fm.data(troubles=troubles)
>
>      fm.end()
> @@ -1385,65 +1385,65 @@
>      """ check the options passed to `hg evolve` and warn for deprecation
> warning
>      if any """
>
> -    if opts['continue']:
> -        if opts['any']:
> -            raise error.Abort(_('cannot specify both "--any" and
> "--continue"'))
> -        if opts['all']:
> -            raise error.Abort(_('cannot specify both "--all" and
> "--continue"'))
> -        if opts['rev']:
> -            raise error.Abort(_('cannot specify both "--rev" and
> "--continue"'))
> -        if opts['stop']:
> -            raise error.Abort(_('cannot specify both "--stop" and'
> -                                ' "--continue"'))
> -        if opts['abort']:
> -            raise error.Abort(_('cannot specify both "--abort" and'
> -                                ' "--continue"'))
> +    if opts[b'continue']:
> +        if opts[b'any']:
> +            raise error.Abort(_(b'cannot specify both "--any" and
> "--continue"'))
> +        if opts[b'all']:
> +            raise error.Abort(_(b'cannot specify both "--all" and
> "--continue"'))
> +        if opts[b'rev']:
> +            raise error.Abort(_(b'cannot specify both "--rev" and
> "--continue"'))
> +        if opts[b'stop']:
> +            raise error.Abort(_(b'cannot specify both "--stop" and'
> +                                b' "--continue"'))
> +        if opts[b'abort']:
> +            raise error.Abort(_(b'cannot specify both "--abort" and'
> +                                b' "--continue"'))
>
> -    if opts['stop']:
> -        if opts['any']:
> -            raise error.Abort(_('cannot specify both "--any" and
> "--stop"'))
> -        if opts['all']:
> -            raise error.Abort(_('cannot specify both "--all" and
> "--stop"'))
> -        if opts['rev']:
> -            raise error.Abort(_('cannot specify both "--rev" and
> "--stop"'))
> -        if opts['abort']:
> -            raise error.Abort(_('cannot specify both "--abort" and
> "--stop"'))
> +    if opts[b'stop']:
> +        if opts[b'any']:
> +            raise error.Abort(_(b'cannot specify both "--any" and
> "--stop"'))
> +        if opts[b'all']:
> +            raise error.Abort(_(b'cannot specify both "--all" and
> "--stop"'))
> +        if opts[b'rev']:
> +            raise error.Abort(_(b'cannot specify both "--rev" and
> "--stop"'))
> +        if opts[b'abort']:
> +            raise error.Abort(_(b'cannot specify both "--abort" and
> "--stop"'))
>
> -    if opts['abort']:
> -        if opts['any']:
> -            raise error.Abort(_('cannot specify both "--any" and
> "--abort"'))
> -        if opts['all']:
> -            raise error.Abort(_('cannot specify both "--all" and
> "--abort"'))
> -        if opts['rev']:
> -            raise error.Abort(_('cannot specify both "--rev" and
> "--abort"'))
> +    if opts[b'abort']:
> +        if opts[b'any']:
> +            raise error.Abort(_(b'cannot specify both "--any" and
> "--abort"'))
> +        if opts[b'all']:
> +            raise error.Abort(_(b'cannot specify both "--all" and
> "--abort"'))
> +        if opts[b'rev']:
> +            raise error.Abort(_(b'cannot specify both "--rev" and
> "--abort"'))
>
> -    if opts['rev']:
> -        if opts['any']:
> -            raise error.Abort(_('cannot specify both "--rev" and
> "--any"'))
> -        if opts['all']:
> -            raise error.Abort(_('cannot specify both "--rev" and
> "--all"'))
> +    if opts[b'rev']:
> +        if opts[b'any']:
> +            raise error.Abort(_(b'cannot specify both "--rev" and
> "--any"'))
> +        if opts[b'all']:
> +            raise error.Abort(_(b'cannot specify both "--rev" and
> "--all"'))
>
>      # Backward compatibility
> -    if opts['unstable']:
> -        msg = ("'evolve --unstable' is deprecated, "
> -               "use 'evolve --orphan'")
> -        repo.ui.deprecwarn(msg, '4.4')
> +    if opts[b'unstable']:
> +        msg = (b"'evolve --unstable' is deprecated, "
> +               b"use 'evolve --orphan'")
> +        repo.ui.deprecwarn(msg, b'4.4')
>
> -        opts['orphan'] = opts['divergent']
> +        opts[b'orphan'] = opts[b'divergent']
>
> -    if opts['divergent']:
> -        msg = ("'evolve --divergent' is deprecated, "
> -               "use 'evolve --content-divergent'")
> -        repo.ui.deprecwarn(msg, '4.4')
> +    if opts[b'divergent']:
> +        msg = (b"'evolve --divergent' is deprecated, "
> +               b"use 'evolve --content-divergent'")
> +        repo.ui.deprecwarn(msg, b'4.4')
>
> -        opts['content_divergent'] = opts['divergent']
> +        opts[b'content_divergent'] = opts[b'divergent']
>
> -    if opts['bumped']:
> -        msg = ("'evolve --bumped' is deprecated, "
> -               "use 'evolve --phase-divergent'")
> -        repo.ui.deprecwarn(msg, '4.4')
> +    if opts[b'bumped']:
> +        msg = (b"'evolve --bumped' is deprecated, "
> +               b"use 'evolve --phase-divergent'")
> +        repo.ui.deprecwarn(msg, b'4.4')
>
> -        opts['phase_divergent'] = opts['bumped']
> +        opts[b'phase_divergent'] = opts[b'bumped']
>
>      return opts
>
> @@ -1454,8 +1454,8 @@
>          unfi = repo.unfiltered()
>          succ = utility._singlesuccessor(repo, unfi[startnode])
>          hg.updaterepo(repo, repo[succ].node(), False)
> -    if repo['.'].node() != startnode:
> -        ui.status(_('working directory is now at %s\n') % repo['.'])
> +    if repo[b'.'].node() != startnode:
> +        ui.status(_(b'working directory is now at %s\n') % repo[b'.'])
>
>  def divergentsets(repo, ctx):
>      """Compute sets of commits divergent with a given one"""
> @@ -1475,40 +1475,40 @@
>                  continue
>              base[tuple(nsuccset)] = n
>      divergence = []
> -    for divset, b in base.iteritems():
> +    for divset, b in base.items():
>          divergence.append({
> -            'divergentnodes': divset,
> -            'commonprecursor': b
> +            b'divergentnodes': divset,
> +            b'commonprecursor': b
>          })
>
>      return divergence
>
>  @eh.command(
> -    'evolve|stabilize|solve',
> -    [('n', 'dry-run', False,
> -      _('do not perform actions, just print what would be done')),
> -     ('', 'confirm', False,
> -      _('ask for confirmation before performing the action')),
> -     ('A', 'any', False,
> -      _('also consider troubled changesets unrelated to current working '
> -        'directory')),
> -     ('r', 'rev', [], _('solves troubles of these revisions'), _('REV')),
> -     ('', 'bumped', False, _('solves only bumped changesets
> (DEPRECATED)')),
> -     ('', 'phase-divergent', False, _('solves only phase-divergent
> changesets')),
> -     ('', 'divergent', False, _('solves only divergent changesets
> (DEPRECATED)')),
> -     ('', 'content-divergent', False, _('solves only content-divergent
> changesets')),
> -     ('', 'unstable', False, _('solves only unstable changesets
> (DEPRECATED)')),
> -     ('', 'orphan', False, _('solves only orphan changesets (default)')),
> -     ('a', 'all', None, _('evolve all troubled changesets related to the '
> -                          'current working directory and its
> descendants')),
> -     ('', 'update', False, _('update to the head of evolved changesets')),
> -     ('c', 'continue', False, _('continue an interrupted evolution')),
> -     ('', 'stop', False, _('stop the interrupted evolution')),
> -     ('', 'abort', False, _('abort the interrupted evolution')),
> -     ('l', 'list', False, _('provide details on troubled changesets'
> -                            ' in the repo')),
> -    ] + mergetoolopts,
> -    _('[OPTIONS]...'),
> +    b'evolve|stabilize|solve',
> +    [(b'n', b'dry-run', False,
> +      _(b'do not perform actions, just print what would be done')),
> +     (b'', b'confirm', False,
> +      _(b'ask for confirmation before performing the action')),
> +     (b'A', b'any', False,
> +      _(b'also consider troubled changesets unrelated to current working '
> +        b'directory')),
> +     (b'r', b'rev', [], _(b'solves troubles of these revisions'),
> _(b'REV')),
> +     (b'', b'bumped', False, _(b'solves only bumped changesets
> (DEPRECATED)')),
> +     (b'', b'phase-divergent', False, _(b'solves only phase-divergent
> changesets')),
> +     (b'', b'divergent', False, _(b'solves only divergent changesets
> (DEPRECATED)')),
> +     (b'', b'content-divergent', False, _(b'solves only content-divergent
> changesets')),
> +     (b'', b'unstable', False, _(b'solves only unstable changesets
> (DEPRECATED)')),
> +     (b'', b'orphan', False, _(b'solves only orphan changesets
> (default)')),
> +     (b'a', b'all', None, _(b'evolve all troubled changesets related to
> the '
> +                            b'current working directory and its
> descendants')),
> +     (b'', b'update', False, _(b'update to the head of evolved
> changesets')),
> +     (b'c', b'continue', False, _(b'continue an interrupted evolution')),
> +     (b'', b'stop', False, _(b'stop the interrupted evolution')),
> +     (b'', b'abort', False, _(b'abort the interrupted evolution')),
> +     (b'l', b'list', False, _(b'provide details on troubled changesets'
> +                              b' in the repo')),
> +     ] + mergetoolopts,
> +    _(b'[OPTIONS]...'),
>      helpbasic=True
>  )
>  def evolve(ui, repo, **opts):
> @@ -1606,72 +1606,72 @@
>
>      opts = _checkevolveopts(repo, opts)
>      # Options
> -    contopt = opts['continue']
> -    anyopt = opts['any']
> -    allopt = opts['all']
> +    contopt = opts[b'continue']
> +    anyopt = opts[b'any']
> +    allopt = opts[b'all']
>      if allopt is None:
>          allopt = True
> -    startnode = repo['.'].node()
> -    dryrunopt = opts['dry_run']
> -    confirmopt = opts['confirm']
> -    revopt = opts['rev']
> -    stopopt = opts['stop']
> -    abortopt = opts['abort']
> -    shouldupdate = opts['update']
> +    startnode = repo[b'.'].node()
> +    dryrunopt = opts[b'dry_run']
> +    confirmopt = opts[b'confirm']
> +    revopt = opts[b'rev']
> +    stopopt = opts[b'stop']
> +    abortopt = opts[b'abort']
> +    shouldupdate = opts[b'update']
>
> -    troublecategories = ['phase_divergent', 'content_divergent', 'orphan']
> -    specifiedcategories = [t.replace('_', '')
> +    troublecategories = [b'phase_divergent', b'content_divergent',
> b'orphan']
> +    specifiedcategories = [t.replace(b'_', b'')
>                             for t in troublecategories
>                             if opts[t]]
> -    if opts['list']:
> -        ui.pager('evolve')
> +    if opts[b'list']:
> +        ui.pager(b'evolve')
>          listtroubles(ui, repo, specifiedcategories, **opts)
>          return
>
> -    targetcat = 'orphan'
> +    targetcat = b'orphan'
>      has_some_opts = bool(revopt or anyopt or allopt or contopt or stopopt
> or abortopt)
>      if 1 < len(specifiedcategories):
> -        msg = _('cannot specify more than one trouble category to solve
> (yet)')
> +        msg = _(b'cannot specify more than one trouble category to solve
> (yet)')
>          raise error.Abort(msg)
>      elif len(specifiedcategories) == 1:
>          targetcat = specifiedcategories[0]
> -    elif repo['.'].obsolete() and not has_some_opts:
> +    elif repo[b'.'].obsolete() and not has_some_opts:
>          # if no args and parent is obsolete, update to successors
>          return solveobswdp(ui, repo, opts)
>
> -    ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'evolve')
> +    ui.setconfig(b'ui', b'forcemerge', opts.get(b'tool', b''), b'evolve')
>
>      evolvestate = state.cmdstate(repo)
>      # Continuation handling
>      if contopt:
>          if not evolvestate:
> -            raise error.Abort(_('no interrupted evolve to continue'))
> +            raise error.Abort(_(b'no interrupted evolve to continue'))
>          evolvestate.load()
>          continueevolve(ui, repo, evolvestate)
> -        if evolvestate['command'] != 'evolve':
> +        if evolvestate[b'command'] != b'evolve':
>              evolvestate.delete()
>              return
> -        startnode = repo.unfiltered()[evolvestate['startnode']]
> -        if 'update' in evolvestate:
> -            shouldupdate = evolvestate['update']
> +        startnode = repo.unfiltered()[evolvestate[b'startnode']]
> +        if b'update' in evolvestate:
> +            shouldupdate = evolvestate[b'update']
>          evolvestate.delete()
>      elif stopopt:
>          if not evolvestate:
> -            raise error.Abort(_('no interrupted evolve to stop'))
> +            raise error.Abort(_(b'no interrupted evolve to stop'))
>          evolvestate.load()
>          stopevolve(ui, repo, evolvestate)
>          evolvestate.delete()
>          return
>      elif abortopt:
>          if not evolvestate:
> -            raise error.Abort(_('no interrupted evolve to stop'))
> +            raise error.Abort(_(b'no interrupted evolve to stop'))
>          evolvestate.load()
>          # `hg next --evolve` in play
> -        if evolvestate['command'] != 'evolve':
> -            pctx = repo['.']
> +        if evolvestate[b'command'] != b'evolve':
> +            pctx = repo[b'.']
>              hg.updaterepo(repo, pctx.node(), True)
> -            ui.status(_('evolve aborted\n'))
> -            ui.status(_('working directory is now at %s\n')
> +            ui.status(_(b'evolve aborted\n'))
> +            ui.status(_(b'working directory is now at %s\n')
>                        % pctx.hex()[:12])
>              evolvestate.delete()
>              return 0
> @@ -1685,7 +1685,7 @@
>          # Handling it here otherwise `revs` set would change, after
>          # performing update to successor of obsolete wdir parent.
>          # (in case when user passes a revset related to wdir parent '.::')
> -        if repo['.'].obsolete():
> +        if repo[b'.'].obsolete():
>              result = solveobswdp(ui, repo, opts)
>              if result != 0 or result is True:
>                  return result
> @@ -1700,27 +1700,27 @@
>
>          def progresscb():
>              if showprogress:
> -                compat.progress(ui, _('evolve'), seen,
> unit=_('changesets'),
> +                compat.progress(ui, _(b'evolve'), seen,
> unit=_(b'changesets'),
>                                  total=count)
>
>          # Order the revisions
>          revs = _orderrevs(repo, revs)
>
>          # cbor does not know how to serialize sets, using list for
> skippedrevs
> -        stateopts = {'category': targetcat, 'replacements': {},
> -                     'revs': list(revs), 'confirm': confirmopt,
> -                     'startnode': startnode, 'skippedrevs': [],
> -                     'command': 'evolve', 'orphanmerge': False,
> -                     'bookmarkchanges': [], 'temprevs': [], 'obsmarkers':
> [],
> -                     'update': shouldupdate}
> +        stateopts = {b'category': targetcat, b'replacements': {},
> +                     b'revs': list(revs), b'confirm': confirmopt,
> +                     b'startnode': startnode, b'skippedrevs': [],
> +                     b'command': b'evolve', b'orphanmerge': False,
> +                     b'bookmarkchanges': [], b'temprevs': [],
> b'obsmarkers': [],
> +                     b'update': shouldupdate}
>          evolvestate.addopts(stateopts)
>          # lastsolved: keep track of successor of last troubled cset we
> evolved
>          # to confirm that if atop msg should be suppressed to remove
> redundancy
>          lastsolved = None
>
> -        activetopic = getattr(repo, 'currenttopic', '')
> +        activetopic = getattr(repo, 'currenttopic', b'')
>          with repo.wlock(), repo.lock():
> -            tr = repo.transaction("evolve")
> +            tr = repo.transaction(b"evolve")
>              with util.acceptintervention(tr):
>                  for rev in revs:
>                      lastsolved = _solveonerev(ui, repo, rev, evolvestate,
> @@ -1730,7 +1730,7 @@
>                      seen += 1
>
>          if showprogress:
> -            compat.progress(ui, _('evolve'), None)
> +            compat.progress(ui, _(b'evolve'), None)
>
>      _cleanup(ui, repo, startnode, shouldupdate)
>
> @@ -1742,7 +1742,7 @@
>      stabilizes for both parents of orphan merges.
>      """
>      curctx = repo[rev]
> -    revtopic = getattr(curctx, 'topic', lambda: '')()
> +    revtopic = getattr(curctx, 'topic', lambda: b'')()
>      topicidx = getattr(curctx, 'topicidx', lambda: None)()
>      stacktmplt = False
>      # check if revision being evolved is in active topic to make sure
> @@ -1754,44 +1754,44 @@
>                      confirmopt, progresscb, targetcat,
>                      lastsolved=lastsolved, stacktmplt=stacktmplt)
>      if ret[0]:
> -        evolvestate['replacements'][curctx.node()] = ret[1]
> +        evolvestate[b'replacements'][curctx.node()] = ret[1]
>          lastsolved = ret[1]
>      else:
> -        evolvestate['skippedrevs'].append(curctx.node())
> +        evolvestate[b'skippedrevs'].append(curctx.node())
>
> -    if evolvestate['orphanmerge']:
> +    if evolvestate[b'orphanmerge']:
>          # we were processing an orphan merge with both parents obsolete,
>          # stabilized for second parent, re-stabilize for the first parent
>          ret = _solveone(ui, repo, repo[ret[1]], evolvestate, dryrunopt,
>                          confirmopt, progresscb, targetcat,
>                          stacktmplt=stacktmplt)
>          if ret[0]:
> -            evolvestate['replacements'][curctx.node()] = ret[1]
> +            evolvestate[b'replacements'][curctx.node()] = ret[1]
>              lastsolved = ret[1]
>          else:
> -            evolvestate['skippedrevs'].append(curctx.node())
> +            evolvestate[b'skippedrevs'].append(curctx.node())
>
> -        evolvestate['orphanmerge'] = False
> +        evolvestate[b'orphanmerge'] = False
>      return lastsolved
>
>  def solveobswdp(ui, repo, opts):
>      """this function updates to the successor of obsolete wdir parent"""
> -    oldid = repo['.'].node()
> -    startctx = repo['.']
> -    dryrunopt = opts.get('dry_run', False)
> +    oldid = repo[b'.'].node()
> +    startctx = repo[b'.']
> +    dryrunopt = opts.get(b'dry_run', False)
>      displayer = compat.changesetdisplayer(ui, repo,
> -                                          {'template': shorttemplate})
> +                                          {b'template': shorttemplate})
>      try:
> -        ctx = repo[utility._singlesuccessor(repo, repo['.'])]
> +        ctx = repo[utility._singlesuccessor(repo, repo[b'.'])]
>      except utility.MultipleSuccessorsError as exc:
> -        repo.ui.write_err(_('parent is obsolete with multiple'
> -                            ' successors:\n'))
> +        repo.ui.write_err(_(b'parent is obsolete with multiple'
> +                            b' successors:\n'))
>          for ln in exc.successorssets:
>              for n in ln:
>                  displayer.show(repo[n])
>          return 2
>
> -    ui.status(_('update:'))
> +    ui.status(_(b'update:'))
>      if not ui.quiet:
>          displayer.show(ctx)
>
> @@ -1801,33 +1801,33 @@
>      newid = ctx.node()
>
>      if ctx != startctx:
> -        with repo.wlock(), repo.lock(), repo.transaction('evolve') as tr:
> +        with repo.wlock(), repo.lock(), repo.transaction(b'evolve') as tr:
>              bmupdater = rewriteutil.bookmarksupdater(repo, oldid, tr)
>              bmupdater(newid)
> -        ui.status(_('working directory is now at %s\n') % ctx)
> +        ui.status(_(b'working directory is now at %s\n') % ctx)
>      return res
>
>  def stopevolve(ui, repo, evolvestate):
>      """logic for handling of `hg evolve --stop`"""
>      updated = False
>      pctx = None
> -    if (evolvestate['command'] == 'evolve'
> -        and evolvestate['category'] == 'contentdivergent'
> -        and evolvestate['relocated']):
> -        oldother = evolvestate['old-other']
> +    if (evolvestate[b'command'] == b'evolve'
> +        and evolvestate[b'category'] == b'contentdivergent'
> +        and evolvestate[b'relocated']):
> +        oldother = evolvestate[b'old-other']
>          if oldother:
>              with repo.wlock(), repo.lock():
>                  repo = repo.unfiltered()
>                  hg.updaterepo(repo, oldother, True)
> -                strips = [evolvestate['relocated']]
> +                strips = [evolvestate[b'relocated']]
>                  repair.strip(ui, repo, strips, False)
>                  updated = True
>                  pctx = repo[oldother]
>      if not updated:
> -        pctx = repo['.']
> +        pctx = repo[b'.']
>          hg.updaterepo(repo, pctx.node(), True)
> -    ui.status(_('stopped the interrupted evolve\n'))
> -    ui.status(_('working directory is now at %s\n') % pctx)
> +    ui.status(_(b'stopped the interrupted evolve\n'))
> +    ui.status(_(b'working directory is now at %s\n') % pctx)
>
>  def abortevolve(ui, repo, evolvestate):
>      """ logic for handling of `hg evolve --abort`"""
> @@ -1837,11 +1837,11 @@
>          evolvedctx = []
>          # boolean value to say whether we should strip or not
>          cleanup = True
> -        startnode = evolvestate['startnode']
> -        for old, new in evolvestate['replacements'].iteritems():
> +        startnode = evolvestate[b'startnode']
> +        for old, new in evolvestate[b'replacements'].items():
>              if new:
>                  evolvedctx.append(repo[new])
> -        for temp in evolvestate['temprevs']:
> +        for temp in evolvestate[b'temprevs']:
>              if temp:
>                  evolvedctx.append(repo[temp])
>          evolvedrevs = [c.rev() for c in evolvedctx]
> @@ -1849,9 +1849,9 @@
>          # checking if phase changed of any of the evolved rev
>          immutable = [c for c in evolvedctx if not c.mutable()]
>          if immutable:
> -            repo.ui.warn(_("cannot clean up public changesets: %s\n")
> -                         % ', '.join(str(c) for c in immutable),
> -                         hint=_("see 'hg help phases' for details"))
> +            repo.ui.warn(_(b"cannot clean up public changesets: %s\n")
> +                         % b', '.join(str(c) for c in immutable),
> +                         hint=_(b"see 'hg help phases' for details"))
>              cleanup = False
>
>          # checking no new changesets are created on evolved revs
> @@ -1859,15 +1859,15 @@
>          if evolvedrevs:
>              descendants = set(repo.changelog.descendants(evolvedrevs))
>          if descendants - set(evolvedrevs):
> -            repo.ui.warn(_("warning: new changesets detected on
> destination "
> -                           "branch\n"))
> +            repo.ui.warn(_(b"warning: new changesets detected on
> destination "
> +                           b"branch\n"))
>              cleanup = False
>
>          # finding the indices of the obsmarkers to be stripped and
> stripping
>          # them
> -        if evolvestate['obsmarkers']:
> +        if evolvestate[b'obsmarkers']:
>              stripmarkers = set()
> -            for m in evolvestate['obsmarkers']:
> +            for m in evolvestate[b'obsmarkers']:
>                  m = (m[0], m[1])
>                  stripmarkers.add(m)
>              indices = []
> @@ -1878,12 +1878,12 @@
>                      indices.append(i)
>
>              repair.deleteobsmarkers(repo.obsstore, indices)
> -            repo.ui.debug('deleted %d obsmarkers\n' % len(indices))
> +            repo.ui.debug(b'deleted %d obsmarkers\n' % len(indices))
>
>          if cleanup:
>              if evolvedrevs:
>                  strippoints = [c.node()
> -                               for c in repo.set('roots(%ld)',
> evolvedrevs)]
> +                               for c in repo.set(b'roots(%ld)',
> evolvedrevs)]
>
>              # updating the working directory
>              hg.updaterepo(repo, startnode, True)
> @@ -1893,19 +1893,19 @@
>                  # no backup of evolved cset versions needed
>                  repair.strip(repo.ui, repo, strippoints, False)
>
> -            with repo.transaction('evolve') as tr:
> +            with repo.transaction(b'evolve') as tr:
>                  # restoring bookmarks at there original place
> -                bmchanges = evolvestate['bookmarkchanges']
> +                bmchanges = evolvestate[b'bookmarkchanges']
>                  if bmchanges:
>                      repo._bookmarks.applychanges(repo, tr, bmchanges)
>
>              evolvestate.delete()
> -            ui.status(_('evolve aborted\n'))
> -            ui.status(_('working directory is now at %s\n')
> +            ui.status(_(b'evolve aborted\n'))
> +            ui.status(_(b'working directory is now at %s\n')
>                        % nodemod.hex(startnode)[:12])
>          else:
> -            raise error.Abort(_("unable to abort interrupted evolve, use
> 'hg "
> -                                "evolve --stop' to stop evolve"))
> +            raise error.Abort(_(b"unable to abort interrupted evolve, use
> 'hg "
> +                                b"evolve --stop' to stop evolve"))
>
>  def continueevolve(ui, repo, evolvestate):
>      """logic for handling of `hg evolve --continue`"""
> @@ -1913,81 +1913,81 @@
>      with repo.wlock(), repo.lock():
>          ms = merge.mergestate.read(repo)
>          mergeutil.checkunresolved(ms)
> -        if (evolvestate['command'] == 'next'
> -            or evolvestate['category'] == 'orphan'):
> +        if (evolvestate[b'command'] == b'next'
> +            or evolvestate[b'category'] == b'orphan'):
>              _completeorphan(ui, repo, evolvestate)
> -        elif evolvestate['category'] == 'phasedivergent':
> +        elif evolvestate[b'category'] == b'phasedivergent':
>              _completephasedivergent(ui, repo, evolvestate)
> -        elif evolvestate['category'] == 'contentdivergent':
> +        elif evolvestate[b'category'] == b'contentdivergent':
>              _continuecontentdivergent(ui, repo, evolvestate, None)
>          else:
> -            repo.ui.status(_("continuing interrupted '%s' resolution is
> not yet"
> -                             " supported\n") % evolvestate['category'])
> +            repo.ui.status(_(b"continuing interrupted '%s' resolution is
> not yet"
> +                             b" supported\n") % evolvestate[b'category'])
>              return
>
>          # make sure we are continuing evolve and not `hg next --evolve`
> -        if evolvestate['command'] != 'evolve':
> +        if evolvestate[b'command'] != b'evolve':
>              return
>
>          # Progress handling
>          seen = 1
> -        count = len(evolvestate['revs'])
> +        count = len(evolvestate[b'revs'])
>
>          def progresscb():
> -            compat.progress(ui, _('evolve'), seen, unit=_('changesets'),
> +            compat.progress(ui, _(b'evolve'), seen, unit=_(b'changesets'),
>                              total=count)
>
> -        category = evolvestate['category']
> -        confirm = evolvestate['confirm']
> +        category = evolvestate[b'category']
> +        confirm = evolvestate[b'confirm']
>          unfi = repo.unfiltered()
>          # lastsolved: keep track of successor of last troubled cset we
>          # evolved to confirm that if atop msg should be suppressed to
> remove
>          # redundancy
>          lastsolved = None
> -        activetopic = getattr(repo, 'currenttopic', '')
> -        tr = repo.transaction("evolve")
> +        activetopic = getattr(repo, 'currenttopic', b'')
> +        tr = repo.transaction(b"evolve")
>          with util.acceptintervention(tr):
> -            for rev in evolvestate['revs']:
> +            for rev in evolvestate[b'revs']:
>                  # XXX: prevent this lookup by storing nodes instead of
> revnums
>                  curctx = unfi[rev]
>
>                  # check if we can use stack template
> -                revtopic = getattr(curctx, 'topic', lambda: '')()
> +                revtopic = getattr(curctx, 'topic', lambda: b'')()
>                  topicidx = getattr(curctx, 'topicidx', lambda: None)()
>                  stacktmplt = False
>                  if (activetopic and (activetopic == revtopic)
>                      and topicidx is not None):
>                      stacktmplt = True
>
> -                if (curctx.node() not in evolvestate['replacements']
> -                    and curctx.node() not in evolvestate['skippedrevs']):
> +                if (curctx.node() not in evolvestate[b'replacements']
> +                    and curctx.node() not in evolvestate[b'skippedrevs']):
>                      newnode = _solveone(ui, repo, curctx, evolvestate,
> False,
>                                          confirm, progresscb, category,
>                                          lastsolved=lastsolved,
>                                          stacktmplt=stacktmplt)
>                      if newnode[0]:
> -                        evolvestate['replacements'][curctx.node()] =
> newnode[1]
> +                        evolvestate[b'replacements'][curctx.node()] =
> newnode[1]
>                          lastsolved = newnode[1]
>                      else:
> -                        evolvestate['skippedrevs'].append(curctx.node())
> +                        evolvestate[b'skippedrevs'].append(curctx.node())
>                  seen += 1
>
>  def _continuecontentdivergent(ui, repo, evolvestate, progresscb):
>      """function to continue the interrupted content-divergence
> resolution."""
> -    tr = repo.transaction('evolve')
> +    tr = repo.transaction(b'evolve')
>      with util.acceptintervention(tr):
> -        divergent = evolvestate['divergent']
> -        base = evolvestate['base']
> +        divergent = evolvestate[b'divergent']
> +        base = evolvestate[b'base']
>          repo = repo.unfiltered()
> -        if evolvestate['relocating']:
> +        if evolvestate[b'relocating']:
>              newother = _completerelocation(ui, repo, evolvestate)
> -            current = repo[evolvestate['current']]
> +            current = repo[evolvestate[b'current']]
>              obsolete.createmarkers(repo, [(current, (repo[newother],))],
> -                                   operation='evolve')
> -            evolvestate['relocating'] = False
> -            evolvestate['relocated'] = newother
> -            evolvestate['temprevs'].append(newother)
> -            evolvestate['other-divergent'] = newother
> +                                   operation=b'evolve')
> +            evolvestate[b'relocating'] = False
> +            evolvestate[b'relocated'] = newother
> +            evolvestate[b'temprevs'].append(newother)
> +            evolvestate[b'other-divergent'] = newother
>              # continue the resolution by merging the content-divergence
>              _mergecontentdivergents(repo, progresscb,
>                                      repo[divergent],
> @@ -1995,16 +1995,16 @@
>                                      repo[base],
>                                      evolvestate)
>
> -        other = evolvestate['other-divergent']
> +        other = evolvestate[b'other-divergent']
>          ret = _completecontentdivergent(ui, repo, progresscb,
>                                          repo[divergent],
>                                          repo[other],
>                                          repo[base],
>                                          evolvestate)
> -        origdivergent = evolvestate['orig-divergent']
> -        evolvestate['replacements'][origdivergent] = ret[1]
> +        origdivergent = evolvestate[b'orig-divergent']
> +        evolvestate[b'replacements'][origdivergent] = ret[1]
>          # logic to continue the public content-divergent
> -        publicnode = evolvestate.get('public-divergent')
> +        publicnode = evolvestate.get(b'public-divergent')
>          if publicnode:
>              res, newnode = ret
>              if not res:
> @@ -2027,19 +2027,19 @@
>      phase-divergence"""
>
>      # need to start transaction for bookmark changes
> -    with repo.transaction('evolve'):
> +    with repo.transaction(b'evolve'):
>          node = _completerelocation(ui, repo, evolvestate)
> -        evolvestate['temprevs'].append(node)
> +        evolvestate[b'temprevs'].append(node)
>          # resolving conflicts can lead to empty wdir and node can be None
> in
>          # those cases
> -        ctx = repo[evolvestate['current']]
> -        newctx = repo[node] if node is not None else repo['.']
> -        obsolete.createmarkers(repo, [(ctx, (newctx,))],
> operation='evolve')
> +        ctx = repo[evolvestate[b'current']]
> +        newctx = repo[node] if node is not None else repo[b'.']
> +        obsolete.createmarkers(repo, [(ctx, (newctx,))],
> operation=b'evolve')
>
>          # now continuing the phase-divergence resolution part
> -        prec = repo[evolvestate['precursor']]
> +        prec = repo[evolvestate[b'precursor']]
>          retvalue = _resolvephasedivergent(ui, repo, prec, newctx)
> -        evolvestate['replacements'][ctx.node()] = retvalue[1]
> +        evolvestate[b'replacements'][ctx.node()] = retvalue[1]
>
>  def _completeorphan(ui, repo, evolvestate):
>      """function to complete the interrupted orphan resolution"""
> @@ -2047,44 +2047,44 @@
>      node = _completerelocation(ui, repo, evolvestate)
>      # resolving conflicts can lead to empty wdir and node can be None in
>      # those cases
> -    ctx = repo[evolvestate['current']]
> +    ctx = repo[evolvestate[b'current']]
>      if node is None:
> -        repo.ui.status(_("evolution of %d:%s created no changes"
> -                         " to commit\n") % (ctx.rev(), ctx))
> -    newctx = repo[node] if node is not None else repo['.']
> -    obsolete.createmarkers(repo, [(ctx, (newctx,))], operation='evolve')
> +        repo.ui.status(_(b"evolution of %d:%s created no changes"
> +                         b" to commit\n") % (ctx.rev(), ctx))
> +    newctx = repo[node] if node is not None else repo[b'.']
> +    obsolete.createmarkers(repo, [(ctx, (newctx,))], operation=b'evolve')
>
>      # make sure we are continuing evolve and not `hg next --evolve`
> -    if evolvestate['command'] == 'evolve':
> -        evolvestate['replacements'][ctx.node()] = node
> -        if evolvestate['orphanmerge']:
> +    if evolvestate[b'command'] == b'evolve':
> +        evolvestate[b'replacements'][ctx.node()] = node
> +        if evolvestate[b'orphanmerge']:
>              # processing a merge changeset with both parents obsoleted,
>              # stabilized on second parent, insert in front of list to
>              # re-process to stabilize on first parent
> -            evolvestate['revs'].insert(0, repo[node].rev())
> -            evolvestate['orphanmerge'] = False
> +            evolvestate[b'revs'].insert(0, repo[node].rev())
> +            evolvestate[b'orphanmerge'] = False
>
>  def _completerelocation(ui, repo, evolvestate):
>      """function to complete the interrupted relocation of a commit
>      return the new node formed
>      """
>
> -    orig = repo[evolvestate['current']]
> +    orig = repo[evolvestate[b'current']]
>      ctx = orig
> -    source = ctx.extra().get('source')
> +    source = ctx.extra().get(b'source')
>      extra = {}
>      if source:
> -        extra['source'] = source
> -        extra['intermediate-source'] = ctx.hex()
> +        extra[b'source'] = source
> +        extra[b'intermediate-source'] = ctx.hex()
>      else:
> -        extra['source'] = ctx.hex()
> +        extra[b'source'] = ctx.hex()
>      user = ctx.user()
>      date = ctx.date()
>      message = ctx.description()
> -    ui.status(_('evolving %d:%s "%s"\n') % (ctx.rev(), ctx,
> -                                            message.split('\n', 1)[0]))
> +    ui.status(_(b'evolving %d:%s "%s"\n') % (ctx.rev(), ctx,
> +                                             message.split(b'\n', 1)[0]))
>      targetphase = max(ctx.phase(), phases.draft)
> -    overrides = {('phases', 'new-commit'): targetphase}
> +    overrides = {(b'phases', b'new-commit'): targetphase}
>
>      ctxparents = orig.parents()
>      if len(ctxparents) == 2:
> @@ -2111,7 +2111,7 @@
>          else:
>              # both the parents were obsoleted, if orphanmerge is set, we
>              # are processing the second parent first (to keep parent
> order)
> -            if evolvestate.get('orphanmerge'):
> +            if evolvestate.get(b'orphanmerge'):
>                  with repo.dirstate.parentchange():
>                      repo.dirstate.setparents(ctxparents[0].node(),
>                                               currentp1)
> @@ -2120,7 +2120,7 @@
>          with repo.dirstate.parentchange():
>              repo.dirstate.setparents(repo.dirstate.parents()[0],
> nodemod.nullid)
>
> -    with repo.ui.configoverride(overrides, 'evolve-continue'):
> +    with repo.ui.configoverride(overrides, b'evolve-continue'):
>          node = repo.commit(text=message, user=user,
>                             date=date, extra=extra)
>      return node
> diff --git a/hgext3rd/evolve/exthelper.py b/hgext3rd/evolve/exthelper.py
> --- a/hgext3rd/evolve/exthelper.py
> +++ b/hgext3rd/evolve/exthelper.py
> @@ -83,12 +83,12 @@
>          self._duckpunchers = []
>          self.cmdtable = {}
>          self.command = registrar.command(self.cmdtable)
> -        if '^init' in commands.table:
> +        if b'^init' in commands.table:
>              olddoregister = self.command._doregister
>
>              def _newdoregister(self, name, *args, **kwargs):
> -                if kwargs.pop('helpbasic', False):
> -                    name = '^' + name
> +                if kwargs.pop(b'helpbasic', False):
> +                    name = b'^' + name
>                  return olddoregister(self, name, *args, **kwargs)
>              self.command._doregister = _newdoregister
>
> @@ -111,7 +111,7 @@
>          self._functionwrappers.extend(other._functionwrappers)
>          self._duckpunchers.extend(other._duckpunchers)
>          self.cmdtable.update(other.cmdtable)
> -        for section, items in other.configtable.iteritems():
> +        for section, items in other.configtable.items():
>              if section in self.configtable:
>                  self.configtable[section].update(items)
>              else:
> @@ -277,9 +277,9 @@
>          else:
>              for opt in opts:
>                  if not isinstance(opt, tuple):
> -                    raise error.ProgrammingError('opts must be list of
> tuples')
> +                    raise error.ProgrammingError(b'opts must be list of
> tuples')
>                  if len(opt) not in (4, 5):
> -                    msg = 'each opt tuple must contain 4 or 5 values'
> +                    msg = b'each opt tuple must contain 4 or 5 values'
>                      raise error.ProgrammingError(msg)
>
>          def dec(wrapper):
> diff --git a/hgext3rd/evolve/firstmergecache.py
> b/hgext3rd/evolve/firstmergecache.py
> --- a/hgext3rd/evolve/firstmergecache.py
> +++ b/hgext3rd/evolve/firstmergecache.py
> @@ -41,7 +41,7 @@
>
>          @localrepo.unfilteredmethod
>          def destroyed(self):
> -            if 'firstmergecach' in vars(self):
> +            if b'firstmergecach' in vars(self):
>                  self.firstmergecache.clear()
>              super(firstmergecacherepo, self).destroyed()
>
> @@ -56,16 +56,16 @@
>
>  class firstmergecache(genericcaches.changelogsourcebase):
>
> -    _filepath = 'evoext-firstmerge-00'
> -    _cachename = 'evo-ext-firstmerge'
> +    _filepath = b'evoext-firstmerge-00'
> +    _cachename = b'evo-ext-firstmerge'
>
>      def __init__(self):
>          super(firstmergecache, self).__init__()
> -        self._data = array.array('l')
> +        self._data = array.array(b'l')
>
>      def get(self, rev):
>          if len(self._data) <= rev:
> -            raise error.ProgrammingError('firstmergecache must be warmed
> before use')
> +            raise error.ProgrammingError(b'firstmergecache must be warmed
> before use')
>          return self._data[rev]
>
>      def _updatefrom(self, repo, data):
> @@ -75,15 +75,15 @@
>          total = len(data)
>
>          def progress(pos, rev):
> -            compat.progress(repo.ui, 'updating firstmerge cache',
> -                            pos, 'rev %s' % rev, unit='revision',
> total=total)
> -        progress(0, '')
> +            compat.progress(repo.ui, b'updating firstmerge cache',
> +                            pos, b'rev %s' % rev, unit=b'revision',
> total=total)
> +        progress(0, b'')
>          for idx, rev in enumerate(data, 1):
>              assert rev == len(self._data), (rev, len(self._data))
>              self._data.append(self._firstmerge(cl, rev))
>              if not (idx % 10000): # progress as a too high performance
> impact
>                  progress(idx, rev)
> -        progress(None, '')
> +        progress(None, b'')
>
>      def _firstmerge(self, changelog, rev):
>          cl = changelog
> @@ -107,7 +107,7 @@
>          Subclasses MUST overide this method to actually affect the cache
> data.
>          """
>          super(firstmergecache, self).clear()
> -        self._data = array.array('l')
> +        self._data = array.array(b'l')
>
>      # crude version of a cache, to show the kind of information we have
> to store
>
> @@ -116,7 +116,7 @@
>          assert repo.filtername is None
>
>          data = repo.cachevfs.tryread(self._filepath)
> -        self._data = array.array('l')
> +        self._data = array.array(b'l')
>          if not data:
>              self._cachekey = self.emptykey
>          else:
> @@ -135,12 +135,12 @@
>              return
>
>          try:
> -            cachefile = repo.cachevfs(self._filepath, 'w',
> atomictemp=True)
> +            cachefile = repo.cachevfs(self._filepath, b'w',
> atomictemp=True)
>              headerdata = self._serializecachekey()
>              cachefile.write(headerdata)
>              cachefile.write(self._data.tostring())
>              cachefile.close()
>              self._ondiskkey = self._cachekey
>          except (IOError, OSError) as exc:
> -            repo.ui.log('firstmergecache', 'could not write update %s\n'
> % exc)
> -            repo.ui.debug('firstmergecache: could not write update %s\n'
> % exc)
> +            repo.ui.log(b'firstmergecache', b'could not write update
> %s\n' % exc)
> +            repo.ui.debug(b'firstmergecache: could not write update %s\n'
> % exc)
> diff --git a/hgext3rd/evolve/genericcaches.py
> b/hgext3rd/evolve/genericcaches.py
> --- a/hgext3rd/evolve/genericcaches.py
> +++ b/hgext3rd/evolve/genericcaches.py
> @@ -31,7 +31,7 @@
>      # default key used for an empty cache
>      emptykey = ()
>
> -    _cachekeyspec = '' # used for serialization
> +    _cachekeyspec = b'' # used for serialization
>      _cachename = None # used for debug message
>
>      @abc.abstractmethod
> @@ -42,7 +42,7 @@
>      @util.propertycache
>      def _cachekeystruct(self):
>          # dynamic property to help subclass to change it
> -        return struct.Struct('>' + self._cachekeyspec)
> +        return struct.Struct(b'>' + self._cachekeyspec)
>
>      @util.propertycache
>      def _cachekeysize(self):
> @@ -112,7 +112,7 @@
>          if newkey == self._cachekey:
>              return
>          if reset or self._cachekey is None:
> -            repo.ui.log('cache', 'strip detected, %s cache reset\n'
> +            repo.ui.log(b'cache', b'strip detected, %s cache reset\n'
>                          % self._cachename)
>              self.clear(reset=True)
>
> @@ -120,7 +120,7 @@
>          self._updatefrom(repo, data)
>          duration = util.timer() - starttime
>          summary = self._updatesummary(data)
> -        repo.ui.log('cache', 'updated %s in %.4f seconds (%s)\n',
> +        repo.ui.log(b'cache', b'updated %s in %.4f seconds (%s)\n',
>                      self._cachename, duration, summary)
>
>          self._cachekey = newkey
> @@ -144,7 +144,7 @@
>
>      # default key used for an empty cache
>      emptykey = (0, node.nullid)
> -    _cachekeyspec = 'i20s'
> +    _cachekeyspec = b'i20s'
>      _cachename = None # used for debug message
>
>      # Useful "public" function (no need to override them)
> @@ -172,4 +172,4 @@
>          return self._fetchchangelogdata(self._cachekey, repo.changelog)
>
>      def _updatesummary(self, data):
> -        return '%ir' % len(data)
> +        return b'%ir' % len(data)
> diff --git a/hgext3rd/evolve/hack/drophack.py
> b/hgext3rd/evolve/hack/drophack.py
> --- a/hgext3rd/evolve/hack/drophack.py
> +++ b/hgext3rd/evolve/hack/drophack.py
> @@ -34,7 +34,7 @@
>      user = ostop[0] - ostart[0]
>      sys = ostop[1] - ostart[1]
>      comb = user + sys
> -    ui.write("%s: wall %f comb %f user %f sys %f\n"
> +    ui.write(b"%s: wall %f comb %f user %f sys %f\n"
>               % (caption, wall, comb, user, sys))
>
>  def obsmarkerchainfrom(obsstore, nodes):
> @@ -66,13 +66,13 @@
>      repo = repo.unfiltered()
>      repo.destroying()
>      oldmarkers = list(repo.obsstore._all)
> -    util.rename(repo.svfs.join('obsstore'),
> -                repo.vfs.join('obsstore.prestrip'))
> +    util.rename(repo.svfs.join(b'obsstore'),
> +                repo.vfs.join(b'obsstore.prestrip'))
>      del repo.obsstore # drop the cache
>      newstore = repo.obsstore
>      assert not newstore # should be empty after rename
>      newmarkers = [m for m in oldmarkers if m not in markers]
> -    tr = repo.transaction('drophack')
> +    tr = repo.transaction(b'drophack')
>      try:
>          newstore.add(tr, newmarkers)
>          tr.close()
> @@ -81,7 +81,7 @@
>      repo.destroyed()
>
>
> -@command('drop', [('r', 'rev', [], 'revision to update')], _('[-r] revs'))
> +@command(b'drop', [(b'r', b'rev', [], b'revision to update')], _(b'[-r]
> revs'))
>  def cmddrop(ui, repo, *revs, **opts):
>      """I'm hacky do not use me!
>
> @@ -95,13 +95,13 @@
>      This intended for Matt Mackall usage only. do not use me.
>      """
>      revs = list(revs)
> -    revs.extend(opts['rev'])
> +    revs.extend(opts[b'rev'])
>      if not revs:
> -        revs = ['.']
> +        revs = [b'.']
>      # get the changeset
>      revs = scmutil.revrange(repo, revs)
>      if not revs:
> -        ui.write_err('no revision to drop\n')
> +        ui.write_err(b'no revision to drop\n')
>          return 1
>      # lock from the beginning to prevent race
>      wlock = lock = None
> @@ -109,49 +109,49 @@
>          wlock = repo.wlock()
>          lock = repo.lock()
>          # check they have no children
> -        if repo.revs('%ld and public()', revs):
> -            ui.write_err('cannot drop public revision')
> +        if repo.revs(b'%ld and public()', revs):
> +            ui.write_err(b'cannot drop public revision')
>              return 1
> -        if repo.revs('children(%ld) - %ld', revs, revs):
> -            ui.write_err('cannot drop revision with children')
> +        if repo.revs(b'children(%ld) - %ld', revs, revs):
> +            ui.write_err(b'cannot drop revision with children')
>              return 1
> -        if repo.revs('. and %ld', revs):
> -            newrevs = repo.revs('max(::. - %ld)', revs)
> +        if repo.revs(b'. and %ld', revs):
> +            newrevs = repo.revs(b'max(::. - %ld)', revs)
>              if newrevs:
>                  assert len(newrevs) == 1
>                  newrev = newrevs.first()
>              else:
>                  newrev = -1
>              commands.update(ui, repo, newrev)
> -            ui.status(_('working directory now at %s\n') % repo[newrev])
> +            ui.status(_(b'working directory now at %s\n') % repo[newrev])
>          # get all markers and successors up to root
>          nodes = [repo[r].node() for r in revs]
> -        with timed(ui, 'search obsmarker'):
> +        with timed(ui, b'search obsmarker'):
>              markers = set(obsmarkerchainfrom(repo.obsstore, nodes))
> -        ui.write('%i obsmarkers found\n' % len(markers))
> +        ui.write(b'%i obsmarkers found\n' % len(markers))
>          cl = repo.unfiltered().changelog
> -        with timed(ui, 'search nodes'):
> +        with timed(ui, b'search nodes'):
>              allnodes = set(nodes)
>              allnodes.update(m[0] for m in markers if cl.hasnode(m[0]))
> -        ui.write('%i nodes found\n' % len(allnodes))
> +        ui.write(b'%i nodes found\n' % len(allnodes))
>          cl = repo.changelog
>          visiblenodes = set(n for n in allnodes if cl.hasnode(n))
>          # check constraint again
> -        if repo.revs('%ln and public()', visiblenodes):
> -            ui.write_err('cannot drop public revision')
> +        if repo.revs(b'%ln and public()', visiblenodes):
> +            ui.write_err(b'cannot drop public revision')
>              return 1
> -        if repo.revs('children(%ln) - %ln', visiblenodes, visiblenodes):
> -            ui.write_err('cannot drop revision with children')
> +        if repo.revs(b'children(%ln) - %ln', visiblenodes, visiblenodes):
> +            ui.write_err(b'cannot drop revision with children')
>              return 1
>
>          if markers:
>              # strip them
> -            with timed(ui, 'strip obsmarker'):
> +            with timed(ui, b'strip obsmarker'):
>                  stripmarker(ui, repo, markers)
>          # strip the changeset
> -        with timed(ui, 'strip nodes'):
> -            repair.strip(ui, repo, list(allnodes), backup="all",
> -                         topic='drophack')
> +        with timed(ui, b'strip nodes'):
> +            repair.strip(ui, repo, list(allnodes), backup=b"all",
> +                         topic=b'drophack')
>
>      finally:
>          lockmod.release(lock, wlock)
> diff --git a/hgext3rd/evolve/legacy.py b/hgext3rd/evolve/legacy.py
> --- a/hgext3rd/evolve/legacy.py
> +++ b/hgext3rd/evolve/legacy.py
> @@ -45,20 +45,20 @@
>      """
>      if not repo.local():
>          return
> -    evolveopts = ui.configlist('experimental', 'evolution')
> +    evolveopts = ui.configlist(b'experimental', b'evolution')
>      if not evolveopts:
> -        evolveopts = 'all'
> -        ui.setconfig('experimental', 'evolution', evolveopts)
> +        evolveopts = b'all'
> +        ui.setconfig(b'experimental', b'evolution', evolveopts)
>      for arg in sys.argv:
> -        if 'debugc' in arg:
> +        if b'debugc' in arg:
>              break
>      else:
> -        data = repo.vfs.tryread('obsolete-relations')
> +        data = repo.vfs.tryread(b'obsolete-relations')
>          if not data:
> -            data = repo.svfs.tryread('obsoletemarkers')
> +            data = repo.svfs.tryread(b'obsoletemarkers')
>          if data:
> -            raise error.Abort('old format of obsolete marker detected!\n'
> -                              'run `hg debugconvertobsolete` once.')
> +            raise error.Abort(b'old format of obsolete marker detected!\n'
> +                              b'run `hg debugconvertobsolete` once.')
>
>  def _obsdeserialize(flike):
>      """read a file like object serialized with _obsserialize
> @@ -77,7 +77,7 @@
>
>  cmdtable = {}
>  command = commandfunc(cmdtable)
> -@command('debugconvertobsolete', [], '')
> +@command(b'debugconvertobsolete', [], b'')
>  def cmddebugconvertobsolete(ui, repo):
>      """import markers from an .hg/obsolete-relations file"""
>      cnt = 0
> @@ -86,13 +86,13 @@
>      some = False
>      try:
>          unlink = []
> -        tr = repo.transaction('convert-obsolete')
> +        tr = repo.transaction(b'convert-obsolete')
>          try:
>              repo._importoldobsolete = True
>              store = repo.obsstore
>              ### very first format
>              try:
> -                f = repo.vfs('obsolete-relations')
> +                f = repo.vfs(b'obsolete-relations')
>                  try:
>                      some = True
>                      for line in f:
> @@ -101,30 +101,30 @@
>                          prec = bin(objhex)
>                          sucs = (suc == nullid) and [] or [suc]
>                          meta = {
> -                            'date': '%i %i' % makedate(),
> -                            'user': ui.username(),
> +                            b'date': b'%i %i' % makedate(),
> +                            b'user': ui.username(),
>                              }
>                          try:
>                              store.create(tr, prec, sucs, 0, metadata=meta)
>                              cnt += 1
>                          except ValueError:
> -                            repo.ui.write_err("invalid old marker line:
> %s"
> +                            repo.ui.write_err(b"invalid old marker line:
> %s"
>                                                % (line))
>                              err += 1
>                  finally:
>                      f.close()
> -                unlink.append(repo.vfs.join('obsolete-relations'))
> +                unlink.append(repo.vfs.join(b'obsolete-relations'))
>              except IOError:
>                  pass
>              ### second (json) format
> -            data = repo.svfs.tryread('obsoletemarkers')
> +            data = repo.svfs.tryread(b'obsoletemarkers')
>              if data:
>                  some = True
>                  for oldmark in json.loads(data):
> -                    del oldmark['id']  # dropped for now
> -                    del oldmark['reason']  # unused until then
> -                    oldobject = str(oldmark.pop('object'))
> -                    oldsubjects = [str(s) for s in
> oldmark.pop('subjects', [])]
> +                    del oldmark[b'id']  # dropped for now
> +                    del oldmark[b'reason']  # unused until then
> +                    oldobject = str(oldmark.pop(b'object'))
> +                    oldsubjects = [str(s) for s in
> oldmark.pop(b'subjects', [])]
>                      lookup_errors = (error.RepoLookupError,
> error.LookupError)
>                      if len(oldobject) != 40:
>                          try:
> @@ -137,9 +137,9 @@
>                          except lookup_errors:
>                              pass
>
> -                    oldmark['date'] = '%i %i' % tuple(oldmark['date'])
> +                    oldmark[b'date'] = b'%i %i' % tuple(oldmark[b'date'])
>                      meta = dict((k.encode('utf-8'), v.encode('utf-8'))
> -                                for k, v in oldmark.iteritems())
> +                                for k, v in oldmark.items())
>                      try:
>                          succs = [bin(n) for n in oldsubjects]
>                          succs = [n for n in succs if n != nullid]
> @@ -147,11 +147,11 @@
>                                       0, metadata=meta)
>                          cnt += 1
>                      except ValueError:
> -                        msg = "invalid marker %s -> %s\n"
> +                        msg = b"invalid marker %s -> %s\n"
>                          msg %= (oldobject, oldsubjects)
>                          repo.ui.write_err(msg)
>                          err += 1
> -                unlink.append(repo.svfs.join('obsoletemarkers'))
> +                unlink.append(repo.svfs.join(b'obsoletemarkers'))
>              tr.close()
>              for path in unlink:
>                  util.unlink(path)
> @@ -161,12 +161,12 @@
>          del repo._importoldobsolete
>          lock.release()
>      if not some:
> -        ui.warn(_('nothing to do\n'))
> -    ui.status('%i obsolete marker converted\n' % cnt)
> +        ui.warn(_(b'nothing to do\n'))
> +    ui.status(b'%i obsolete marker converted\n' % cnt)
>      if err:
> -        ui.write_err('%i conversion failed. check you graph!\n' % err)
> +        ui.write_err(b'%i conversion failed. check you graph!\n' % err)
>
> -@command('debugrecordpruneparents', [], '')
> +@command(b'debugrecordpruneparents', [], b'')
>  def cmddebugrecordpruneparents(ui, repo):
>      """add parent data to prune markers when possible
>
> @@ -174,14 +174,14 @@
>      If the pruned node is locally known, it creates a new marker with
> parent
>      data.
>      """
> -    pgop = 'reading markers'
> +    pgop = b'reading markers'
>
>      # lock from the beginning to prevent race
>      wlock = lock = tr = None
>      try:
>          wlock = repo.wlock()
>          lock = repo.lock()
> -        tr = repo.transaction('recordpruneparents')
> +        tr = repo.transaction(b'recordpruneparents')
>          unfi = repo.unfiltered()
>          nm = unfi.changelog.nodemap
>          store = repo.obsstore
> @@ -196,7 +196,7 @@
>                      store.create(tr, prec=mark[0], succs=mark[1],
> flag=mark[2],
>                                   metadata=dict(mark[3]), parents=parents)
>                      if len(store._all) - before:
> -                        ui.write(_('created new markers for %i\n') % rev)
> +                        ui.write(_(b'created new markers for %i\n') % rev)
>              ui.progress(pgop, idx, total=pgtotal)
>          tr.close()
>          ui.progress(pgop, None)
> diff --git a/hgext3rd/evolve/metadata.py b/hgext3rd/evolve/metadata.py
> --- a/hgext3rd/evolve/metadata.py
> +++ b/hgext3rd/evolve/metadata.py
> @@ -5,7 +5,7 @@
>  # This software may be used and distributed according to the terms of the
>  # GNU General Public License version 2 or any later version.
>
> -__version__ = '8.6.0.dev'
> -testedwith = '4.5.2 4.6.2 4.7 4.8 4.9 5.0'
> -minimumhgversion = '4.5'
> -buglink = 'https://bz.mercurial-scm.org/'
> +__version__ = b'8.6.0.dev'
> +testedwith = b'4.5.2 4.6.2 4.7 4.8 4.9 5.0'
> +minimumhgversion = b'4.5'
> +buglink = b'https://bz.mercurial-scm.org/'
> diff --git a/hgext3rd/evolve/obscache.py b/hgext3rd/evolve/obscache.py
> --- a/hgext3rd/evolve/obscache.py
> +++ b/hgext3rd/evolve/obscache.py
> @@ -28,7 +28,7 @@
>  obsstorefilecache = localrepo.localrepository.obsstore
>
>  # obsstore is a filecache so we have do to some spacial dancing
> -@eh.wrapfunction(obsstorefilecache, 'func')
> +@eh.wrapfunction(obsstorefilecache, b'func')
>  def obsstorewithcache(orig, repo):
>      obsstore = orig(repo)
>      obsstore.obscache = obscache(repo.unfiltered())
> @@ -50,10 +50,10 @@
>              length, cachekey will be set to None."""
>              # default value
>              obsstoresize = 0
> -            keydata = ''
> +            keydata = b''
>              # try to get actual data from the obsstore
>              try:
> -                with self.svfs('obsstore') as obsfile:
> +                with self.svfs(b'obsstore') as obsfile:
>                      obsfile.seek(0, 2)
>                      obsstoresize = obsfile.tell()
>                      if index is None:
> @@ -82,11 +82,11 @@
>  def markersfrom(obsstore, byteoffset, firstmarker):
>      if not firstmarker:
>          return list(obsstore)
> -    elif '_all' in vars(obsstore):
> +    elif b'_all' in vars(obsstore):
>          # if the data are in memory, just use that
>          return obsstore._all[firstmarker:]
>      else:
> -        obsdata = obsstore.svfs.tryread('obsstore')
> +        obsdata = obsstore.svfs.tryread(b'obsstore')
>          return obsolete._readmarkers(obsdata, byteoffset)[1]
>
>
> @@ -178,7 +178,7 @@
>
>          reset, revs, obsmarkers, obskeypair = upgrade
>          if reset or self._cachekey is None:
> -            repo.ui.log('evoext-cache', 'strip detected, %s cache
> reset\n' % self._cachename)
> +            repo.ui.log(b'evoext-cache', b'strip detected, %s cache
> reset\n' % self._cachename)
>              self.clear(reset=True)
>
>          starttime = util.timer()
> @@ -186,7 +186,7 @@
>          obsmarkers = list(obsmarkers)
>          self._updatefrom(repo, revs, obsmarkers)
>          duration = util.timer() - starttime
> -        repo.ui.log('evoext-cache', 'updated %s in %.4f seconds (%sr,
> %so)\n',
> +        repo.ui.log(b'evoext-cache', b'updated %s in %.4f seconds (%sr,
> %so)\n',
>                      self._cachename, duration, len(revs), len(obsmarkers))
>
>          # update the key from the new data
> @@ -314,10 +314,10 @@
>          zero. That would be especially useful for the '.pending' overlay.
>      """
>
> -    _filepath = 'evoext-obscache-00'
> -    _headerformat = '>q20sQQ20s'
> +    _filepath = b'evoext-obscache-00'
> +    _headerformat = b'>q20sQQ20s'
>
> -    _cachename = 'evo-ext-obscache' # used for error message
> +    _cachename = b'evo-ext-obscache' # used for error message
>
>      def __init__(self, repo):
>          super(obscache, self).__init__()
> @@ -339,7 +339,7 @@
>      def _setdata(self, data):
>          """set a new bytearray data, invalidating the 'get' shortcut if
> needed"""
>          self._data = data
> -        if 'get' in vars(self):
> +        if b'get' in vars(self):
>              del self.get
>
>      def clear(self, reset=False):
> @@ -403,15 +403,15 @@
>              return
>
>          try:
> -            cachefile = repo.cachevfs(self._filepath, 'w',
> atomictemp=True)
> +            cachefile = repo.cachevfs(self._filepath, b'w',
> atomictemp=True)
>              headerdata = struct.pack(self._headerformat, *self._cachekey)
>              cachefile.write(headerdata)
>              cachefile.write(self._data)
>              cachefile.close()
>              self._ondiskkey = self._cachekey
>          except (IOError, OSError) as exc:
> -            repo.ui.log('obscache', 'could not write update %s\n' % exc)
> -            repo.ui.debug('obscache: could not write update %s\n' % exc)
> +            repo.ui.log(b'obscache', b'could not write update %s\n' % exc)
> +            repo.ui.debug(b'obscache: could not write update %s\n' % exc)
>
>      def load(self, repo):
>          """load data from disk"""
> @@ -447,10 +447,10 @@
>          # will be about as fast...
>          if not obscache.uptodate(repo):
>              if repo.currenttransaction() is None:
> -                repo.ui.log('evoext-cache',
> -                            'obscache is out of date, '
> -                            'falling back to slower obsstore version\n')
> -                repo.ui.debug('obscache is out of date\n')
> +                repo.ui.log(b'evoext-cache',
> +                            b'obscache is out of date, '
> +                            b'falling back to slower obsstore version\n')
> +                repo.ui.debug(b'obscache is out of date\n')
>                  return orig(repo)
>              else:
>                  # If a transaction is open, it is worthwhile to update
> and use
> @@ -465,9 +465,9 @@
>
>  @eh.uisetup
>  def cachefuncs(ui):
> -    orig = obsolete.cachefuncs['obsolete']
> +    orig = obsolete.cachefuncs[b'obsolete']
>      wrapped = lambda repo: _computeobsoleteset(orig, repo)
> -    obsolete.cachefuncs['obsolete'] = wrapped
> +    obsolete.cachefuncs[b'obsolete'] = wrapped
>
>  @eh.reposetup
>  def setupcache(ui, repo):
> @@ -476,7 +476,7 @@
>
>          @localrepo.unfilteredmethod
>          def destroyed(self):
> -            if 'obsstore' in vars(self):
> +            if b'obsstore' in vars(self):
>                  self.obsstore.obscache.clear()
>              super(obscacherepo, self).destroyed()
>
> diff --git a/hgext3rd/evolve/obsdiscovery.py
> b/hgext3rd/evolve/obsdiscovery.py
> --- a/hgext3rd/evolve/obsdiscovery.py
> +++ b/hgext3rd/evolve/obsdiscovery.py
> @@ -67,11 +67,11 @@
>  obsexcmsg = utility.obsexcmsg
>
>  # Config
> -eh.configitem('experimental', 'evolution.obsdiscovery', True)
> -eh.configitem('experimental', 'obshashrange', True)
> -eh.configitem('experimental', 'obshashrange.warm-cache', 'auto')
> -eh.configitem('experimental', 'obshashrange.max-revs', None)
> -eh.configitem('experimental', 'obshashrange.lru-size', 2000)
> +eh.configitem(b'experimental', b'evolution.obsdiscovery', True)
> +eh.configitem(b'experimental', b'obshashrange', True)
> +eh.configitem(b'experimental', b'obshashrange.warm-cache', b'auto')
> +eh.configitem(b'experimental', b'obshashrange.max-revs', None)
> +eh.configitem(b'experimental', b'obshashrange.lru-size', 2000)
>
>  ##################################
>  ###  Code performing discovery ###
> @@ -89,15 +89,15 @@
>      undecided = set(probeset)
>      totalnb = len(undecided)
>      heads = [rev for rev in cl.headrevs() if rev != node.nullrev]
> -    compat.progress(ui, _("comparing with other"), 0, total=totalnb,
> -                    unit=_("changesets"))
> -    if util.safehasattr(setdiscovery, '_takefullsample'):
> +    compat.progress(ui, _(b"comparing with other"), 0, total=totalnb,
> +                    unit=_(b"changesets"))
> +    if util.safehasattr(setdiscovery, b'_takefullsample'):
>          # hg compat <= hg-4.9 (e5ece0f46b40)
>          _takefullsample = setdiscovery._takefullsample
>      else:
>          obsdiscov = setdiscovery.partialdiscovery(local, heads)
>          _takefullsample = obsdiscov.takefullsample
> -    if remote.capable('_evoext_obshash_1'):
> +    if remote.capable(b'_evoext_obshash_1'):
>          getremotehash = remote.evoext_obshash1
>          localhash = _obsrelsethashtreefm1(local)
>      else:
> @@ -106,11 +106,11 @@
>
>      while undecided:
>
> -        ui.note(_("sampling from both directions\n"))
> +        ui.note(_(b"sampling from both directions\n"))
>          if len(undecided) < fullsamplesize:
>              sample = set(undecided)
>          else:
> -            if util.safehasattr(setdiscovery, '_takefullsample'):
> +            if util.safehasattr(setdiscovery, b'_takefullsample'):
>                  # compat <= hg-4.9 (e5ece0f46b40)
>                  if len(inspect.getargspec(_takefullsample)[0]) == 4:
>                      # Mercurial 4.8 changed calling convention.
> @@ -124,9 +124,9 @@
>                  sample = _takefullsample(None, size=fullsamplesize)
>
>          roundtrips += 1
> -        compat.progress(ui, _("comparing with other"), totalnb -
> len(undecided),
> -                        total=totalnb, unit=_("changesets"))
> -        ui.debug("query %i; still undecided: %i, sample size is: %i\n"
> +        compat.progress(ui, _(b"comparing with other"), totalnb -
> len(undecided),
> +                        total=totalnb, unit=_(b"changesets"))
> +        ui.debug(b"query %i; still undecided: %i, sample size is: %i\n"
>                   % (roundtrips, len(undecided), len(sample)))
>          # indices between sample and externalized version must match
>          sample = list(sample)
> @@ -144,9 +144,9 @@
>          undecided.difference_update(missing)
>          undecided.difference_update(common)
>
> -    compat.progress(ui, _("comparing with other"), None)
> +    compat.progress(ui, _(b"comparing with other"), None)
>      result = dag.headsetofconnecteds(common)
> -    ui.debug("%d total queries\n" % roundtrips)
> +    ui.debug(b"%d total queries\n" % roundtrips)
>
>      if not result:
>          return set([node.nullid])
> @@ -158,7 +158,7 @@
>      missing = set()
>      starttime = util.timer()
>
> -    heads = local.revs('heads(%ld)', probeset)
> +    heads = local.revs(b'heads(%ld)', probeset)
>      local.stablerange.warmup(local)
>
>      rangelength = local.stablerange.rangelength
> @@ -186,8 +186,8 @@
>
>      local.obsstore.rangeobshashcache.update(local)
>      querycount = 0
> -    compat.progress(ui, _("comparing obsmarker with other"), querycount,
> -                    unit=_("queries"))
> +    compat.progress(ui, _(b"comparing obsmarker with other"), querycount,
> +                    unit=_(b"queries"))
>      overflow = []
>      while sample or overflow:
>          if overflow:
> @@ -199,7 +199,7 @@
>              overflow = sample[samplesize:]
>              sample = sample[:samplesize]
>          elif len(sample) < samplesize:
> -            ui.debug("query %i; add more sample (target %i, current %i)\n"
> +            ui.debug(b"query %i; add more sample (target %i, current
> %i)\n"
>                       % (querycount, samplesize, len(sample)))
>              # we need more sample !
>              needed = samplesize - len(sample)
> @@ -225,7 +225,7 @@
>
>          nbsample = len(sample)
>          maxsize = max([rangelength(local, r) for r in sample])
> -        ui.debug("query %i; sample size is %i, largest range %i\n"
> +        ui.debug(b"query %i; sample size is %i, largest range %i\n"
>                   % (querycount, nbsample, maxsize))
>          nbreplies = 0
>          replies = list(_queryrange(ui, local, remote, sample))
> @@ -242,15 +242,15 @@
>                      addentry(new)
>          assert nbsample == nbreplies
>          querycount += 1
> -        compat.progress(ui, _("comparing obsmarker with other"),
> querycount,
> -                        unit=_("queries"))
> -    compat.progress(ui, _("comparing obsmarker with other"), None)
> +        compat.progress(ui, _(b"comparing obsmarker with other"),
> querycount,
> +                        unit=_(b"queries"))
> +    compat.progress(ui, _(b"comparing obsmarker with other"), None)
>      local.obsstore.rangeobshashcache.save(local)
>      duration = util.timer() - starttime
> -    logmsg = ('obsdiscovery, %d/%d mismatch'
> -              ' - %d obshashrange queries in %.4f seconds\n')
> +    logmsg = (b'obsdiscovery, %d/%d mismatch'
> +              b' - %d obshashrange queries in %.4f seconds\n')
>      logmsg %= (len(missing), len(probeset), querycount, duration)
> -    ui.log('evoext-obsdiscovery', logmsg)
> +    ui.log(b'evoext-obsdiscovery', logmsg)
>      ui.debug(logmsg)
>      return sorted(missing)
>
> @@ -269,30 +269,30 @@
>  ##############################
>
>  @eh.command(
> -    'debugobshashrange',
> +    b'debugobshashrange',
>      [
> -        ('', 'rev', [], 'display obshash for all (rev, 0) range in REVS'),
> -        ('', 'subranges', False, 'display all subranges'),
> -    ],
> -    _(''))
> +        (b'', b'rev', [], b'display obshash for all (rev, 0) range in
> REVS'),
> +        (b'', b'subranges', False, b'display all subranges'),
> +     ],
> +    _(b''))
>  def debugobshashrange(ui, repo, **opts):
>      """display the ::REVS set topologically sorted in a stable way
>      """
>      s = node.short
> -    revs = scmutil.revrange(repo, opts['rev'])
> +    revs = scmutil.revrange(repo, opts[b'rev'])
>      # prewarm depth cache
>      if revs:
>          repo.stablerange.warmup(repo, max(revs))
>      cl = repo.changelog
>      rangelength = repo.stablerange.rangelength
>      depthrev = repo.stablerange.depthrev
> -    if opts['subranges']:
> +    if opts[b'subranges']:
>          ranges = stablerange.subrangesclosure(repo, repo.stablerange,
> revs)
>      else:
>          ranges = [(r, 0) for r in revs]
> -    headers = ('rev', 'node', 'index', 'size', 'depth', 'obshash')
> -    linetemplate = '%12d %12s %12d %12d %12d %12s\n'
> -    headertemplate = linetemplate.replace('d', 's')
> +    headers = (b'rev', b'node', b'index', b'size', b'depth', b'obshash')
> +    linetemplate = b'%12d %12s %12d %12d %12d %12s\n'
> +    headertemplate = linetemplate.replace(b'd', b's')
>      ui.status(headertemplate % headers)
>      repo.obsstore.rangeobshashcache.update(repo)
>      for r in ranges:
> @@ -348,7 +348,7 @@
>                                   idx     INTEGER NOT NULL,
>                                   obshash BLOB    NOT NULL,
>                                   PRIMARY KEY(rev, idx));""",
> -    "CREATE INDEX range_index ON obshashrange(rev, idx);",
> +    b"CREATE INDEX range_index ON obshashrange(rev, idx);",
>      """CREATE TABLE meta(schemaversion INTEGER NOT NULL,
>                           tiprev        INTEGER NOT NULL,
>                           tipnode       BLOB    NOT NULL,
> @@ -357,17 +357,17 @@
>                           obskey        BLOB    NOT NULL
>                          );""",
>  ]
> -_queryexist = "SELECT name FROM sqlite_master WHERE type='table' AND
> name='meta';"
> +_queryexist = b"SELECT name FROM sqlite_master WHERE type='table' AND
> name='meta';"
>  _clearmeta = """DELETE FROM meta;"""
>  _newmeta = """INSERT INTO meta (schemaversion, tiprev, tipnode,
> nbobsmarker, obssize, obskey)
>              VALUES (?,?,?,?,?,?);"""
> -_updateobshash = "INSERT INTO obshashrange(rev, idx, obshash) VALUES
> (?,?,?);"
> -_querymeta = "SELECT schemaversion, tiprev, tipnode, nbobsmarker,
> obssize, obskey FROM meta;"
> -_queryobshash = "SELECT obshash FROM obshashrange WHERE (rev = ? AND idx
> = ?);"
> -_query_max_stored = "SELECT MAX(rev) FROM obshashrange"
> +_updateobshash = b"INSERT INTO obshashrange(rev, idx, obshash) VALUES
> (?,?,?);"
> +_querymeta = b"SELECT schemaversion, tiprev, tipnode, nbobsmarker,
> obssize, obskey FROM meta;"
> +_queryobshash = b"SELECT obshash FROM obshashrange WHERE (rev = ? AND idx
> = ?);"
> +_query_max_stored = b"SELECT MAX(rev) FROM obshashrange"
>
> -_reset = "DELETE FROM obshashrange;"
> -_delete = "DELETE FROM obshashrange WHERE (rev = ? AND idx = ?);"
> +_reset = b"DELETE FROM obshashrange;"
> +_delete = b"DELETE FROM obshashrange WHERE (rev = ? AND idx = ?);"
>
>  def _affectedby(repo, markers):
>      """return all nodes whose relevant set is affected by this changeset
> @@ -415,8 +415,8 @@
>
>      _schemaversion = 3
>
> -    _cachename = 'evo-ext-obshashrange' # used for error message
> -    _filename = 'evoext_obshashrange_v2.sqlite'
> +    _cachename = b'evo-ext-obshashrange' # used for error message
> +    _filename = b'evoext_obshashrange_v2.sqlite'
>
>      def __init__(self, repo):
>          super(_obshashcache, self).__init__()
> @@ -435,7 +435,7 @@
>          self._new.clear()
>          if reset:
>              self._valid = False
> -        if '_con' in vars(self):
> +        if b'_con' in vars(self):
>              del self._con
>
>      def get(self, rangeid):
> @@ -444,7 +444,7 @@
>          # XXX there are issue with cache warming, we hack around it for
> now
>          if not getattr(self, '_updating', False):
>              if self._cachekey[0] < rangeid[0]:
> -                msg = ('using unwarmed obshashrangecache (%s %s)'
> +                msg = (b'using unwarmed obshashrangecache (%s %s)'
>                         % (rangeid[0], self._cachekey[0]))
>                  raise error.ProgrammingError(msg)
>
> @@ -459,7 +459,7 @@
>              except (sqlite3.DatabaseError, sqlite3.OperationalError):
>                  # something is wrong with the sqlite db
>                  # Since this is a cache, we ignore it.
> -                if '_con' in vars(self):
> +                if b'_con' in vars(self):
>                      del self._con
>                  self._new.clear()
>          return value
> @@ -488,8 +488,8 @@
>              affected = []
>              if RESET_ABOVE < len(obsmarkers):
>                  # lots of new obsmarkers, probably smarter to reset the
> cache
> -                repo.ui.log('evoext-cache', 'obshashcache reset - '
> -                            'many new markers (%d)\n'
> +                repo.ui.log(b'evoext-cache', b'obshashcache reset - '
> +                            b'many new markers (%d)\n'
>                              % len(obsmarkers))
>                  reset = True
>              elif obsmarkers:
> @@ -502,23 +502,23 @@
>                              if r is not None and r <= max_stored]
>
>              if RESET_ABOVE < len(affected):
> -                repo.ui.log('evoext-cache', 'obshashcache reset - '
> -                            'new markers affect many changeset (%d)\n'
> +                repo.ui.log(b'evoext-cache', b'obshashcache reset - '
> +                            b'new markers affect many changeset (%d)\n'
>                              % len(affected))
>                  reset = True
>
>              if affected or reset:
>                  if not reset:
> -                    repo.ui.log('evoext-cache', 'obshashcache clean - '
> -                                'new markers affect %d changeset and
> cached ranges\n'
> +                    repo.ui.log(b'evoext-cache', b'obshashcache clean - '
> +                                b'new markers affect %d changeset and
> cached ranges\n'
>                                  % len(affected))
>                  if con is not None:
>                      # always reset for now, the code detecting affect is
> buggy
>                      # so we need to reset more broadly than we would like.
>                      try:
>                          if repo.stablerange._con is None:
> -                            repo.ui.log('evoext-cache', 'obshashcache
> reset - '
> -                                        'underlying stablerange cache
> unavailable\n')
> +                            repo.ui.log(b'evoext-cache', b'obshashcache
> reset - '
> +                                        b'underlying stablerange cache
> unavailable\n')
>                              reset = True
>                          if reset:
>                              con.execute(_reset)
> @@ -529,7 +529,7 @@
>                              for r in ranges:
>                                  self._data.pop(r, None)
>                      except (sqlite3.DatabaseError,
> sqlite3.OperationalError) as exc:
> -                        repo.ui.log('evoext-cache', 'error while updating
> obshashrange cache: %s' % exc)
> +                        repo.ui.log(b'evoext-cache', b'error while
> updating obshashrange cache: %s' % exc)
>                          del self._updating
>                          return
>
> @@ -539,7 +539,7 @@
>                  # single revision is quite costly)
>                  newrevs = []
>                  stop = self._cachekey[0] # tiprev
> -                for h in repo.filtered('immutable').changelog.headrevs():
> +                for h in repo.filtered(b'immutable').changelog.headrevs():
>                      if h <= stop and h in affected:
>                          newrevs.append(h)
>                  newrevs.extend(revs)
> @@ -549,14 +549,14 @@
>          total = len(revs)
>
>          def progress(pos, rev):
> -            compat.progress(repo.ui, 'updating obshashrange cache',
> -                            pos, 'rev %s' % rev, unit='revision',
> total=total)
> +            compat.progress(repo.ui, b'updating obshashrange cache',
> +                            pos, b'rev %s' % rev, unit=b'revision',
> total=total)
>          # warm the cache for the new revs
> -        progress(0, '')
> +        progress(0, b'')
>          for idx, r in enumerate(revs):
>              _obshashrange(repo, (r, 0))
>              progress(idx, r)
> -        progress(None, '')
> +        progress(None, b'')
>
>          del self._updating
>
> @@ -575,7 +575,7 @@
>              util.makedirs(self._vfs.dirname(self._path))
>          except OSError:
>              return None
> -        con = sqlite3.connect(self._path, timeout=30,
> isolation_level="IMMEDIATE")
> +        con = sqlite3.connect(self._path, timeout=30,
> isolation_level=b"IMMEDIATE")
>          con.text_factory = str
>          return con
>
> @@ -608,14 +608,14 @@
>          repo = repo.unfiltered()
>          try:
>              with repo.lock():
> -                if 'stablerange' in vars(repo):
> +                if b'stablerange' in vars(repo):
>                      repo.stablerange.save(repo)
>                  self._save(repo)
>          except error.LockError:
>              # Exceptionnally we are noisy about it since performance
> impact
>              # is large We should address that before using this more
>              # widely.
> -            msg = _('obshashrange cache: skipping save unable to lock
> repo\n')
> +            msg = _(b'obshashrange cache: skipping save unable to lock
> repo\n')
>              repo.ui.warn(msg)
>
>      def _save(self, repo):
> @@ -628,22 +628,22 @@
>              #
>              # operational error catch read-only and locked database
>              # IntegrityError catch Unique constraint error that may arise
> -            if '_con' in vars(self):
> +            if b'_con' in vars(self):
>                  del self._con
>              self._new.clear()
> -            repo.ui.log('evoext-cache', 'error while saving new data: %s'
> % exc)
> -            repo.ui.debug('evoext-cache: error while saving new data: %s'
> % exc)
> +            repo.ui.log(b'evoext-cache', b'error while saving new data:
> %s' % exc)
> +            repo.ui.debug(b'evoext-cache: error while saving new data:
> %s' % exc)
>
>      def _trysave(self, repo):
>          if self._con is None:
>              util.unlinkpath(self._path, ignoremissing=True)
> -            if '_con' in vars(self):
> +            if b'_con' in vars(self):
>                  del self._con
>
>              con = self._db()
>              if con is None:
> -                repo.ui.log('evoext-cache', 'unable to write obshashrange
> cache'
> -                            ' - cannot create database')
> +                repo.ui.log(b'evoext-cache', b'unable to write
> obshashrange cache'
> +                            b' - cannot create database')
>                  return
>              with con:
>                  for req in _sqliteschema:
> @@ -660,12 +660,12 @@
>                  # drifting is currently an issue because this means
> another
>                  # process might have already added the cache line we are
> about
>                  # to add. This will confuse sqlite
> -                msg = _('obshashrange cache: skipping write, '
> -                        'database drifted under my feet\n')
> +                msg = _(b'obshashrange cache: skipping write, '
> +                        b'database drifted under my feet\n')
>                  repo.ui.warn(msg)
>                  self._new.clear()
>                  self._valid = False
> -                if '_con' in vars(self):
> +                if b'_con' in vars(self):
>                      del self._con
>                  self._valid = False
>                  return
> @@ -677,7 +677,7 @@
>              self._new.clear()
>              self._valid = True
>              self._ondiskcachekey = self._cachekey
> -@eh.wrapfunction(obsolete.obsstore, '_addmarkers')
> +@eh.wrapfunction(obsolete.obsstore, b'_addmarkers')
>  def _addmarkers(orig, obsstore, *args, **kwargs):
>      obsstore.rangeobshashcache.clear()
>      return orig(obsstore, *args, **kwargs)
> @@ -686,7 +686,7 @@
>
>
>  # obsstore is a filecache so we have do to some spacial dancing
> -@eh.wrapfunction(obsstorefilecache, 'func')
> +@eh.wrapfunction(obsstorefilecache, b'func')
>  def obsstorewithcache(orig, repo):
>      obsstore = orig(repo)
>      obsstore.rangeobshashcache = _obshashcache(repo.unfiltered())
> @@ -698,9 +698,9 @@
>      class obshashrepo(repo.__class__):
>          @localrepo.unfilteredmethod
>          def destroyed(self):
> -            if 'obsstore' in vars(self):
> +            if b'obsstore' in vars(self):
>                  self.obsstore.rangeobshashcache.clear()
> -            toplevel = not util.safehasattr(self, '_destroying')
> +            toplevel = not util.safehasattr(self, b'_destroying')
>              if toplevel:
>                  self._destroying = True
>              try:
> @@ -747,7 +747,7 @@
>      return _obshashrange_v0(peer._repo, ranges)
>
>
> -_indexformat = '>I'
> +_indexformat = b'>I'
>  _indexsize = _calcsize(_indexformat)
>  def _encrange(node_rangeid):
>      """encode a (node) range"""
> @@ -765,13 +765,13 @@
>  def peer_obshashrange_v0(self, ranges):
>      binranges = [_encrange(r) for r in ranges]
>      encranges = encodelist(binranges)
> -    d = self._call("evoext_obshashrange_v1", ranges=encranges)
> +    d = self._call(b"evoext_obshashrange_v1", ranges=encranges)
>      try:
>          return decodelist(d)
>      except ValueError:
> -        self._abort(error.ResponseError(_("unexpected response:"), d))
> +        self._abort(error.ResponseError(_(b"unexpected response:"), d))
>
> -@compat.wireprotocommand(eh, 'evoext_obshashrange_v1', 'ranges')
> +@compat.wireprotocommand(eh, b'evoext_obshashrange_v1', b'ranges')
>  def srv_obshashrange_v1(repo, proto, ranges):
>      ranges = decodelist(ranges)
>      ranges = [_decrange(r) for r in ranges]
> @@ -779,16 +779,16 @@
>      return encodelist(hashes)
>
>  def _useobshashrange(repo):
> -    base = repo.ui.configbool('experimental', 'obshashrange')
> +    base = repo.ui.configbool(b'experimental', b'obshashrange')
>      if base:
> -        maxrevs = repo.ui.configint('experimental',
> 'obshashrange.max-revs')
> +        maxrevs = repo.ui.configint(b'experimental',
> b'obshashrange.max-revs')
>          if maxrevs is not None and maxrevs < len(repo.unfiltered()):
>              base = False
>      return base
>
>  def _canobshashrange(local, remote):
>      return (_useobshashrange(local)
> -            and remote.capable('_evoext_obshashrange_v1'))
> +            and remote.capable(b'_evoext_obshashrange_v1'))
>
>  def _obshashrange_capabilities(orig, repo, proto):
>      """wrapper to advertise new capability"""
> @@ -798,7 +798,7 @@
>
>          # Compat hg 4.6+ (2f7290555c96)
>          bytesresponse = False
> -        if util.safehasattr(caps, 'data'):
> +        if util.safehasattr(caps, b'data'):
>              bytesresponse = True
>              caps = caps.data
>
> @@ -815,14 +815,14 @@
>  @eh.extsetup
>  def obshashrange_extsetup(ui):
>      ###
> -    extensions.wrapfunction(wireprotov1server, 'capabilities',
> +    extensions.wrapfunction(wireprotov1server, b'capabilities',
>                              _obshashrange_capabilities)
>      # wrap command content
> -    oldcap, args = wireprotov1server.commands['capabilities']
> +    oldcap, args = wireprotov1server.commands[b'capabilities']
>
>      def newcap(repo, proto):
>          return _obshashrange_capabilities(oldcap, repo, proto)
> -    wireprotov1server.commands['capabilities'] = (newcap, args)
> +    wireprotov1server.commands[b'capabilities'] = (newcap, args)
>
>  #############################
>  ### Tree Hash computation ###
> @@ -833,12 +833,12 @@
>  # node where the parent is used in the computation
>
>  def _canobshashtree(repo, remote):
> -    return remote.capable('_evoext_obshash_0')
> +    return remote.capable(b'_evoext_obshash_0')
>
>  @eh.command(
> -    'debugobsrelsethashtree',
> -    [('', 'v0', None, 'hash on marker format "0"'),
> -     ('', 'v1', None, 'hash on marker format "1" (default)')], _(''))
> +    b'debugobsrelsethashtree',
> +    [(b'', b'v0', None, b'hash on marker format "0"'),
> +     (b'', b'v1', None, b'hash on marker format "1" (default)')], _(b''))
>  def debugobsrelsethashtree(ui, repo, v0=False, v1=False):
>      """display Obsolete markers, Relevant Set, Hash Tree
>      changeset-node obsrelsethashtree-node
> @@ -846,14 +846,14 @@
>      It computed form the "orsht" of its parent and markers
>      relevant to the changeset itself."""
>      if v0 and v1:
> -        raise error.Abort('cannot only specify one format')
> +        raise error.Abort(b'cannot only specify one format')
>      elif v0:
>          treefunc = _obsrelsethashtreefm0
>      else:
>          treefunc = _obsrelsethashtreefm1
>
>      for chg, obs in treefunc(repo):
> -        ui.status('%s %s\n' % (node.hex(chg), node.hex(obs)))
> +        ui.status(b'%s %s\n' % (node.hex(chg), node.hex(obs)))
>
>  def _obsrelsethashtreefm0(repo):
>      return _obsrelsethashtree(repo, obsolete._fm0encodeonemarker)
> @@ -865,8 +865,8 @@
>      cache = []
>      unfi = repo.unfiltered()
>      markercache = {}
> -    compat.progress(repo.ui, _("preparing locally"), 0, total=len(unfi),
> -                    unit=_("changesets"))
> +    compat.progress(repo.ui, _(b"preparing locally"), 0, total=len(unfi),
> +                    unit=_(b"changesets"))
>      for i in unfi:
>          ctx = unfi[i]
>          entry = 0
> @@ -896,9 +896,9 @@
>              cache.append((ctx.node(), sha.digest()))
>          else:
>              cache.append((ctx.node(), node.nullid))
> -        compat.progress(repo.ui, _("preparing locally"), i,
> total=len(unfi),
> -                        unit=_("changesets"))
> -    compat.progress(repo.ui, _("preparing locally"), None)
> +        compat.progress(repo.ui, _(b"preparing locally"), i,
> total=len(unfi),
> +                        unit=_(b"changesets"))
> +    compat.progress(repo.ui, _(b"preparing locally"), None)
>      return cache
>
>  def _obshash(repo, nodes, version=0):
> @@ -922,25 +922,25 @@
>
>  @eh.addattr(wirepeer, 'evoext_obshash')
>  def peer_obshash(self, nodes):
> -    d = self._call("evoext_obshash", nodes=encodelist(nodes))
> +    d = self._call(b"evoext_obshash", nodes=encodelist(nodes))
>      try:
>          return decodelist(d)
>      except ValueError:
> -        self._abort(error.ResponseError(_("unexpected response:"), d))
> +        self._abort(error.ResponseError(_(b"unexpected response:"), d))
>
>  @eh.addattr(wirepeer, 'evoext_obshash1')
>  def peer_obshash1(self, nodes):
> -    d = self._call("evoext_obshash1", nodes=encodelist(nodes))
> +    d = self._call(b"evoext_obshash1", nodes=encodelist(nodes))
>      try:
>          return decodelist(d)
>      except ValueError:
> -        self._abort(error.ResponseError(_("unexpected response:"), d))
> +        self._abort(error.ResponseError(_(b"unexpected response:"), d))
>
> -@compat.wireprotocommand(eh, 'evoext_obshash', 'nodes')
> +@compat.wireprotocommand(eh, b'evoext_obshash', b'nodes')
>  def srv_obshash(repo, proto, nodes):
>      return encodelist(_obshash(repo, decodelist(nodes)))
>
> -@compat.wireprotocommand(eh, 'evoext_obshash1', 'nodes')
> +@compat.wireprotocommand(eh, b'evoext_obshash1', b'nodes')
>  def srv_obshash1(repo, proto, nodes):
>      return encodelist(_obshash(repo, decodelist(nodes),
>                        version=1))
> @@ -949,11 +949,11 @@
>      """wrapper to advertise new capability"""
>      caps = orig(repo, proto)
>      if (obsolete.isenabled(repo, obsolete.exchangeopt)
> -        and repo.ui.configbool('experimental', 'evolution.obsdiscovery')):
> +        and repo.ui.configbool(b'experimental',
> b'evolution.obsdiscovery')):
>
>          # Compat hg 4.6+ (2f7290555c96)
>          bytesresponse = False
> -        if util.safehasattr(caps, 'data'):
> +        if util.safehasattr(caps, b'data'):
>              bytesresponse = True
>              caps = caps.data
>
> @@ -970,14 +970,14 @@
>
>  @eh.extsetup
>  def obshash_extsetup(ui):
> -    extensions.wrapfunction(wireprotov1server, 'capabilities',
> +    extensions.wrapfunction(wireprotov1server, b'capabilities',
>                              _obshash_capabilities)
>      # wrap command content
> -    oldcap, args = wireprotov1server.commands['capabilities']
> +    oldcap, args = wireprotov1server.commands[b'capabilities']
>
>      def newcap(repo, proto):
>          return _obshash_capabilities(oldcap, repo, proto)
> -    wireprotov1server.commands['capabilities'] = (newcap, args)
> +    wireprotov1server.commands[b'capabilities'] = (newcap, args)
>
>  ##########################################
>  ###  trigger discovery during exchange ###
> @@ -989,7 +989,7 @@
>              # exchange of obsmarkers is enabled locally
>              and obsolete.isenabled(pushop.repo, obsolete.exchangeopt)
>              # remote server accept markers
> -            and 'obsolete' in pushop.remote.listkeys('namespaces'))
> +            and b'obsolete' in pushop.remote.listkeys(b'namespaces'))
>
>  def _pushobshashrange(pushop, commonrevs):
>      repo = pushop.repo.unfiltered()
> @@ -1003,7 +1003,7 @@
>      remote = pushop.remote
>      node = repo.changelog.node
>      common = findcommonobsmarkers(pushop.ui, repo, remote, commonrevs)
> -    revs = list(repo.revs('only(%ln, %ln)', pushop.futureheads, common))
> +    revs = list(repo.revs(b'only(%ln, %ln)', pushop.futureheads, common))
>      return [node(r) for r in revs]
>
>  # available discovery method, first valid is used
> @@ -1019,15 +1019,15 @@
>  """
>
>  def usediscovery(repo):
> -    return repo.ui.configbool('experimental', 'evolution.obsdiscovery')
> +    return repo.ui.configbool(b'experimental', b'evolution.obsdiscovery')
>
> -@eh.wrapfunction(exchange, '_pushdiscoveryobsmarkers')
> +@eh.wrapfunction(exchange, b'_pushdiscoveryobsmarkers')
>  def _pushdiscoveryobsmarkers(orig, pushop):
>      if _dopushmarkers(pushop):
>          repo = pushop.repo
>          remote = pushop.remote
> -        obsexcmsg(repo.ui, "computing relevant nodes\n")
> -        revs = list(repo.revs('::%ln', pushop.futureheads))
> +        obsexcmsg(repo.ui, b"computing relevant nodes\n")
> +        revs = list(repo.revs(b'::%ln', pushop.futureheads))
>          unfi = repo.unfiltered()
>
>          if not usediscovery(repo):
> @@ -1047,27 +1047,27 @@
>              # obs markers.
>              return orig(pushop)
>
> -        obsexcmsg(repo.ui, "looking for common markers in %i nodes\n"
> +        obsexcmsg(repo.ui, b"looking for common markers in %i nodes\n"
>                             % len(revs))
> -        commonrevs = list(unfi.revs('::%ln', pushop.outgoing.commonheads))
> +        commonrevs = list(unfi.revs(b'::%ln',
> pushop.outgoing.commonheads))
>          # find the nodes where the relevant obsmarkers mismatches
>          nodes = discovery(pushop, commonrevs)
>
>          if nodes:
> -            obsexcmsg(repo.ui, "computing markers relevant to %i nodes\n"
> +            obsexcmsg(repo.ui, b"computing markers relevant to %i nodes\n"
>                                 % len(nodes))
>              pushop.outobsmarkers = repo.obsstore.relevantmarkers(nodes)
>          else:
> -            obsexcmsg(repo.ui, "markers already in sync\n")
> +            obsexcmsg(repo.ui, b"markers already in sync\n")
>              pushop.outobsmarkers = []
>
>  @eh.extsetup
>  def _installobsmarkersdiscovery(ui):
> -    olddisco = exchange.pushdiscoverymapping['obsmarker']
> +    olddisco = exchange.pushdiscoverymapping[b'obsmarker']
>
>      def newdisco(pushop):
>          _pushdiscoveryobsmarkers(olddisco, pushop)
> -    exchange.pushdiscoverymapping['obsmarker'] = newdisco
> +    exchange.pushdiscoverymapping[b'obsmarker'] = newdisco
>
>  def buildpullobsmarkersboundaries(pullop, bundle2=True):
>      """small function returning the argument for pull markers call
> @@ -1077,29 +1077,29 @@
>      repo = pullop.repo
>      remote = pullop.remote
>      unfi = repo.unfiltered()
> -    revs = unfi.revs('::(%ln - null)', pullop.common)
> -    boundaries = {'heads': pullop.pulledsubset}
> +    revs = unfi.revs(b'::(%ln - null)', pullop.common)
> +    boundaries = {b'heads': pullop.pulledsubset}
>      if not revs: # nothing common
> -        boundaries['common'] = [node.nullid]
> +        boundaries[b'common'] = [node.nullid]
>          return boundaries
>
>      if not usediscovery(repo):
>          # discovery disabled by users.
>          repo.ui.status(obsdiscovery_skip_message)
> -        boundaries['common'] = [node.nullid]
> +        boundaries[b'common'] = [node.nullid]
>          return boundaries
>
>      if bundle2 and _canobshashrange(repo, remote):
> -        obsexcmsg(repo.ui, "looking for common markers in %i nodes\n"
> +        obsexcmsg(repo.ui, b"looking for common markers in %i nodes\n"
>                    % len(revs))
> -        boundaries['missing'] = findmissingrange(repo.ui, unfi,
> pullop.remote,
> -                                                 revs)
> -    elif remote.capable('_evoext_obshash_0'):
> -        obsexcmsg(repo.ui, "looking for common markers in %i nodes\n"
> +        boundaries[b'missing'] = findmissingrange(repo.ui, unfi,
> pullop.remote,
> +                                                  revs)
> +    elif remote.capable(b'_evoext_obshash_0'):
> +        obsexcmsg(repo.ui, b"looking for common markers in %i nodes\n"
>                             % len(revs))
> -        boundaries['common'] = findcommonobsmarkers(repo.ui, unfi,
> remote, revs)
> +        boundaries[b'common'] = findcommonobsmarkers(repo.ui, unfi,
> remote, revs)
>      else:
> -        boundaries['common'] = [node.nullid]
> +        boundaries[b'common'] = [node.nullid]
>      return boundaries
>
>  # merge later for outer layer wrapping
> diff --git a/hgext3rd/evolve/obsexchange.py
> b/hgext3rd/evolve/obsexchange.py
> --- a/hgext3rd/evolve/obsexchange.py
> +++ b/hgext3rd/evolve/obsexchange.py
> @@ -37,7 +37,7 @@
>  obsexcmsg = utility.obsexcmsg
>  obsexcprg = utility.obsexcprg
>
> -eh.configitem('experimental', 'verbose-obsolescence-exchange', False)
> +eh.configitem(b'experimental', b'verbose-obsolescence-exchange', False)
>
>  _bestformat = max(obsolete.formats.keys())
>
> @@ -58,49 +58,49 @@
>          # <= hg 4.5
>          from mercurial import wireproto
>          gboptsmap = wireproto.gboptsmap
> -    gboptsmap['evo_obscommon'] = 'nodes'
> -    gboptsmap['evo_missing_nodes'] = 'nodes'
> +    gboptsmap[b'evo_obscommon'] = b'nodes'
> +    gboptsmap[b'evo_missing_nodes'] = b'nodes'
>
> -@eh.wrapfunction(exchange, '_pullbundle2extraprepare')
> +@eh.wrapfunction(exchange, b'_pullbundle2extraprepare')
>  def _addobscommontob2pull(orig, pullop, kwargs):
>      ret = orig(pullop, kwargs)
>      ui = pullop.repo.ui
> -    if ('obsmarkers' in kwargs
> -        and pullop.remote.capable('_evoext_getbundle_obscommon')):
> +    if (b'obsmarkers' in kwargs
> +        and pullop.remote.capable(b'_evoext_getbundle_obscommon')):
>          boundaries = obsdiscovery.buildpullobsmarkersboundaries(pullop)
> -        if 'common' in boundaries:
> -            common = boundaries['common']
> +        if b'common' in boundaries:
> +            common = boundaries[b'common']
>              if common != pullop.common:
> -                obsexcmsg(ui, 'request obsmarkers for some common
> nodes\n')
> +                obsexcmsg(ui, b'request obsmarkers for some common
> nodes\n')
>              if common != [node.nullid]:
> -                kwargs['evo_obscommon'] = common
> -        elif 'missing' in boundaries:
> -            missing = boundaries['missing']
> +                kwargs[b'evo_obscommon'] = common
> +        elif b'missing' in boundaries:
> +            missing = boundaries[b'missing']
>              if missing:
> -                obsexcmsg(ui, 'request obsmarkers for %d common nodes\n'
> +                obsexcmsg(ui, b'request obsmarkers for %d common nodes\n'
>                            % len(missing))
> -            kwargs['evo_missing_nodes'] = missing
> +            kwargs[b'evo_missing_nodes'] = missing
>      return ret
>
>  def _getbundleobsmarkerpart(orig, bundler, repo, source, **kwargs):
> -    if not (set(['evo_obscommon', 'evo_missing_nodes']) & set(kwargs)):
> +    if not (set([b'evo_obscommon', b'evo_missing_nodes']) & set(kwargs)):
>          return orig(bundler, repo, source, **kwargs)
>
> -    if kwargs.get('obsmarkers', False):
> -        heads = kwargs.get('heads')
> -        if 'evo_obscommon' in kwargs:
> +    if kwargs.get(b'obsmarkers', False):
> +        heads = kwargs.get(b'heads')
> +        if b'evo_obscommon' in kwargs:
>              if heads is None:
>                  heads = repo.heads()
> -            obscommon = kwargs.get('evo_obscommon', ())
> +            obscommon = kwargs.get(b'evo_obscommon', ())
>              assert obscommon
> -            obsset = repo.unfiltered().set('::%ln - ::%ln', heads,
> obscommon)
> +            obsset = repo.unfiltered().set(b'::%ln - ::%ln', heads,
> obscommon)
>              subset = [c.node() for c in obsset]
>          else:
> -            common = kwargs.get('common')
> -            subset = [c.node() for c in repo.unfiltered().set('only(%ln,
> %ln)', heads, common)]
> -            subset += kwargs['evo_missing_nodes']
> +            common = kwargs.get(b'common')
> +            subset = [c.node() for c in repo.unfiltered().set(b'only(%ln,
> %ln)', heads, common)]
> +            subset += kwargs[b'evo_missing_nodes']
>          markers = repo.obsstore.relevantmarkers(subset)
> -        if util.safehasattr(bundle2, 'buildobsmarkerspart'):
> +        if util.safehasattr(bundle2, b'buildobsmarkerspart'):
>              bundle2.buildobsmarkerspart(bundler, markers)
>          else:
>              exchange.buildobsmarkerspart(bundler, markers)
> @@ -113,7 +113,7 @@
>
>          # Compat hg 4.6+ (2f7290555c96)
>          bytesresponse = False
> -        if util.safehasattr(caps, 'data'):
> +        if util.safehasattr(caps, b'data'):
>              bytesresponse = True
>              caps = caps.data
>
> @@ -138,36 +138,36 @@
>          from mercurial import wireproto
>          gboptsmap = wireproto.gboptsmap
>          wireprotov1server = wireproto
> -    gboptsmap['evo_obscommon'] = 'nodes'
> +    gboptsmap[b'evo_obscommon'] = b'nodes'
>
>      # wrap module content
> -    origfunc = exchange.getbundle2partsmapping['obsmarkers']
> +    origfunc = exchange.getbundle2partsmapping[b'obsmarkers']
>
>      def newfunc(*args, **kwargs):
>          return _getbundleobsmarkerpart(origfunc, *args, **kwargs)
> -    exchange.getbundle2partsmapping['obsmarkers'] = newfunc
> +    exchange.getbundle2partsmapping[b'obsmarkers'] = newfunc
>
> -    extensions.wrapfunction(wireprotov1server, 'capabilities',
> +    extensions.wrapfunction(wireprotov1server, b'capabilities',
>                              _obscommon_capabilities)
>      # wrap command content
> -    oldcap, args = wireprotov1server.commands['capabilities']
> +    oldcap, args = wireprotov1server.commands[b'capabilities']
>
>      def newcap(repo, proto):
>          return _obscommon_capabilities(oldcap, repo, proto)
> -    wireprotov1server.commands['capabilities'] = (newcap, args)
> +    wireprotov1server.commands[b'capabilities'] = (newcap, args)
>
>  def _pushobsmarkers(repo, data):
>      tr = lock = None
>      try:
>          lock = repo.lock()
> -        tr = repo.transaction('pushkey: obsolete markers')
> +        tr = repo.transaction(b'pushkey: obsolete markers')
>          new = repo.obsstore.mergemarkers(tr, data)
>          if new is not None:
> -            obsexcmsg(repo.ui, "%i obsolescence markers added\n" % new,
> True)
> +            obsexcmsg(repo.ui, b"%i obsolescence markers added\n" % new,
> True)
>          tr.close()
>      finally:
>          lockmod.release(tr, lock)
> -    repo.hook('evolve_pushobsmarkers')
> +    repo.hook(b'evolve_pushobsmarkers')
>
>  def srv_pushobsmarkers(repo, proto):
>      """wireprotocol command"""
> @@ -187,18 +187,18 @@
>  def _getobsmarkersstream(repo, heads=None, common=None):
>      """Get a binary stream for all markers relevant to `::<heads> -
> ::<common>`
>      """
> -    revset = ''
> +    revset = b''
>      args = []
>      repo = repo.unfiltered()
>      if heads is None:
> -        revset = 'all()'
> +        revset = b'all()'
>      elif heads:
> -        revset += "(::%ln)"
> +        revset += b"(::%ln)"
>          args.append(heads)
>      else:
> -        assert False, 'pulling no heads?'
> +        assert False, b'pulling no heads?'
>      if common:
> -        revset += ' - (::%ln)'
> +        revset += b' - (::%ln)'
>          args.append(common)
>      nodes = [c.node() for c in repo.set(revset, *args)]
>      markers = repo.obsstore.relevantmarkers(nodes)
> @@ -220,20 +220,20 @@
>      except (ImportError, AttributeError):
>          from mercurial import wireproto as wireprototypes
>          wireprotov1server = wireprototypes
> -    opts = wireprotov1server.options('', ['heads', 'common'], others)
> -    for k, v in opts.iteritems():
> -        if k in ('heads', 'common'):
> +    opts = wireprotov1server.options(b'', [b'heads', b'common'], others)
> +    for k, v in opts.items():
> +        if k in (b'heads', b'common'):
>              opts[k] = wireprototypes.decodelist(v)
>      obsdata = _getobsmarkersstream(repo, **opts)
>      finaldata = StringIO()
>      obsdata = obsdata.getvalue()
> -    finaldata.write('%20i' % len(obsdata))
> +    finaldata.write(b'%20i' % len(obsdata))
>      finaldata.write(obsdata)
>      finaldata.seek(0)
>      return wireprototypes.streamres(reader=finaldata, v1compressible=True)
>
> -abortmsg = "won't exchange obsmarkers through pushkey"
> -hint = "upgrade your client or server to use the bundle2 protocol"
> +abortmsg = b"won't exchange obsmarkers through pushkey"
> +hint = b"upgrade your client or server to use the bundle2 protocol"
>
>  class HTTPCompatibleAbort(hgwebcommon.ErrorResponse, error.Abort):
>      def __init__(self, message, code, hint=None):
> @@ -256,4 +256,4 @@
>
>  @eh.uisetup
>  def setuppushkeyforbidding(ui):
> -    pushkey._namespaces['obsolete'] = (forbidpushkey, forbidlistkey)
> +    pushkey._namespaces[b'obsolete'] = (forbidpushkey, forbidlistkey)
> diff --git a/hgext3rd/evolve/obshistory.py b/hgext3rd/evolve/obshistory.py
> --- a/hgext3rd/evolve/obshistory.py
> +++ b/hgext3rd/evolve/obshistory.py
> @@ -30,26 +30,26 @@
>  eh = exthelper.exthelper()
>
>  # Config
> -efd = {'default': True} # pass a default value unless the config is
> registered
> +efd = {b'default': True} # pass a default value unless the config is
> registered
>
>  @eh.extsetup
>  def enableeffectflags(ui):
>      item = (getattr(ui, '_knownconfig', {})
> -            .get('experimental', {})
> -            .get('evolution.effect-flags'))
> +            .get(b'experimental', {})
> +            .get(b'evolution.effect-flags'))
>      if item is not None:
>          item.default = True
>          efd.clear()
>
>  @eh.command(
> -    'obslog|olog',
> -    [('G', 'graph', True, _("show the revision DAG")),
> -     ('r', 'rev', [], _('show the specified revision or revset'),
> _('REV')),
> -     ('a', 'all', False, _('show all related changesets, not only
> precursors')),
> -     ('p', 'patch', False, _('show the patch between two obs versions')),
> -     ('f', 'filternonlocal', False, _('filter out non local commits')),
> -    ] + commands.formatteropts,
> -    _('hg olog [OPTION]... [REV]'))
> +    b'obslog|olog',
> +    [(b'G', b'graph', True, _(b"show the revision DAG")),
> +     (b'r', b'rev', [], _(b'show the specified revision or revset'),
> _(b'REV')),
> +     (b'a', b'all', False, _(b'show all related changesets, not only
> precursors')),
> +     (b'p', b'patch', False, _(b'show the patch between two obs
> versions')),
> +     (b'f', b'filternonlocal', False, _(b'filter out non local commits')),
> +     ] + commands.formatteropts,
> +    _(b'hg olog [OPTION]... [REV]'))
>  def cmdobshistory(ui, repo, *revs, **opts):
>      """show the obsolescence history of the specified revisions
>
> @@ -78,13 +78,13 @@
>
>      Returns 0 on success.
>      """
> -    ui.pager('obslog')
> -    revs = list(revs) + opts['rev']
> +    ui.pager(b'obslog')
> +    revs = list(revs) + opts[b'rev']
>      if not revs:
> -        revs = ['.']
> +        revs = [b'.']
>      revs = scmutil.revrange(repo, revs)
>
> -    if opts['graph']:
> +    if opts[b'graph']:
>          return _debugobshistorygraph(ui, repo, revs, opts)
>
>      revs.reverse()
> @@ -130,7 +130,7 @@
>
>      values = []
>      for sset in fullsuccessorsets:
> -        values.append({'successors': sset, 'markers': sset.markers})
> +        values.append({b'successors': sset, b'markers': sset.markers})
>
>      return values
>
> @@ -142,21 +142,21 @@
>
>      def __init__(self, ui, repo, *args, **kwargs):
>
> -        if kwargs.pop('obspatch', False):
> +        if kwargs.pop(b'obspatch', False):
>              if compat.changesetdiffer is None:
> -                kwargs['matchfn'] = scmutil.matchall(repo)
> +                kwargs[b'matchfn'] = scmutil.matchall(repo)
>              else:
> -                kwargs['differ'] = scmutil.matchall(repo)
> +                kwargs[b'differ'] = scmutil.matchall(repo)
>
>          super(obsmarker_printer, self).__init__(ui, repo, *args, **kwargs)
> -        diffopts = kwargs.get('diffopts', {})
> +        diffopts = kwargs.get(b'diffopts', {})
>
>          # Compat 4.6
> -        if not util.safehasattr(self, "_includediff"):
> -            self._includediff = diffopts and diffopts.get('patch')
> +        if not util.safehasattr(self, b"_includediff"):
> +            self._includediff = diffopts and diffopts.get(b'patch')
>
> -        self.template = diffopts and diffopts.get('template')
> -        self.filter = diffopts and diffopts.get('filternonlocal')
> +        self.template = diffopts and diffopts.get(b'template')
> +        self.filter = diffopts and diffopts.get(b'filternonlocal')
>
>      def show(self, ctx, copies=None, matchfn=None, **props):
>          if self.buffered:
> @@ -164,12 +164,12 @@
>
>              changenode = ctx.node()
>
> -            _props = {"template": self.template}
> -            fm = self.ui.formatter('debugobshistory', _props)
> +            _props = {b"template": self.template}
> +            fm = self.ui.formatter(b'debugobshistory', _props)
>
>              _debugobshistorydisplaynode(fm, self.repo, changenode)
>
> -            markerfm = fm.nested("markers")
> +            markerfm = fm.nested(b"markers")
>
>              # Succs markers
>              if self.filter is False:
> @@ -185,21 +185,21 @@
>                  r = _successorsandmarkers(self.repo, ctx)
>
>                  for succset in sorted(r):
> -                    markers = succset["markers"]
> +                    markers = succset[b"markers"]
>                      if not markers:
>                          continue
> -                    successors = succset["successors"]
> +                    successors = succset[b"successors"]
>                      _debugobshistorydisplaysuccsandmarkers(markerfm,
> successors, markers, ctx.node(), self.repo, self._includediff)
>
>              markerfm.end()
>
> -            markerfm.plain('\n')
> +            markerfm.plain(b'\n')
>              fm.end()
>
>              self.hunk[ctx.node()] = self.ui.popbuffer()
>          else:
>              ### graph output is buffered only
> -            msg = 'cannot be used outside of the graphlog (yet)'
> +            msg = b'cannot be used outside of the graphlog (yet)'
>              raise error.ProgrammingError(msg)
>
>      def flush(self, ctx):
> @@ -210,43 +210,43 @@
>
>  def patchavailable(node, repo, successors):
>      if node not in repo:
> -        return False, "context is not local"
> +        return False, b"context is not local"
>
>      if len(successors) == 0:
> -        return False, "no successors"
> +        return False, b"no successors"
>      elif len(successors) > 1:
> -        return False, "too many successors (%d)" % len(successors)
> +        return False, b"too many successors (%d)" % len(successors)
>
>      succ = successors[0]
>
>      if succ not in repo:
> -        return False, "successor is unknown locally"
> +        return False, b"successor is unknown locally"
>
>      # Check that both node and succ have the same parents
>      nodep1, nodep2 = repo[node].p1(), repo[node].p2()
>      succp1, succp2 = repo[succ].p1(), repo[succ].p2()
>
>      if nodep1 != succp1 or nodep2 != succp2:
> -        return False, "changesets rebased"
> +        return False, b"changesets rebased"
>
>      return True, succ
>
>  def getmarkerdescriptionpatch(repo, basedesc, succdesc):
>      # description are stored without final new line,
>      # add one to avoid ugly diff
> -    basedesc += '\n'
> -    succdesc += '\n'
> +    basedesc += b'\n'
> +    succdesc += b'\n'
>
>      # fake file name
> -    basename = "changeset-description"
> -    succname = "changeset-description"
> +    basename = b"changeset-description"
> +    succname = b"changeset-description"
>
>      d = compat.strdiff(basedesc, succdesc, basename, succname)
>      uheaders, hunks = d
>
>      # Copied from patch.diff
> -    text = ''.join(sum((list(hlines) for hrange, hlines in hunks), []))
> -    patch = "\n".join(uheaders + [text])
> +    text = b''.join(sum((list(hlines) for hrange, hlines in hunks), []))
> +    patch = b"\n".join(uheaders + [text])
>
>      return patch
>
> @@ -332,7 +332,7 @@
>              # Then choose a random node from the cycle
>              breaknode = sorted(cycle)[0]
>              # And display it by force
> -            repo.ui.debug('obs-cycle detected, forcing display of %s\n'
> +            repo.ui.debug(b'obs-cycle detected, forcing display of %s\n'
>                            % nodemod.short(breaknode))
>              validcandidates = [breaknode]
>
> @@ -425,13 +425,13 @@
>
>      displayer = obsmarker_printer(ui, repo.unfiltered(), obspatch=True,
> diffopts=opts, buffered=True)
>      edges = graphmod.asciiedges
> -    walker = _obshistorywalker(repo.unfiltered(), revs, opts.get('all',
> False), opts.get('filternonlocal', False))
> +    walker = _obshistorywalker(repo.unfiltered(), revs, opts.get(b'all',
> False), opts.get(b'filternonlocal', False))
>      compat.displaygraph(ui, repo, walker, displayer, edges)
>
>  def _debugobshistoryrevs(ui, repo, revs, opts):
>      """ Display the obsolescence history for revset
>      """
> -    fm = ui.formatter('debugobshistory', opts)
> +    fm = ui.formatter(b'debugobshistory', opts)
>      precursors = repo.obsstore.predecessors
>      successors = repo.obsstore.successors
>      nodec = repo.changelog.node
> @@ -447,9 +447,9 @@
>
>          succs = successors.get(ctxnode, ())
>
> -        markerfm = fm.nested("markers")
> +        markerfm = fm.nested(b"markers")
>          for successor in sorted(succs):
> -            includediff = opts and opts.get("patch")
> +            includediff = opts and opts.get(b"patch")
>              _debugobshistorydisplaymarker(markerfm, successor, ctxnode,
> unfi, includediff)
>          markerfm.end()
>
> @@ -473,24 +473,24 @@
>          shortdescription = shortdescription.splitlines()[0]
>
>      fm.startitem()
> -    fm.write('node', '%s', str(ctx),
> -             label="evolve.node")
> -    fm.plain(' ')
> +    fm.write(b'node', b'%s', str(ctx),
> +             label=b"evolve.node")
> +    fm.plain(b' ')
>
> -    fm.write('rev', '(%d)', ctx.rev(),
> -             label="evolve.rev")
> -    fm.plain(' ')
> +    fm.write(b'rev', b'(%d)', ctx.rev(),
> +             label=b"evolve.rev")
> +    fm.plain(b' ')
>
> -    fm.write('shortdescription', '%s', shortdescription,
> -             label="evolve.short_description")
> -    fm.plain('\n')
> +    fm.write(b'shortdescription', b'%s', shortdescription,
> +             label=b"evolve.short_description")
> +    fm.plain(b'\n')
>
>  def _debugobshistorydisplaymissingctx(fm, nodewithoutctx):
>      hexnode = nodemod.short(nodewithoutctx)
>      fm.startitem()
> -    fm.write('node', '%s', hexnode,
> -             label="evolve.node evolve.missing_change_ctx")
> -    fm.plain('\n')
> +    fm.write(b'node', b'%s', hexnode,
> +             label=b"evolve.node evolve.missing_change_ctx")
> +    fm.plain(b'\n')
>
>  def _debugobshistorydisplaymarker(fm, marker, node, repo,
> includediff=False):
>      succnodes = marker[1]
> @@ -498,18 +498,18 @@
>      metadata = dict(marker[3])
>
>      fm.startitem()
> -    fm.plain('  ')
> +    fm.plain(b'  ')
>
>      # Detect pruned revisions
>      if len(succnodes) == 0:
> -        verb = 'pruned'
> +        verb = b'pruned'
>      else:
> -        verb = 'rewritten'
> +        verb = b'rewritten'
>
> -    fm.write('verb', '%s', verb,
> -             label="evolve.verb")
> +    fm.write(b'verb', b'%s', verb,
> +             label=b"evolve.verb")
>
> -    effectflag = metadata.get('ef1')
> +    effectflag = metadata.get(b'ef1')
>      if effectflag is not None:
>          try:
>              effectflag = int(effectflag)
> @@ -520,50 +520,50 @@
>
>          # XXX should be a dict
>          if effectflag & DESCCHANGED:
> -            effect.append('description')
> +            effect.append(b'description')
>          if effectflag & METACHANGED:
> -            effect.append('meta')
> +            effect.append(b'meta')
>          if effectflag & USERCHANGED:
> -            effect.append('user')
> +            effect.append(b'user')
>          if effectflag & DATECHANGED:
> -            effect.append('date')
> +            effect.append(b'date')
>          if effectflag & BRANCHCHANGED:
> -            effect.append('branch')
> +            effect.append(b'branch')
>          if effectflag & PARENTCHANGED:
> -            effect.append('parent')
> +            effect.append(b'parent')
>          if effectflag & DIFFCHANGED:
> -            effect.append('content')
> +            effect.append(b'content')
>
>          if effect:
> -            fmteffect = fm.formatlist(effect, 'effect', sep=', ')
> -            fm.write('effect', '(%s)', fmteffect)
> +            fmteffect = fm.formatlist(effect, b'effect', sep=b', ')
> +            fm.write(b'effect', b'(%s)', fmteffect)
>
>      if len(succnodes) > 0:
> -        fm.plain(' as ')
> +        fm.plain(b' as ')
>
>          shortsnodes = (nodemod.short(succnode) for succnode in
> sorted(succnodes))
> -        nodes = fm.formatlist(shortsnodes, 'succnodes', sep=', ')
> -        fm.write('succnodes', '%s', nodes,
> -                 label="evolve.node")
> +        nodes = fm.formatlist(shortsnodes, b'succnodes', sep=b', ')
> +        fm.write(b'succnodes', b'%s', nodes,
> +                 label=b"evolve.node")
>
> -    operation = metadata.get('operation')
> +    operation = metadata.get(b'operation')
>      if operation:
> -        fm.plain(' using ')
> -        fm.write('operation', '%s', operation, label="evolve.operation")
> +        fm.plain(b' using ')
> +        fm.write(b'operation', b'%s', operation,
> label=b"evolve.operation")
>
> -    fm.plain(' by ')
> +    fm.plain(b' by ')
>
> -    fm.write('user', '%s', metadata['user'],
> -             label="evolve.user")
> -    fm.plain(' ')
> +    fm.write(b'user', b'%s', metadata[b'user'],
> +             label=b"evolve.user")
> +    fm.plain(b' ')
>
> -    fm.write('date', '(%s)', fm.formatdate(date),
> -             label="evolve.date")
> +    fm.write(b'date', b'(%s)', fm.formatdate(date),
> +             label=b"evolve.date")
>
>      # initial support for showing note
> -    if metadata.get('note'):
> -        fm.plain('\n    note: ')
> -        fm.write('note', "%s", metadata['note'], label="evolve.note")
> +    if metadata.get(b'note'):
> +        fm.plain(b'\n    note: ')
> +        fm.write(b'note', b"%s", metadata[b'note'], label=b"evolve.note")
>
>      # Patch display
>      if includediff is True:
> @@ -581,20 +581,20 @@
>
>              if descriptionpatch:
>                  # add the diffheader
> -                diffheader = "diff -r %s -r %s changeset-description\n" %
> \
> +                diffheader = b"diff -r %s -r %s changeset-description\n"
> %\
>                               (basectx, succctx)
>                  descriptionpatch = diffheader + descriptionpatch
>
>                  def tolist(text):
>                      return [text]
>
> -                fm.plain("\n")
> +                fm.plain(b"\n")
>
>                  for chunk, label in patch.difflabel(tolist,
> descriptionpatch):
> -                    chunk = chunk.strip('\t')
> -                    if chunk and chunk != '\n':
> -                        fm.plain('    ')
> -                    fm.write('desc-diff', '%s', chunk, label=label)
> +                    chunk = chunk.strip(b'\t')
> +                    if chunk and chunk != b'\n':
> +                        fm.plain(b'    ')
> +                    fm.write(b'desc-diff', b'%s', chunk, label=label)
>
>              # Content patch
>              diffopts = patch.diffallopts(repo.ui, {})
> @@ -603,18 +603,18 @@
>              for chunk, label in patch.diffui(repo, node, succ, matchfn,
>                                               opts=diffopts):
>                  if firstline:
> -                    fm.plain('\n')
> +                    fm.plain(b'\n')
>                      firstline = False
> -                if chunk and chunk != '\n':
> -                    fm.plain('    ')
> -                fm.write('patch', '%s', chunk, label=label)
> +                if chunk and chunk != b'\n':
> +                    fm.plain(b'    ')
> +                fm.write(b'patch', b'%s', chunk, label=label)
>          else:
> -            nopatch = "    (No patch available, %s)" % _patchavailable[1]
> -            fm.plain("\n")
> +            nopatch = b"    (No patch available, %s)" % _patchavailable[1]
> +            fm.plain(b"\n")
>              # TODO: should be in json too
>              fm.plain(nopatch)
>
> -    fm.plain("\n")
> +    fm.plain(b"\n")
>
>  def _debugobshistorydisplaysuccsandmarkers(fm, succnodes, markers, node,
> repo, includediff=False):
>      """
> @@ -622,17 +622,17 @@
>      to accept multiple markers as input.
>      """
>      fm.startitem()
> -    fm.plain('  ')
> +    fm.plain(b'  ')
>
>      # Detect pruned revisions
> -    verb = _successorsetverb(succnodes, markers)["verb"]
> +    verb = _successorsetverb(succnodes, markers)[b"verb"]
>
> -    fm.write('verb', '%s', verb,
> -             label="evolve.verb")
> +    fm.write(b'verb', b'%s', verb,
> +             label=b"evolve.verb")
>
>      # Effect flag
>      metadata = [dict(marker[3]) for marker in markers]
> -    ef1 = [data.get('ef1') for data in metadata]
> +    ef1 = [data.get(b'ef1') for data in metadata]
>
>      effectflag = 0
>      for ef in ef1:
> @@ -644,45 +644,45 @@
>
>          # XXX should be a dict
>          if effectflag & DESCCHANGED:
> -            effect.append('description')
> +            effect.append(b'description')
>          if effectflag & METACHANGED:
> -            effect.append('meta')
> +            effect.append(b'meta')
>          if effectflag & USERCHANGED:
> -            effect.append('user')
> +            effect.append(b'user')
>          if effectflag & DATECHANGED:
> -            effect.append('date')
> +            effect.append(b'date')
>          if effectflag & BRANCHCHANGED:
> -            effect.append('branch')
> +            effect.append(b'branch')
>          if effectflag & PARENTCHANGED:
> -            effect.append('parent')
> +            effect.append(b'parent')
>          if effectflag & DIFFCHANGED:
> -            effect.append('content')
> +            effect.append(b'content')
>
>          if effect:
> -            fmteffect = fm.formatlist(effect, 'effect', sep=', ')
> -            fm.write('effect', '(%s)', fmteffect)
> +            fmteffect = fm.formatlist(effect, b'effect', sep=b', ')
> +            fm.write(b'effect', b'(%s)', fmteffect)
>
>      if len(succnodes) > 0:
> -        fm.plain(' as ')
> +        fm.plain(b' as ')
>
>          shortsnodes = (nodemod.short(succnode) for succnode in
> sorted(succnodes))
> -        nodes = fm.formatlist(shortsnodes, 'succnodes', sep=', ')
> -        fm.write('succnodes', '%s', nodes,
> -                 label="evolve.node")
> +        nodes = fm.formatlist(shortsnodes, b'succnodes', sep=b', ')
> +        fm.write(b'succnodes', b'%s', nodes,
> +                 label=b"evolve.node")
>
>      # Operations
>      operations = compat.markersoperations(markers)
>      if operations:
> -        fm.plain(' using ')
> -        fm.write('operation', '%s', ", ".join(operations),
> label="evolve.operation")
> +        fm.plain(b' using ')
> +        fm.write(b'operation', b'%s', b", ".join(operations),
> label=b"evolve.operation")
>
> -    fm.plain(' by ')
> +    fm.plain(b' by ')
>
>      # Users
>      users = compat.markersusers(markers)
> -    fm.write('user', '%s', ", ".join(users),
> -             label="evolve.user")
> -    fm.plain(' ')
> +    fm.write(b'user', b'%s', b", ".join(users),
> +             label=b"evolve.user")
> +    fm.plain(b' ')
>
>      # Dates
>      dates = compat.markersdates(markers)
> @@ -691,10 +691,10 @@
>          max_date = max(dates)
>
>          if min_date == max_date:
> -            fm.write("date", "(at %s)", fm.formatdate(min_date),
> label="evolve.date")
> +            fm.write(b"date", b"(at %s)", fm.formatdate(min_date),
> label=b"evolve.date")
>          else:
> -            fm.write("date", "(between %s and %s)",
> fm.formatdate(min_date),
> -                     fm.formatdate(max_date), label="evolve.date")
> +            fm.write(b"date", b"(between %s and %s)",
> fm.formatdate(min_date),
> +                     fm.formatdate(max_date), label=b"evolve.date")
>
>      # initial support for showing note
>      # if metadata.get('note'):
> @@ -717,20 +717,20 @@
>
>              if descriptionpatch:
>                  # add the diffheader
> -                diffheader = "diff -r %s -r %s changeset-description\n" %
> \
> +                diffheader = b"diff -r %s -r %s changeset-description\n"
> %\
>                               (basectx, succctx)
>                  descriptionpatch = diffheader + descriptionpatch
>
>                  def tolist(text):
>                      return [text]
>
> -                fm.plain("\n")
> +                fm.plain(b"\n")
>
>                  for chunk, label in patch.difflabel(tolist,
> descriptionpatch):
> -                    chunk = chunk.strip('\t')
> -                    if chunk and chunk != '\n':
> -                        fm.plain('    ')
> -                    fm.write('desc-diff', '%s', chunk, label=label)
> +                    chunk = chunk.strip(b'\t')
> +                    if chunk and chunk != b'\n':
> +                        fm.plain(b'    ')
> +                    fm.write(b'desc-diff', b'%s', chunk, label=label)
>
>              # Content patch
>              diffopts = patch.diffallopts(repo.ui, {})
> @@ -739,18 +739,18 @@
>              for chunk, label in patch.diffui(repo, node, succ, matchfn,
>                                               opts=diffopts):
>                  if firstline:
> -                    fm.plain('\n')
> +                    fm.plain(b'\n')
>                      firstline = False
> -                if chunk and chunk != '\n':
> -                    fm.plain('    ')
> -                fm.write('patch', '%s', chunk, label=label)
> +                if chunk and chunk != b'\n':
> +                    fm.plain(b'    ')
> +                fm.write(b'patch', b'%s', chunk, label=label)
>          else:
> -            nopatch = "    (No patch available, %s)" % _patchavailable[1]
> -            fm.plain("\n")
> +            nopatch = b"    (No patch available, %s)" % _patchavailable[1]
> +            fm.plain(b"\n")
>              # TODO: should be in json too
>              fm.plain(nopatch)
>
> -    fm.plain("\n")
> +    fm.plain(b"\n")
>
>  # logic around storing and using effect flags
>  DESCCHANGED = 1 << 0 # action changed the description
> @@ -762,11 +762,11 @@
>  BRANCHCHANGED = 1 << 6 # the branch changed
>
>  METABLACKLIST = [
> -    re.compile('^__touch-noise__$'),
> -    re.compile('^branch$'),
> -    re.compile('^.*-source$'),
> -    re.compile('^.*_source$'),
> -    re.compile('^source$'),
> +    re.compile(b'^__touch-noise__$'),
> +    re.compile(b'^branch$'),
> +    re.compile(b'^.*-source$'),
> +    re.compile(b'^.*_source$'),
> +    re.compile(b'^source$'),
>  ]
>
>  def ismetablacklisted(metaitem):
> @@ -810,17 +810,17 @@
>
>      if len(successorssets) == 0:
>          # The commit has been pruned
> -        return 'pruned'
> +        return b'pruned'
>      elif len(successorssets) > 1:
> -        return 'diverged'
> +        return b'diverged'
>      else:
>          # No divergence, only one set of successors
>          successors = successorssets[0]
>
>          if len(successors) == 1:
> -            return 'superseed'
> +            return b'superseed'
>          else:
> -            return 'superseed_split'
> +            return b'superseed_split'
>
>  def _getobsfateandsuccs(repo, revnode, successorssets=None):
>      """ Return a tuple containing:
> @@ -853,8 +853,8 @@
>      dates = [m[4] for m in markers]
>
>      return {
> -        'min_date': min(dates),
> -        'max_date': max(dates)
> +        b'min_date': min(dates),
> +        b'max_date': max(dates)
>      }
>
>  def _successorsetusers(successorset, markers):
> @@ -865,18 +865,18 @@
>
>      # Check that user is present in meta
>      markersmeta = [dict(m[3]) for m in markers]
> -    users = set(meta.get('user') for meta in markersmeta if
> meta.get('user'))
> +    users = set(meta.get(b'user') for meta in markersmeta if
> meta.get(b'user'))
>
> -    return {'users': sorted(users)}
> +    return {b'users': sorted(users)}
>
>  VERBMAPPING = {
> -    DESCCHANGED: "reworded",
> -    METACHANGED: "meta-changed",
> -    USERCHANGED: "reauthored",
> -    DATECHANGED: "date-changed",
> -    BRANCHCHANGED: "branch-changed",
> -    PARENTCHANGED: "rebased",
> -    DIFFCHANGED: "amended"
> +    DESCCHANGED: b"reworded",
> +    METACHANGED: b"meta-changed",
> +    USERCHANGED: b"reauthored",
> +    DATECHANGED: b"date-changed",
> +    BRANCHCHANGED: b"branch-changed",
> +    PARENTCHANGED: b"rebased",
> +    DIFFCHANGED: b"amended"
>  }
>
>  def _successorsetverb(successorset, markers):
> @@ -884,12 +884,12 @@
>      """
>      verb = None
>      if not successorset:
> -        verb = 'pruned'
> +        verb = b'pruned'
>      elif len(successorset) == 1:
>          # Check for effect flag
>
>          metadata = [dict(marker[3]) for marker in markers]
> -        ef1 = [data.get('ef1') for data in metadata]
> +        ef1 = [data.get(b'ef1') for data in metadata]
>
>          if all(ef1):
>              combined = 0
> @@ -901,28 +901,28 @@
>                  verb = VERBMAPPING[combined]
>
>          if verb is None:
> -            verb = 'rewritten'
> +            verb = b'rewritten'
>      else:
> -        verb = 'split'
> -    return {'verb': verb}
> +        verb = b'split'
> +    return {b'verb': verb}
>
>  # Use a more advanced version of obsfateverb that uses effect-flag
> -if util.safehasattr(obsutil, 'obsfateverb'):
> +if util.safehasattr(obsutil, b'obsfateverb'):
>
> -    @eh.wrapfunction(obsutil, 'obsfateverb')
> +    @eh.wrapfunction(obsutil, b'obsfateverb')
>      def obsfateverb(orig, *args, **kwargs):
> -        return _successorsetverb(*args, **kwargs)['verb']
> +        return _successorsetverb(*args, **kwargs)[b'verb']
>
>  # Hijack callers of successorsetverb
> -elif util.safehasattr(obsutil, 'obsfateprinter'):
> +elif util.safehasattr(obsutil, b'obsfateprinter'):
>
> -    @eh.wrapfunction(obsutil, 'obsfateprinter')
> +    @eh.wrapfunction(obsutil, b'obsfateprinter')
>      def obsfateprinter(orig, successors, markers, ui):
>
>          def closure(successors):
> -            return _successorsetverb(successors, markers)['verb']
> +            return _successorsetverb(successors, markers)[b'verb']
>
> -        if not util.safehasattr(obsutil, 'successorsetverb'):
> +        if not util.safehasattr(obsutil, b'successorsetverb'):
>              return orig(successors, markers, ui)
>
>          # Save the old value
> @@ -996,8 +996,8 @@
>
>      # Format basic data
>      data = {
> -        "successors": sorted(successorset),
> -        "markers": sorted(markers)
> +        b"successors": sorted(successorset),
> +        b"markers": sorted(markers)
>      }
>
>      # Call an extensible list of functions to override or add new data
> diff --git a/hgext3rd/evolve/rewind.py b/hgext3rd/evolve/rewind.py
> --- a/hgext3rd/evolve/rewind.py
> +++ b/hgext3rd/evolve/rewind.py
> @@ -26,14 +26,14 @@
>  identicalflag = 4
>
>  @eh.command(
> -    'rewind|undo',
> -    [('', 'to', [], _("rewind to these revisions"), _('REV')),
> -     ('', 'as-divergence', None, _("preserve current latest successors")),
> -     ('', 'exact', None, _("only rewind explicitly selected revisions")),
> -     ('', 'from', [],
> -      _("rewind these revisions to their predecessors"), _('REV')),
> -    ],
> -    _(''),
> +    b'rewind|undo',
> +    [(b'', b'to', [], _(b"rewind to these revisions"), _(b'REV')),
> +     (b'', b'as-divergence', None, _(b"preserve current latest
> successors")),
> +     (b'', b'exact', None, _(b"only rewind explicitly selected
> revisions")),
> +     (b'', b'from', [],
> +      _(b"rewind these revisions to their predecessors"), _(b'REV')),
> +     ],
> +    _(b''),
>      helpbasic=True)
>  def rewind(ui, repo, **opts):
>      """rewind a stack of changesets to a previous state
> @@ -85,20 +85,20 @@
>
>          rewinded = _select_rewinded(repo, opts)
>
> -        if not opts['as_divergence']:
> +        if not opts[b'as_divergence']:
>              for rev in rewinded:
>                  ctx = unfi[rev]
>                  ssets = obsutil.successorssets(repo, ctx.node(), sscache)
>                  if 1 < len(ssets):
> -                    msg = _('rewind confused by divergence on %s') % ctx
> -                    hint = _('solve divergence first or use
> "--as-divergence"')
> +                    msg = _(b'rewind confused by divergence on %s') % ctx
> +                    hint = _(b'solve divergence first or use
> "--as-divergence"')
>                      raise error.Abort(msg, hint=hint)
>                  if ssets and ssets[0]:
>                      for succ in ssets[0]:
>                          successorsmap[succ].add(ctx.node())
>
>          # Check that we can rewind these changesets
> -        with repo.transaction('rewind'):
> +        with repo.transaction(b'rewind'):
>              for rev in sorted(rewinded):
>                  ctx = unfi[rev]
>                  rewindmap[ctx.node()] = _revive_revision(unfi, rev,
> rewindmap)
> @@ -113,36 +113,36 @@
>                  relationships.append(rel)
>                  if wctxp.node() == source:
>                      update_target = newdest[-1]
> -            obsolete.createmarkers(unfi, relationships,
> operation='rewind')
> +            obsolete.createmarkers(unfi, relationships,
> operation=b'rewind')
>              if update_target is not None:
>                  hg.updaterepo(repo, update_target, False)
>
> -    repo.ui.status(_('rewinded to %d changesets\n') % len(rewinded))
> +    repo.ui.status(_(b'rewinded to %d changesets\n') % len(rewinded))
>      if relationships:
> -        repo.ui.status(_('(%d changesets obsoleted)\n') %
> len(relationships))
> +        repo.ui.status(_(b'(%d changesets obsoleted)\n') %
> len(relationships))
>      if update_target is not None:
> -        ui.status(_('working directory is now at %s\n') % repo['.'])
> +        ui.status(_(b'working directory is now at %s\n') % repo[b'.'])
>
>  def _select_rewinded(repo, opts):
>      """select the revision we shoudl rewind to
>      """
>      unfi = repo.unfiltered()
>      rewinded = set()
> -    revsto = opts.get('to')
> -    revsfrom = opts.get('from')
> +    revsto = opts.get(b'to')
> +    revsfrom = opts.get(b'from')
>      if not (revsto or revsfrom):
> -        revsfrom.append('.')
> +        revsfrom.append(b'.')
>      if revsto:
>          rewinded.update(scmutil.revrange(repo, revsto))
>      if revsfrom:
>          succs = scmutil.revrange(repo, revsfrom)
> -        rewinded.update(unfi.revs('predecessors(%ld)', succs))
> +        rewinded.update(unfi.revs(b'predecessors(%ld)', succs))
>
>      if not rewinded:
> -        raise error.Abort('no revision to rewind to')
> +        raise error.Abort(b'no revision to rewind to')
>
> -    if not opts['exact']:
> -        rewinded = unfi.revs('obsolete() and ::%ld', rewinded)
> +    if not opts[b'exact']:
> +        rewinded = unfi.revs(b'obsolete() and ::%ld', rewinded)
>
>      return sorted(rewinded)
>
> @@ -152,27 +152,27 @@
>      ctx = unfi[rev]
>      extra = ctx.extra().copy()
>      # rewind hash should be unique over multiple rewind.
> -    user = unfi.ui.config('devel', 'user.obsmarker')
> +    user = unfi.ui.config(b'devel', b'user.obsmarker')
>      if not user:
>          user = unfi.ui.username()
> -    date = unfi.ui.configdate('devel', 'default-date')
> +    date = unfi.ui.configdate(b'devel', b'default-date')
>      if date is None:
>          date = compat.makedate()
> -    noise = "%s\0%s\0%d\0%d" % (ctx.node(), user, date[0], date[1])
> -    extra['__rewind-hash__'] = hashlib.sha256(noise).hexdigest()
> +    noise = b"%s\0%s\0%d\0%d" % (ctx.node(), user, date[0], date[1])
> +    extra[b'__rewind-hash__'] = hashlib.sha256(noise).hexdigest()
>
>      p1 = ctx.p1().node()
>      p1 = rewindmap.get(p1, p1)
>      p2 = ctx.p2().node()
>      p2 = rewindmap.get(p2, p2)
>
> -    extradict = {'extra': extra}
> +    extradict = {b'extra': extra}
>
>      new, unusedvariable = rewriteutil.rewrite(unfi, ctx, [], ctx,
>                                                [p1, p2],
>                                                commitopts=extradict)
>
>      obsolete.createmarkers(unfi, [(ctx, (unfi[new],))],
> -                           flag=identicalflag, operation='rewind')
> +                           flag=identicalflag, operation=b'rewind')
>
>      return new
> diff --git a/hgext3rd/evolve/rewriteutil.py
> b/hgext3rd/evolve/rewriteutil.py
> --- a/hgext3rd/evolve/rewriteutil.py
> +++ b/hgext3rd/evolve/rewriteutil.py
> @@ -44,37 +44,37 @@
>      numrevs = len(revs)
>      if numrevs < maxrevs:
>          shorts = [node.short(tonode(r)) for r in revs]
> -        summary = ', '.join(shorts)
> +        summary = b', '.join(shorts)
>      else:
>          first = revs.first()
> -        summary = _('%s and %d others')
> +        summary = _(b'%s and %d others')
>          summary %= (node.short(tonode(first)), numrevs - 1)
>      return summary
>
> -def precheck(repo, revs, action='rewrite'):
> +def precheck(repo, revs, action=b'rewrite'):
>      """check if <revs> can be rewritten
>
>      <action> can be used to control the commit message.
>      """
>      if node.nullrev in revs:
> -        msg = _("cannot %s the null revision") % (action)
> -        hint = _("no changeset checked out")
> +        msg = _(b"cannot %s the null revision") % (action)
> +        hint = _(b"no changeset checked out")
>          raise error.Abort(msg, hint=hint)
> -    if any(util.safehasattr(r, 'rev') for r in revs):
> -        msg = "rewriteutil.precheck called with ctx not revs"
> +    if any(util.safehasattr(r, b'rev') for r in revs):
> +        msg = b"rewriteutil.precheck called with ctx not revs"
>          repo.ui.develwarn(msg)
>          revs = (r.rev() for r in revs)
> -    publicrevs = repo.revs('%ld and public()', revs)
> +    publicrevs = repo.revs(b'%ld and public()', revs)
>      if publicrevs:
>          summary = _formatrevs(repo, publicrevs)
> -        msg = _("cannot %s public changesets: %s") % (action, summary)
> -        hint = _("see 'hg help phases' for details")
> +        msg = _(b"cannot %s public changesets: %s") % (action, summary)
> +        hint = _(b"see 'hg help phases' for details")
>          raise error.Abort(msg, hint=hint)
>      newunstable = disallowednewunstable(repo, revs)
>      if newunstable:
> -        msg = _("%s will orphan %i descendants")
> +        msg = _(b"%s will orphan %i descendants")
>          msg %= (action, len(newunstable))
> -        hint = _("see 'hg help evolution.instability'")
> +        hint = _(b"see 'hg help evolution.instability'")
>          raise error.Abort(msg, hint=hint)
>
>  def bookmarksupdater(repo, oldid, tr):
> @@ -96,22 +96,22 @@
>      allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
>      if allowunstable:
>          return revset.baseset()
> -    return repo.revs("(%ld::) - %ld", revs, revs)
> +    return repo.revs(b"(%ld::) - %ld", revs, revs)
>
>  def foldcheck(repo, revs):
>      """check that <revs> can be folded"""
> -    precheck(repo, revs, action='fold')
> -    roots = repo.revs('roots(%ld)', revs)
> +    precheck(repo, revs, action=b'fold')
> +    roots = repo.revs(b'roots(%ld)', revs)
>      if len(roots) > 1:
> -        raise error.Abort(_("cannot fold non-linear revisions "
> -                            "(multiple roots given)"))
> +        raise error.Abort(_(b"cannot fold non-linear revisions "
> +                            b"(multiple roots given)"))
>      root = repo[roots.first()]
>      if root.phase() <= phases.public:
> -        raise error.Abort(_("cannot fold public revisions"))
> -    heads = repo.revs('heads(%ld)', revs)
> +        raise error.Abort(_(b"cannot fold public revisions"))
> +    heads = repo.revs(b'heads(%ld)', revs)
>      if len(heads) > 1:
> -        raise error.Abort(_("cannot fold non-linear revisions "
> -                            "(multiple heads given)"))
> +        raise error.Abort(_(b"cannot fold non-linear revisions "
> +                            b"(multiple heads given)"))
>      head = repo[heads.first()]
>      return root, head
>
> @@ -120,14 +120,14 @@
>      try:
>          wlock = repo.wlock()
>          lock = repo.lock()
> -        tr = repo.transaction('prune')
> +        tr = repo.transaction(b'prune')
>          bmchanges = []
>          for bookmark in bookmarks:
>              bmchanges.append((bookmark, None))
>          repo._bookmarks.applychanges(repo, tr, bmchanges)
>          tr.close()
>          for bookmark in sorted(bookmarks):
> -            repo.ui.write(_("bookmark '%s' deleted\n") % bookmark)
> +            repo.ui.write(_(b"bookmark '%s' deleted\n") % bookmark)
>      finally:
>          lockmod.release(tr, lock, wlock)
>
> @@ -143,14 +143,14 @@
>      """
>      repomarks = repo._bookmarks
>      if not bookmarks.issubset(repomarks):
> -        raise error.Abort(_("bookmark '%s' not found") %
> -                          ','.join(sorted(bookmarks -
> set(repomarks.keys()))))
> +        raise error.Abort(_(b"bookmark '%s' not found") %
> +                          b','.join(sorted(bookmarks -
> set(repomarks.keys()))))
>
>      # If the requested bookmark is not the only one pointing to a
>      # a revision we have to only delete the bookmark and not strip
>      # anything. revsets cannot detect that case.
>      nodetobookmarks = {}
> -    for mark, bnode in repomarks.iteritems():
> +    for mark, bnode in repomarks.items():
>          nodetobookmarks.setdefault(bnode, []).append(mark)
>      for marks in nodetobookmarks.values():
>          if bookmarks.issuperset(marks):
> @@ -170,9 +170,9 @@
>      try:
>          wlock = repo.wlock()
>          lock = repo.lock()
> -        tr = repo.transaction('rewrite')
> +        tr = repo.transaction(b'rewrite')
>          if len(old.parents()) > 1: # XXX remove this unnecessary
> limitation.
> -            raise error.Abort(_('cannot amend merge changesets'))
> +            raise error.Abort(_(b'cannot amend merge changesets'))
>          base = old.p1()
>          updatebookmarks = bookmarksupdater(repo, old.node(), tr)
>
> @@ -213,13 +213,13 @@
>          if not message:
>              message = old.description()
>
> -        user = commitopts.get('user') or old.user()
> +        user = commitopts.get(b'user') or old.user()
>          # TODO: In case not date is given, we should take the old commit
> date
>          # if we are working one one changeset or mimic the fold behavior
> about
>          # date
> -        date = commitopts.get('date') or None
> -        extra = dict(commitopts.get('extra', old.extra()))
> -        extra['branch'] = head.branch()
> +        date = commitopts.get(b'date') or None
> +        extra = dict(commitopts.get(b'extra', old.extra()))
> +        extra[b'branch'] = head.branch()
>
>          new = context.memctx(repo,
>                               parents=newbases,
> @@ -230,7 +230,7 @@
>                               date=date,
>                               extra=extra)
>
> -        if commitopts.get('edit'):
> +        if commitopts.get(b'edit'):
>              new._text = cmdutil.commitforceeditor(repo, new, [])
>          revcount = len(repo)
>          newid = repo.commitctx(new)
> diff --git a/hgext3rd/evolve/safeguard.py b/hgext3rd/evolve/safeguard.py
> --- a/hgext3rd/evolve/safeguard.py
> +++ b/hgext3rd/evolve/safeguard.py
> @@ -20,9 +20,9 @@
>  eh = exthelper.exthelper()
>
>  # hg <= 4.8
> -if 'auto-publish' not in configitems.coreitems.get('experimental', {}):
> +if b'auto-publish' not in configitems.coreitems.get(b'experimental', {}):
>
> -    eh.configitem('experimental', 'auto-publish', 'publish')
> +    eh.configitem(b'experimental', b'auto-publish', b'publish')
>
>      @eh.reposetup
>      def setuppublishprevention(ui, repo):
> @@ -31,25 +31,25 @@
>
>              def checkpush(self, pushop):
>                  super(noautopublishrepo, self).checkpush(pushop)
> -                behavior = self.ui.config('experimental', 'auto-publish')
> -                nocheck = behavior not in ('warn', 'abort')
> +                behavior = self.ui.config(b'experimental',
> b'auto-publish')
> +                nocheck = behavior not in (b'warn', b'abort')
>                  if nocheck or getattr(pushop, 'publish', False):
>                      return
> -                remotephases = pushop.remote.listkeys('phases')
> -                publishing = remotephases.get('publishing', False)
> +                remotephases = pushop.remote.listkeys(b'phases')
> +                publishing = remotephases.get(b'publishing', False)
>                  if publishing:
>                      if pushop.revs is None:
> -                        published = self.filtered('served').revs("not
> public()")
> +                        published = self.filtered(b'served').revs(b"not
> public()")
>                      else:
> -                        published = self.revs("::%ln - public()",
> pushop.revs)
> +                        published = self.revs(b"::%ln - public()",
> pushop.revs)
>                      if published:
> -                        if behavior == 'warn':
> -                            self.ui.warn(_('%i changesets about to be
> published\n')
> +                        if behavior == b'warn':
> +                            self.ui.warn(_(b'%i changesets about to be
> published\n')
>                                           % len(published))
> -                        elif behavior == 'abort':
> -                            msg = _('push would publish 1 changesets')
> -                            hint = _("behavior controlled by "
> -                                     "'experimental.auto-publish' config")
> +                        elif behavior == b'abort':
> +                            msg = _(b'push would publish 1 changesets')
> +                            hint = _(b"behavior controlled by "
> +                                     b"'experimental.auto-publish'
> config")
>                              raise error.Abort(msg, hint=hint)
>
>          repo.__class__ = noautopublishrepo
> diff --git a/hgext3rd/evolve/serveronly.py b/hgext3rd/evolve/serveronly.py
> --- a/hgext3rd/evolve/serveronly.py
> +++ b/hgext3rd/evolve/serveronly.py
> @@ -24,7 +24,7 @@
>          obsexchange,
>      )
>  except ValueError as exc:
> -    if str(exc) != 'Attempted relative import in non-package':
> +    if str(exc) != b'Attempted relative import in non-package':
>          raise
>      # extension imported using direct path
>      sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
> @@ -53,11 +53,11 @@
>
>  @eh.reposetup
>  def default2evolution(ui, repo):
> -    evolveopts = repo.ui.configlist('experimental', 'evolution')
> +    evolveopts = repo.ui.configlist(b'experimental', b'evolution')
>      if not evolveopts:
> -        evolveopts = 'all'
> -        repo.ui.setconfig('experimental', 'evolution', evolveopts)
> -    if obsolete.isenabled(repo, 'exchange'):
> +        evolveopts = b'all'
> +        repo.ui.setconfig(b'experimental', b'evolution', evolveopts)
> +    if obsolete.isenabled(repo, b'exchange'):
>          # if no config explicitly set, disable bundle1
> -        if not isinstance(repo.ui.config('server', 'bundle1'), str):
> -            repo.ui.setconfig('server', 'bundle1', False)
> +        if not isinstance(repo.ui.config(b'server', b'bundle1'), str):
> +            repo.ui.setconfig(b'server', b'bundle1', False)
> diff --git a/hgext3rd/evolve/stablerange.py
> b/hgext3rd/evolve/stablerange.py
> --- a/hgext3rd/evolve/stablerange.py
> +++ b/hgext3rd/evolve/stablerange.py
> @@ -64,23 +64,23 @@
>      return ranges
>
>  _stablerangemethodmap = {
> -    'branchpoint': lambda repo: stablerange(),
> -    'default': lambda repo: repo.stablerange,
> -    'basic-branchpoint': lambda repo: stablerangebasic(),
> -    'basic-mergepoint': lambda repo: stablerangedummy_mergepoint(),
> -    'mergepoint': lambda repo: stablerange_mergepoint(),
> +    b'branchpoint': lambda repo: stablerange(),
> +    b'default': lambda repo: repo.stablerange,
> +    b'basic-branchpoint': lambda repo: stablerangebasic(),
> +    b'basic-mergepoint': lambda repo: stablerangedummy_mergepoint(),
> +    b'mergepoint': lambda repo: stablerange_mergepoint(),
>  }
>
>  @eh.command(
> -    'debugstablerange',
> +    b'debugstablerange',
>      [
> -        ('r', 'rev', [], 'operate on (rev, 0) ranges for rev in REVS'),
> -        ('', 'subranges', False, 'recursively display data for subranges
> too'),
> -        ('', 'verify', False, 'checks subranges content (EXPENSIVE)'),
> -        ('', 'method', 'branchpoint',
> -         'method to use, one of "branchpoint", "mergepoint"')
> -    ],
> -    _(''))
> +        (b'r', b'rev', [], b'operate on (rev, 0) ranges for rev in REVS'),
> +        (b'', b'subranges', False, b'recursively display data for
> subranges too'),
> +        (b'', b'verify', False, b'checks subranges content (EXPENSIVE)'),
> +        (b'', b'method', b'branchpoint',
> +         b'method to use, one of "branchpoint", "mergepoint"')
> +     ],
> +    _(b''))
>  def debugstablerange(ui, repo, **opts):
>      """display standard stable subrange for a set of ranges
>
> @@ -88,11 +88,11 @@
>      --verbose to get the extra details in ().
>      """
>      short = nodemod.short
> -    revs = scmutil.revrange(repo, opts['rev'])
> +    revs = scmutil.revrange(repo, opts[b'rev'])
>      if not revs:
> -        raise error.Abort('no revisions specified')
> +        raise error.Abort(b'no revisions specified')
>      if ui.verbose:
> -        template = '%s-%d (%d, %d, %d)'
> +        template = b'%s-%d (%d, %d, %d)'
>
>          def _rangestring(repo, rangeid):
>              return template % (
> @@ -103,7 +103,7 @@
>                  length(unfi, rangeid)
>              )
>      else:
> -        template = '%s-%d'
> +        template = b'%s-%d'
>
>          def _rangestring(repo, rangeid):
>              return template % (
> @@ -114,10 +114,10 @@
>      unfi = repo.unfiltered()
>      node = unfi.changelog.node
>
> -    method = opts['method']
> +    method = opts[b'method']
>      getstablerange = _stablerangemethodmap.get(method)
>      if getstablerange is None:
> -        raise error.Abort('unknown stable sort method: "%s"' % method)
> +        raise error.Abort(b'unknown stable sort method: "%s"' % method)
>
>      stablerange = getstablerange(unfi)
>      depth = stablerange.depthrev
> @@ -125,28 +125,28 @@
>      subranges = stablerange.subranges
>      stablerange.warmup(repo, max(revs))
>
> -    if opts['subranges']:
> +    if opts[b'subranges']:
>          ranges = subrangesclosure(unfi, stablerange, revs)
>      else:
>          ranges = [(r, 0) for r in revs]
>
>      for r in ranges:
>          subs = subranges(unfi, r)
> -        subsstr = ', '.join(_rangestring(unfi, s) for s in subs)
> +        subsstr = b', '.join(_rangestring(unfi, s) for s in subs)
>          rstr = _rangestring(unfi, r)
> -        if opts['verify']:
> -            status = 'leaf'
> +        if opts[b'verify']:
> +            status = b'leaf'
>              if 1 < length(unfi, r):
> -                status = 'complete'
> +                status = b'complete'
>                  revs = set(stablerange.revsfromrange(unfi, r))
>                  subrevs = set()
>                  for s in subs:
>                      subrevs.update(stablerange.revsfromrange(unfi, s))
>                  if revs != subrevs:
> -                    status = 'missing'
> -            ui.status('%s [%s] - %s\n' % (rstr, status, subsstr))
> +                    status = b'missing'
> +            ui.status(b'%s [%s] - %s\n' % (rstr, status, subsstr))
>          else:
> -            ui.status('%s - %s\n' % (rstr, subsstr))
> +            ui.status(b'%s - %s\n' % (rstr, subsstr))
>
>  class abstractstablerange(object):
>      """The official API for a stablerange"""
> @@ -214,7 +214,7 @@
>
>      def depthrev(self, repo, rev):
>          """depth a revision"""
> -        return len(repo.revs('::%d', rev))
> +        return len(repo.revs(b'::%d', rev))
>
>      def revsfromrange(self, repo, rangeid):
>          """return revision contained in a range
> @@ -620,12 +620,12 @@
>          rangeheap = []
>          for idx, r in enumerate(revs):
>              if not idx % 1000:
> -                compat.progress(ui, _("filling depth cache"), idx,
> total=nbrevs,
> -                                unit=_("changesets"))
> +                compat.progress(ui, _(b"filling depth cache"), idx,
> total=nbrevs,
> +                                unit=_(b"changesets"))
>              # warm up depth
>              self.depthrev(repo, r)
>              rangeheap.append((-r, (r, 0)))
> -        compat.progress(ui, _("filling depth cache"), None, total=nbrevs)
> +        compat.progress(ui, _(b"filling depth cache"), None, total=nbrevs)
>
>          heappop = heapq.heappop
>          heappush = heapq.heappush
> @@ -646,8 +646,8 @@
>                      progress_new = time.time()
>                      if (1 < progress_each) and (0.1 < progress_new -
> progress_last):
>                          progress_each /= 10
> -                    compat.progress(ui, _("filling stablerange cache"),
> seen,
> -                                    total=nbrevs, unit=_("changesets"))
> +                    compat.progress(ui, _(b"filling stablerange cache"),
> seen,
> +                                    total=nbrevs, unit=_(b"changesets"))
>                      progress_last = progress_new
>                  seen += 1
>                  original.remove(value) # might have been added from other
> source
> @@ -656,13 +656,13 @@
>                  for sub in self.subranges(repo, rangeid):
>                      if self._getsub(sub) is None:
>                          heappush(rangeheap, (-sub[0], sub))
> -        compat.progress(ui, _("filling stablerange cache"), None,
> total=nbrevs)
> +        compat.progress(ui, _(b"filling stablerange cache"), None,
> total=nbrevs)
>
>          self._tiprev = upto
>          self._tipnode = cl.node(upto)
>
>          duration = util.timer() - starttime
> -        repo.ui.log('evoext-cache', 'updated stablerange cache in %.4f
> seconds\n',
> +        repo.ui.log(b'evoext-cache', b'updated stablerange cache in %.4f
> seconds\n',
>                      duration)
>
>      def subranges(self, repo, rangeid):
> diff --git a/hgext3rd/evolve/stablerangecache.py
> b/hgext3rd/evolve/stablerangecache.py
> --- a/hgext3rd/evolve/stablerangecache.py
> +++ b/hgext3rd/evolve/stablerangecache.py
> @@ -98,8 +98,8 @@
>                          warned_long = True
>                      if (1 < progress_each) and (0.1 < progress_new -
> progress_last):
>                          progress_each /= 10
> -                    compat.progress(ui, _("filling stablerange cache"),
> seen,
> -                                    total=total, unit=_("changesets"))
> +                    compat.progress(ui, _(b"filling stablerange cache"),
> seen,
> +                                    total=total, unit=_(b"changesets"))
>                      progress_last = progress_new
>                  seen += 1
>                  original.remove(rangeid) # might have been added from
> other source
> @@ -108,7 +108,7 @@
>                  for sub in self.subranges(repo, rangeid):
>                      if self._getsub(sub) is None:
>                          heappush(rangeheap, sub)
> -        compat.progress(ui, _("filling stablerange cache"), None,
> total=total)
> +        compat.progress(ui, _(b"filling stablerange cache"), None,
> total=total)
>
>      def clear(self, reset=False):
>          super(stablerangeondiskbase, self).clear()
> @@ -131,23 +131,23 @@
>                                FOREIGN KEY (suprev, supidx) REFERENCES
> range(rev, idx),
>                                FOREIGN KEY (subrev, subidx) REFERENCES
> range(rev, idx)
>      );""",
> -    "CREATE INDEX subranges_index ON subranges (suprev, supidx);",
> -    "CREATE INDEX superranges_index ON subranges (subrev, subidx);",
> -    "CREATE INDEX range_index ON range (rev, idx);",
> +    b"CREATE INDEX subranges_index ON subranges (suprev, supidx);",
> +    b"CREATE INDEX superranges_index ON subranges (subrev, subidx);",
> +    b"CREATE INDEX range_index ON range (rev, idx);",
>      """CREATE TABLE meta(schemaversion INTEGER NOT NULL,
>                           tiprev        INTEGER NOT NULL,
>                           tipnode       BLOB    NOT NULL
>                          );""",
>  ]
> -_newmeta = "INSERT INTO meta (schemaversion, tiprev, tipnode) VALUES
> (?,?,?);"
> -_updatemeta = "UPDATE meta SET tiprev = ?, tipnode = ?;"
> -_updaterange = "INSERT INTO range(rev, idx) VALUES (?,?);"
> +_newmeta = b"INSERT INTO meta (schemaversion, tiprev, tipnode) VALUES
> (?,?,?);"
> +_updatemeta = b"UPDATE meta SET tiprev = ?, tipnode = ?;"
> +_updaterange = b"INSERT INTO range(rev, idx) VALUES (?,?);"
>  _updatesubranges = """INSERT
>                         INTO subranges(listidx, suprev, supidx, subrev,
> subidx)
>                         VALUES (?,?,?,?,?);"""
> -_queryexist = "SELECT name FROM sqlite_master WHERE type='table' AND
> name='meta';"
> -_querymeta = "SELECT schemaversion, tiprev, tipnode FROM meta;"
> -_queryrange = "SELECT * FROM range WHERE (rev = ? AND idx = ?);"
> +_queryexist = b"SELECT name FROM sqlite_master WHERE type='table' AND
> name='meta';"
> +_querymeta = b"SELECT schemaversion, tiprev, tipnode FROM meta;"
> +_queryrange = b"SELECT * FROM range WHERE (rev = ? AND idx = ?);"
>  _querysubranges = """SELECT subrev, subidx
>                       FROM subranges
>                       WHERE (suprev = ? AND supidx = ?)
> @@ -157,11 +157,11 @@
>                             FROM subranges
>                             WHERE %s;"""
>
> -_querysuperrangesbody = '(subrev = %d and subidx = %d)'
> +_querysuperrangesbody = b'(subrev = %d and subidx = %d)'
>
>  def _make_querysuperranges(ranges):
>      # building a tree of OR would allow for more ranges
> -    body = ' OR '.join(_querysuperrangesbody % r for r in ranges)
> +    body = b' OR '.join(_querysuperrangesbody % r for r in ranges)
>      return _querysuperrangesmain % body
>
>  class stablerangesqlbase(stablerange.stablerangecached):
> @@ -218,7 +218,7 @@
>              except (sqlite3.DatabaseError, sqlite3.OperationalError):
>                  # something is wrong with the sqlite db
>                  # Since this is a cache, we ignore it.
> -                if '_con' in vars(self):
> +                if b'_con' in vars(self):
>                      del self._con
>                  self._unsavedsubranges.clear()
>
> @@ -234,7 +234,7 @@
>              util.makedirs(self._vfs.dirname(self._path))
>          except OSError:
>              return None
> -        con = sqlite3.connect(self._path, timeout=30,
> isolation_level="IMMEDIATE")
> +        con = sqlite3.connect(self._path, timeout=30,
> isolation_level=b"IMMEDIATE")
>          con.text_factory = str
>          return con
>
> @@ -272,11 +272,11 @@
>              #
>              # operational error catch read-only and locked database
>              # IntegrityError catch Unique constraint error that may arise
> -            if '_con' in vars(self):
> +            if b'_con' in vars(self):
>                  del self._con
>              self._unsavedsubranges.clear()
> -            repo.ui.log('evoext-cache', 'error while saving new data: %s'
> % exc)
> -            repo.ui.debug('evoext-cache: error while saving new data: %s'
> % exc)
> +            repo.ui.log(b'evoext-cache', b'error while saving new data:
> %s' % exc)
> +            repo.ui.debug(b'evoext-cache: error while saving new data:
> %s' % exc)
>
>      def _trysave(self, repo):
>          repo = repo.unfiltered()
> @@ -288,7 +288,7 @@
>
>          if self._con is None:
>              util.unlinkpath(self._path, ignoremissing=True)
> -            if '_con' in vars(self):
> +            if b'_con' in vars(self):
>                  del self._con
>
>              con = self._db()
> @@ -313,9 +313,9 @@
>                  # drifting is currently an issue because this means
> another
>                  # process might have already added the cache line we are
> about
>                  # to add. This will confuse sqlite
> -                msg = _('stable-range cache: skipping write, '
> -                        'database drifted under my feet\n')
> -                hint = _('(disk: %s-%s vs mem: %s-%s)\n')
> +                msg = _(b'stable-range cache: skipping write, '
> +                        b'database drifted under my feet\n')
> +                hint = _(b'(disk: %s-%s vs mem: %s-%s)\n')
>                  data = (nodemod.hex(meta[2]), meta[1],
>                          nodemod.hex(self._ondisktipnode),
> self._ondisktiprev)
>                  repo.ui.warn(msg)
> @@ -369,7 +369,7 @@
>
>      def clear(self, reset=False):
>          super(stablerangesql, self).clear(reset=reset)
> -        if '_con' in vars(self):
> +        if b'_con' in vars(self):
>              del self._con
>          self._subrangescache.clear()
>
> @@ -390,13 +390,13 @@
>  class mergepointsql(stablerangesql, stablerange.stablerange_mergepoint):
>
>      _schemaversion = 3
> -    _cachefile = 'evoext_stablerange_v2.sqlite'
> -    _cachename = 'evo-ext-stablerange-mergepoint'
> +    _cachefile = b'evoext_stablerange_v2.sqlite'
> +    _cachename = b'evo-ext-stablerange-mergepoint'
>
>  class sqlstablerange(stablerangesqlbase, stablerange.stablerange):
>
>      _schemaversion = 1
> -    _cachefile = 'evoext_stablerange_v1.sqlite'
> +    _cachefile = b'evoext_stablerange_v1.sqlite'
>
>      def warmup(self, repo, upto=None):
>          self._con # make sure the data base is loaded
> @@ -413,8 +413,8 @@
>          except error.LockError:
>              # Exceptionnally we are noisy about it since performance
> impact is
>              # large We should address that before using this more widely.
> -            repo.ui.warn('stable-range cache: unable to lock repo while
> warming\n')
> -            repo.ui.warn('(cache will not be saved)\n')
> +            repo.ui.warn(b'stable-range cache: unable to lock repo while
> warming\n')
> +            repo.ui.warn(b'(cache will not be saved)\n')
>              super(sqlstablerange, self).warmup(repo, upto)
>
>  @eh.reposetup
> @@ -430,7 +430,7 @@
>
>          @localrepo.unfilteredmethod
>          def destroyed(self):
> -            if 'stablerange' in vars(self):
> +            if b'stablerange' in vars(self):
>                  self.stablerange.clear()
>                  del self.stablerange
>              super(stablerangerepo, self).destroyed()
> diff --git a/hgext3rd/evolve/stablesort.py b/hgext3rd/evolve/stablesort.py
> --- a/hgext3rd/evolve/stablesort.py
> +++ b/hgext3rd/evolve/stablesort.py
> @@ -52,30 +52,30 @@
>      return key
>
>  @eh.command(
> -    'debugstablesort',
> +    b'debugstablesort',
>      [
> -        ('r', 'rev', [], 'heads to start from'),
> -        ('', 'method', 'branchpoint', "method used for sorting, one of: "
> -         "branchpoint, basic-mergepoint and basic-headstart"),
> -        ('l', 'limit', '', 'number of revision display (default to all)')
> -    ] + commands.formatteropts,
> -    _(''))
> +        (b'r', b'rev', [], b'heads to start from'),
> +        (b'', b'method', b'branchpoint', b"method used for sorting, one
> of: "
> +         b"branchpoint, basic-mergepoint and basic-headstart"),
> +        (b'l', b'limit', b'', b'number of revision display (default to
> all)')
> +     ] + commands.formatteropts,
> +    _(b''))
>  def debugstablesort(ui, repo, **opts):
>      """display the ::REVS set topologically sorted in a stable way
>      """
> -    revs = scmutil.revrange(repo, opts['rev'])
> +    revs = scmutil.revrange(repo, opts[b'rev'])
>
> -    method = opts['method']
> +    method = opts[b'method']
>      sorting = _methodmap.get(method)
>      if sorting is None:
> -        valid_method = ', '.join(sorted(_methodmap))
> -        raise error.Abort('unknown sorting method: "%s"' % method,
> -                          hint='pick one of: %s' % valid_method)
> +        valid_method = b', '.join(sorted(_methodmap))
> +        raise error.Abort(b'unknown sorting method: "%s"' % method,
> +                          hint=b'pick one of: %s' % valid_method)
>
>      displayer = compat.changesetdisplayer(ui, repo, opts, buffered=True)
>      kwargs = {}
> -    if opts['limit']:
> -        kwargs['limit'] = int(opts['limit'])
> +    if opts[b'limit']:
> +        kwargs[b'limit'] = int(opts[b'limit'])
>      for r in sorting(repo, revs, **kwargs):
>          ctx = repo[r]
>          displayer.show(ctx)
> @@ -178,7 +178,7 @@
>          heads = list(sorted(revs))
>      else:
>          # keeps heads only
> -        heads = sorted(repo.revs('sort(heads(%ld::%ld))', revs, revs),
> key=tiebreaker)
> +        heads = sorted(repo.revs(b'sort(heads(%ld::%ld))', revs, revs),
> key=tiebreaker)
>
>      results = []
>      while heads:
> @@ -244,24 +244,24 @@
>      return result
>
>  def stablesort_mergepoint_head_basic(repo, revs, limit=None):
> -    heads = repo.revs('sort(heads(%ld))', revs)
> +    heads = repo.revs(b'sort(heads(%ld))', revs)
>      if not heads:
>          return []
>      elif 2 < len(heads):
> -        raise error.Abort('cannot use head based merging, %d heads found'
> +        raise error.Abort(b'cannot use head based merging, %d heads found'
>                            % len(heads))
>      head = heads.first()
> -    revs = stablesort_mergepoint_bounded(repo, head, repo.revs('::%d',
> head))
> +    revs = stablesort_mergepoint_bounded(repo, head, repo.revs(b'::%d',
> head))
>      if limit is None:
>          return revs
>      return revs[-limit:]
>
>  def stablesort_mergepoint_head_debug(repo, revs, limit=None):
> -    heads = repo.revs('sort(heads(%ld))', revs)
> +    heads = repo.revs(b'sort(heads(%ld))', revs)
>      if not heads:
>          return []
>      elif 2 < len(heads):
> -        raise error.Abort('cannot use head based merging, %d heads found'
> +        raise error.Abort(b'cannot use head based merging, %d heads found'
>                            % len(heads))
>      head = heads.first()
>      revs = stablesort_mergepoint_head(repo, head)
> @@ -292,7 +292,7 @@
>          ps = sorted(ps, key=tiebreaker)
>
>          # get the part from the highest parent. This is the part that
> changes
> -        mid_revs = repo.revs('only(%d, %d)', ps[1], ps[0])
> +        mid_revs = repo.revs(b'only(%d, %d)', ps[1], ps[0])
>          if mid_revs:
>              mid = stablesort_mergepoint_bounded(repo, ps[1], mid_revs)
>
> @@ -302,20 +302,20 @@
>      return bottom + mid + top
>
>  def stablesort_mergepoint_head_cached(repo, revs, limit=None):
> -    heads = repo.revs('sort(heads(%ld))', revs)
> +    heads = repo.revs(b'sort(heads(%ld))', revs)
>      if not heads:
>          return []
>      elif 2 < len(heads):
> -        raise error.Abort('cannot use head based merging, %d heads found'
> +        raise error.Abort(b'cannot use head based merging, %d heads found'
>                            % len(heads))
>      head = heads.first()
>      cache = stablesortcache()
>      first = list(cache.get(repo, head, limit=limit))
>      second = list(cache.get(repo, head, limit=limit))
>      if first != second:
> -        repo.ui.warn('stablesort-cache: initial run different from
> re-run:\n'
> -                     '    %s\n'
> -                     '    %s\n' % (first, second))
> +        repo.ui.warn(b'stablesort-cache: initial run different from
> re-run:\n'
> +                     b'    %s\n'
> +                     b'    %s\n' % (first, second))
>      return second
>
>  class stablesortcache(object):
> @@ -502,11 +502,11 @@
>              recordjump(previous, lower, size)
>
>  def stablesort_mergepoint_head_ondisk(repo, revs, limit=None):
> -    heads = repo.revs('sort(heads(%ld))', revs)
> +    heads = repo.revs(b'sort(heads(%ld))', revs)
>      if not heads:
>          return []
>      elif 2 < len(heads):
> -        raise error.Abort('cannot use head based merging, %d heads found'
> +        raise error.Abort(b'cannot use head based merging, %d heads found'
>                            % len(heads))
>      head = heads.first()
>      unfi = repo.unfiltered()
> @@ -514,22 +514,22 @@
>      cache.save(unfi)
>      return cache.get(repo, head, limit=limit)
>
> -S_INDEXSIZE = struct.Struct('>I')
> +S_INDEXSIZE = struct.Struct(b'>I')
>
>  class ondiskstablesortcache(stablesortcache,
> genericcaches.changelogsourcebase):
>
> -    _filepath = 'evoext-stablesortcache-00'
> -    _cachename = 'evo-ext-stablesort'
> +    _filepath = b'evoext-stablesortcache-00'
> +    _cachename = b'evo-ext-stablesort'
>
>      def __init__(self):
>          super(ondiskstablesortcache, self).__init__()
> -        self._index = array.array('l')
> -        self._data = array.array('l')
> +        self._index = array.array(b'l')
> +        self._data = array.array(b'l')
>          del self._jumps
>
>      def getjumps(self, repo, rev):
>          if len(self._index) < rev:
> -            msg = 'stablesortcache must be warmed before use (%d < %d)'
> +            msg = b'stablesortcache must be warmed before use (%d < %d)'
>              msg %= (len(self._index), rev)
>              raise error.ProgrammingError(msg)
>          return self._getjumps(rev)
> @@ -577,10 +577,10 @@
>          total = len(data)
>
>          def progress(pos, rev):
> -            compat.progress(repo.ui, 'updating stablesort cache',
> -                            pos, 'rev %s' % rev, unit='revision',
> total=total)
> +            compat.progress(repo.ui, b'updating stablesort cache',
> +                            pos, b'rev %s' % rev, unit=b'revision',
> total=total)
>
> -        progress(0, '')
> +        progress(0, b'')
>          for idx, rev in enumerate(data):
>              parents = filterparents(repo.changelog.parentrevs(rev))
>              if len(parents) <= 1:
> @@ -594,12 +594,12 @@
>                          break
>              if not (idx % 1000): # progress as a too high performance
> impact
>                  progress(idx, rev)
> -        progress(None, '')
> +        progress(None, b'')
>
>      def clear(self, reset=False):
>          super(ondiskstablesortcache, self).clear()
> -        self._index = array.array('l')
> -        self._data = array.array('l')
> +        self._index = array.array(b'l')
> +        self._data = array.array(b'l')
>
>      def load(self, repo):
>          """load data from disk
> @@ -609,8 +609,8 @@
>          assert repo.filtername is None
>
>          data = repo.cachevfs.tryread(self._filepath)
> -        self._index = array.array('l')
> -        self._data = array.array('l')
> +        self._index = array.array(b'l')
> +        self._data = array.array(b'l')
>          if not data:
>              self._cachekey = self.emptykey
>          else:
> @@ -634,7 +634,7 @@
>          if self._cachekey is None or self._cachekey == self._ondiskkey:
>              return
>          try:
> -            cachefile = repo.cachevfs(self._filepath, 'w',
> atomictemp=True)
> +            cachefile = repo.cachevfs(self._filepath, b'w',
> atomictemp=True)
>
>              # data to write
>              headerdata = self._serializecachekey()
> @@ -650,8 +650,8 @@
>              cachefile.close()
>              self._ondiskkey = self._cachekey
>          except (IOError, OSError) as exc:
> -            repo.ui.log('stablesortcache', 'could not write update %s\n'
> % exc)
> -            repo.ui.debug('stablesortcache: could not write update %s\n'
> % exc)
> +            repo.ui.log(b'stablesortcache', b'could not write update
> %s\n' % exc)
> +            repo.ui.debug(b'stablesortcache: could not write update %s\n'
> % exc)
>
>  @eh.reposetup
>  def setupcache(ui, repo):
> @@ -666,7 +666,7 @@
>
>          @localrepo.unfilteredmethod
>          def destroyed(self):
> -            if 'stablesort' in vars(self):
> +            if b'stablesort' in vars(self):
>                  self.stablesort.clear()
>              super(stablesortrepo, self).destroyed()
>
> @@ -680,12 +680,12 @@
>      repo.__class__ = stablesortrepo
>
>  _methodmap = {
> -    'branchpoint': stablesort_branchpoint,
> -    'basic-mergepoint': stablesort_mergepoint_multirevs,
> -    'basic-headstart': stablesort_mergepoint_head_basic,
> -    'headstart': stablesort_mergepoint_head_debug,
> -    'headcached': stablesort_mergepoint_head_cached,
> -    'headondisk': stablesort_mergepoint_head_ondisk,
> +    b'branchpoint': stablesort_branchpoint,
> +    b'basic-mergepoint': stablesort_mergepoint_multirevs,
> +    b'basic-headstart': stablesort_mergepoint_head_basic,
> +    b'headstart': stablesort_mergepoint_head_debug,
> +    b'headcached': stablesort_mergepoint_head_cached,
> +    b'headondisk': stablesort_mergepoint_head_ondisk,
>  }
>
>  # merge last so that repo setup wrap after that one.
> diff --git a/hgext3rd/evolve/state.py b/hgext3rd/evolve/state.py
> --- a/hgext3rd/evolve/state.py
> +++ b/hgext3rd/evolve/state.py
> @@ -37,7 +37,7 @@
>      can populate the object data reading that file
>      """
>
> -    def __init__(self, repo, path='evolvestate', opts={}):
> +    def __init__(self, repo, path=b'evolvestate', opts={}):
>          self._repo = repo
>          self.path = path
>          self.opts = opts
> @@ -63,7 +63,7 @@
>          op = self._read()
>          if isinstance(op, dict):
>              self.opts.update(op)
> -        elif self.path == 'evolvestate':
> +        elif self.path == b'evolvestate':
>              # it is the old evolvestate file
>              oldop = _oldevolvestateread(self._repo)
>              self.opts.update(oldop)
> @@ -77,13 +77,13 @@
>
>          we use third-party library cbor to serialize data to write in the
> file.
>          """
> -        with self._repo.vfs(self.path, 'wb', atomictemp=True) as fp:
> +        with self._repo.vfs(self.path, b'wb', atomictemp=True) as fp:
>              cbor.dump(self.opts, fp)
>
>      def _read(self):
>          """reads the evolvestate file and returns a dictionary which
> contain
>          data in the same format as it was before storing"""
> -        with self._repo.vfs(self.path, 'rb') as fp:
> +        with self._repo.vfs(self.path, b'rb') as fp:
>              return cbor.load(fp)
>
>      def delete(self):
> @@ -99,20 +99,20 @@
>
>      This exists for BC reasons."""
>      try:
> -        f = repo.vfs('evolvestate')
> +        f = repo.vfs(b'evolvestate')
>      except IOError as err:
>          if err.errno != errno.ENOENT:
>              raise
>      try:
>          versionblob = f.read(4)
>          if len(versionblob) < 4:
> -            repo.ui.debug('ignoring corrupted evolvestate (file contains
> %i bits)'
> +            repo.ui.debug(b'ignoring corrupted evolvestate (file contains
> %i bits)'
>                            % len(versionblob))
>              return None
> -        version = struct._unpack('>I', versionblob)[0]
> +        version = struct._unpack(b'>I', versionblob)[0]
>          if version != 0:
> -            msg = _('unknown evolvestate version %i') % version
> -            raise error.Abort(msg, hint=_('upgrade your evolve'))
> +            msg = _(b'unknown evolvestate version %i') % version
> +            raise error.Abort(msg, hint=_(b'upgrade your evolve'))
>          records = []
>          data = f.read()
>          off = 0
> @@ -120,22 +120,22 @@
>          while off < end:
>              rtype = data[off]
>              off += 1
> -            length = struct._unpack('>I', data[off:(off + 4)])[0]
> +            length = struct._unpack(b'>I', data[off:(off + 4)])[0]
>              off += 4
>              record = data[off:(off + length)]
>              off += length
> -            if rtype == 't':
> +            if rtype == b't':
>                  rtype, record = record[0], record[1:]
>              records.append((rtype, record))
>          state = {}
>          for rtype, rdata in records:
> -            if rtype == 'C':
> -                state['current'] = rdata
> +            if rtype == b'C':
> +                state[b'current'] = rdata
>              elif rtype.lower():
> -                repo.ui.debug('ignore evolve state record type %s' %
> rtype)
> +                repo.ui.debug(b'ignore evolve state record type %s' %
> rtype)
>              else:
> -                raise error.Abort(_('unknown evolvestate field type %r')
> -                                  % rtype, hint=_('upgrade your evolve'))
> +                raise error.Abort(_(b'unknown evolvestate field type %r')
> +                                  % rtype, hint=_(b'upgrade your evolve'))
>          return state
>      finally:
>          f.close()
> diff --git a/hgext3rd/evolve/templatekw.py b/hgext3rd/evolve/templatekw.py
> --- a/hgext3rd/evolve/templatekw.py
> +++ b/hgext3rd/evolve/templatekw.py
> @@ -23,45 +23,45 @@
>
>  ### template keywords
>
> -if util.safehasattr(templatekw, 'compatlist'):
> -    @eh.templatekeyword('instabilities', requires=set(['ctx', 'templ']))
> +if util.safehasattr(templatekw, b'compatlist'):
> +    @eh.templatekeyword(b'instabilities', requires=set([b'ctx',
> b'templ']))
>      def showinstabilities(context, mapping):
>          """List of strings. Evolution instabilities affecting the
> changeset
>          (zero or more of "orphan", "content-divergent" or
> "phase-divergent")."""
> -        ctx = context.resource(mapping, 'ctx')
> -        return templatekw.compatlist(context, mapping, 'instability',
> +        ctx = context.resource(mapping, b'ctx')
> +        return templatekw.compatlist(context, mapping, b'instability',
>                                       ctx.instabilities(),
> -                                     plural='instabilities')
> +                                     plural=b'instabilities')
>
> -    @eh.templatekeyword('troubles', requires=set(['ctx', 'templ']))
> +    @eh.templatekeyword(b'troubles', requires=set([b'ctx', b'templ']))
>      def showtroubles(context, mapping):   # legacy name for instabilities
> -        ctx = context.resource(mapping, 'ctx')
> -        return templatekw.compatlist(context, mapping, 'trouble',
> -                                     ctx.instabilities(),
> plural='troubles')
> +        ctx = context.resource(mapping, b'ctx')
> +        return templatekw.compatlist(context, mapping, b'trouble',
> +                                     ctx.instabilities(),
> plural=b'troubles')
>  else:
>      # older template API in hg < 4.6
> -    @eh.templatekeyword('instabilities')
> +    @eh.templatekeyword(b'instabilities')
>      def showinstabilities(**args):
>          """List of strings. Evolution instabilities affecting the
> changeset
>          (zero or more of "orphan", "content-divergent" or
> "phase-divergent")."""
> -        ctx = args['ctx']
> -        return templatekw.showlist('instability', ctx.instabilities(),
> args,
> -                                   plural='instabilities')
> +        ctx = args[b'ctx']
> +        return templatekw.showlist(b'instability', ctx.instabilities(),
> args,
> +                                   plural=b'instabilities')
>
> -    @eh.templatekeyword('troubles')
> +    @eh.templatekeyword(b'troubles')
>      def showtroubles(**args):
> -        ctx = args['ctx']
> -        return templatekw.showlist('trouble', ctx.instabilities(), args,
> -                                   plural='troubles')
> +        ctx = args[b'ctx']
> +        return templatekw.showlist(b'trouble', ctx.instabilities(), args,
> +                                   plural=b'troubles')
>
> -templatekw.keywords["precursors"] = templatekw.showpredecessors
> +templatekw.keywords[b"precursors"] = templatekw.showpredecessors
>
>  def closestsuccessors(repo, nodeid):
>      """ returns the closest visible successors sets instead.
>      """
>      return directsuccessorssets(repo, nodeid)
>
> -templatekw.keywords["successors"] = templatekw.showsuccessorssets
> +templatekw.keywords[b"successors"] = templatekw.showsuccessorssets
>
>  def _getusername(ui):
>      """the default username in the config or None"""
> @@ -74,24 +74,24 @@
>      """ Returns a dict with the default templates for obs fate
>      """
>      # Prepare templates
> -    verbtempl = '{verb}'
> -    usertempl = '{if(users, " by {join(users, ", ")}")}'
> -    succtempl = '{if(successors, " as ")}{successors}' # Bypass if
> limitation
> -    datetempleq = ' (at {min_date|isodate})'
> -    datetemplnoteq = ' (between {min_date|isodate} and
> {max_date|isodate})'
> -    datetempl = '{if(max_date, "{ifeq(min_date, max_date, "%s",
> "%s")}")}' % (datetempleq, datetemplnoteq)
> +    verbtempl = b'{verb}'
> +    usertempl = b'{if(users, " by {join(users, ", ")}")}'
> +    succtempl = b'{if(successors, " as ")}{successors}' # Bypass if
> limitation
> +    datetempleq = b' (at {min_date|isodate})'
> +    datetemplnoteq = b' (between {min_date|isodate} and
> {max_date|isodate})'
> +    datetempl = b'{if(max_date, "{ifeq(min_date, max_date, "%s",
> "%s")}")}' % (datetempleq, datetemplnoteq)
>
>      optionalusertempl = usertempl
>      username = _getusername(ui)
>      if username is not None:
> -        optionalusertempl = ('{ifeq(join(users, "\0"), "%s", "", "%s")}'
> +        optionalusertempl = (b'{ifeq(join(users, "\0"), "%s", "", "%s")}'
>                               % (username, usertempl))
>
>      # Assemble them
>      return {
> -        'obsfate_quiet': verbtempl + succtempl,
> -        'obsfate': verbtempl + succtempl + optionalusertempl,
> -        'obsfate_verbose': verbtempl + succtempl + usertempl + datetempl,
> +        b'obsfate_quiet': verbtempl + succtempl,
> +        b'obsfate': verbtempl + succtempl + optionalusertempl,
> +        b'obsfate_verbose': verbtempl + succtempl + usertempl + datetempl,
>      }
>
>  def obsfatedata(repo, ctx):
> @@ -141,18 +141,18 @@
>      line = []
>
>      # Verb
> -    line.append(obsfateline['verb'])
> +    line.append(obsfateline[b'verb'])
>
>      # Successors
> -    successors = obsfateline["successors"]
> +    successors = obsfateline[b"successors"]
>
>      if successors:
>          fmtsuccessors = map(lambda s: s[:12], successors)
> -        line.append(" as %s" % ", ".join(fmtsuccessors))
> +        line.append(b" as %s" % b", ".join(fmtsuccessors))
>
>      # Users
> -    if (verbose or normal) and 'users' in obsfateline:
> -        users = obsfateline['users']
> +    if (verbose or normal) and b'users' in obsfateline:
> +        users = obsfateline[b'users']
>
>          if not verbose:
>              # If current user is the only user, do not show anything if
> not in
> @@ -162,24 +162,24 @@
>                  users = None
>
>          if users:
> -            line.append(" by %s" % ", ".join(users))
> +            line.append(b" by %s" % b", ".join(users))
>
>      # Date
>      if verbose:
> -        min_date = obsfateline['min_date']
> -        max_date = obsfateline['max_date']
> +        min_date = obsfateline[b'min_date']
> +        max_date = obsfateline[b'max_date']
>
>          if min_date == max_date:
> -            fmtmin_date = util.datestr(min_date, '%Y-%m-%d %H:%M %1%2')
> -            line.append(" (at %s)" % fmtmin_date)
> +            fmtmin_date = util.datestr(min_date, b'%Y-%m-%d %H:%M %1%2')
> +            line.append(b" (at %s)" % fmtmin_date)
>          else:
> -            fmtmin_date = util.datestr(min_date, '%Y-%m-%d %H:%M %1%2')
> -            fmtmax_date = util.datestr(max_date, '%Y-%m-%d %H:%M %1%2')
> -            line.append(" (between %s and %s)" % (fmtmin_date,
> fmtmax_date))
> +            fmtmin_date = util.datestr(min_date, b'%Y-%m-%d %H:%M %1%2')
> +            fmtmax_date = util.datestr(max_date, b'%Y-%m-%d %H:%M %1%2')
> +            line.append(b" (between %s and %s)" % (fmtmin_date,
> fmtmax_date))
>
> -    return "".join(line)
> +    return b"".join(line)
>
> -def obsfateprinter(obsfate, ui, prefix=""):
> +def obsfateprinter(obsfate, ui, prefix=b""):
>      lines = []
>      for raw in obsfate:
>          lines.append(obsfatelineprinter(raw, ui))
> @@ -187,16 +187,16 @@
>      if prefix:
>          lines = [prefix + line for line in lines]
>
> -    return "\n".join(lines)
> +    return b"\n".join(lines)
>
> -if not util.safehasattr(templatekw, 'obsfateverb'): # <= hg-4.5
> -    @eh.templatekeyword("obsfatedata")
> +if not util.safehasattr(templatekw, b'obsfateverb'): # <= hg-4.5
> +    @eh.templatekeyword(b"obsfatedata")
>      def showobsfatedata(repo, ctx, **args):
>          # Get the needed obsfate data
>          values = obsfatedata(repo, ctx)
>
>          if values is None:
> -            return templatekw.showlist("obsfatedata", [], args)
> +            return templatekw.showlist(b"obsfatedata", [], args)
>
>          return _showobsfatedata(repo, ctx, values, **args)
>
> @@ -207,36 +207,36 @@
>          # As we can't do something like
>          # "{join(map(nodeshort, successors), ', '}" in template, manually
>          # create a correct textual representation
> -        gen = ', '.join(n[:12] for n in raw['successors'])
> +        gen = b', '.join(n[:12] for n in raw[b'successors'])
>
> -        makemap = lambda x: {'successor': x}
> -        joinfmt = lambda d: "%s" % d['successor']
> -        raw['successors'] = templatekw._hybrid(gen, raw['successors'],
> makemap,
> -                                               joinfmt)
> +        makemap = lambda x: {b'successor': x}
> +        joinfmt = lambda d: b"%s" % d[b'successor']
> +        raw[b'successors'] = templatekw._hybrid(gen, raw[b'successors'],
> makemap,
> +                                                joinfmt)
>
>      # And then format them
>      # Insert default obsfate templates
> -    args['templ'].cache.update(obsfatedefaulttempl(repo.ui))
> +    args[b'templ'].cache.update(obsfatedefaulttempl(repo.ui))
>
>      if repo.ui.quiet:
> -        name = "obsfate_quiet"
> +        name = b"obsfate_quiet"
>      elif repo.ui.verbose:
> -        name = "obsfate_verbose"
> +        name = b"obsfate_verbose"
>      elif repo.ui.debugflag:
> -        name = "obsfate_debug"
> +        name = b"obsfate_debug"
>      else:
> -        name = "obsfate"
> +        name = b"obsfate"
>
>      # Format a single value
>      def fmt(d):
>          nargs = args.copy()
>          nargs.update(d[name])
> -        templ = args['templ']
> +        templ = args[b'templ']
>          # HG 4.6
>          if hasattr(templ, "generate"):
>              return templ.generate(name, nargs)
>          else:
> -            return args['templ'](name, **nargs)
> +            return args[b'templ'](name, **nargs)
>
>      # Generate a good enough string representation using templater
>      gen = []
> @@ -251,8 +251,8 @@
>          except StopIteration:
>              pass
>
> -        gen.append("".join(chunkstr))
> -    gen = "; ".join(gen)
> +        gen.append(b"".join(chunkstr))
> +    gen = b"; ".join(gen)
>
>      return templatekw._hybrid(gen, values, lambda x: {name: x}, fmt)
>
> diff --git a/hgext3rd/evolve/thirdparty/cbor.py
> b/hgext3rd/evolve/thirdparty/cbor.py
> --- a/hgext3rd/evolve/thirdparty/cbor.py
> +++ b/hgext3rd/evolve/thirdparty/cbor.py
> @@ -79,23 +79,23 @@
>  CBOR_TAG_MIME = 36 # following text is MIME message, headers, separators
> and all
>  CBOR_TAG_CBOR_FILEHEADER = 55799 # can open a file with 0xd9d9f7
>
> -_CBOR_TAG_BIGNUM_BYTES = struct.pack('B', CBOR_TAG | CBOR_TAG_BIGNUM)
> +_CBOR_TAG_BIGNUM_BYTES = struct.pack(b'B', CBOR_TAG | CBOR_TAG_BIGNUM)
>
>
>  def dumps_int(val):
> -    "return bytes representing int val in CBOR"
> +    b"return bytes representing int val in CBOR"
>      if val >= 0:
>          # CBOR_UINT is 0, so I'm lazy/efficient about not OR-ing it in.
>          if val <= 23:
> -            return struct.pack('B', val)
> +            return struct.pack(b'B', val)
>          if val <= 0x0ff:
> -            return struct.pack('BB', CBOR_UINT8_FOLLOWS, val)
> +            return struct.pack(b'BB', CBOR_UINT8_FOLLOWS, val)
>          if val <= 0x0ffff:
> -            return struct.pack('!BH', CBOR_UINT16_FOLLOWS, val)
> +            return struct.pack(b'!BH', CBOR_UINT16_FOLLOWS, val)
>          if val <= 0x0ffffffff:
> -            return struct.pack('!BI', CBOR_UINT32_FOLLOWS, val)
> +            return struct.pack(b'!BI', CBOR_UINT32_FOLLOWS, val)
>          if val <= 0x0ffffffffffffffff:
> -            return struct.pack('!BQ', CBOR_UINT64_FOLLOWS, val)
> +            return struct.pack(b'!BQ', CBOR_UINT64_FOLLOWS, val)
>          outb = _dumps_bignum_to_bytearray(val)
>          return _CBOR_TAG_BIGNUM_BYTES + _encode_type_num(CBOR_BYTES,
> len(outb)) + outb
>      val = -1 - val
> @@ -119,28 +119,28 @@
>
>
>  def dumps_float(val):
> -    return struct.pack("!Bd", CBOR_FLOAT64, val)
> +    return struct.pack(b"!Bd", CBOR_FLOAT64, val)
>
>
> -_CBOR_TAG_NEGBIGNUM_BYTES = struct.pack('B', CBOR_TAG |
> CBOR_TAG_NEGBIGNUM)
> +_CBOR_TAG_NEGBIGNUM_BYTES = struct.pack(b'B', CBOR_TAG |
> CBOR_TAG_NEGBIGNUM)
>
>
>  def _encode_type_num(cbor_type, val):
>      """For some CBOR primary type [0..7] and an auxiliary unsigned
> number, return CBOR encoded bytes"""
>      assert val >= 0
>      if val <= 23:
> -        return struct.pack('B', cbor_type | val)
> +        return struct.pack(b'B', cbor_type | val)
>      if val <= 0x0ff:
> -        return struct.pack('BB', cbor_type | CBOR_UINT8_FOLLOWS, val)
> +        return struct.pack(b'BB', cbor_type | CBOR_UINT8_FOLLOWS, val)
>      if val <= 0x0ffff:
> -        return struct.pack('!BH', cbor_type | CBOR_UINT16_FOLLOWS, val)
> +        return struct.pack(b'!BH', cbor_type | CBOR_UINT16_FOLLOWS, val)
>      if val <= 0x0ffffffff:
> -        return struct.pack('!BI', cbor_type | CBOR_UINT32_FOLLOWS, val)
> +        return struct.pack(b'!BI', cbor_type | CBOR_UINT32_FOLLOWS, val)
>      if (((cbor_type == CBOR_NEGINT) and (val <= 0x07fffffffffffffff)) or
>          ((cbor_type != CBOR_NEGINT) and (val <= 0x0ffffffffffffffff))):
> -        return struct.pack('!BQ', cbor_type | CBOR_UINT64_FOLLOWS, val)
> +        return struct.pack(b'!BQ', cbor_type | CBOR_UINT64_FOLLOWS, val)
>      if cbor_type != CBOR_NEGINT:
> -        raise Exception("value too big for CBOR unsigned number:
> {0!r}".format(val))
> +        raise Exception(b"value too big for CBOR unsigned number:
> {0!r}".format(val))
>      outb = _dumps_bignum_to_bytearray(val)
>      return _CBOR_TAG_NEGBIGNUM_BYTES + _encode_type_num(CBOR_BYTES,
> len(outb)) + outb
>
> @@ -193,7 +193,7 @@
>                  parts.append(dumps(k, sort_keys=sort_keys))
>                  parts.append(dumps(v, sort_keys=sort_keys))
>          else:
> -            for k,v in d.iteritems():
> +            for k,v in d.items():
>                  parts.append(dumps(k, sort_keys=sort_keys))
>                  parts.append(dumps(v, sort_keys=sort_keys))
>          return b''.join(parts)
> @@ -201,8 +201,8 @@
>
>  def dumps_bool(b):
>      if b:
> -        return struct.pack('B', CBOR_TRUE)
> -    return struct.pack('B', CBOR_FALSE)
> +        return struct.pack(b'B', CBOR_TRUE)
> +    return struct.pack(b'B', CBOR_FALSE)
>
>
>  def dumps_tag(t, sort_keys=False):
> @@ -223,7 +223,7 @@
>
>  def dumps(ob, sort_keys=False):
>      if ob is None:
> -        return struct.pack('B', CBOR_NULL)
> +        return struct.pack(b'B', CBOR_NULL)
>      if isinstance(ob, bool):
>          return dumps_bool(ob)
>      if _is_stringish(ob):
> @@ -239,7 +239,7 @@
>          return dumps_int(ob)
>      if isinstance(ob, Tag):
>          return dumps_tag(ob, sort_keys=sort_keys)
> -    raise Exception("don't know how to cbor serialize object of type %s",
> type(ob))
> +    raise Exception(b"don't know how to cbor serialize object of type
> %s", type(ob))
>
>
>  # same basic signature as json.dump, but with no options (yet)
> @@ -260,7 +260,7 @@
>          self.value = value
>
>      def __repr__(self):
> -        return "Tag({0!r}, {1!r})".format(self.tag, self.value)
> +        return b"Tag({0!r}, {1!r})".format(self.tag, self.value)
>
>      def __eq__(self, other):
>          if not isinstance(other, Tag):
> @@ -273,7 +273,7 @@
>      Parse CBOR bytes and return Python objects.
>      """
>      if data is None:
> -        raise ValueError("got None for buffer to decode in loads")
> +        raise ValueError(b"got None for buffer to decode in loads")
>      fp = StringIO(data)
>      return _loads(fp)[0]
>
> @@ -296,22 +296,22 @@
>          aux = tag_aux
>      elif tag_aux == CBOR_UINT8_FOLLOWS:
>          data = fp.read(1)
> -        aux = struct.unpack_from("!B", data, 0)[0]
> +        aux = struct.unpack_from(b"!B", data, 0)[0]
>          bytes_read += 1
>      elif tag_aux == CBOR_UINT16_FOLLOWS:
>          data = fp.read(2)
> -        aux = struct.unpack_from("!H", data, 0)[0]
> +        aux = struct.unpack_from(b"!H", data, 0)[0]
>          bytes_read += 2
>      elif tag_aux == CBOR_UINT32_FOLLOWS:
>          data = fp.read(4)
> -        aux = struct.unpack_from("!I", data, 0)[0]
> +        aux = struct.unpack_from(b"!I", data, 0)[0]
>          bytes_read += 4
>      elif tag_aux == CBOR_UINT64_FOLLOWS:
>          data = fp.read(8)
> -        aux = struct.unpack_from("!Q", data, 0)[0]
> +        aux = struct.unpack_from(b"!Q", data, 0)[0]
>          bytes_read += 8
>      else:
> -        assert tag_aux == CBOR_VAR_FOLLOWS, "bogus tag {0:02x}".format(tb)
> +        assert tag_aux == CBOR_VAR_FOLLOWS, b"bogus tag
> {0:02x}".format(tb)
>          aux = None
>
>      return tag, tag_aux, aux, bytes_read
> @@ -385,9 +385,9 @@
>          return ob, bytes_read
>
>  def _loads(fp, limit=None, depth=0, returntags=False):
> -    "return (object, bytes read)"
> +    b"return (object, bytes read)"
>      if depth > _MAX_DEPTH:
> -        raise Exception("hit CBOR loads recursion depth limit")
> +        raise Exception(b"hit CBOR loads recursion depth limit")
>
>      tb = _read_byte(fp)
>
> @@ -397,16 +397,16 @@
>      # Some special cases of CBOR_7 best handled by special struct.unpack
> logic here
>      if tb == CBOR_FLOAT16:
>          data = fp.read(2)
> -        hibyte, lowbyte = struct.unpack_from("BB", data, 0)
> +        hibyte, lowbyte = struct.unpack_from(b"BB", data, 0)
>          exp = (hibyte >> 2) & 0x1F
>          mant = ((hibyte & 0x03) << 8) | lowbyte
>          if exp == 0:
>              val = mant * (2.0 ** -24)
>          elif exp == 31:
>              if mant == 0:
> -                val = float('Inf')
> +                val = float(b'Inf')
>              else:
> -                val = float('NaN')
> +                val = float(b'NaN')
>          else:
>              val = (mant + 1024.0) * (2 ** (exp - 25))
>          if hibyte & 0x80:
> @@ -414,11 +414,11 @@
>          return (val, 3)
>      elif tb == CBOR_FLOAT32:
>          data = fp.read(4)
> -        pf = struct.unpack_from("!f", data, 0)
> +        pf = struct.unpack_from(b"!f", data, 0)
>          return (pf[0], 5)
>      elif tb == CBOR_FLOAT64:
>          data = fp.read(8)
> -        pf = struct.unpack_from("!d", data, 0)
> +        pf = struct.unpack_from(b"!d", data, 0)
>          return (pf[0], 9)
>
>      tag, tag_aux, aux, bytes_read = _tag_aux(fp, tb)
> @@ -461,7 +461,7 @@
>              return (None, bytes_read)
>          if tb == CBOR_UNDEFINED:
>              return (None, bytes_read)
> -        raise ValueError("unknown cbor tag 7 byte: {:02x}".format(tb))
> +        raise ValueError(b"unknown cbor tag 7 byte: {:02x}".format(tb))
>
>
>  def loads_bytes(fp, aux, btag=CBOR_BYTES):
> @@ -481,7 +481,7 @@
>              total_bytes_read += 1
>              break
>          tag, tag_aux, aux, bytes_read = _tag_aux(fp, tb)
> -        assert tag == btag, 'variable length value contains unexpected
> component'
> +        assert tag == btag, b'variable length value contains unexpected
> component'
>          ob = fp.read(aux)
>          chunklist.append(ob)
>          total_bytes_read += bytes_read + aux
> diff --git a/hgext3rd/evolve/utility.py b/hgext3rd/evolve/utility.py
> --- a/hgext3rd/evolve/utility.py
> +++ b/hgext3rd/evolve/utility.py
> @@ -17,20 +17,20 @@
>      compat,
>  )
>
> -shorttemplate = "[{label('evolve.rev', rev)}] {desc|firstline}\n"
> +shorttemplate = b"[{label('evolve.rev', rev)}] {desc|firstline}\n"
>  stacktemplate = """[{label('evolve.rev', if(topicidx, "s{topicidx}",
> rev))}] {desc|firstline}\n"""
>
>  def obsexcmsg(ui, message, important=False):
> -    verbose = ui.configbool('experimental',
> 'verbose-obsolescence-exchange')
> +    verbose = ui.configbool(b'experimental',
> b'verbose-obsolescence-exchange')
>      if verbose:
> -        message = 'OBSEXC: ' + message
> +        message = b'OBSEXC: ' + message
>      if important or verbose:
>          ui.status(message)
>
>  def obsexcprg(ui, *args, **kwargs):
> -    topic = 'obsmarkers exchange'
> -    if ui.configbool('experimental', 'verbose-obsolescence-exchange'):
> -        topic = 'OBSEXC'
> +    topic = b'obsmarkers exchange'
> +    if ui.configbool(b'experimental', b'verbose-obsolescence-exchange'):
> +        topic = b'OBSEXC'
>      compat.progress(ui, topic, *args, **kwargs)
>
>  def filterparents(parents):
> @@ -50,28 +50,28 @@
>  def shouldwarmcache(repo, tr):
>      configbool = repo.ui.configbool
>      config = repo.ui.config
> -    desc = getattr(tr, 'desc', '')
> +    desc = getattr(tr, 'desc', b'')
>
>      autocase = False
>      if tr is None and not getattr(repo, '_destroying', False):
>          autocase = True
> -    elif desc.startswith('serve'):
> +    elif desc.startswith(b'serve'):
>          autocase = True
> -    elif desc.startswith('push') and not desc.startswith('push-response'):
> +    elif desc.startswith(b'push') and not
> desc.startswith(b'push-response'):
>          autocase = True
>
> -    autocache = config('experimental', 'obshashrange.warm-cache',
> -                       'auto') == 'auto'
> +    autocache = config(b'experimental', b'obshashrange.warm-cache',
> +                       b'auto') == b'auto'
>      if autocache:
>          warm = autocase
>      else:
>          # note: we should not get to the default case
> -        warm = configbool('experimental', 'obshashrange.warm-cache')
> -    if not configbool('experimental', 'obshashrange'):
> +        warm = configbool(b'experimental', b'obshashrange.warm-cache')
> +    if not configbool(b'experimental', b'obshashrange'):
>          return False
>      if not warm:
>          return False
> -    maxrevs = repo.ui.configint('experimental', 'obshashrange.max-revs')
> +    maxrevs = repo.ui.configint(b'experimental', b'obshashrange.max-revs')
>      if maxrevs is not None and maxrevs < len(repo.unfiltered()):
>          return False
>      return True
> @@ -123,8 +123,8 @@
>      newer = obsutil.successorssets(repo, obs.node())
>      # search of a parent which is not killed
>      while not newer:
> -        ui.debug("stabilize target %s is plain dead,"
> -                 " trying to stabilize on its parent\n" %
> +        ui.debug(b"stabilize target %s is plain dead,"
> +                 b" trying to stabilize on its parent\n" %
>                   obs)
>          obs = obs.parents()[0]
>          newer = obsutil.successorssets(repo, obs.node())
> @@ -141,7 +141,7 @@
>                  for successorsset in exc.successorssets
>                  for node in successorsset}
>
> -def revselectionprompt(ui, repo, revs, customheader=""):
> +def revselectionprompt(ui, repo, revs, customheader=b""):
>      """function to prompt user to choose a revision from all the revs and
> return
>      that revision for further tasks
>
> @@ -161,29 +161,29 @@
>      if not ui.interactive():
>          return None
>
> -    promptmsg = customheader + "\n"
> +    promptmsg = customheader + b"\n"
>      for idx, rev in enumerate(revs):
>          curctx = repo[rev]
> -        revmsg = "%d: [%s] %s\n" % (idx + 1, curctx,
> -                                    curctx.description().split("\n")[0])
> +        revmsg = b"%d: [%s] %s\n" % (idx + 1, curctx,
> +                                     curctx.description().split(b"\n")[0])
>          promptmsg += revmsg
>
> -    promptmsg += _("q: quit the prompt\n")
> -    promptmsg += _("enter the index of the revision you want to select:")
> +    promptmsg += _(b"q: quit the prompt\n")
> +    promptmsg += _(b"enter the index of the revision you want to select:")
>      idxselected = ui.prompt(promptmsg)
>
>      intidx = None
>      try:
>          intidx = int(idxselected)
>      except ValueError:
> -        if idxselected == 'q':
> +        if idxselected == b'q':
>              return None
> -        ui.write_err(_("invalid value '%s' entered for index\n") %
> idxselected)
> +        ui.write_err(_(b"invalid value '%s' entered for index\n") %
> idxselected)
>          return None
>
>      if intidx > len(revs) or intidx <= 0:
>          # we can make this error message better
> -        ui.write_err(_("invalid value '%d' entered for index\n") % intidx)
> +        ui.write_err(_(b"invalid value '%d' entered for index\n") %
> intidx)
>          return None
>
>      return revs[intidx - 1]
> diff --git a/hgext3rd/pullbundle.py b/hgext3rd/pullbundle.py
> --- a/hgext3rd/pullbundle.py
> +++ b/hgext3rd/pullbundle.py
> @@ -92,10 +92,10 @@
>
>  from mercurial.i18n import _
>
> -__version__ = '0.1.1'
> -testedwith = '4.4 4.5 4.6 4.7.1'
> -minimumhgversion = '4.4'
> -buglink = 'https://bz.mercurial-scm.org/'
> +__version__ = b'0.1.1'
> +testedwith = b'4.4 4.5 4.6 4.7.1'
> +minimumhgversion = b'4.4'
> +buglink = b'https://bz.mercurial-scm.org/'
>
>  cmdtable = {}
>  command = registrar.command(cmdtable)
> @@ -103,14 +103,14 @@
>  configtable = {}
>  configitem = registrar.configitem(configtable)
>
> -configitem('pullbundle', 'cache-directory',
> +configitem(b'pullbundle', b'cache-directory',
>             default=None,
>  )
>
>  # generic wrapping
>
>  def uisetup(ui):
> -    exchange.getbundle2partsmapping['changegroup'] =
> _getbundlechangegrouppart
> +    exchange.getbundle2partsmapping[b'changegroup'] =
> _getbundlechangegrouppart
>
>  def _getbundlechangegrouppart(bundler, repo, source, bundlecaps=None,
>                                b2caps=None, heads=None, common=None,
> **kwargs):
> @@ -118,13 +118,13 @@
>      if not kwargs.get(r'cg', True):
>          return
>
> -    version = '01'
> -    cgversions = b2caps.get('changegroup')
> +    version = b'01'
> +    cgversions = b2caps.get(b'changegroup')
>      if cgversions:  # 3.1 and 3.2 ship with an empty value
>          cgversions = [v for v in cgversions
>                        if v in changegroup.supportedoutgoingversions(repo)]
>          if not cgversions:
> -            raise ValueError(_('no common changegroup version'))
> +            raise ValueError(_(b'no common changegroup version'))
>          version = max(cgversions)
>
>      outgoing = exchange._computeoutgoing(repo, heads, common)
> @@ -145,20 +145,20 @@
>      # END OF ALTERED PART
>
>      if kwargs.get(r'narrow', False) and (include or exclude):
> -        narrowspecpart = bundler.newpart('narrow:spec')
> +        narrowspecpart = bundler.newpart(b'narrow:spec')
>          if include:
>              narrowspecpart.addparam(
> -                'include', '\n'.join(include), mandatory=True)
> +                b'include', b'\n'.join(include), mandatory=True)
>          if exclude:
>              narrowspecpart.addparam(
> -                'exclude', '\n'.join(exclude), mandatory=True)
> +                b'exclude', b'\n'.join(exclude), mandatory=True)
>
>  def makeallcgpart(newpart, repo, outgoing, version, source,
>                    bundlecaps, filematcher, cgversions):
>
>      pullbundle = not filematcher
> -    if pullbundle and not util.safehasattr(repo, 'stablerange'):
> -        repo.ui.warn('pullbundle: required extension "evolve" are
> missing, skipping pullbundle\n')
> +    if pullbundle and not util.safehasattr(repo, b'stablerange'):
> +        repo.ui.warn(b'pullbundle: required extension "evolve" are
> missing, skipping pullbundle\n')
>          pullbundle = False
>      if filematcher:
>          makeonecgpart(newpart, repo, None, outgoing, version, source,
> bundlecaps,
> @@ -167,8 +167,8 @@
>          start = util.timer()
>          slices = sliceoutgoing(repo, outgoing)
>          end = util.timer()
> -        msg = _('pullbundle-cache: "missing" set sliced into %d subranges
> '
> -                'in %s seconds\n')
> +        msg = _(b'pullbundle-cache: "missing" set sliced into %d
> subranges '
> +                b'in %s seconds\n')
>          repo.ui.write(msg % (len(slices), end - start))
>          for sliceid, sliceout in slices:
>              makeonecgpart(newpart, repo, sliceid, sliceout, version,
> source, bundlecaps,
> @@ -192,7 +192,7 @@
>      missingheads = [rev(n) for n in sorted(outgoing.missingheads,
> reverse=True)]
>      for head in missingheads:
>          localslices = []
> -        localmissing = set(repo.revs('%ld and ::%d', missingrevs, head))
> +        localmissing = set(repo.revs(b'%ld and ::%d', missingrevs, head))
>          thisrunmissing = localmissing.copy()
>          while localmissing:
>              slicerevs = []
> @@ -207,11 +207,11 @@
>              missingrevs.difference_update(slicerevs)
>              localmissing.difference_update(slicerevs)
>              if localmissing:
> -                heads = list(repo.revs('heads(%ld)', localmissing))
> +                heads = list(repo.revs(b'heads(%ld)', localmissing))
>                  heads.sort(key=node)
>                  head = heads.pop()
>                  if heads:
> -                    thisrunmissing = repo.revs('%ld and only(%d, %ld)',
> +                    thisrunmissing = repo.revs(b'%ld and only(%d, %ld)',
>                                                 localmissing,
>                                                 head,
>                                                 heads)
> @@ -220,15 +220,15 @@
>          if DEBUG:
>              for s in reversed(ss):
>                  ms -= set(s)
> -                missingbase = repo.revs('parents(%ld) and %ld', s, ms)
> +                missingbase = repo.revs(b'parents(%ld) and %ld', s, ms)
>                  if missingbase:
> -                    repo.ui.write_err('!!! rev bundled while parents
> missing\n')
> -                    repo.ui.write_err('    parent: %s\n' %
> list(missingbase))
> -                    pb = repo.revs('%ld and children(%ld)', s,
> missingbase)
> -                    repo.ui.write_err('    children: %s\n' % list(pb))
> -                    h = repo.revs('heads(%ld)', s)
> -                    repo.ui.write_err('    heads: %s\n' % list(h))
> -                    raise error.ProgrammingError('issuing a range before
> its parents')
> +                    repo.ui.write_err(b'!!! rev bundled while parents
> missing\n')
> +                    repo.ui.write_err(b'    parent: %s\n' %
> list(missingbase))
> +                    pb = repo.revs(b'%ld and children(%ld)', s,
> missingbase)
> +                    repo.ui.write_err(b'    children: %s\n' % list(pb))
> +                    h = repo.revs(b'heads(%ld)', s)
> +                    repo.ui.write_err(b'    heads: %s\n' % list(h))
> +                    raise error.ProgrammingError(b'issuing a range before
> its parents')
>
>          for s in reversed(localslices):
>              allslices.extend(s)
> @@ -381,8 +381,8 @@
>  # changegroup part construction
>
>  def _changegroupinfo(repo, nodes, source):
> -    if repo.ui.verbose or source == 'bundle':
> -        repo.ui.status(_("%d changesets found\n") % len(nodes))
> +    if repo.ui.verbose or source == b'bundle':
> +        repo.ui.status(_(b"%d changesets found\n") % len(nodes))
>
>  def _makenewstream(newpart, repo, outgoing, version, source,
>                     bundlecaps, filematcher, cgversions):
> @@ -408,23 +408,23 @@
>  def _makepartfromstream(newpart, repo, cgstream, nbchanges, version):
>      # same as upstream code
>
> -    part = newpart('changegroup', data=cgstream)
> +    part = newpart(b'changegroup', data=cgstream)
>      if version:
> -        part.addparam('version', version)
> +        part.addparam(b'version', version)
>
> -    part.addparam('nbchanges', '%d' % nbchanges,
> +    part.addparam(b'nbchanges', b'%d' % nbchanges,
>                    mandatory=False)
>
> -    if 'treemanifest' in repo.requirements:
> -        part.addparam('treemanifest', '1')
> +    if b'treemanifest' in repo.requirements:
> +        part.addparam(b'treemanifest', b'1')
>
>  # cache management
>
>  def cachedir(repo):
> -    cachedir = repo.ui.config('pullbundle', 'cache-directory')
> +    cachedir = repo.ui.config(b'pullbundle', b'cache-directory')
>      if cachedir is not None:
>          return cachedir
> -    return repo.cachevfs.join('pullbundles')
> +    return repo.cachevfs.join(b'pullbundles')
>
>  def getcache(repo, bundlename):
>      cdir = cachedir(repo)
> @@ -436,7 +436,7 @@
>      # opening too many file will not work.
>
>      def data():
> -        with open(bundlepath, 'rb') as fd:
> +        with open(bundlepath, b'rb') as fd:
>              for chunk in util.filechunkiter(fd):
>                  yield chunk
>      return data()
> @@ -454,7 +454,7 @@
>              cachefile.write(chunk)
>              yield chunk
>
> -BUNDLEMASK = "%s-%s-%010iskip-%010isize.hg"
> +BUNDLEMASK = b"%s-%s-%010iskip-%010isize.hg"
>
>  def makeonecgpart(newpart, repo, rangeid, outgoing, version, source,
>                    bundlecaps, filematcher, cgversions):
> @@ -472,19 +472,19 @@
>              cgstream = cachewriter(repo, bundlename, partdata[0])
>              partdata = (cgstream,) + partdata[1:]
>      else:
> -        if repo.ui.verbose or source == 'bundle':
> -            repo.ui.status(_("%d changesets found in caches\n") %
> nbchanges)
> +        if repo.ui.verbose or source == b'bundle':
> +            repo.ui.status(_(b"%d changesets found in caches\n") %
> nbchanges)
>          pversion = None
>          if cgversions:
>              pversion = version
>          partdata = (cachedata, nbchanges, pversion)
>      return _makepartfromstream(newpart, repo, *partdata)
>
> -@command('debugpullbundlecacheoverlap',
> -         [('', 'count', 100, _('of "client" pulling')),
> -          ('', 'min-cache', 1, _('minimum size of cached bundle')),
> -         ],
> -         _('hg debugpullbundlecacheoverlap [--client 100] REVSET'))
> +@command(b'debugpullbundlecacheoverlap',
> +         [(b'', b'count', 100, _(b'of "client" pulling')),
> +          (b'', b'min-cache', 1, _(b'minimum size of cached bundle')),
> +          ],
> +         _(b'hg debugpullbundlecacheoverlap [--client 100] REVSET'))
>  def debugpullbundlecacheoverlap(ui, repo, *revs, **opts):
>      '''Display statistic on bundle cache hit
>
> @@ -494,21 +494,21 @@
>      '''
>      actionrevs = scmutil.revrange(repo, revs)
>      if not revs:
> -        raise error.Abort('No revision selected')
> -    count = opts['count']
> -    min_cache = opts['min_cache']
> +        raise error.Abort(b'No revision selected')
> +    count = opts[b'count']
> +    min_cache = opts[b'min_cache']
>
>      bundlehits = collections.defaultdict(lambda: 0)
>      pullstats = []
>
>      rlen = lambda rangeid: repo.stablerange.rangelength(repo, rangeid)
>
> -    repo.ui.write("gathering %d sample pulls within %d revisions\n"
> +    repo.ui.write(b"gathering %d sample pulls within %d revisions\n"
>                    % (count, len(actionrevs)))
>      if 1 < min_cache:
> -        repo.ui.write("  not caching ranges smaller than %d changesets\n"
> % min_cache)
> +        repo.ui.write(b"  not caching ranges smaller than %d
> changesets\n" % min_cache)
>      for i in xrange(count):
> -        repo.ui.progress('gathering data', i, total=count)
> +        repo.ui.progress(b'gathering data', i, total=count)
>          outgoing = takeonesample(repo, actionrevs)
>          ranges = sliceoutgoing(repo, outgoing)
>          hitranges = 0
> @@ -532,7 +532,7 @@
>                   hitranges,
>                   )
>          pullstats.append(stats)
> -    repo.ui.progress('gathering data', None)
> +    repo.ui.progress(b'gathering data', None)
>
>      sizes = []
>      changesmissing = []
> @@ -563,36 +563,36 @@
>          cachedhits.append(hits)
>
>      sizesdist = distribution(sizes)
> -    repo.ui.write(fmtdist('pull size', sizesdist))
> +    repo.ui.write(fmtdist(b'pull size', sizesdist))
>
>      changesmissingdist = distribution(changesmissing)
> -    repo.ui.write(fmtdist('non-cached changesets', changesmissingdist))
> +    repo.ui.write(fmtdist(b'non-cached changesets', changesmissingdist))
>
>      changesratiodist = distribution(changesratio)
> -    repo.ui.write(fmtdist('ratio of cached changesets', changesratiodist))
> +    repo.ui.write(fmtdist(b'ratio of cached changesets',
> changesratiodist))
>
>      bundlecountdist = distribution(bundlecount)
> -    repo.ui.write(fmtdist('bundle count', bundlecountdist))
> +    repo.ui.write(fmtdist(b'bundle count', bundlecountdist))
>
>      rangesratiodist = distribution(rangesratio)
> -    repo.ui.write(fmtdist('ratio of cached bundles', rangesratiodist))
> +    repo.ui.write(fmtdist(b'ratio of cached bundles', rangesratiodist))
>
> -    repo.ui.write('changesets served:\n')
> -    repo.ui.write('  total:      %7d\n' % totalchanges)
> -    repo.ui.write('  from cache: %7d (%2d%%)\n'
> +    repo.ui.write(b'changesets served:\n')
> +    repo.ui.write(b'  total:      %7d\n' % totalchanges)
> +    repo.ui.write(b'  from cache: %7d (%2d%%)\n'
>                    % (totalcached, (totalcached * 100 // totalchanges)))
> -    repo.ui.write('  bundle:     %7d\n' % sum(bundlecount))
> +    repo.ui.write(b'  bundle:     %7d\n' % sum(bundlecount))
>
>      cachedsizesdist = distribution(cachedsizes)
> -    repo.ui.write(fmtdist('size of cached bundles', cachedsizesdist))
> +    repo.ui.write(fmtdist(b'size of cached bundles', cachedsizesdist))
>
>      cachedhitsdist = distribution(cachedhits)
> -    repo.ui.write(fmtdist('hit on cached bundles', cachedhitsdist))
> +    repo.ui.write(fmtdist(b'hit on cached bundles', cachedhitsdist))
>
>  def takeonesample(repo, revs):
>      node = repo.changelog.node
>      pulled = random.sample(revs, max(4, len(revs) // 1000))
> -    pulled = repo.revs('%ld::%ld', pulled, pulled)
> +    pulled = repo.revs(b'%ld::%ld', pulled, pulled)
>      nodes = [node(r) for r in pulled]
>      return outgoingfromnodes(repo, nodes)
>
> @@ -600,14 +600,14 @@
>      data.sort()
>      length = len(data)
>      return {
> -        'min': data[0],
> -        '10%': data[length // 10],
> -        '25%': data[length // 4],
> -        '50%': data[length // 2],
> -        '75%': data[(length // 4) * 3],
> -        '90%': data[(length // 10) * 9],
> -        '95%': data[(length // 20) * 19],
> -        'max': data[-1],
> +        b'min': data[0],
> +        b'10%': data[length // 10],
> +        b'25%': data[length // 4],
> +        b'50%': data[length // 2],
> +        b'75%': data[(length // 4) * 3],
> +        b'90%': data[(length // 10) * 9],
> +        b'95%': data[(length // 20) * 19],
> +        b'max': data[-1],
>      }
>
>  STATSFORMAT = """{name}:
> diff --git a/hgext3rd/serverminitopic.py b/hgext3rd/serverminitopic.py
> --- a/hgext3rd/serverminitopic.py
> +++ b/hgext3rd/serverminitopic.py
> @@ -29,11 +29,11 @@
>  except ImportError: # <= hg-4.5
>      from mercurial import wireprotov1server as wireproto
>
> -if util.safehasattr(registrar, 'configitem'):
> +if util.safehasattr(registrar, b'configitem'):
>
>      configtable = {}
>      configitem = registrar.configitem(configtable)
> -    configitem('experimental', 'server-mini-topic',
> +    configitem(b'experimental', b'server-mini-topic',
>                 default=False,
>      )
>
> @@ -44,7 +44,7 @@
>      """
>      enabled = getattr(repo, '_hasminitopic', None)
>      if enabled is None:
> -        enabled = (repo.ui.configbool('experimental', 'server-mini-topic')
> +        enabled = (repo.ui.configbool(b'experimental',
> b'server-mini-topic')
>                     and not repo.publishing())
>          repo._hasminitopic = enabled
>      return enabled
> @@ -54,10 +54,10 @@
>  def topicbranch(orig, self):
>      branch = orig(self)
>      if hasminitopic(self._repo) and self.phase():
> -        topic = self._changeset.extra.get('topic')
> +        topic = self._changeset.extra.get(b'topic')
>          if topic is not None:
>              topic = encoding.tolocal(topic)
> -            branch = '%s:%s' % (branch, topic)
> +            branch = b'%s:%s' % (branch, topic)
>      return branch
>
>  ### avoid caching topic data in rev-branch-cache
> @@ -67,7 +67,7 @@
>
>      def _init__(self, *args, **kwargs):
>          super(revbranchcacheoverlay, self).__init__(*args, **kwargs)
> -        if 'branchinfo' in vars(self):
> +        if b'branchinfo' in vars(self):
>              del self.branchinfo
>
>      def branchinfo(self, rev, changelog=None):
> @@ -95,7 +95,7 @@
>                      class topicawarerbc(revbranchcacheoverlay,
> cache.__class__):
>                          pass
>                      cache.__class__ = topicawarerbc
> -                    if 'branchinfo' in vars(cache):
> +                    if b'branchinfo' in vars(cache):
>                          del cache.branchinfo
>                      self._revbranchcache = cache
>                  return self._revbranchcache
> @@ -120,7 +120,7 @@
>      if revs:
>          s = hashlib.sha1()
>          for rev in revs:
> -            s.update('%s;' % rev)
> +            s.update(b'%s;' % rev)
>          key = s.digest()
>      return key
>
> @@ -138,8 +138,8 @@
>          branchmap.branchcache = previous
>
>  _publiconly = set([
> -    'base',
> -    'immutable',
> +    b'base',
> +    b'immutable',
>  ])
>
>  def mighttopic(repo):
> @@ -159,7 +159,7 @@
>
>      def copy(self):
>          """return an deep copy of the branchcache object"""
> -        if util.safehasattr(self, '_entries'):
> +        if util.safehasattr(self, b'_entries'):
>              _entries = self._entries
>          else:
>              # hg <= 4.9 (624d6683c705, b137a6793c51)
> @@ -216,7 +216,7 @@
>  def wireprotocaps(orig, repo, proto):
>      caps = orig(repo, proto)
>      if hasminitopic(repo):
> -        caps.append('topics')
> +        caps.append(b'topics')
>      return caps
>
>  # wrap the necessary bit
> @@ -234,13 +234,13 @@
>      assert issubclass(current, new), (current, new, targetclass)
>
>  def uisetup(ui):
> -    wrapclass(branchmap, 'branchcache', _topiccache)
> +    wrapclass(branchmap, b'branchcache', _topiccache)
>      try:
>          # Mercurial 4.8 and older
> -        extensions.wrapfunction(branchmap, 'read', wrapread)
> +        extensions.wrapfunction(branchmap, b'read', wrapread)
>      except AttributeError:
>          # Mercurial 4.9; branchcache.fromfile now takes care of this
>          # which is alredy defined on _topiccache
>          pass
> -    extensions.wrapfunction(wireproto, '_capabilities', wireprotocaps)
> -    extensions.wrapfunction(context.changectx, 'branch', topicbranch)
> +    extensions.wrapfunction(wireproto, b'_capabilities', wireprotocaps)
> +    extensions.wrapfunction(context.changectx, b'branch', topicbranch)
> diff --git a/hgext3rd/topic/README b/hgext3rd/topic/README
> --- a/hgext3rd/topic/README
> +++ b/hgext3rd/topic/README
> @@ -48,6 +48,6 @@
>  Documentation
>  -------------
>
> -* See 'hg help -e topic' for a generic help.
> -* See 'hg help topics' and 'hg help stack' for help on specific commands.
> -* See the 'tests/test-topic-tutorial.t' file for a quick tutorial.
> +* See b'hg help -e topic' for a generic help.
> +* See b'hg help topics' and b'hg help stack' for help on specific
> commands.
> +* See the b'tests/test-topic-tutorial.t' file for a quick tutorial.
> diff --git a/hgext3rd/topic/__init__.py b/hgext3rd/topic/__init__.py
> --- a/hgext3rd/topic/__init__.py
> +++ b/hgext3rd/topic/__init__.py
> @@ -153,62 +153,62 @@
>
>  cmdtable = {}
>  command = registrar.command(cmdtable)
> -colortable = {'topic.active': 'green',
> -              'topic.list.unstablecount': 'red',
> -              'topic.list.headcount.multiple': 'yellow',
> -              'topic.list.behindcount': 'cyan',
> -              'topic.list.behinderror': 'red',
> -              'topic.stack.index': 'yellow',
> -              'topic.stack.index.base': 'none dim',
> -              'topic.stack.desc.base': 'none dim',
> -              'topic.stack.shortnode.base': 'none dim',
> -              'topic.stack.state.base': 'dim',
> -              'topic.stack.state.clean': 'green',
> -              'topic.stack.index.current': 'cyan',       # random pick
> -              'topic.stack.state.current': 'cyan bold',  # random pick
> -              'topic.stack.desc.current': 'cyan',        # random pick
> -              'topic.stack.shortnode.current': 'cyan',   # random pick
> -              'topic.stack.state.orphan': 'red',
> -              'topic.stack.state.content-divergent': 'red',
> -              'topic.stack.state.phase-divergent': 'red',
> -              'topic.stack.summary.behindcount': 'cyan',
> -              'topic.stack.summary.behinderror': 'red',
> -              'topic.stack.summary.headcount.multiple': 'yellow',
> +colortable = {b'topic.active': b'green',
> +              b'topic.list.unstablecount': b'red',
> +              b'topic.list.headcount.multiple': b'yellow',
> +              b'topic.list.behindcount': b'cyan',
> +              b'topic.list.behinderror': b'red',
> +              b'topic.stack.index': b'yellow',
> +              b'topic.stack.index.base': b'none dim',
> +              b'topic.stack.desc.base': b'none dim',
> +              b'topic.stack.shortnode.base': b'none dim',
> +              b'topic.stack.state.base': b'dim',
> +              b'topic.stack.state.clean': b'green',
> +              b'topic.stack.index.current': b'cyan',       # random pick
> +              b'topic.stack.state.current': b'cyan bold',  # random pick
> +              b'topic.stack.desc.current': b'cyan',        # random pick
> +              b'topic.stack.shortnode.current': b'cyan',   # random pick
> +              b'topic.stack.state.orphan': b'red',
> +              b'topic.stack.state.content-divergent': b'red',
> +              b'topic.stack.state.phase-divergent': b'red',
> +              b'topic.stack.summary.behindcount': b'cyan',
> +              b'topic.stack.summary.behinderror': b'red',
> +              b'topic.stack.summary.headcount.multiple': b'yellow',
>                # default color to help log output and thg
>                # (first pick I could think off, update as needed
> -              'log.topic': 'green_background',
> -              'topic.active': 'green',
> -             }
> +              b'log.topic': b'green_background',
> +              b'topic.active': b'green',
> +              }
>
> -__version__ = '0.15.0.dev'
> +__version__ = b'0.15.0.dev'
>
> -testedwith = '4.5.2 4.6.2 4.7 4.8 4.9 5.0'
> -minimumhgversion = '4.5'
> -buglink = 'https://bz.mercurial-scm.org/'
> +testedwith = b'4.5.2 4.6.2 4.7 4.8 4.9 5.0'
> +minimumhgversion = b'4.5'
> +buglink = b'https://bz.mercurial-scm.org/'
>
> -if util.safehasattr(registrar, 'configitem'):
> +if util.safehasattr(registrar, b'configitem'):
>
>      from mercurial import configitems
>
>      configtable = {}
>      configitem = registrar.configitem(configtable)
>
> -    configitem('experimental', 'enforce-topic',
> +    configitem(b'experimental', b'enforce-topic',
>                 default=False,
>      )
> -    configitem('experimental', 'enforce-single-head',
> +    configitem(b'experimental', b'enforce-single-head',
>                 default=False,
>      )
> -    configitem('experimental', 'topic-mode',
> +    configitem(b'experimental', b'topic-mode',
>                 default=None,
>      )
> -    configitem('experimental', 'topic.publish-bare-branch',
> +    configitem(b'experimental', b'topic.publish-bare-branch',
>                 default=False,
>      )
> -    configitem('_internal', 'keep-topic',
> +    configitem(b'_internal', b'keep-topic',
>                 default=False,
>      )
> -    configitem('experimental', 'topic-mode.server',
> +    configitem(b'experimental', b'topic-mode.server',
>                 default=configitems.dynamicdefault,
>      )
>
> @@ -219,25 +219,25 @@
>          # nobody else did so far.
>          from mercurial import configitems
>          extraitem = functools.partial(configitems._register,
> ui._knownconfig)
> -        if ('experimental' not in ui._knownconfig
> -                or not
> ui._knownconfig['experimental'].get('thg.displaynames')):
> -            extraitem('experimental', 'thg.displaynames',
> +        if (b'experimental' not in ui._knownconfig
> +                or not
> ui._knownconfig[b'experimental'].get(b'thg.displaynames')):
> +            extraitem(b'experimental', b'thg.displaynames',
>                        default=None,
>              )
> -        if ('devel' not in ui._knownconfig
> -                or not ui._knownconfig['devel'].get('random')):
> -            extraitem('devel', 'randomseed',
> +        if (b'devel' not in ui._knownconfig
> +                or not ui._knownconfig[b'devel'].get(b'random')):
> +            extraitem(b'devel', b'randomseed',
>                        default=None,
>              )
>
>  # we need to do old style declaration for <= 4.5
>  templatekeyword = registrar.templatekeyword()
> -post45template = 'requires=' in templatekeyword.__doc__
> +post45template = b'requires=' in templatekeyword.__doc__
>
>  def _contexttopic(self, force=False):
>      if not (force or self.mutable()):
> -        return ''
> -    return self.extra().get(constants.extrakey, '')
> +        return b''
> +    return self.extra().get(constants.extrakey, b'')
>  context.basectx.topic = _contexttopic
>
>  def _contexttopicidx(self):
> @@ -265,38 +265,38 @@
>          idx = int(name[1:])
>          tname = topic = repo.currenttopic
>          if topic:
> -            ttype = 'topic'
> +            ttype = b'topic'
>              revs = list(stack.stack(repo, topic=topic))
>          else:
> -            ttype = 'branch'
> +            ttype = b'branch'
>              tname = branch = repo[None].branch()
>              revs = list(stack.stack(repo, branch=branch))
>      elif topicrev.match(name):
>          idx = int(name[1:])
> -        ttype = 'topic'
> +        ttype = b'topic'
>          tname = topic = repo.currenttopic
>          if not tname:
> -            raise error.Abort(_('cannot resolve "%s": no active topic') %
> name)
> +            raise error.Abort(_(b'cannot resolve "%s": no active topic')
> % name)
>          revs = list(stack.stack(repo, topic=topic))
>
>      if revs is not None:
>          try:
>              r = revs[idx]
>          except IndexError:
> -            if ttype == 'topic':
> -                msg = _('cannot resolve "%s": %s "%s" has only %d
> changesets')
> -            elif ttype == 'branch':
> -                msg = _('cannot resolve "%s": %s "%s" has only %d
> non-public changesets')
> +            if ttype == b'topic':
> +                msg = _(b'cannot resolve "%s": %s "%s" has only %d
> changesets')
> +            elif ttype == b'branch':
> +                msg = _(b'cannot resolve "%s": %s "%s" has only %d
> non-public changesets')
>              raise error.Abort(msg % (name, ttype, tname, len(revs) - 1))
>          # t0 or s0 can be None
>          if r == -1 and idx == 0:
> -            msg = _('the %s "%s" has no %s')
> +            msg = _(b'the %s "%s" has no %s')
>              raise error.Abort(msg % (ttype, tname, name))
>          return [repo[r].node()]
>      if name not in repo.topics:
>          return []
>      node = repo.changelog.node
> -    return [node(rev) for rev in repo.revs('topic(%s)', name)]
> +    return [node(rev) for rev in repo.revs(b'topic(%s)', name)]
>
>  def _nodemap(repo, node):
>      ctx = repo[node]
> @@ -311,47 +311,47 @@
>      topicmap.modsetup(ui)
>      setupimportexport(ui)
>
> -    extensions.afterloaded('rebase', _fixrebase)
> +    extensions.afterloaded(b'rebase', _fixrebase)
>
>      flow.installpushflag(ui)
>
> -    entry = extensions.wrapcommand(commands.table, 'commit', commitwrap)
> -    entry[1].append(('t', 'topic', '',
> -                     _("use specified topic"), _('TOPIC')))
> +    entry = extensions.wrapcommand(commands.table, b'commit', commitwrap)
> +    entry[1].append((b't', b'topic', b'',
> +                     _(b"use specified topic"), _(b'TOPIC')))
>
> -    entry = extensions.wrapcommand(commands.table, 'push',
> pushoutgoingwrap)
> -    entry[1].append(('t', 'topic', '',
> -                     _("topic to push"), _('TOPIC')))
> +    entry = extensions.wrapcommand(commands.table, b'push',
> pushoutgoingwrap)
> +    entry[1].append((b't', b'topic', b'',
> +                     _(b"topic to push"), _(b'TOPIC')))
>
> -    entry = extensions.wrapcommand(commands.table, 'outgoing',
> +    entry = extensions.wrapcommand(commands.table, b'outgoing',
>                                     pushoutgoingwrap)
> -    entry[1].append(('t', 'topic', '',
> -                     _("topic to push"), _('TOPIC')))
> +    entry[1].append((b't', b'topic', b'',
> +                     _(b"topic to push"), _(b'TOPIC')))
>
> -    extensions.wrapfunction(cmdutil, 'buildcommittext', committextwrap)
> -    extensions.wrapfunction(merge, 'update', mergeupdatewrap)
> +    extensions.wrapfunction(cmdutil, b'buildcommittext', committextwrap)
> +    extensions.wrapfunction(merge, b'update', mergeupdatewrap)
>      # We need to check whether t0 or b0 or s0 is passed to override the
> default update
>      # behaviour of changing topic and I can't find a better way
>      # to do that as scmutil.revsingle returns the rev number and hence we
> can't
>      # plug into logic for this into mergemod.update().
> -    extensions.wrapcommand(commands.table, 'update', checkt0)
> +    extensions.wrapcommand(commands.table, b'update', checkt0)
>
>      try:
> -        evolve = extensions.find('evolve')
> -        extensions.wrapfunction(evolve.rewriteutil, "presplitupdate",
> +        evolve = extensions.find(b'evolve')
> +        extensions.wrapfunction(evolve.rewriteutil, b"presplitupdate",
>                                  presplitupdatetopic)
>      except (KeyError, AttributeError):
>          pass
>
> -    cmdutil.summaryhooks.add('topic', summaryhook)
> +    cmdutil.summaryhooks.add(b'topic', summaryhook)
>
>      if not post45template:
> -        templatekw.keywords['topic'] = topickw
> -        templatekw.keywords['topicidx'] = topicidxkw
> +        templatekw.keywords[b'topic'] = topickw
> +        templatekw.keywords[b'topicidx'] = topicidxkw
>      # Wrap workingctx extra to return the topic name
> -    extensions.wrapfunction(context.workingctx, '__init__', wrapinit)
> +    extensions.wrapfunction(context.workingctx, b'__init__', wrapinit)
>      # Wrap changelog.add to drop empty topic
> -    extensions.wrapfunction(changelog.changelog, 'add', wrapadd)
> +    extensions.wrapfunction(changelog.changelog, b'add', wrapadd)
>
>  def reposetup(ui, repo):
>      if not isinstance(repo, localrepo.localrepository):
> @@ -359,9 +359,9 @@
>
>      repo = repo.unfiltered()
>
> -    if repo.ui.config('experimental', 'thg.displaynames') is None:
> -        repo.ui.setconfig('experimental', 'thg.displaynames', 'topics',
> -                          source='topic-extension')
> +    if repo.ui.config(b'experimental', b'thg.displaynames') is None:
> +        repo.ui.setconfig(b'experimental', b'thg.displaynames', b'topics',
> +                          source=b'topic-extension')
>
>      class topicrepo(repo.__class__):
>
> @@ -370,15 +370,15 @@
>
>          def _restrictcapabilities(self, caps):
>              caps = super(topicrepo, self)._restrictcapabilities(caps)
> -            caps.add('topics')
> +            caps.add(b'topics')
>              return caps
>
>          def commit(self, *args, **kwargs):
> -            backup = self.ui.backupconfig('ui', 'allowemptycommit')
> +            backup = self.ui.backupconfig(b'ui', b'allowemptycommit')
>              try:
> -                if self.currenttopic != self['.'].topic():
> +                if self.currenttopic != self[b'.'].topic():
>                      # bypass the core "nothing changed" logic
> -                    self.ui.setconfig('ui', 'allowemptycommit', True)
> +                    self.ui.setconfig(b'ui', b'allowemptycommit', True)
>                  return super(topicrepo, self).commit(*args, **kwargs)
>              finally:
>                  self.ui.restoreconfig(backup)
> @@ -394,7 +394,7 @@
>                  if current:
>                      ctx.extra()[constants.extrakey] = current
>              if (isinstance(ctx, context.memctx)
> -                and ctx.extra().get('amend_source')
> +                and ctx.extra().get(b'amend_source')
>                  and ctx.topic()
>                  and not self.currenttopic):
>                  # we are amending and need to remove a topic
> @@ -405,16 +405,16 @@
>          def topics(self):
>              if self._topics is not None:
>                  return self._topics
> -            topics = set(['', self.currenttopic])
> -            for c in self.set('not public()'):
> +            topics = set([b'', self.currenttopic])
> +            for c in self.set(b'not public()'):
>                  topics.add(c.topic())
> -            topics.remove('')
> +            topics.remove(b'')
>              self._topics = topics
>              return topics
>
>          @property
>          def currenttopic(self):
> -            return self.vfs.tryread('topic')
> +            return self.vfs.tryread(b'topic')
>
>          # overwritten at the instance level by topicmap.py
>          _autobranchmaptopic = True
> @@ -445,12 +445,12 @@
>          def transaction(self, desc, *a, **k):
>              ctr = self.currenttransaction()
>              tr = super(topicrepo, self).transaction(desc, *a, **k)
> -            if desc in ('strip', 'repair') or ctr is not None:
> +            if desc in (b'strip', b'repair') or ctr is not None:
>                  return tr
>
>              reporef = weakref.ref(self)
> -            if self.ui.configbool('experimental', 'enforce-single-head'):
> -                if util.safehasattr(tr, 'validator'): # hg <= 4.7
> +            if self.ui.configbool(b'experimental',
> b'enforce-single-head'):
> +                if util.safehasattr(tr, b'validator'): # hg <= 4.7
>                      origvalidator = tr.validator
>                  else:
>                      origvalidator = tr._validator
> @@ -460,16 +460,16 @@
>                      flow.enforcesinglehead(repo, tr2)
>                      origvalidator(tr2)
>
> -                if util.safehasattr(tr, 'validator'): # hg <= 4.7
> +                if util.safehasattr(tr, b'validator'): # hg <= 4.7
>                      tr.validator = validator
>                  else:
>                      tr._validator = validator
>
> -            topicmodeserver = self.ui.config('experimental',
> -                                             'topic-mode.server',
> 'ignore')
> -            ispush = (desc.startswith('push') or desc.startswith('serve'))
> -            if (topicmodeserver != 'ignore' and ispush):
> -                if util.safehasattr(tr, 'validator'): # hg <= 4.7
> +            topicmodeserver = self.ui.config(b'experimental',
> +                                             b'topic-mode.server',
> b'ignore')
> +            ispush = (desc.startswith(b'push') or
> desc.startswith(b'serve'))
> +            if (topicmodeserver != b'ignore' and ispush):
> +                if util.safehasattr(tr, b'validator'): # hg <= 4.7
>                      origvalidator = tr.validator
>                  else:
>                      origvalidator = tr._validator
> @@ -478,14 +478,14 @@
>                      repo = reporef()
>                      flow.rejectuntopicedchangeset(repo, tr2)
>                      return origvalidator(tr2)
> -                if util.safehasattr(tr, 'validator'): # hg <= 4.7
> +                if util.safehasattr(tr, b'validator'): # hg <= 4.7
>                      tr.validator = validator
>                  else:
>                      tr._validator = validator
>
> -            elif (self.ui.configbool('experimental',
> 'topic.publish-bare-branch')
> -                    and (desc.startswith('push')
> -                         or desc.startswith('serve'))
> +            elif (self.ui.configbool(b'experimental',
> b'topic.publish-bare-branch')
> +                    and (desc.startswith(b'push')
> +                         or desc.startswith(b'serve'))
>                      ):
>                  origclose = tr.close
>                  trref = weakref.ref(tr)
> @@ -511,62 +511,62 @@
>                  csetcount = stack.stack(repo, topic=ct).changesetcount
>                  empty = csetcount == 0
>                  if empty and not ctwasempty:
> -                    ui.status('active topic %r is now empty\n' % ct)
> +                    ui.status(b'active topic %r is now empty\n' % ct)
>                      trnames = getattr(tr, 'names', getattr(tr, '_names',
> ()))
> -                    if ('phase' in trnames
> -                            or any(n.startswith('push-response')
> +                    if (b'phase' in trnames
> +                            or any(n.startswith(b'push-response')
>                                     for n in trnames)):
> -                        ui.status(_("(use 'hg topic --clear' to clear it
> if needed)\n"))
> -                hint = _("(see 'hg help topics' for more information)\n")
> +                        ui.status(_(b"(use 'hg topic --clear' to clear it
> if needed)\n"))
> +                hint = _(b"(see 'hg help topics' for more information)\n")
>                  if ctwasempty and not empty:
>                      if csetcount == 1:
> -                        msg = _('active topic %r grew its first
> changeset\n%s')
> +                        msg = _(b'active topic %r grew its first
> changeset\n%s')
>                          ui.status(msg % (ct, hint))
>                      else:
> -                        msg = _('active topic %r grew its %s first
> changesets\n%s')
> +                        msg = _(b'active topic %r grew its %s first
> changesets\n%s')
>                          ui.status(msg % (ct, csetcount, hint))
>
> -            tr.addpostclose('signalcurrenttopicempty', currenttopicempty)
> +            tr.addpostclose(b'signalcurrenttopicempty', currenttopicempty)
>              return tr
>
>      repo.__class__ = topicrepo
>      repo._topics = None
> -    if util.safehasattr(repo, 'names'):
> +    if util.safehasattr(repo, b'names'):
>          repo.names.addnamespace(namespaces.namespace(
> -            'topics', 'topic', namemap=_namemap, nodemap=_nodemap,
> +            b'topics', b'topic', namemap=_namemap, nodemap=_nodemap,
>              listnames=lambda repo: repo.topics))
>
>  if post45template:
> -    @templatekeyword('topic', requires={'ctx'})
> +    @templatekeyword(b'topic', requires={b'ctx'})
>      def topickw(context, mapping):
>          """:topic: String. The topic of the changeset"""
> -        ctx = context.resource(mapping, 'ctx')
> +        ctx = context.resource(mapping, b'ctx')
>          return ctx.topic()
>
> -    @templatekeyword('topicidx', requires={'ctx'})
> +    @templatekeyword(b'topicidx', requires={b'ctx'})
>      def topicidxkw(context, mapping):
>          """:topicidx: Integer. Index of the changeset as a stack alias"""
> -        ctx = context.resource(mapping, 'ctx')
> +        ctx = context.resource(mapping, b'ctx')
>          return ctx.topicidx()
>  else:
>      def topickw(**args):
>          """:topic: String. The topic of the changeset"""
> -        return args['ctx'].topic()
> +        return args[b'ctx'].topic()
>
>      def topicidxkw(**args):
>          """:topicidx: Integer. Index of the changeset as a stack alias"""
> -        return args['ctx'].topicidx()
> +        return args[b'ctx'].topicidx()
>
>  def wrapinit(orig, self, repo, *args, **kwargs):
>      orig(self, repo, *args, **kwargs)
>      if not hastopicext(repo):
>          return
>      if constants.extrakey not in self._extra:
> -        if getattr(repo, 'currenttopic', ''):
> +        if getattr(repo, 'currenttopic', b''):
>              self._extra[constants.extrakey] = repo.currenttopic
>          else:
>              # Empty key will be dropped from extra by another hack at the
> changegroup level
> -            self._extra[constants.extrakey] = ''
> +            self._extra[constants.extrakey] = b''
>
>  def wrapadd(orig, cl, manifest, files, desc, transaction, p1, p2, user,
>              date=None, extra=None, p1copies=None, p2copies=None):
> @@ -576,23 +576,23 @@
>      # hg <= 4.9 (0e41f40b01cc)
>      kwargs = {}
>      if p1copies is not None:
> -        kwargs['p1copies'] = p1copies
> +        kwargs[b'p1copies'] = p1copies
>      if p2copies is not None:
> -        kwargs['p2copies'] = p2copies
> +        kwargs[b'p2copies'] = p2copies
>      return orig(cl, manifest, files, desc, transaction, p1, p2, user,
>                  date=date, extra=extra, **kwargs)
>
>  # revset predicates are automatically registered at loading via this
> symbol
>  revsetpredicate = topicrevset.revsetpredicate
>
> -@command('topics', [
> -        ('', 'clear', False, 'clear active topic if any'),
> -        ('r', 'rev', [], 'revset of existing revisions', _('REV')),
> -        ('l', 'list', False, 'show the stack of changeset in the topic'),
> -        ('', 'age', False, 'show when you last touched the topics'),
> -        ('', 'current', None, 'display the current topic only'),
> +@command(b'topics', [
> +        (b'', b'clear', False, b'clear active topic if any'),
> +        (b'r', b'rev', [], b'revset of existing revisions', _(b'REV')),
> +        (b'l', b'list', False, b'show the stack of changeset in the
> topic'),
> +        (b'', b'age', False, b'show when you last touched the topics'),
> +        (b'', b'current', None, b'display the current topic only'),
>      ] + commands.formatteropts,
> -    _('hg topics [TOPIC]'))
> +    _(b'hg topics [TOPIC]'))
>  def topics(ui, repo, topic=None, **opts):
>      """View current topic, set current topic, change topic for a set of
> revisions, or see all topics.
>
> @@ -630,20 +630,20 @@
>
>      The --verbose version of this command display various information on
> the state of each topic."""
>
> -    clear = opts.get('clear')
> -    list = opts.get('list')
> -    rev = opts.get('rev')
> -    current = opts.get('current')
> -    age = opts.get('age')
> +    clear = opts.get(b'clear')
> +    list = opts.get(b'list')
> +    rev = opts.get(b'rev')
> +    current = opts.get(b'current')
> +    age = opts.get(b'age')
>
>      if current and topic:
> -        raise error.Abort(_("cannot use --current when setting a topic"))
> +        raise error.Abort(_(b"cannot use --current when setting a topic"))
>      if current and clear:
> -        raise error.Abort(_("cannot use --current and --clear"))
> +        raise error.Abort(_(b"cannot use --current and --clear"))
>      if clear and topic:
> -        raise error.Abort(_("cannot use --clear when setting a topic"))
> +        raise error.Abort(_(b"cannot use --clear when setting a topic"))
>      if age and topic:
> -        raise error.Abort(_("cannot use --age while setting a topic"))
> +        raise error.Abort(_(b"cannot use --age while setting a topic"))
>
>      touchedrevs = set()
>      if rev:
> @@ -652,49 +652,49 @@
>      if topic:
>          topic = topic.strip()
>          if not topic:
> -            raise error.Abort(_("topic name cannot consist entirely of
> whitespaces"))
> +            raise error.Abort(_(b"topic name cannot consist entirely of
> whitespaces"))
>          # Have some restrictions on the topic name just like bookmark name
> -        scmutil.checknewlabel(repo, topic, 'topic')
> +        scmutil.checknewlabel(repo, topic, b'topic')
>
>          rmatch = re.match(br'[-_.\w]+', topic)
>          if not rmatch or rmatch.group(0) != topic:
> -            helptxt = _("topic names can only consist of alphanumeric,
> '-'"
> -                        " '_' and '.' characters")
> -            raise error.Abort(_("invalid topic name: '%s'") % topic,
> hint=helptxt)
> +            helptxt = _(b"topic names can only consist of alphanumeric,
> '-'"
> +                        b" '_' and '.' characters")
> +            raise error.Abort(_(b"invalid topic name: '%s'") % topic,
> hint=helptxt)
>
>      if list:
> -        ui.pager('topics')
> +        ui.pager(b'topics')
>          if clear or rev:
> -            raise error.Abort(_("cannot use --clear or --rev with
> --list"))
> +            raise error.Abort(_(b"cannot use --clear or --rev with
> --list"))
>          if not topic:
>              topic = repo.currenttopic
>          if not topic:
> -            raise error.Abort(_('no active topic to list'))
> +            raise error.Abort(_(b'no active topic to list'))
>          return stack.showstack(ui, repo, topic=topic, opts=opts)
>
>      if touchedrevs:
>          if not obsolete.isenabled(repo, obsolete.createmarkersopt):
> -            raise error.Abort(_('must have obsolete enabled to change
> topics'))
> +            raise error.Abort(_(b'must have obsolete enabled to change
> topics'))
>          if clear:
>              topic = None
> -        elif opts.get('current'):
> +        elif opts.get(b'current'):
>              topic = repo.currenttopic
>          elif not topic:
> -            raise error.Abort('changing topic requires a topic name or
> --clear')
> -        if repo.revs('%ld and public()', touchedrevs):
> -            raise error.Abort("can't change topic of a public change")
> +            raise error.Abort(b'changing topic requires a topic name or
> --clear')
> +        if repo.revs(b'%ld and public()', touchedrevs):
> +            raise error.Abort(b"can't change topic of a public change")
>          wl = lock = txn = None
>          try:
>              wl = repo.wlock()
>              lock = repo.lock()
> -            txn = repo.transaction('rewrite-topics')
> +            txn = repo.transaction(b'rewrite-topics')
>              rewrote = _changetopics(ui, repo, touchedrevs, topic)
>              txn.close()
>              if topic is None:
> -                ui.status('cleared topic on %d changesets\n' % rewrote)
> +                ui.status(b'cleared topic on %d changesets\n' % rewrote)
>              else:
> -                ui.status('changed topic on %d changesets to "%s"\n' %
> (rewrote,
> -
> topic))
> +                ui.status(b'changed topic on %d changesets to "%s"\n' %
> (rewrote,
> +
>  topic))
>          finally:
>              lockmod.release(txn, lock, wl)
>              repo.invalidate()
> @@ -705,37 +705,37 @@
>          if ct:
>              empty = stack.stack(repo, topic=ct).changesetcount == 0
>              if empty:
> -                ui.status(_('clearing empty topic "%s"\n') % ct)
> +                ui.status(_(b'clearing empty topic "%s"\n') % ct)
>          return _changecurrenttopic(repo, None)
>
>      if topic:
>          if not ct:
> -            ui.status(_('marked working directory as topic: %s\n') %
> topic)
> +            ui.status(_(b'marked working directory as topic: %s\n') %
> topic)
>          return _changecurrenttopic(repo, topic)
>
> -    ui.pager('topics')
> +    ui.pager(b'topics')
>      # `hg topic --current`
>      ret = 0
>      if current and not ct:
> -        ui.write_err(_('no active topic\n'))
> +        ui.write_err(_(b'no active topic\n'))
>          ret = 1
>      elif current:
> -        fm = ui.formatter('topic', opts)
> -        namemask = '%s\n'
> -        label = 'topic.active'
> +        fm = ui.formatter(b'topic', opts)
> +        namemask = b'%s\n'
> +        label = b'topic.active'
>          fm.startitem()
> -        fm.write('topic', namemask, ct, label=label)
> +        fm.write(b'topic', namemask, ct, label=label)
>          fm.end()
>      else:
>          _listtopics(ui, repo, opts)
>      return ret
>
> -@command('stack', [
> -        ('c', 'children', None,
> -            _('display data about children outside of the stack'))
> +@command(b'stack', [
> +        (b'c', b'children', None,
> +            _(b'display data about children outside of the stack'))
>      ] + commands.formatteropts,
> -    _('hg stack [TOPIC]'))
> -def cmdstack(ui, repo, topic='', **opts):
> +    _(b'hg stack [TOPIC]'))
> +def cmdstack(ui, repo, topic=b'', **opts):
>      """list all changesets in a topic and other information
>
>      List the current topic by default.
> @@ -749,30 +749,30 @@
>          topic = repo.currenttopic
>      if topic is None:
>          branch = repo[None].branch()
> -    ui.pager('stack')
> +    ui.pager(b'stack')
>      return stack.showstack(ui, repo, branch=branch, topic=topic,
> opts=opts)
>
> -@command('debugcb|debugconvertbookmark', [
> -        ('b', 'bookmark', '', _('bookmark to convert to topic')),
> -        ('', 'all', None, _('convert all bookmarks to topics')),
> +@command(b'debugcb|debugconvertbookmark', [
> +        (b'b', b'bookmark', b'', _(b'bookmark to convert to topic')),
> +        (b'', b'all', None, _(b'convert all bookmarks to topics')),
>      ],
> -    _('[-b BOOKMARK] [--all]'))
> +    _(b'[-b BOOKMARK] [--all]'))
>  def debugconvertbookmark(ui, repo, **opts):
>      """Converts a bookmark to a topic with the same name.
>      """
>
> -    bookmark = opts.get('bookmark')
> -    convertall = opts.get('all')
> +    bookmark = opts.get(b'bookmark')
> +    convertall = opts.get(b'all')
>
>      if convertall and bookmark:
> -        raise error.Abort(_("cannot use '--all' and '-b' together"))
> +        raise error.Abort(_(b"cannot use '--all' and '-b' together"))
>      if not (convertall or bookmark):
> -        raise error.Abort(_("you must specify either '--all' or '-b'"))
> +        raise error.Abort(_(b"you must specify either '--all' or '-b'"))
>
>      bmstore = repo._bookmarks
>
>      nodetobook = {}
> -    for book, revnode in bmstore.iteritems():
> +    for book, revnode in bmstore.items():
>          if nodetobook.get(revnode):
>              nodetobook[revnode].append(book)
>          else:
> @@ -792,28 +792,28 @@
>              try:
>                  node = bmstore[bookmark]
>              except KeyError:
> -                raise error.Abort(_("no such bookmark exists: '%s'") %
> bookmark)
> +                raise error.Abort(_(b"no such bookmark exists: '%s'") %
> bookmark)
>
>              revnum = repo[node].rev()
>              if len(nodetobook[node]) > 1:
> -                ui.status(_("skipping revision '%d' as it has multiple
> bookmarks "
> -                          "on it\n") % revnum)
> +                ui.status(_(b"skipping revision '%d' as it has multiple
> bookmarks "
> +                          b"on it\n") % revnum)
>                  return
>              targetrevs = _findconvertbmarktopic(repo, bookmark)
>              if targetrevs:
>                  actions[(bookmark, revnum)] = targetrevs
>
>          elif convertall:
> -            for bmark, revnode in sorted(bmstore.iteritems()):
> +            for bmark, revnode in sorted(bmstore.items()):
>                  revnum = repo[revnode].rev()
>                  if revnum in skipped:
>                      continue
>                  if len(nodetobook[revnode]) > 1:
> -                    ui.status(_("skipping '%d' as it has multiple
> bookmarks on"
> -                              " it\n") % revnum)
> +                    ui.status(_(b"skipping '%d' as it has multiple
> bookmarks on"
> +                              b" it\n") % revnum)
>                      skipped.append(revnum)
>                      continue
> -                if bmark == '@':
> +                if bmark == b'@':
>                      continue
>                  targetrevs = _findconvertbmarktopic(repo, bmark)
>                  if targetrevs:
> @@ -821,8 +821,8 @@
>
>          if actions:
>              try:
> -                tr = repo.transaction('debugconvertbookmark')
> -                for ((bmark, revnum), targetrevs) in
> sorted(actions.iteritems()):
> +                tr = repo.transaction(b'debugconvertbookmark')
> +                for ((bmark, revnum), targetrevs) in
> sorted(actions.items()):
>                      _applyconvertbmarktopic(ui, repo, targetrevs, revnum,
> bmark, tr)
>                  tr.close()
>              finally:
> @@ -869,9 +869,9 @@
>      # changeset
>      if rewrote == 0:
>          return
> -    ui.status(_('changed topic to "%s" on %d revisions\n') % (bmark,
> +    ui.status(_(b'changed topic to "%s" on %d revisions\n') % (bmark,
>                rewrote))
> -    ui.debug('removing bookmark "%s" from "%d"' % (bmark, old))
> +    ui.debug(b'removing bookmark "%s" from "%d"' % (bmark, old))
>      bookmarks.delete(repo, tr, [bmark])
>
>  def _changecurrenttopic(repo, newtopic):
> @@ -879,11 +879,11 @@
>
>      if newtopic:
>          with repo.wlock():
> -            with repo.vfs.open('topic', 'w') as f:
> +            with repo.vfs.open(b'topic', b'w') as f:
>                  f.write(newtopic)
>      else:
> -        if repo.vfs.exists('topic'):
> -            repo.vfs.unlink('topic')
> +        if repo.vfs.exists(b'topic'):
> +            repo.vfs.unlink(b'topic')
>
>  def _changetopics(ui, repo, revs, newtopic):
>      """ Changes topic to newtopic of all the revisions in the revset and
> return
> @@ -902,8 +902,8 @@
>              except error.ManifestLookupError:
>                  return None
>          fixedextra = dict(c.extra())
> -        ui.debug('old node id is %s\n' % node.hex(c.node()))
> -        ui.debug('origextra: %r\n' % fixedextra)
> +        ui.debug(b'old node id is %s\n' % node.hex(c.node()))
> +        ui.debug(b'origextra: %r\n' % fixedextra)
>          oldtopic = fixedextra.get(constants.extrakey, None)
>          if oldtopic == newtopic:
>              continue
> @@ -912,16 +912,16 @@
>          else:
>              fixedextra[constants.extrakey] = newtopic
>          fixedextra[constants.changekey] = c.hex()
> -        if 'amend_source' in fixedextra:
> +        if b'amend_source' in fixedextra:
>              # TODO: right now the commitctx wrapper in
>              # topicrepo overwrites the topic in extra if
>              # amend_source is set to support 'hg commit
>              # --amend'. Support for amend should be adjusted
>              # to not be so invasive.
> -            del fixedextra['amend_source']
> -        ui.debug('changing topic of %s from %s to %s\n' % (
> +            del fixedextra[b'amend_source']
> +        ui.debug(b'changing topic of %s from %s to %s\n' % (
>              c, oldtopic, newtopic))
> -        ui.debug('fixedextra: %r\n' % fixedextra)
> +        ui.debug(b'fixedextra: %r\n' % fixedextra)
>          # While changing topic of set of linear commits, make sure that
>          # we base our commits on new parent rather than old parent which
>          # was obsoleted while changing the topic
> @@ -942,18 +942,18 @@
>
>          # phase handling
>          commitphase = c.phase()
> -        overrides = {('phases', 'new-commit'): commitphase}
> -        with repo.ui.configoverride(overrides, 'changetopic'):
> +        overrides = {(b'phases', b'new-commit'): commitphase}
> +        with repo.ui.configoverride(overrides, b'changetopic'):
>              newnode = repo.commitctx(mc)
>
>          successors[c.node()] = (newnode,)
> -        ui.debug('new node id is %s\n' % node.hex(newnode))
> +        ui.debug(b'new node id is %s\n' % node.hex(newnode))
>          rewrote += 1
>
>      # create obsmarkers and move bookmarks
>      # XXX we should be creating marker as we go instead of only at the
> end,
>      # this makes the operations more modulars
> -    scmutil.cleanupnodes(repo, successors, 'changetopics')
> +    scmutil.cleanupnodes(repo, successors, b'changetopics')
>
>      # move the working copy too
>      wctx = repo[None]
> @@ -965,13 +965,13 @@
>      return rewrote
>
>  def _listtopics(ui, repo, opts):
> -    fm = ui.formatter('topics', opts)
> +    fm = ui.formatter(b'topics', opts)
>      activetopic = repo.currenttopic
> -    namemask = '%s'
> +    namemask = b'%s'
>      if repo.topics:
>          maxwidth = max(len(t) for t in repo.topics)
> -        namemask = '%%-%is' % maxwidth
> -    if opts.get('age'):
> +        namemask = b'%%-%is' % maxwidth
> +    if opts.get(b'age'):
>          # here we sort by age and topic name
>          topicsdata = sorted(_getlasttouched(repo, repo.topics))
>      else:
> @@ -982,70 +982,70 @@
>          )
>      for age, topic, date, user in topicsdata:
>          fm.startitem()
> -        marker = ' '
> -        label = 'topic'
> +        marker = b' '
> +        label = b'topic'
>          active = (topic == activetopic)
>          if active:
> -            marker = '*'
> -            label = 'topic.active'
> +            marker = b'*'
> +            label = b'topic.active'
>          if not ui.quiet:
>              # registering the active data is made explicitly later
> -            fm.plain(' %s ' % marker, label=label)
> -        fm.write('topic', namemask, topic, label=label)
> +            fm.plain(b' %s ' % marker, label=label)
> +        fm.write(b'topic', namemask, topic, label=label)
>          fm.data(active=active)
>
>          if ui.quiet:
> -            fm.plain('\n')
> +            fm.plain(b'\n')
>              continue
> -        fm.plain(' (')
> +        fm.plain(b' (')
>          if date:
>              if age == -1:
> -                timestr = 'empty and active'
> +                timestr = b'empty and active'
>              else:
>                  timestr = templatefilters.age(date)
> -            fm.write('lasttouched', '%s', timestr,
> label='topic.list.time')
> +            fm.write(b'lasttouched', b'%s', timestr,
> label=b'topic.list.time')
>          if user:
> -            fm.write('usertouched', ' by %s', user,
> label='topic.list.user')
> +            fm.write(b'usertouched', b' by %s', user,
> label=b'topic.list.user')
>          if date:
> -            fm.plain(', ')
> +            fm.plain(b', ')
>          data = stack.stack(repo, topic=topic)
>          if ui.verbose:
> -            fm.write('branches+', 'on branch: %s',
> -                     '+'.join(data.branches), # XXX use list directly
> after 4.0 is released
> -                     label='topic.list.branches')
> +            fm.write(b'branches+', b'on branch: %s',
> +                     b'+'.join(data.branches), # XXX use list directly
> after 4.0 is released
> +                     label=b'topic.list.branches')
>
> -            fm.plain(', ')
> -        fm.write('changesetcount', '%d changesets', data.changesetcount,
> -                 label='topic.list.changesetcount')
> +            fm.plain(b', ')
> +        fm.write(b'changesetcount', b'%d changesets', data.changesetcount,
> +                 label=b'topic.list.changesetcount')
>
>          if data.unstablecount:
> -            fm.plain(', ')
> -            fm.write('unstablecount', '%d unstable',
> +            fm.plain(b', ')
> +            fm.write(b'unstablecount', b'%d unstable',
>                       data.unstablecount,
> -                     label='topic.list.unstablecount')
> +                     label=b'topic.list.unstablecount')
>
>          headcount = len(data.heads)
>          if 1 < headcount:
> -            fm.plain(', ')
> -            fm.write('headcount', '%d heads',
> +            fm.plain(b', ')
> +            fm.write(b'headcount', b'%d heads',
>                       headcount,
> -                     label='topic.list.headcount.multiple')
> +                     label=b'topic.list.headcount.multiple')
>
>          if ui.verbose:
>              # XXX we should include the data even when not verbose
>
>              behindcount = data.behindcount
>              if 0 < behindcount:
> -                fm.plain(', ')
> -                fm.write('behindcount', '%d behind',
> +                fm.plain(b', ')
> +                fm.write(b'behindcount', b'%d behind',
>                           behindcount,
> -                         label='topic.list.behindcount')
> +                         label=b'topic.list.behindcount')
>              elif -1 == behindcount:
> -                fm.plain(', ')
> -                fm.write('behinderror', '%s',
> -                         _('ambiguous destination: %s') %
> data.behinderror,
> -                         label='topic.list.behinderror')
> -        fm.plain(')\n')
> +                fm.plain(b', ')
> +                fm.write(b'behinderror', b'%s',
> +                         _(b'ambiguous destination: %s') %
> data.behinderror,
> +                         label=b'topic.list.behinderror')
> +        fm.plain(b')\n')
>      fm.end()
>
>  def _getlasttouched(repo, topics):
> @@ -1058,7 +1058,7 @@
>          age = -1
>          user = None
>          maxtime = (0, 0)
> -        trevs = repo.revs("topic(%s)", topic)
> +        trevs = repo.revs(b"topic(%s)", topic)
>          # Need to check for the time of all changesets in the topic,
> whether
>          # they are obsolete of non-heads
>          # XXX: can we just rely on the max rev number for this
> @@ -1075,7 +1075,7 @@
>              for marker in obsmarkers:
>                  rt = marker.date()
>                  if rt[0] > maxtime[0]:
> -                    user = marker.metadata().get('user', user)
> +                    user = marker.metadata().get(b'user', user)
>                      maxtime = rt
>
>          username = stack.parseusername(user)
> @@ -1085,31 +1085,31 @@
>          yield (age, topic, maxtime, username)
>
>  def summaryhook(ui, repo):
> -    t = getattr(repo, 'currenttopic', '')
> +    t = getattr(repo, 'currenttopic', b'')
>      if not t:
>          return
>      # i18n: column positioning for "hg summary"
> -    ui.write(_("topic:  %s\n") % ui.label(t, 'topic.active'))
> +    ui.write(_(b"topic:  %s\n") % ui.label(t, b'topic.active'))
>
>  _validmode = [
> -    'ignore',
> -    'warning',
> -    'enforce',
> -    'enforce-all',
> -    'random',
> -    'random-all',
> +    b'ignore',
> +    b'warning',
> +    b'enforce',
> +    b'enforce-all',
> +    b'random',
> +    b'random-all',
>  ]
>
>  def _configtopicmode(ui):
>      """ Parse the config to get the topicmode
>      """
> -    topicmode = ui.config('experimental', 'topic-mode')
> +    topicmode = ui.config(b'experimental', b'topic-mode')
>
>      # Fallback to read enforce-topic
>      if topicmode is None:
> -        enforcetopic = ui.configbool('experimental', 'enforce-topic')
> +        enforcetopic = ui.configbool(b'experimental', b'enforce-topic')
>          if enforcetopic:
> -            topicmode = "enforce"
> +            topicmode = b"enforce"
>      if topicmode not in _validmode:
>          topicmode = _validmode[0]
>
> @@ -1123,37 +1123,37 @@
>          ismergecommit = len(repo[None].parents()) == 2
>
>          notopic = not repo.currenttopic
> -        mayabort = (topicmode == "enforce" and not ismergecommit)
> -        maywarn = (topicmode == "warning"
> -                   or (topicmode == "enforce" and ismergecommit))
> +        mayabort = (topicmode == b"enforce" and not ismergecommit)
> +        maywarn = (topicmode == b"warning"
> +                   or (topicmode == b"enforce" and ismergecommit))
>
>          mayrandom = False
> -        if topicmode == "random":
> +        if topicmode == b"random":
>              mayrandom = not ismergecommit
> -        elif topicmode == "random-all":
> +        elif topicmode == b"random-all":
>              mayrandom = True
>
> -        if topicmode == 'enforce-all':
> +        if topicmode == b'enforce-all':
>              ismergecommit = False
>              mayabort = True
>              maywarn = False
>
> -        hint = _("see 'hg help -e topic.topic-mode' for details")
> -        if opts.get('topic'):
> -            t = opts['topic']
> -            with repo.vfs.open('topic', 'w') as f:
> +        hint = _(b"see 'hg help -e topic.topic-mode' for details")
> +        if opts.get(b'topic'):
> +            t = opts[b'topic']
> +            with repo.vfs.open(b'topic', b'w') as f:
>                  f.write(t)
> -        elif opts.get('amend'):
> +        elif opts.get(b'amend'):
>              pass
>          elif notopic and mayabort:
> -            msg = _("no active topic")
> +            msg = _(b"no active topic")
>              raise error.Abort(msg, hint=hint)
>          elif notopic and maywarn:
> -            ui.warn(_("warning: new draft commit without topic\n"))
> +            ui.warn(_(b"warning: new draft commit without topic\n"))
>              if not ui.quiet:
> -                ui.warn(("(%s)\n") % hint)
> +                ui.warn((b"(%s)\n") % hint)
>          elif notopic and mayrandom:
> -            with repo.vfs.open('topic', 'w') as f:
> +            with repo.vfs.open(b'topic', b'w') as f:
>                  f.write(randomname.randomtopicname(ui))
>          return orig(ui, repo, *args, **opts)
>
> @@ -1162,18 +1162,18 @@
>      if hastopicext(repo):
>          t = repo.currenttopic
>          if t:
> -            ret = ret.replace("\nHG: branch",
> -                              "\nHG: topic '%s'\nHG: branch" % t)
> +            ret = ret.replace(b"\nHG: branch",
> +                              b"\nHG: topic '%s'\nHG: branch" % t)
>      return ret
>
>  def pushoutgoingwrap(orig, ui, repo, *args, **opts):
> -    if opts.get('topic'):
> -        topicrevs = repo.revs('topic(%s) - obsolete()', opts['topic'])
> -        opts.setdefault('rev', []).extend(topicrevs)
> +    if opts.get(b'topic'):
> +        topicrevs = repo.revs(b'topic(%s) - obsolete()', opts[b'topic'])
> +        opts.setdefault(b'rev', []).extend(topicrevs)
>      return orig(ui, repo, *args, **opts)
>
>  def mergeupdatewrap(orig, repo, node, branchmerge, force, *args,
> **kwargs):
> -    matcher = kwargs.get('matcher')
> +    matcher = kwargs.get(b'matcher')
>      partial = not (matcher is None or matcher.always())
>      wlock = repo.wlock()
>      isrebase = False
> @@ -1188,37 +1188,37 @@
>          # rebased commit. We have explicitly stored in config if rebase is
>          # running.
>          ot = repo.currenttopic
> -        if repo.ui.hasconfig('experimental', 'topicrebase'):
> +        if repo.ui.hasconfig(b'experimental', b'topicrebase'):
>              isrebase = True
> -        if repo.ui.configbool('_internal', 'keep-topic'):
> +        if repo.ui.configbool(b'_internal', b'keep-topic'):
>              ist0 = True
>          if ((not partial and not branchmerge) or isrebase) and not ist0:
> -            t = ''
> +            t = b''
>              pctx = repo[node]
>              if pctx.phase() > phases.public:
>                  t = pctx.topic()
> -            with repo.vfs.open('topic', 'w') as f:
> +            with repo.vfs.open(b'topic', b'w') as f:
>                  f.write(t)
>              if t and t != ot:
> -                repo.ui.status(_("switching to topic %s\n") % t)
> +                repo.ui.status(_(b"switching to topic %s\n") % t)
>              if ot and not t:
>                  empty = stack.stack(repo, topic=ot).changesetcount == 0
>                  if empty:
> -                    repo.ui.status(_('clearing empty topic "%s"\n') % ot)
> +                    repo.ui.status(_(b'clearing empty topic "%s"\n') % ot)
>          elif ist0:
> -            repo.ui.status(_("preserving the current topic '%s'\n") % ot)
> +            repo.ui.status(_(b"preserving the current topic '%s'\n") % ot)
>          return ret
>      finally:
>          wlock.release()
>
>  def checkt0(orig, ui, repo, node=None, rev=None, *args, **kwargs):
>
> -    thezeros = set(['t0', 'b0', 's0'])
> -    backup = repo.ui.backupconfig('_internal', 'keep-topic')
> +    thezeros = set([b't0', b'b0', b's0'])
> +    backup = repo.ui.backupconfig(b'_internal', b'keep-topic')
>      try:
>          if node in thezeros or rev in thezeros:
> -            repo.ui.setconfig('_internal', 'keep-topic', 'yes',
> -                              source='topic-extension')
> +            repo.ui.setconfig(b'_internal', b'keep-topic', b'yes',
> +                              source=b'topic-extension')
>          return orig(ui, repo, node=node, rev=rev, *args, **kwargs)
>      finally:
>          repo.ui.restoreconfig(backup)
> @@ -1232,25 +1232,25 @@
>              extra[constants.extrakey] = ctx.topic()
>
>      def setrebaseconfig(orig, ui, repo, **opts):
> -        repo.ui.setconfig('experimental', 'topicrebase', 'yes',
> -                          source='topic-extension')
> +        repo.ui.setconfig(b'experimental', b'topicrebase', b'yes',
> +                          source=b'topic-extension')
>          return orig(ui, repo, **opts)
>
>      def new_init(orig, *args, **kwargs):
>          runtime = orig(*args, **kwargs)
>
> -        if util.safehasattr(runtime, 'extrafns'):
> +        if util.safehasattr(runtime, b'extrafns'):
>              runtime.extrafns.append(savetopic)
>
>          return runtime
>
>      try:
> -        rebase = extensions.find("rebase")
> -        extensions.wrapfunction(rebase.rebaseruntime, '__init__',
> new_init)
> +        rebase = extensions.find(b"rebase")
> +        extensions.wrapfunction(rebase.rebaseruntime, b'__init__',
> new_init)
>          # This exists to store in the config that rebase is running so
> that we can
>          # update the topic according to rebase. This is a hack and should
> be removed
>          # when we have better options.
> -        extensions.wrapcommand(rebase.cmdtable, 'rebase', setrebaseconfig)
> +        extensions.wrapcommand(rebase.cmdtable, b'rebase',
> setrebaseconfig)
>      except KeyError:
>          pass
>
> @@ -1259,27 +1259,27 @@
>  def _exporttopic(seq, ctx):
>      topic = ctx.topic()
>      if topic:
> -        return 'EXP-Topic %s' % topic
> +        return b'EXP-Topic %s' % topic
>      return None
>
>  def _importtopic(repo, patchdata, extra, opts):
> -    if 'topic' in patchdata:
> -        extra['topic'] = patchdata['topic']
> +    if b'topic' in patchdata:
> +        extra[b'topic'] = patchdata[b'topic']
>
>  def setupimportexport(ui):
>      """run at ui setup time to install import/export logic"""
> -    cmdutil.extraexport.append('topic')
> -    cmdutil.extraexportmap['topic'] = _exporttopic
> -    cmdutil.extrapreimport.append('topic')
> -    cmdutil.extrapreimportmap['topic'] = _importtopic
> -    patch.patchheadermap.append(('EXP-Topic', 'topic'))
> +    cmdutil.extraexport.append(b'topic')
> +    cmdutil.extraexportmap[b'topic'] = _exporttopic
> +    cmdutil.extrapreimport.append(b'topic')
> +    cmdutil.extrapreimportmap[b'topic'] = _importtopic
> +    patch.patchheadermap.append((b'EXP-Topic', b'topic'))
>
>  ## preserve topic during split
>
>  def presplitupdatetopic(original, repo, ui, prev, ctx):
>      # Save topic of revision
>      topic = None
> -    if util.safehasattr(ctx, 'topic'):
> +    if util.safehasattr(ctx, b'topic'):
>          topic = ctx.topic()
>
>      # Update the working directory
> diff --git a/hgext3rd/topic/constants.py b/hgext3rd/topic/constants.py
> --- a/hgext3rd/topic/constants.py
> +++ b/hgext3rd/topic/constants.py
> @@ -1,2 +1,2 @@
> -extrakey = 'topic'
> -changekey = '_rewrite_noise'
> +extrakey = b'topic'
> +changekey = b'_rewrite_noise'
> diff --git a/hgext3rd/topic/destination.py b/hgext3rd/topic/destination.py
> --- a/hgext3rd/topic/destination.py
> +++ b/hgext3rd/topic/destination.py
> @@ -13,11 +13,11 @@
>  )
>  from .evolvebits import builddependencies
>
> -def _destmergebranch(orig, repo, action='merge', sourceset=None,
> +def _destmergebranch(orig, repo, action=b'merge', sourceset=None,
>                       onheadcheck=True, destspace=None):
>      # XXX: take destspace into account
>      if sourceset is None:
> -        p1 = repo['.']
> +        p1 = repo[b'.']
>      else:
>          # XXX: using only the max here is flacky. That code should
> eventually
>          # be updated to take care of the whole sourceset.
> @@ -26,11 +26,11 @@
>      if common.hastopicext(repo):
>          top = p1.topic()
>      if top:
> -        revs = repo.revs('topic(%s) - obsolete()', top)
> +        revs = repo.revs(b'topic(%s) - obsolete()', top)
>          deps, rdeps = builddependencies(repo, revs)
>          heads = [r for r in revs if not rdeps[r]]
>          if onheadcheck and p1.rev() not in heads:
> -            raise error.Abort(_("not at topic head, update or explicit"))
> +            raise error.Abort(_(b"not at topic head, update or explicit"))
>
>          # prune heads above the source
>          otherheads = set(heads)
> @@ -43,20 +43,20 @@
>              # nothing to do at the topic level
>              bhead = ngtip(repo, p1.branch(), all=True)
>              if not bhead:
> -                raise error.NoMergeDestAbort(_("nothing to merge"))
> +                raise error.NoMergeDestAbort(_(b"nothing to merge"))
>              elif 1 == len(bhead):
>                  return bhead[0]
>              else:
> -                msg = _("branch '%s' has %d heads "
> -                        "- please merge with an explicit rev")
> -                hint = _("run 'hg heads .' to see heads")
> +                msg = _(b"branch '%s' has %d heads "
> +                        b"- please merge with an explicit rev")
> +                hint = _(b"run 'hg heads .' to see heads")
>                  raise error.ManyMergeDestAbort(msg % (p1.branch(),
> len(bhead)),
>                                                 hint=hint)
>          elif len(otherheads) == 1:
>              return otherheads.pop()
>          else:
> -            msg = _("topic '%s' has %d heads "
> -                    "- please merge with an explicit rev") % (top,
> len(heads))
> +            msg = _(b"topic '%s' has %d heads "
> +                    b"- please merge with an explicit rev") % (top,
> len(heads))
>              raise error.ManyMergeDestAbort(msg)
>      return orig(repo, action, sourceset, onheadcheck, destspace=destspace)
>
> @@ -67,23 +67,23 @@
>      movemark = node = None
>      topic = repo.currenttopic
>      if topic:
> -        revs = repo.revs('.::topic(%s)', topic)
> +        revs = repo.revs(b'.::topic(%s)', topic)
>      else:
>          revs = []
>      if not revs:
>          return None, None, None
>      node = revs.last()
>      if bookmarks.isactivewdirparent(repo):
> -        movemark = repo['.'].node()
> +        movemark = repo[b'.'].node()
>      return node, movemark, None
>
>  def desthistedit(orig, ui, repo):
>      if not common.hastopicext(repo):
>          return None
> -    if not (ui.config('histedit', 'defaultrev', None) is None
> +    if not (ui.config(b'histedit', b'defaultrev', None) is None
>              and repo.currenttopic):
>          return orig(ui, repo)
> -    revs = repo.revs('::. and stack()')
> +    revs = repo.revs(b'::. and stack()')
>      if revs:
>          return revs.min()
>      return None
> @@ -106,8 +106,8 @@
>
>  def modsetup(ui):
>      """run a uisetup time to install all destinations wrapping"""
> -    extensions.wrapfunction(destutil, '_destmergebranch',
> _destmergebranch)
> -    bridx = destutil.destupdatesteps.index('branch')
> -    destutil.destupdatesteps.insert(bridx, 'topic')
> -    destutil.destupdatestepmap['topic'] = _destupdatetopic
> -    extensions.wrapfunction(destutil, 'desthistedit', desthistedit)
> +    extensions.wrapfunction(destutil, b'_destmergebranch',
> _destmergebranch)
> +    bridx = destutil.destupdatesteps.index(b'branch')
> +    destutil.destupdatesteps.insert(bridx, b'topic')
> +    destutil.destupdatestepmap[b'topic'] = _destupdatetopic
> +    extensions.wrapfunction(destutil, b'desthistedit', desthistedit)
> diff --git a/hgext3rd/topic/discovery.py b/hgext3rd/topic/discovery.py
> --- a/hgext3rd/topic/discovery.py
> +++ b/hgext3rd/topic/discovery.py
> @@ -27,12 +27,12 @@
>      repo = pushop.repo.unfiltered()
>      remote = pushop.remote
>
> -    publishing = ('phases' not in remote.listkeys('namespaces')
> -                  or bool(remote.listkeys('phases').get('publishing',
> False)))
> +    publishing = (b'phases' not in remote.listkeys(b'namespaces')
> +                  or bool(remote.listkeys(b'phases').get(b'publishing',
> False)))
>
>      if not common.hastopicext(pushop.repo):
>          return orig(pushop, *args, **kwargs)
> -    elif ((publishing or not remote.capable('topics'))
> +    elif ((publishing or not remote.capable(b'topics'))
>              and not getattr(pushop, 'publish', False)):
>          return orig(pushop, *args, **kwargs)
>
> @@ -40,7 +40,7 @@
>      remotebranchmap = None
>      origremotebranchmap = remote.branchmap
>      publishednode = [c.node() for c in pushop.outdatedphases]
> -    publishedset = repo.revs('ancestors(%ln + %ln)',
> +    publishedset = repo.revs(b'ancestors(%ln + %ln)',
>                               publishednode,
>                               pushop.remotephases.publicheads)
>
> @@ -49,18 +49,18 @@
>      def remotebranchmap():
>          # drop topic information from changeset about to be published
>          result = collections.defaultdict(list)
> -        for branch, heads in origremotebranchmap().iteritems():
> -            if ':' not in branch:
> +        for branch, heads in origremotebranchmap().items():
> +            if b':' not in branch:
>                  result[branch].extend(heads)
>              else:
> -                namedbranch = branch.split(':', 1)[0]
> +                namedbranch = branch.split(b':', 1)[0]
>                  for h in heads:
>                      r = rev(h)
>                      if r is not None and r in publishedset:
>                          result[namedbranch].append(h)
>                      else:
>                          result[branch].append(h)
> -        for heads in result.itervalues():
> +        for heads in result.values():
>              heads.sort()
>          return result
>
> @@ -77,7 +77,7 @@
>                      return branch
>                  topic = ctx.topic()
>                  if topic:
> -                    branch = "%s:%s" % (branch, topic)
> +                    branch = b"%s:%s" % (branch, topic)
>                  return branch
>
>              ctx.branch = branch
> @@ -95,7 +95,7 @@
>                      return branch, close
>                  topic = repo[rev].topic()
>                  if topic:
> -                    branch = "%s:%s" % (branch, topic)
> +                    branch = b"%s:%s" % (branch, topic)
>                  return branch, close
>
>              rbc.branchinfo = branchinfo
> @@ -106,17 +106,17 @@
>          repo.__class__ = repocls
>          if remotebranchmap is not None:
>              remote.branchmap = remotebranchmap
> -        unxx = repo.filtered('unfiltered-topic')
> +        unxx = repo.filtered(b'unfiltered-topic')
>          repo.unfiltered = lambda: unxx
>          pushop.repo = repo
>          summary = orig(pushop)
> -        for key, value in summary.iteritems():
> -            if ':' in key: # This is a topic
> +        for key, value in summary.items():
> +            if b':' in key: # This is a topic
>                  if value[0] is None and value[1]:
>                      summary[key] = ([value[1][0]], ) + value[1:]
>          return summary
>      finally:
> -        if 'unfiltered' in vars(repo):
> +        if b'unfiltered' in vars(repo):
>              del repo.unfiltered
>          repo.__class__ = oldrepocls
>          if remotebranchmap is not None:
> @@ -146,7 +146,7 @@
>  def _nbheads(repo):
>      data = {}
>      for b in repo.branchmap().iterbranches():
> -        if ':' in b[0]:
> +        if b':' in b[0]:
>              continue
>          data[b[0]] = len(b[1])
>      return data
> @@ -157,11 +157,11 @@
>      if not common.hastopicext(op.repo) or op.repo.publishing():
>          return
>      tr = op.gettransaction()
> -    if tr.hookargs['source'] not in ('push', 'serve'): # not a push
> +    if tr.hookargs[b'source'] not in (b'push', b'serve'): # not a push
>          return
>      tr._prepushheads = _nbheads(op.repo)
>      reporef = weakref.ref(op.repo)
> -    if util.safehasattr(tr, 'validator'): # hg <= 4.7
> +    if util.safehasattr(tr, b'validator'): # hg <= 4.7
>          oldvalidator = tr.validator
>      else:
>          oldvalidator = tr._validator
> @@ -171,18 +171,18 @@
>          if repo is not None:
>              repo.invalidatecaches()
>              finalheads = _nbheads(repo)
> -            for branch, oldnb in tr._prepushheads.iteritems():
> +            for branch, oldnb in tr._prepushheads.items():
>                  newnb = finalheads.pop(branch, 0)
>                  if oldnb < newnb:
> -                    msg = _('push create a new head on branch "%s"' %
> branch)
> +                    msg = _(b'push create a new head on branch "%s"' %
> branch)
>                      raise error.Abort(msg)
> -            for branch, newnb in finalheads.iteritems():
> +            for branch, newnb in finalheads.items():
>                  if 1 < newnb:
> -                    msg = _('push create more than 1 head on new branch
> "%s"'
> +                    msg = _(b'push create more than 1 head on new branch
> "%s"'
>                              % branch)
>                      raise error.Abort(msg)
>          return oldvalidator(tr)
> -    if util.safehasattr(tr, 'validator'): # hg <= 4.7
> +    if util.safehasattr(tr, b'validator'): # hg <= 4.7
>          tr.validator = validator
>      else:
>          tr._validator = validator
> @@ -190,7 +190,7 @@
>
>  def _pushb2phases(orig, pushop, bundler):
>      if common.hastopicext(pushop.repo):
> -        checktypes = ('check:heads', 'check:updated-heads')
> +        checktypes = (b'check:heads', b'check:updated-heads')
>          hascheck = any(p.type in checktypes for p in bundler._parts)
>          if not hascheck and pushop.outdatedphases:
>              exchange._pushb2ctxcheckheads(pushop, bundler)
> @@ -198,23 +198,23 @@
>
>  def wireprotocaps(orig, repo, proto):
>      caps = orig(repo, proto)
> -    if common.hastopicext(repo) and repo.peer().capable('topics'):
> -        caps.append('topics')
> +    if common.hastopicext(repo) and repo.peer().capable(b'topics'):
> +        caps.append(b'topics')
>      return caps
>
>  def modsetup(ui):
>      """run at uisetup time to install all destinations wrapping"""
> -    extensions.wrapfunction(discovery, '_headssummary', _headssummary)
> -    extensions.wrapfunction(wireproto, 'branchmap', wireprotobranchmap)
> -    extensions.wrapfunction(wireproto, '_capabilities', wireprotocaps)
> +    extensions.wrapfunction(discovery, b'_headssummary', _headssummary)
> +    extensions.wrapfunction(wireproto, b'branchmap', wireprotobranchmap)
> +    extensions.wrapfunction(wireproto, b'_capabilities', wireprotocaps)
>      # we need a proper wrap b2 part stuff
> -    extensions.wrapfunction(bundle2, 'handlecheckheads', handlecheckheads)
> +    extensions.wrapfunction(bundle2, b'handlecheckheads',
> handlecheckheads)
>      bundle2.handlecheckheads.params = frozenset()
> -    bundle2.parthandlermapping['check:heads'] = bundle2.handlecheckheads
> -    if util.safehasattr(bundle2, 'handlecheckupdatedheads'):
> +    bundle2.parthandlermapping[b'check:heads'] = bundle2.handlecheckheads
> +    if util.safehasattr(bundle2, b'handlecheckupdatedheads'):
>          # we still need a proper wrap b2 part stuff
> -        extensions.wrapfunction(bundle2, 'handlecheckupdatedheads',
> handlecheckheads)
> +        extensions.wrapfunction(bundle2, b'handlecheckupdatedheads',
> handlecheckheads)
>          bundle2.handlecheckupdatedheads.params = frozenset()
> -        bundle2.parthandlermapping['check:updated-heads'] =
> bundle2.handlecheckupdatedheads
> -    extensions.wrapfunction(exchange, '_pushb2phases', _pushb2phases)
> -    exchange.b2partsgenmapping['phase'] = exchange._pushb2phases
> +        bundle2.parthandlermapping[b'check:updated-heads'] =
> bundle2.handlecheckupdatedheads
> +    extensions.wrapfunction(exchange, b'_pushb2phases', _pushb2phases)
> +    exchange.b2partsgenmapping[b'phase'] = exchange._pushb2phases
> diff --git a/hgext3rd/topic/evolvebits.py b/hgext3rd/topic/evolvebits.py
> --- a/hgext3rd/topic/evolvebits.py
> +++ b/hgext3rd/topic/evolvebits.py
> @@ -78,8 +78,8 @@
>      newer = obsutil.successorssets(repo, obs.node())
>      # search of a parent which is not killed
>      while not newer:
> -        ui.debug("stabilize target %s is plain dead,"
> -                 " trying to stabilize on its parent\n" %
> +        ui.debug(b"stabilize target %s is plain dead,"
> +                 b" trying to stabilize on its parent\n" %
>                   obs)
>          obs = obs.parents()[0]
>          newer = obsutil.successorssets(repo, obs.node())
> @@ -88,7 +88,7 @@
>          # we should pick as arbitrary one
>          raise MultipleSuccessorsError(newer)
>      elif 1 < len(newer[0]):
> -        splitheads = list(repo.revs('heads(%ln::%ln)', newer[0],
> newer[0]))
> +        splitheads = list(repo.revs(b'heads(%ln::%ln)', newer[0],
> newer[0]))
>          if 1 < len(splitheads):
>              # split case, See if we can make sense of it.
>              raise MultipleSuccessorsError(newer)
> diff --git a/hgext3rd/topic/flow.py b/hgext3rd/topic/flow.py
> --- a/hgext3rd/topic/flow.py
> +++ b/hgext3rd/topic/flow.py
> @@ -12,18 +12,18 @@
>  from mercurial.i18n import _
>
>  def enforcesinglehead(repo, tr):
> -    for name, heads in repo.filtered('visible').branchmap().iteritems():
> +    for name, heads in repo.filtered(b'visible').branchmap().items():
>          if len(heads) > 1:
>              hexs = [node.short(n) for n in heads]
> -            raise error.Abort(_('%d heads on "%s"') % (len(heads), name),
> -                              hint=(', '.join(hexs)))
> +            raise error.Abort(_(b'%d heads on "%s"') % (len(heads), name),
> +                              hint=(b', '.join(hexs)))
>
>  def publishbarebranch(repo, tr):
>      """Publish changeset without topic"""
> -    if 'node' not in tr.hookargs: # no new node
> +    if b'node' not in tr.hookargs: # no new node
>          return
> -    startnode = node.bin(tr.hookargs['node'])
> -    topublish = repo.revs('not public() and (%n:) - hidden() - topic()',
> startnode)
> +    startnode = node.bin(tr.hookargs[b'node'])
> +    topublish = repo.revs(b'not public() and (%n:) - hidden() - topic()',
> startnode)
>      if topublish:
>          cl = repo.changelog
>          nodes = [cl.node(r) for r in topublish]
> @@ -31,43 +31,43 @@
>
>  def rejectuntopicedchangeset(repo, tr):
>      """Reject the push if there are changeset without topic"""
> -    if 'node' not in tr.hookargs: # no new revs
> +    if b'node' not in tr.hookargs: # no new revs
>          return
>
> -    startnode = node.bin(tr.hookargs['node'])
> +    startnode = node.bin(tr.hookargs[b'node'])
>
> -    mode = repo.ui.config('experimental', 'topic-mode.server', 'ignore')
> +    mode = repo.ui.config(b'experimental', b'topic-mode.server',
> b'ignore')
>
> -    untopiced = repo.revs('not public() and (%n:) - hidden() - topic()',
> startnode)
> +    untopiced = repo.revs(b'not public() and (%n:) - hidden() - topic()',
> startnode)
>      if untopiced:
>          num = len(untopiced)
>          fnode = repo[untopiced.first()].hex()[:10]
>          if num == 1:
> -            msg = _("%s") % fnode
> +            msg = _(b"%s") % fnode
>          else:
> -            msg = _("%s and %d more") % (fnode, num - 1)
> -        if mode == 'warning':
> -            fullmsg = _("pushed draft changeset without topic: %s\n")
> +            msg = _(b"%s and %d more") % (fnode, num - 1)
> +        if mode == b'warning':
> +            fullmsg = _(b"pushed draft changeset without topic: %s\n")
>              repo.ui.warn(fullmsg % msg)
> -        elif mode == 'enforce':
> -            fullmsg = _("rejecting draft changesets: %s")
> +        elif mode == b'enforce':
> +            fullmsg = _(b"rejecting draft changesets: %s")
>              raise error.Abort(fullmsg % msg)
>          else:
> -            repo.ui.warn(_("unknown 'topic-mode.server': %s\n" % mode))
> +            repo.ui.warn(_(b"unknown 'topic-mode.server': %s\n" % mode))
>
>  def wrappush(orig, repo, remote, *args, **kwargs):
>      """interpret the --publish flag and pass it to the push operation"""
>      newargs = kwargs.copy()
> -    if kwargs.pop('publish', False):
> -        opargs = kwargs.get('opargs')
> +    if kwargs.pop(b'publish', False):
> +        opargs = kwargs.get(b'opargs')
>          if opargs is None:
>              opargs = {}
> -        newargs['opargs'] = opargs.copy()
> -        newargs['opargs']['publish'] = True
> +        newargs[b'opargs'] = opargs.copy()
> +        newargs[b'opargs'][b'publish'] = True
>      return orig(repo, remote, *args, **newargs)
>
>  def extendpushoperation(orig, self, *args, **kwargs):
> -    publish = kwargs.pop('publish', False)
> +    publish = kwargs.pop(b'publish', False)
>      orig(self, *args, **kwargs)
>      self.publish = publish
>
> @@ -77,16 +77,16 @@
>          if not pushop.remotephases.publishing:
>              unfi = pushop.repo.unfiltered()
>              droots = pushop.remotephases.draftroots
> -            revset = '%ln and (not public() or %ln::)'
> +            revset = b'%ln and (not public() or %ln::)'
>              future = list(unfi.set(revset, pushop.futureheads, droots))
>              pushop.outdatedphases = future
>
>  def installpushflag(ui):
> -    entry = extensions.wrapcommand(commands.table, 'push', wrappush)
> -    if not any(opt for opt in entry[1] if opt[1] == 'publish'): # hg <=
> 4.9
> -        entry[1].append(('', 'publish', False,
> -                         _('push the changeset as public')))
> -    extensions.wrapfunction(exchange.pushoperation, '__init__',
> +    entry = extensions.wrapcommand(commands.table, b'push', wrappush)
> +    if not any(opt for opt in entry[1] if opt[1] == b'publish'): # hg <=
> 4.9
> +        entry[1].append((b'', b'publish', False,
> +                         _(b'push the changeset as public')))
> +    extensions.wrapfunction(exchange.pushoperation, b'__init__',
>                              extendpushoperation)
> -    extensions.wrapfunction(exchange, '_pushdiscoveryphase',
> wrapphasediscovery)
> -    exchange.pushdiscoverymapping['phase'] = exchange._pushdiscoveryphase
> +    extensions.wrapfunction(exchange, b'_pushdiscoveryphase',
> wrapphasediscovery)
> +    exchange.pushdiscoverymapping[b'phase'] = exchange._pushdiscoveryphase
> diff --git a/hgext3rd/topic/randomname.py b/hgext3rd/topic/randomname.py
> --- a/hgext3rd/topic/randomname.py
> +++ b/hgext3rd/topic/randomname.py
> @@ -8,1003 +8,1003 @@
>  import random
>
>  animals = [
> -    'aardvark',
> -    'albatross',
> -    'alligator',
> -    'alpaca',
> -    'ant',
> -    'anteater',
> -    'antelope',
> -    'ape',
> -    'armadillo',
> -    'baboon',
> -    'badger',
> -    'barracuda',
> -    'bat',
> -    'bear',
> -    'beaver',
> -    'bee',
> -    'beetle',
> -    'bison',
> -    'boar',
> -    'buffalo',
> -    'bushbaby',
> -    'bustard',
> -    'butterfly',
> -    'camel',
> -    'capuchin',
> -    'carabao',
> -    'caribou',
> -    'cat',
> -    'caterpillar',
> -    'cattle',
> -    'chameleon',
> -    'chamois',
> -    'cheetah',
> -    'chicken',
> -    'chimpanzee',
> -    'chinchilla',
> -    'chipmunk',
> -    'chough',
> -    'cicada',
> -    'clam',
> -    'cobra',
> -    'cockroach',
> -    'cod',
> -    'cormorant',
> -    'coyote',
> -    'crab',
> -    'crane',
> -    'cricket',
> -    'crocodile',
> -    'crow',
> -    'curlew',
> -    'deer',
> -    'dinosaur',
> -    'dog',
> -    'dogfish',
> -    'dolphin',
> -    'donkey',
> -    'dotterel',
> -    'dove',
> -    'dragon',
> -    'dragonfly',
> -    'duck',
> -    'dugong',
> -    'dunlin',
> -    'eagle',
> -    'echidna',
> -    'eel',
> -    'eland',
> -    'elephant',
> -    'elk',
> -    'emu',
> -    'falcon',
> -    'ferret',
> -    'finch',
> -    'fish',
> -    'flamingo',
> -    'fly',
> -    'fox',
> -    'frog',
> -    'gaur',
> -    'gazelle',
> -    'gecko',
> -    'gerbil',
> -    'giraffe',
> -    'gnat',
> -    'gnu',
> -    'goat',
> -    'goldfish',
> -    'goose',
> -    'gorilla',
> -    'goshawk',
> -    'grasshopper',
> -    'grouse',
> -    'guanaco',
> -    'guinea',
> -    'gull',
> -    'hamster',
> -    'hare',
> -    'hawk',
> -    'hedgehog',
> -    'heron',
> -    'herring',
> -    'hippopotamus',
> -    'hornet',
> -    'horse',
> -    'horsecrab',
> -    'hound',
> -    'hummingbird',
> -    'hyena',
> -    'hyrax',
> -    'ibex',
> -    'ibis',
> -    'iguana',
> -    'impala',
> -    'insect',
> -    'jackal',
> -    'jaguar',
> -    'jay',
> -    'jellyfish',
> -    'kangaroo',
> -    'koala',
> -    'kouprey',
> -    'kudu',
> -    'lapwing',
> -    'lark',
> -    'lemming',
> -    'lemur',
> -    'leopard',
> -    'lion',
> -    'lizard',
> -    'llama',
> -    'lobster',
> -    'locust',
> -    'loris',
> -    'louse',
> -    'lynx',
> -    'lyrebird',
> -    'magpie',
> -    'mallard',
> -    'mammoth',
> -    'manatee',
> -    'marten',
> -    'meerkat',
> -    'mink',
> -    'minnow',
> -    'mole',
> -    'mongoose',
> -    'monkey',
> -    'moose',
> -    'mosquito',
> -    'mouse',
> -    'mule',
> -    'muskrat',
> -    'narwhal',
> -    'newt',
> -    'nightingale',
> -    'numbat',
> -    'octopus',
> -    'okapi',
> -    'opossum',
> -    'oryx',
> -    'ostrich',
> -    'otter',
> -    'owl',
> -    'ox',
> -    'oyster',
> -    'panda',
> -    'panther',
> -    'parrot',
> -    'partridge',
> -    'peacock',
> -    'peafowl',
> -    'pelican',
> -    'penguin',
> -    'pheasant',
> -    'pig',
> -    'pigeon',
> -    'platypus',
> -    'pony',
> -    'porcupine',
> -    'porpoise',
> -    'puffin',
> -    'pug',
> -    'quagga',
> -    'quail',
> -    'quelea',
> -    'rabbit',
> -    'raccoon',
> -    'ram',
> -    'rat',
> -    'raven',
> -    'reindeer',
> -    'rhea',
> -    'rhinoceros',
> -    'rook',
> -    'ruff',
> -    'salamander',
> -    'salmon',
> -    'sambar',
> -    'sandpiper',
> -    'sardine',
> -    'scorpion',
> -    'seahorse',
> -    'seal',
> -    'serval',
> -    'shark',
> -    'sheep',
> -    'shrew',
> -    'shrimp',
> -    'skink',
> -    'skunk',
> -    'snail',
> -    'snake',
> -    'spider',
> -    'squid',
> -    'squirrel',
> -    'starling',
> -    'stinkbug',
> -    'stork',
> -    'swan',
> -    'tapir',
> -    'tarsier',
> -    'termite',
> -    'tern',
> -    'tiger',
> -    'toad',
> -    'trout',
> -    'turkey',
> -    'turtle',
> -    'unicorn',
> -    'viper',
> -    'vulture',
> -    'wallaby',
> -    'walrus',
> -    'wasp',
> -    'weasel',
> -    'whale',
> -    'wolf',
> -    'wolverine',
> -    'wombat',
> -    'woodchuck',
> -    'woodcock',
> -    'woodpecker',
> -    'worm',
> -    'wren',
> -    'yak',
> -    'zebra',
> -    'zorilla'
> +    b'aardvark',
> +    b'albatross',
> +    b'alligator',
> +    b'alpaca',
> +    b'ant',
> +    b'anteater',
> +    b'antelope',
> +    b'ape',
> +    b'armadillo',
> +    b'baboon',
> +    b'badger',
> +    b'barracuda',
> +    b'bat',
> +    b'bear',
> +    b'beaver',
> +    b'bee',
> +    b'beetle',
> +    b'bison',
> +    b'boar',
> +    b'buffalo',
> +    b'bushbaby',
> +    b'bustard',
> +    b'butterfly',
> +    b'camel',
> +    b'capuchin',
> +    b'carabao',
> +    b'caribou',
> +    b'cat',
> +    b'caterpillar',
> +    b'cattle',
> +    b'chameleon',
> +    b'chamois',
> +    b'cheetah',
> +    b'chicken',
> +    b'chimpanzee',
> +    b'chinchilla',
> +    b'chipmunk',
> +    b'chough',
> +    b'cicada',
> +    b'clam',
> +    b'cobra',
> +    b'cockroach',
> +    b'cod',
> +    b'cormorant',
> +    b'coyote',
> +    b'crab',
> +    b'crane',
> +    b'cricket',
> +    b'crocodile',
> +    b'crow',
> +    b'curlew',
> +    b'deer',
> +    b'dinosaur',
> +    b'dog',
> +    b'dogfish',
> +    b'dolphin',
> +    b'donkey',
> +    b'dotterel',
> +    b'dove',
> +    b'dragon',
> +    b'dragonfly',
> +    b'duck',
> +    b'dugong',
> +    b'dunlin',
> +    b'eagle',
> +    b'echidna',
> +    b'eel',
> +    b'eland',
> +    b'elephant',
> +    b'elk',
> +    b'emu',
> +    b'falcon',
> +    b'ferret',
> +    b'finch',
> +    b'fish',
> +    b'flamingo',
> +    b'fly',
> +    b'fox',
> +    b'frog',
> +    b'gaur',
> +    b'gazelle',
> +    b'gecko',
> +    b'gerbil',
> +    b'giraffe',
> +    b'gnat',
> +    b'gnu',
> +    b'goat',
> +    b'goldfish',
> +    b'goose',
> +    b'gorilla',
> +    b'goshawk',
> +    b'grasshopper',
> +    b'grouse',
> +    b'guanaco',
> +    b'guinea',
> +    b'gull',
> +    b'hamster',
> +    b'hare',
> +    b'hawk',
> +    b'hedgehog',
> +    b'heron',
> +    b'herring',
> +    b'hippopotamus',
> +    b'hornet',
> +    b'horse',
> +    b'horsecrab',
> +    b'hound',
> +    b'hummingbird',
> +    b'hyena',
> +    b'hyrax',
> +    b'ibex',
> +    b'ibis',
> +    b'iguana',
> +    b'impala',
> +    b'insect',
> +    b'jackal',
> +    b'jaguar',
> +    b'jay',
> +    b'jellyfish',
> +    b'kangaroo',
> +    b'koala',
> +    b'kouprey',
> +    b'kudu',
> +    b'lapwing',
> +    b'lark',
> +    b'lemming',
> +    b'lemur',
> +    b'leopard',
> +    b'lion',
> +    b'lizard',
> +    b'llama',
> +    b'lobster',
> +    b'locust',
> +    b'loris',
> +    b'louse',
> +    b'lynx',
> +    b'lyrebird',
> +    b'magpie',
> +    b'mallard',
> +    b'mammoth',
> +    b'manatee',
> +    b'marten',
> +    b'meerkat',
> +    b'mink',
> +    b'minnow',
> +    b'mole',
> +    b'mongoose',
> +    b'monkey',
> +    b'moose',
> +    b'mosquito',
> +    b'mouse',
> +    b'mule',
> +    b'muskrat',
> +    b'narwhal',
> +    b'newt',
> +    b'nightingale',
> +    b'numbat',
> +    b'octopus',
> +    b'okapi',
> +    b'opossum',
> +    b'oryx',
> +    b'ostrich',
> +    b'otter',
> +    b'owl',
> +    b'ox',
> +    b'oyster',
> +    b'panda',
> +    b'panther',
> +    b'parrot',
> +    b'partridge',
> +    b'peacock',
> +    b'peafowl',
> +    b'pelican',
> +    b'penguin',
> +    b'pheasant',
> +    b'pig',
> +    b'pigeon',
> +    b'platypus',
> +    b'pony',
> +    b'porcupine',
> +    b'porpoise',
> +    b'puffin',
> +    b'pug',
> +    b'quagga',
> +    b'quail',
> +    b'quelea',
> +    b'rabbit',
> +    b'raccoon',
> +    b'ram',
> +    b'rat',
> +    b'raven',
> +    b'reindeer',
> +    b'rhea',
> +    b'rhinoceros',
> +    b'rook',
> +    b'ruff',
> +    b'salamander',
> +    b'salmon',
> +    b'sambar',
> +    b'sandpiper',
> +    b'sardine',
> +    b'scorpion',
> +    b'seahorse',
> +    b'seal',
> +    b'serval',
> +    b'shark',
> +    b'sheep',
> +    b'shrew',
> +    b'shrimp',
> +    b'skink',
> +    b'skunk',
> +    b'snail',
> +    b'snake',
> +    b'spider',
> +    b'squid',
> +    b'squirrel',
> +    b'starling',
> +    b'stinkbug',
> +    b'stork',
> +    b'swan',
> +    b'tapir',
> +    b'tarsier',
> +    b'termite',
> +    b'tern',
> +    b'tiger',
> +    b'toad',
> +    b'trout',
> +    b'turkey',
> +    b'turtle',
> +    b'unicorn',
> +    b'viper',
> +    b'vulture',
> +    b'wallaby',
> +    b'walrus',
> +    b'wasp',
> +    b'weasel',
> +    b'whale',
> +    b'wolf',
> +    b'wolverine',
> +    b'wombat',
> +    b'woodchuck',
> +    b'woodcock',
> +    b'woodpecker',
> +    b'worm',
> +    b'wren',
> +    b'yak',
> +    b'zebra',
> +    b'zorilla'
>  ]
>
>  adjectives = [
> -    'abiding',
> -    'abject',
> -    'ablaze',
> -    'able',
> -    'aboard',
> -    'abounding',
> -    'absorbed',
> -    'absorbing',
> -    'abstracted',
> -    'abundant',
> -    'acceptable',
> -    'accessible',
> -    'accurate',
> -    'acoustic',
> -    'adamant',
> -    'adaptable',
> -    'adhesive',
> -    'adjoining',
> -    'adorable',
> -    'adventurous',
> -    'affable',
> -    'affectionate',
> -    'agreeable',
> -    'alert',
> -    'alive',
> -    'alluring',
> -    'amazing',
> -    'ambiguous',
> -    'ambitious',
> -    'amiable',
> -    'amicable',
> -    'amused',
> -    'amusing',
> -    'ancient',
> -    'animated',
> -    'apricot',
> -    'aquatic',
> -    'arctic',
> -    'arenaceous',
> -    'aromatic',
> -    'aspiring',
> -    'assiduous',
> -    'assorted',
> -    'astonishing',
> -    'attractive',
> -    'auspicious',
> -    'automatic',
> -    'available',
> -    'average',
> -    'awake',
> -    'aware',
> -    'awesome',
> -    'axiomatic',
> -    'bashful',
> -    'bawdy',
> -    'beautiful',
> -    'beefy',
> -    'befitting',
> -    'beneficial',
> -    'benevolent',
> -    'bent',
> -    'best',
> -    'better',
> -    'bewildered',
> -    'bewitching',
> -    'big',
> -    'billowy',
> -    'bizarre',
> -    'black',
> -    'blithe',
> -    'blue',
> -    'blushing',
> -    'bouncy',
> -    'boundless',
> -    'brainy',
> -    'brash',
> -    'brave',
> -    'brawny',
> -    'brazen',
> -    'breezy',
> -    'brief',
> -    'bright',
> -    'brilliant',
> -    'broad',
> -    'brown',
> -    'bucolic',
> -    'bulky',
> -    'bumpy',
> -    'burgundy',
> -    'burly',
> -    'bustling',
> -    'busy',
> -    'calm',
> -    'capable',
> -    'capricious',
> -    'captivating',
> -    'carefree',
> -    'careful',
> -    'caring',
> -    'carrot',
> -    'ceaseless',
> -    'cerise',
> -    'certain',
> -    'challenging',
> -    'changeable',
> -    'charming',
> -    'cheerful',
> -    'chief',
> -    'chilly',
> -    'chipper',
> -    'classy',
> -    'clean',
> -    'clear',
> -    'clever',
> -    'cloudy',
> -    'coherent',
> -    'colorful',
> -    'colossal',
> -    'comfortable',
> -    'common',
> -    'communicative',
> -    'compassionate',
> -    'complete',
> -    'complex',
> -    'compulsive',
> -    'confused',
> -    'conscientious',
> -    'conscious',
> -    'conservative',
> -    'considerate',
> -    'convivial',
> -    'cooing',
> -    'cool',
> -    'cooperative',
> -    'coordinated',
> -    'courageous',
> -    'courteous',
> -    'crazy',
> -    'creative',
> -    'crispy',
> -    'crooked',
> -    'crowded',
> -    'cuddly',
> -    'cultured',
> -    'cunning',
> -    'curious',
> -    'curly',
> -    'curved',
> -    'curvy',
> -    'cut',
> -    'cute',
> -    'daily',
> -    'damp',
> -    'dapper',
> -    'dashing',
> -    'dazzling',
> -    'dear',
> -    'debonair',
> -    'decisive',
> -    'decorous',
> -    'deep',
> -    'defiant',
> -    'delicate',
> -    'delicious',
> -    'delighted',
> -    'delightful',
> -    'delirious',
> -    'descriptive',
> -    'detached',
> -    'detailed',
> -    'determined',
> -    'different',
> -    'diligent',
> -    'diminutive',
> -    'diplomatic',
> -    'discreet',
> -    'distinct',
> -    'distinctive',
> -    'dramatic',
> -    'dry',
> -    'dynamic',
> -    'dynamite',
> -    'eager',
> -    'early',
> -    'earthy',
> -    'easy',
> -    'easygoing',
> -    'eatable',
> -    'economic',
> -    'ecstatic',
> -    'educated',
> -    'efficacious',
> -    'efficient',
> -    'effortless',
> -    'eight',
> -    'elastic',
> -    'elated',
> -    'electric',
> -    'elegant',
> -    'elfin',
> -    'elite',
> -    'eminent',
> -    'emotional',
> -    'enchanted',
> -    'enchanting',
> -    'encouraging',
> -    'endless',
> -    'energetic',
> -    'enormous',
> -    'entertaining',
> -    'enthusiastic',
> -    'envious',
> -    'epicurean',
> -    'equable',
> -    'equal',
> -    'eternal',
> -    'ethereal',
> -    'evanescent',
> -    'even',
> -    'excellent',
> -    'excited',
> -    'exciting',
> -    'exclusive',
> -    'exotic',
> -    'expensive',
> -    'exquisite',
> -    'extroverted',
> -    'exuberant',
> -    'exultant',
> -    'fabulous',
> -    'fair',
> -    'faithful',
> -    'familiar',
> -    'famous',
> -    'fancy',
> -    'fantastic',
> -    'far',
> -    'fascinated',
> -    'fast',
> -    'fearless',
> -    'female',
> -    'fertile',
> -    'festive',
> -    'few',
> -    'fine',
> -    'first',
> -    'five',
> -    'fixed',
> -    'flamboyant',
> -    'flashy',
> -    'flat',
> -    'flawless',
> -    'flirtatious',
> -    'florid',
> -    'flowery',
> -    'fluffy',
> -    'fluttering',
> -    'foamy',
> -    'foolish',
> -    'foregoing',
> -    'fortunate',
> -    'four',
> -    'frank',
> -    'free',
> -    'frequent',
> -    'fresh',
> -    'friendly',
> -    'full',
> -    'functional',
> -    'funny',
> -    'furry',
> -    'future',
> -    'futuristic',
> -    'fuzzy',
> -    'gabby',
> -    'gainful',
> -    'garrulous',
> -    'general',
> -    'generous',
> -    'gentle',
> -    'giant',
> -    'giddy',
> -    'gifted',
> -    'gigantic',
> -    'gilded',
> -    'glamorous',
> -    'gleaming',
> -    'glorious',
> -    'glossy',
> -    'glowing',
> -    'godly',
> -    'good',
> -    'goofy',
> -    'gorgeous',
> -    'graceful',
> -    'grandiose',
> -    'grateful',
> -    'gratis',
> -    'gray',
> -    'great',
> -    'green',
> -    'gregarious',
> -    'grey',
> -    'groovy',
> -    'guiltless',
> -    'gusty',
> -    'guttural',
> -    'habitual',
> -    'half',
> -    'hallowed',
> -    'halting',
> -    'handsome',
> -    'happy',
> -    'hard',
> -    'hardworking',
> -    'harmonious',
> -    'heady',
> -    'healthy',
> -    'heavenly',
> -    'helpful',
> -    'hilarious',
> -    'historical',
> -    'holistic',
> -    'hollow',
> -    'honest',
> -    'honorable',
> -    'hopeful',
> -    'hospitable',
> -    'hot',
> -    'huge',
> -    'humorous',
> -    'hungry',
> -    'hushed',
> -    'hypnotic',
> -    'illustrious',
> -    'imaginary',
> -    'imaginative',
> -    'immense',
> -    'imminent',
> -    'impartial',
> -    'important',
> -    'imported',
> -    'impossible',
> -    'incandescent',
> -    'inconclusive',
> -    'incredible',
> -    'independent',
> -    'industrious',
> -    'inexpensive',
> -    'innate',
> -    'innocent',
> -    'inquisitive',
> -    'instinctive',
> -    'intellectual',
> -    'intelligent',
> -    'intense',
> -    'interesting',
> -    'internal',
> -    'intuitive',
> -    'inventive',
> -    'invincible',
> -    'jazzy',
> -    'jolly',
> -    'joyful',
> -    'joyous',
> -    'judicious',
> -    'juicy',
> -    'jumpy',
> -    'keen',
> -    'kind',
> -    'kindhearted',
> -    'kindly',
> -    'knotty',
> -    'knowing',
> -    'knowledgeable',
> -    'known',
> -    'laconic',
> -    'large',
> -    'lavish',
> -    'lean',
> -    'learned',
> -    'left',
> -    'legal',
> -    'level',
> -    'light',
> -    'likeable',
> -    'literate',
> -    'little',
> -    'lively',
> -    'living',
> -    'long',
> -    'longing',
> -    'loud',
> -    'lovely',
> -    'loving',
> -    'loyal',
> -    'lucky',
> -    'luminous',
> -    'lush',
> -    'luxuriant',
> -    'luxurious',
> -    'lyrical',
> -    'magenta',
> -    'magical',
> -    'magnificent',
> -    'majestic',
> -    'male',
> -    'mammoth',
> -    'many',
> -    'marvelous',
> -    'massive',
> -    'material',
> -    'mature',
> -    'meandering',
> -    'meaty',
> -    'medical',
> -    'mellow',
> -    'melodic',
> -    'melted',
> -    'merciful',
> -    'mighty',
> -    'miniature',
> -    'miniscule',
> -    'minor',
> -    'minute',
> -    'misty',
> -    'modern',
> -    'modest',
> -    'momentous',
> -    'motionless',
> -    'mountainous',
> -    'mute',
> -    'mysterious',
> -    'narrow',
> -    'natural',
> -    'near',
> -    'neat',
> -    'nebulous',
> -    'necessary',
> -    'neighborly',
> -    'new',
> -    'next',
> -    'nice',
> -    'nifty',
> -    'nimble',
> -    'nine',
> -    'nippy',
> -    'noiseless',
> -    'noisy',
> -    'nonchalant',
> -    'normal',
> -    'numberless',
> -    'numerous',
> -    'nutritious',
> -    'obedient',
> -    'observant',
> -    'obtainable',
> -    'oceanic',
> -    'omniscient',
> -    'one',
> -    'open',
> -    'opposite',
> -    'optimal',
> -    'optimistic',
> -    'opulent',
> -    'orange',
> -    'ordinary',
> -    'organic',
> -    'outgoing',
> -    'outrageous',
> -    'outstanding',
> -    'oval',
> -    'overjoyed',
> -    'overt',
> -    'palatial',
> -    'panoramic',
> -    'parallel',
> -    'passionate',
> -    'past',
> -    'pastoral',
> -    'patient',
> -    'peaceful',
> -    'perfect',
> -    'periodic',
> -    'permissible',
> -    'perpetual',
> -    'persistent',
> -    'petite',
> -    'philosophical',
> -    'physical',
> -    'picturesque',
> -    'pink',
> -    'pioneering',
> -    'piquant',
> -    'plausible',
> -    'pleasant',
> -    'plucky',
> -    'poised',
> -    'polite',
> -    'possible',
> -    'powerful',
> -    'practical',
> -    'precious',
> -    'premium',
> -    'present',
> -    'pretty',
> -    'previous',
> -    'private',
> -    'probable',
> -    'productive',
> -    'profound',
> -    'profuse',
> -    'protective',
> -    'proud',
> -    'psychedelic',
> -    'public',
> -    'pumped',
> -    'purple',
> -    'purring',
> -    'puzzled',
> -    'puzzling',
> -    'quaint',
> -    'quick',
> -    'quicker',
> -    'quickest',
> -    'quiet',
> -    'quirky',
> -    'quixotic',
> -    'quizzical',
> -    'rainy',
> -    'rapid',
> -    'rare',
> -    'rational',
> -    'ready',
> -    'real',
> -    'rebel',
> -    'receptive',
> -    'red',
> -    'reflective',
> -    'regular',
> -    'relaxed',
> -    'reliable',
> -    'relieved',
> -    'remarkable',
> -    'reminiscent',
> -    'reserved',
> -    'resolute',
> -    'resonant',
> -    'resourceful',
> -    'responsible',
> -    'rich',
> -    'ridiculous',
> -    'right',
> -    'rightful',
> -    'ripe',
> -    'ritzy',
> -    'roasted',
> -    'robust',
> -    'romantic',
> -    'roomy',
> -    'round',
> -    'royal',
> -    'ruddy',
> -    'rural',
> -    'rustic',
> -    'sable',
> -    'safe',
> -    'salty',
> -    'same',
> -    'satisfying',
> -    'savory',
> -    'scientific',
> -    'scintillating',
> -    'scrumptious',
> -    'second',
> -    'secret',
> -    'secretive',
> -    'seemly',
> -    'selective',
> -    'sensible',
> -    'separate',
> -    'shaggy',
> -    'shaky',
> -    'shining',
> -    'shiny',
> -    'short',
> -    'shy',
> -    'silent',
> -    'silky',
> -    'silly',
> -    'simple',
> -    'simplistic',
> -    'sincere',
> -    'six',
> -    'sizzling',
> -    'skillful',
> -    'sleepy',
> -    'slick',
> -    'slim',
> -    'smart',
> -    'smiling',
> -    'smooth',
> -    'soaring',
> -    'sociable',
> -    'soft',
> -    'solid',
> -    'sophisticated',
> -    'sparkling',
> -    'special',
> -    'spectacular',
> -    'speedy',
> -    'spicy',
> -    'spiffy',
> -    'spiritual',
> -    'splendid',
> -    'spooky',
> -    'spotless',
> -    'spotted',
> -    'square',
> -    'standing',
> -    'statuesque',
> -    'steadfast',
> -    'steady',
> -    'steep',
> -    'stimulating',
> -    'straight',
> -    'straightforward',
> -    'striking',
> -    'striped',
> -    'strong',
> -    'stunning',
> -    'stupendous',
> -    'sturdy',
> -    'subsequent',
> -    'substantial',
> -    'subtle',
> -    'successful',
> -    'succinct',
> -    'sudden',
> -    'super',
> -    'superb',
> -    'supreme',
> -    'swanky',
> -    'sweet',
> -    'swift',
> -    'sympathetic',
> -    'synonymous',
> -    'talented',
> -    'tall',
> -    'tame',
> -    'tan',
> -    'tangible',
> -    'tangy',
> -    'tasteful',
> -    'tasty',
> -    'telling',
> -    'temporary',
> -    'tempting',
> -    'ten',
> -    'tender',
> -    'terrific',
> -    'tested',
> -    'thankful',
> -    'therapeutic',
> -    'thin',
> -    'thinkable',
> -    'third',
> -    'thoughtful',
> -    'three',
> -    'thrifty',
> -    'tidy',
> -    'tiny',
> -    'toothsome',
> -    'towering',
> -    'tranquil',
> -    'tremendous',
> -    'tricky',
> -    'true',
> -    'truthful',
> -    'two',
> -    'typical',
> -    'ubiquitous',
> -    'ultra',
> -    'unassuming',
> -    'unbiased',
> -    'uncovered',
> -    'understanding',
> -    'understood',
> -    'unequaled',
> -    'unique',
> -    'unusual',
> -    'unwritten',
> -    'upbeat',
> -    'useful',
> -    'utopian',
> -    'utter',
> -    'uttermost',
> -    'valuable',
> -    'various',
> -    'vast',
> -    'verdant',
> -    'vermilion',
> -    'versatile',
> -    'versed',
> -    'victorious',
> -    'vigorous',
> -    'violet',
> -    'vivacious',
> -    'voiceless',
> -    'voluptuous',
> -    'wacky',
> -    'waiting',
> -    'wakeful',
> -    'wandering',
> -    'warm',
> -    'warmhearted',
> -    'wealthy',
> -    'whimsical',
> -    'whispering',
> -    'white',
> -    'whole',
> -    'wholesale',
> -    'whopping',
> -    'wide',
> -    'wiggly',
> -    'wild',
> -    'willing',
> -    'windy',
> -    'winsome',
> -    'wiry',
> -    'wise',
> -    'wistful',
> -    'witty',
> -    'womanly',
> -    'wonderful',
> -    'workable',
> -    'young',
> -    'youthful',
> -    'yummy',
> -    'zany',
> -    'zealous',
> -    'zesty',
> -    'zippy'
> +    b'abiding',
> +    b'abject',
> +    b'ablaze',
> +    b'able',
> +    b'aboard',
> +    b'abounding',
> +    b'absorbed',
> +    b'absorbing',
> +    b'abstracted',
> +    b'abundant',
> +    b'acceptable',
> +    b'accessible',
> +    b'accurate',
> +    b'acoustic',
> +    b'adamant',
> +    b'adaptable',
> +    b'adhesive',
> +    b'adjoining',
> +    b'adorable',
> +    b'adventurous',
> +    b'affable',
> +    b'affectionate',
> +    b'agreeable',
> +    b'alert',
> +    b'alive',
> +    b'alluring',
> +    b'amazing',
> +    b'ambiguous',
> +    b'ambitious',
> +    b'amiable',
> +    b'amicable',
> +    b'amused',
> +    b'amusing',
> +    b'ancient',
> +    b'animated',
> +    b'apricot',
> +    b'aquatic',
> +    b'arctic',
> +    b'arenaceous',
> +    b'aromatic',
> +    b'aspiring',
> +    b'assiduous',
> +    b'assorted',
> +    b'astonishing',
> +    b'attractive',
> +    b'auspicious',
> +    b'automatic',
> +    b'available',
> +    b'average',
> +    b'awake',
> +    b'aware',
> +    b'awesome',
> +    b'axiomatic',
> +    b'bashful',
> +    b'bawdy',
> +    b'beautiful',
> +    b'beefy',
> +    b'befitting',
> +    b'beneficial',
> +    b'benevolent',
> +    b'bent',
> +    b'best',
> +    b'better',
> +    b'bewildered',
> +    b'bewitching',
> +    b'big',
> +    b'billowy',
> +    b'bizarre',
> +    b'black',
> +    b'blithe',
> +    b'blue',
> +    b'blushing',
> +    b'bouncy',
> +    b'boundless',
> +    b'brainy',
> +    b'brash',
> +    b'brave',
> +    b'brawny',
> +    b'brazen',
> +    b'breezy',
> +    b'brief',
> +    b'bright',
> +    b'brilliant',
> +    b'broad',
> +    b'brown',
> +    b'bucolic',
> +    b'bulky',
> +    b'bumpy',
> +    b'burgundy',
> +    b'burly',
> +    b'bustling',
> +    b'busy',
> +    b'calm',
> +    b'capable',
> +    b'capricious',
> +    b'captivating',
> +    b'carefree',
> +    b'careful',
> +    b'caring',
> +    b'carrot',
> +    b'ceaseless',
> +    b'cerise',
> +    b'certain',
> +    b'challenging',
> +    b'changeable',
> +    b'charming',
> +    b'cheerful',
> +    b'chief',
> +    b'chilly',
> +    b'chipper',
> +    b'classy',
> +    b'clean',
> +    b'clear',
> +    b'clever',
> +    b'cloudy',
> +    b'coherent',
> +    b'colorful',
> +    b'colossal',
> +    b'comfortable',
> +    b'common',
> +    b'communicative',
> +    b'compassionate',
> +    b'complete',
> +    b'complex',
> +    b'compulsive',
> +    b'confused',
> +    b'conscientious',
> +    b'conscious',
> +    b'conservative',
> +    b'considerate',
> +    b'convivial',
> +    b'cooing',
> +    b'cool',
> +    b'cooperative',
> +    b'coordinated',
> +    b'courageous',
> +    b'courteous',
> +    b'crazy',
> +    b'creative',
> +    b'crispy',
> +    b'crooked',
> +    b'crowded',
> +    b'cuddly',
> +    b'cultured',
> +    b'cunning',
> +    b'curious',
> +    b'curly',
> +    b'curved',
> +    b'curvy',
> +    b'cut',
> +    b'cute',
> +    b'daily',
> +    b'damp',
> +    b'dapper',
> +    b'dashing',
> +    b'dazzling',
> +    b'dear',
> +    b'debonair',
> +    b'decisive',
> +    b'decorous',
> +    b'deep',
> +    b'defiant',
> +    b'delicate',
> +    b'delicious',
> +    b'delighted',
> +    b'delightful',
> +    b'delirious',
> +    b'descriptive',
> +    b'detached',
> +    b'detailed',
> +    b'determined',
> +    b'different',
> +    b'diligent',
> +    b'diminutive',
> +    b'diplomatic',
> +    b'discreet',
> +    b'distinct',
> +    b'distinctive',
> +    b'dramatic',
> +    b'dry',
> +    b'dynamic',
> +    b'dynamite',
> +    b'eager',
> +    b'early',
> +    b'earthy',
> +    b'easy',
> +    b'easygoing',
> +    b'eatable',
> +    b'economic',
> +    b'ecstatic',
> +    b'educated',
> +    b'efficacious',
> +    b'efficient',
> +    b'effortless',
> +    b'eight',
> +    b'elastic',
> +    b'elated',
> +    b'electric',
> +    b'elegant',
> +    b'elfin',
> +    b'elite',
> +    b'eminent',
> +    b'emotional',
> +    b'enchanted',
> +    b'enchanting',
> +    b'encouraging',
> +    b'endless',
> +    b'energetic',
> +    b'enormous',
> +    b'entertaining',
> +    b'enthusiastic',
> +    b'envious',
> +    b'epicurean',
> +    b'equable',
> +    b'equal',
> +    b'eternal',
> +    b'ethereal',
> +    b'evanescent',
> +    b'even',
> +    b'excellent',
> +    b'excited',
> +    b'exciting',
> +    b'exclusive',
> +    b'exotic',
> +    b'expensive',
> +    b'exquisite',
> +    b'extroverted',
> +    b'exuberant',
> +    b'exultant',
> +    b'fabulous',
> +    b'fair',
> +    b'faithful',
> +    b'familiar',
> +    b'famous',
> +    b'fancy',
> +    b'fantastic',
> +    b'far',
> +    b'fascinated',
> +    b'fast',
> +    b'fearless',
> +    b'female',
> +    b'fertile',
> +    b'festive',
> +    b'few',
> +    b'fine',
> +    b'first',
> +    b'five',
> +    b'fixed',
> +    b'flamboyant',
> +    b'flashy',
> +    b'flat',
> +    b'flawless',
> +    b'flirtatious',
> +    b'florid',
> +    b'flowery',
> +    b'fluffy',
> +    b'fluttering',
> +    b'foamy',
> +    b'foolish',
> +    b'foregoing',
> +    b'fortunate',
> +    b'four',
> +    b'frank',
> +    b'free',
> +    b'frequent',
> +    b'fresh',
> +    b'friendly',
> +    b'full',
> +    b'functional',
> +    b'funny',
> +    b'furry',
> +    b'future',
> +    b'futuristic',
> +    b'fuzzy',
> +    b'gabby',
> +    b'gainful',
> +    b'garrulous',
> +    b'general',
> +    b'generous',
> +    b'gentle',
> +    b'giant',
> +    b'giddy',
> +    b'gifted',
> +    b'gigantic',
> +    b'gilded',
> +    b'glamorous',
> +    b'gleaming',
> +    b'glorious',
> +    b'glossy',
> +    b'glowing',
> +    b'godly',
> +    b'good',
> +    b'goofy',
> +    b'gorgeous',
> +    b'graceful',
> +    b'grandiose',
> +    b'grateful',
> +    b'gratis',
> +    b'gray',
> +    b'great',
> +    b'green',
> +    b'gregarious',
> +    b'grey',
> +    b'groovy',
> +    b'guiltless',
> +    b'gusty',
> +    b'guttural',
> +    b'habitual',
> +    b'half',
> +    b'hallowed',
> +    b'halting',
> +    b'handsome',
> +    b'happy',
> +    b'hard',
> +    b'hardworking',
> +    b'harmonious',
> +    b'heady',
> +    b'healthy',
> +    b'heavenly',
> +    b'helpful',
> +    b'hilarious',
> +    b'historical',
> +    b'holistic',
> +    b'hollow',
> +    b'honest',
> +    b'honorable',
> +    b'hopeful',
> +    b'hospitable',
> +    b'hot',
> +    b'huge',
> +    b'humorous',
> +    b'hungry',
> +    b'hushed',
> +    b'hypnotic',
> +    b'illustrious',
> +    b'imaginary',
> +    b'imaginative',
> +    b'immense',
> +    b'imminent',
> +    b'impartial',
> +    b'important',
> +    b'imported',
> +    b'impossible',
> +    b'incandescent',
> +    b'inconclusive',
> +    b'incredible',
> +    b'independent',
> +    b'industrious',
> +    b'inexpensive',
> +    b'innate',
> +    b'innocent',
> +    b'inquisitive',
> +    b'instinctive',
> +    b'intellectual',
> +    b'intelligent',
> +    b'intense',
> +    b'interesting',
> +    b'internal',
> +    b'intuitive',
> +    b'inventive',
> +    b'invincible',
> +    b'jazzy',
> +    b'jolly',
> +    b'joyful',
> +    b'joyous',
> +    b'judicious',
> +    b'juicy',
> +    b'jumpy',
> +    b'keen',
> +    b'kind',
> +    b'kindhearted',
> +    b'kindly',
> +    b'knotty',
> +    b'knowing',
> +    b'knowledgeable',
> +    b'known',
> +    b'laconic',
> +    b'large',
> +    b'lavish',
> +    b'lean',
> +    b'learned',
> +    b'left',
> +    b'legal',
> +    b'level',
> +    b'light',
> +    b'likeable',
> +    b'literate',
> +    b'little',
> +    b'lively',
> +    b'living',
> +    b'long',
> +    b'longing',
> +    b'loud',
> +    b'lovely',
> +    b'loving',
> +    b'loyal',
> +    b'lucky',
> +    b'luminous',
> +    b'lush',
> +    b'luxuriant',
> +    b'luxurious',
> +    b'lyrical',
> +    b'magenta',
> +    b'magical',
> +    b'magnificent',
> +    b'majestic',
> +    b'male',
> +    b'mammoth',
> +    b'many',
> +    b'marvelous',
> +    b'massive',
> +    b'material',
> +    b'mature',
> +    b'meandering',
> +    b'meaty',
> +    b'medical',
> +    b'mellow',
> +    b'melodic',
> +    b'melted',
> +    b'merciful',
> +    b'mighty',
> +    b'miniature',
> +    b'miniscule',
> +    b'minor',
> +    b'minute',
> +    b'misty',
> +    b'modern',
> +    b'modest',
> +    b'momentous',
> +    b'motionless',
> +    b'mountainous',
> +    b'mute',
> +    b'mysterious',
> +    b'narrow',
> +    b'natural',
> +    b'near',
> +    b'neat',
> +    b'nebulous',
> +    b'necessary',
> +    b'neighborly',
> +    b'new',
> +    b'next',
> +    b'nice',
> +    b'nifty',
> +    b'nimble',
> +    b'nine',
> +    b'nippy',
> +    b'noiseless',
> +    b'noisy',
> +    b'nonchalant',
> +    b'normal',
> +    b'numberless',
> +    b'numerous',
> +    b'nutritious',
> +    b'obedient',
> +    b'observant',
> +    b'obtainable',
> +    b'oceanic',
> +    b'omniscient',
> +    b'one',
> +    b'open',
> +    b'opposite',
> +    b'optimal',
> +    b'optimistic',
> +    b'opulent',
> +    b'orange',
> +    b'ordinary',
> +    b'organic',
> +    b'outgoing',
> +    b'outrageous',
> +    b'outstanding',
> +    b'oval',
> +    b'overjoyed',
> +    b'overt',
> +    b'palatial',
> +    b'panoramic',
> +    b'parallel',
> +    b'passionate',
> +    b'past',
> +    b'pastoral',
> +    b'patient',
> +    b'peaceful',
> +    b'perfect',
> +    b'periodic',
> +    b'permissible',
> +    b'perpetual',
> +    b'persistent',
> +    b'petite',
> +    b'philosophical',
> +    b'physical',
> +    b'picturesque',
> +    b'pink',
> +    b'pioneering',
> +    b'piquant',
> +    b'plausible',
> +    b'pleasant',
> +    b'plucky',
> +    b'poised',
> +    b'polite',
> +    b'possible',
> +    b'powerful',
> +    b'practical',
> +    b'precious',
> +    b'premium',
> +    b'present',
> +    b'pretty',
> +    b'previous',
> +    b'private',
> +    b'probable',
> +    b'productive',
> +    b'profound',
> +    b'profuse',
> +    b'protective',
> +    b'proud',
> +    b'psychedelic',
> +    b'public',
> +    b'pumped',
> +    b'purple',
> +    b'purring',
> +    b'puzzled',
> +    b'puzzling',
> +    b'quaint',
> +    b'quick',
> +    b'quicker',
> +    b'quickest',
> +    b'quiet',
> +    b'quirky',
> +    b'quixotic',
> +    b'quizzical',
> +    b'rainy',
> +    b'rapid',
> +    b'rare',
> +    b'rational',
> +    b'ready',
> +    b'real',
> +    b'rebel',
> +    b'receptive',
> +    b'red',
> +    b'reflective',
> +    b'regular',
> +    b'relaxed',
> +    b'reliable',
> +    b'relieved',
> +    b'remarkable',
> +    b'reminiscent',
> +    b'reserved',
> +    b'resolute',
> +    b'resonant',
> +    b'resourceful',
> +    b'responsible',
> +    b'rich',
> +    b'ridiculous',
> +    b'right',
> +    b'rightful',
> +    b'ripe',
> +    b'ritzy',
> +    b'roasted',
> +    b'robust',
> +    b'romantic',
> +    b'roomy',
> +    b'round',
> +    b'royal',
> +    b'ruddy',
> +    b'rural',
> +    b'rustic',
> +    b'sable',
> +    b'safe',
> +    b'salty',
> +    b'same',
> +    b'satisfying',
> +    b'savory',
> +    b'scientific',
> +    b'scintillating',
> +    b'scrumptious',
> +    b'second',
> +    b'secret',
> +    b'secretive',
> +    b'seemly',
> +    b'selective',
> +    b'sensible',
> +    b'separate',
> +    b'shaggy',
> +    b'shaky',
> +    b'shining',
> +    b'shiny',
> +    b'short',
> +    b'shy',
> +    b'silent',
> +    b'silky',
> +    b'silly',
> +    b'simple',
> +    b'simplistic',
> +    b'sincere',
> +    b'six',
> +    b'sizzling',
> +    b'skillful',
> +    b'sleepy',
> +    b'slick',
> +    b'slim',
> +    b'smart',
> +    b'smiling',
> +    b'smooth',
> +    b'soaring',
> +    b'sociable',
> +    b'soft',
> +    b'solid',
> +    b'sophisticated',
> +    b'sparkling',
> +    b'special',
> +    b'spectacular',
> +    b'speedy',
> +    b'spicy',
> +    b'spiffy',
> +    b'spiritual',
> +    b'splendid',
> +    b'spooky',
> +    b'spotless',
> +    b'spotted',
> +    b'square',
> +    b'standing',
> +    b'statuesque',
> +    b'steadfast',
> +    b'steady',
> +    b'steep',
> +    b'stimulating',
> +    b'straight',
> +    b'straightforward',
> +    b'striking',
> +    b'striped',
> +    b'strong',
> +    b'stunning',
> +    b'stupendous',
> +    b'sturdy',
> +    b'subsequent',
> +    b'substantial',
> +    b'subtle',
> +    b'successful',
> +    b'succinct',
> +    b'sudden',
> +    b'super',
> +    b'superb',
> +    b'supreme',
> +    b'swanky',
> +    b'sweet',
> +    b'swift',
> +    b'sympathetic',
> +    b'synonymous',
> +    b'talented',
> +    b'tall',
> +    b'tame',
> +    b'tan',
> +    b'tangible',
> +    b'tangy',
> +    b'tasteful',
> +    b'tasty',
> +    b'telling',
> +    b'temporary',
> +    b'tempting',
> +    b'ten',
> +    b'tender',
> +    b'terrific',
> +    b'tested',
> +    b'thankful',
> +    b'therapeutic',
> +    b'thin',
> +    b'thinkable',
> +    b'third',
> +    b'thoughtful',
> +    b'three',
> +    b'thrifty',
> +    b'tidy',
> +    b'tiny',
> +    b'toothsome',
> +    b'towering',
> +    b'tranquil',
> +    b'tremendous',
> +    b'tricky',
> +    b'true',
> +    b'truthful',
> +    b'two',
> +    b'typical',
> +    b'ubiquitous',
> +    b'ultra',
> +    b'unassuming',
> +    b'unbiased',
> +    b'uncovered',
> +    b'understanding',
> +    b'understood',
> +    b'unequaled',
> +    b'unique',
> +    b'unusual',
> +    b'unwritten',
> +    b'upbeat',
> +    b'useful',
> +    b'utopian',
> +    b'utter',
> +    b'uttermost',
> +    b'valuable',
> +    b'various',
> +    b'vast',
> +    b'verdant',
> +    b'vermilion',
> +    b'versatile',
> +    b'versed',
> +    b'victorious',
> +    b'vigorous',
> +    b'violet',
> +    b'vivacious',
> +    b'voiceless',
> +    b'voluptuous',
> +    b'wacky',
> +    b'waiting',
> +    b'wakeful',
> +    b'wandering',
> +    b'warm',
> +    b'warmhearted',
> +    b'wealthy',
> +    b'whimsical',
> +    b'whispering',
> +    b'white',
> +    b'whole',
> +    b'wholesale',
> +    b'whopping',
> +    b'wide',
> +    b'wiggly',
> +    b'wild',
> +    b'willing',
> +    b'windy',
> +    b'winsome',
> +    b'wiry',
> +    b'wise',
> +    b'wistful',
> +    b'witty',
> +    b'womanly',
> +    b'wonderful',
> +    b'workable',
> +    b'young',
> +    b'youthful',
> +    b'yummy',
> +    b'zany',
> +    b'zealous',
> +    b'zesty',
> +    b'zippy'
>  ]
>
>  def randomtopicname(ui):
> -    if ui.configint("devel", "randomseed"):
> -        random.seed(ui.configint("devel", "randomseed"))
> -    return random.choice(adjectives) + "-" + random.choice(animals)
> +    if ui.configint(b"devel", b"randomseed"):
> +        random.seed(ui.configint(b"devel", b"randomseed"))
> +    return random.choice(adjectives) + b"-" + random.choice(animals)
> diff --git a/hgext3rd/topic/revset.py b/hgext3rd/topic/revset.py
> --- a/hgext3rd/topic/revset.py
> +++ b/hgext3rd/topic/revset.py
> @@ -24,11 +24,11 @@
>  revsetpredicate = registrar.revsetpredicate()
>
>  def getstringstrict(x, err):
> -    if x and x[0] == 'string':
> +    if x and x[0] == b'string':
>          return x[1]
>      raise error.ParseError(err)
>
> -@revsetpredicate('topic([string or set])')
> +@revsetpredicate(b'topic([string or set])')
>  def topicset(repo, subset, x):
>      """All changesets with the specified topic or the topics of the given
>      changesets. Without the argument, all changesets with any topic
> specified.
> @@ -36,7 +36,7 @@
>      If `string` starts with `re:` the remainder of the name is treated
>      as a regular expression.
>      """
> -    args = revset.getargs(x, 0, 1, 'topic takes one or no arguments')
> +    args = revset.getargs(x, 0, 1, b'topic takes one or no arguments')
>
>      mutable = revset._notpublic(repo, revset.fullreposet(repo), ())
>
> @@ -44,15 +44,15 @@
>          return (subset & mutable).filter(lambda r: bool(repo[r].topic()))
>
>      try:
> -        topic = getstringstrict(args[0], '')
> +        topic = getstringstrict(args[0], b'')
>      except error.ParseError:
>          # not a string, but another revset
>          pass
>      else:
>          kind, pattern, matcher = mkmatcher(topic)
>
> -        if topic.startswith('literal:') and pattern not in repo.topics:
> -            raise error.RepoLookupError("topic '%s' does not exist" %
> pattern)
> +        if topic.startswith(b'literal:') and pattern not in repo.topics:
> +            raise error.RepoLookupError(b"topic '%s' does not exist" %
> pattern)
>
>          def matches(r):
>              topic = repo[r].topic()
> @@ -64,7 +64,7 @@
>
>      s = revset.getset(repo, revset.fullreposet(repo), x)
>      topics = {repo[r].topic() for r in s}
> -    topics.discard('')
> +    topics.discard(b'')
>
>      def matches(r):
>          if r in s:
> @@ -76,20 +76,20 @@
>
>      return (subset & mutable).filter(matches)
>
> -@revsetpredicate('ngtip([branch])')
> +@revsetpredicate(b'ngtip([branch])')
>  def ngtipset(repo, subset, x):
>      """The untopiced tip.
>
>      Name is horrible so that people change it.
>      """
> -    args = revset.getargs(x, 1, 1, 'ngtip takes one argument')
> +    args = revset.getargs(x, 1, 1, b'ngtip takes one argument')
>      # match a specific topic
> -    branch = revset.getstring(args[0], 'ngtip requires a string')
> -    if branch == '.':
> -        branch = repo['.'].branch()
> +    branch = revset.getstring(args[0], b'ngtip requires a string')
> +    if branch == b'.':
> +        branch = repo[b'.'].branch()
>      return subset & revset.baseset(destination.ngtip(repo, branch))
>
> -@revsetpredicate('stack()')
> +@revsetpredicate(b'stack()')
>  def stackset(repo, subset, x):
>      """All relevant changes in the current topic,
>
> @@ -97,7 +97,7 @@
>      unstable changeset after there future parent (as if evolve where
> already
>      run).
>      """
> -    err = 'stack takes no arguments, it works on current topic'
> +    err = b'stack takes no arguments, it works on current topic'
>      revset.getargs(x, 0, 0, err)
>      topic = None
>      branch = None
> @@ -107,7 +107,7 @@
>          branch = repo[None].branch()
>      return revset.baseset(stack.stack(repo, branch=branch,
> topic=topic)[1:]) & subset
>
> -if util.safehasattr(revset, 'subscriptrelations'):
> +if util.safehasattr(revset, b'subscriptrelations'):
>      def stackrel(repo, subset, x, rel, z, order):
>          """This is a revset-flavored implementation of stack aliases.
>
> @@ -120,8 +120,8 @@
>          if isinstance(z, tuple):
>              a, b = revset.getintrange(
>                  z,
> -                'relation subscript must be an integer or a range',
> -                'relation subscript bounds must be integers',
> +                b'relation subscript must be an integer or a range',
> +                b'relation subscript bounds must be integers',
>                  None, None)
>          else:
>              a = b = z
> @@ -159,12 +159,12 @@
>
>          return subset & revset.baseset(revs)
>
> -    revset.subscriptrelations['stack'] = stackrel
> -    revset.subscriptrelations['s'] = stackrel
> +    revset.subscriptrelations[b'stack'] = stackrel
> +    revset.subscriptrelations[b's'] = stackrel
>
>      def topicrel(repo, subset, x, *args):
>          subset &= topicset(repo, subset, x)
>          return revset.generationsrel(repo, subset, x, *args)
>
> -    revset.subscriptrelations['topic'] = topicrel
> -    revset.subscriptrelations['t'] = topicrel
> +    revset.subscriptrelations[b'topic'] = topicrel
> +    revset.subscriptrelations[b't'] = topicrel
> diff --git a/hgext3rd/topic/stack.py b/hgext3rd/topic/stack.py
> --- a/hgext3rd/topic/stack.py
> +++ b/hgext3rd/topic/stack.py
> @@ -25,7 +25,7 @@
>      username = None
>      if user:
>          # user is of form "abc <abc@xyz.com>"
> -        username = user.split('<')[0]
> +        username = user.split(b'<')[0]
>          if not username:
>              # assuming user is of form "<abc@xyz.com>"
>              if len(user) > 1:
> @@ -44,10 +44,10 @@
>      """
>      phasesets = repo._phasecache._phasesets
>      if not phasesets or None in phasesets[phases.draft:]:
> -        return repo.revs('(not public()) - obsolete()')
> +        return repo.revs(b'(not public()) - obsolete()')
>
>      result = set.union(*phasesets[phases.draft:])
> -    result -= obsolete.getrevs(repo, 'obsolete')
> +    result -= obsolete.getrevs(repo, b'obsolete')
>      return result
>
>  class stack(object):
> @@ -62,13 +62,13 @@
>          subset = _stackcandidates(repo)
>
>          if topic is not None and branch is not None:
> -            raise error.ProgrammingError('both branch and topic specified
> (not defined yet)')
> +            raise error.ProgrammingError(b'both branch and topic
> specified (not defined yet)')
>          elif topic is not None:
> -            trevs = repo.revs("%ld and topic(%s)", subset, topic)
> +            trevs = repo.revs(b"%ld and topic(%s)", subset, topic)
>          elif branch is not None:
> -            trevs = repo.revs("%ld and branch(%s) - topic()", subset,
> branch)
> +            trevs = repo.revs(b"%ld and branch(%s) - topic()", subset,
> branch)
>          else:
> -            raise error.ProgrammingError('neither branch and topic
> specified (not defined yet)')
> +            raise error.ProgrammingError(b'neither branch and topic
> specified (not defined yet)')
>          self._revs = trevs
>
>      def __iter__(self):
> @@ -163,7 +163,7 @@
>          if revs:
>              pt1 = self._repo[revs[0]].p1()
>          else:
> -            pt1 = self._repo['.']
> +            pt1 = self._repo[b'.']
>
>          if pt1.obsolete():
>              pt1 = self._repo[_singlesuccessor(self._repo, pt1)]
> @@ -191,15 +191,15 @@
>          if revs:
>              minroot = [min(r for r in revs if not deps[r])]
>              try:
> -                dest = destutil.destmerge(self._repo, action='rebase',
> +                dest = destutil.destmerge(self._repo, action=b'rebase',
>                                            sourceset=minroot,
>                                            onheadcheck=False)
> -                return len(self._repo.revs("only(%d, %ld)", dest,
> minroot))
> +                return len(self._repo.revs(b"only(%d, %ld)", dest,
> minroot))
>              except error.NoMergeDestAbort:
>                  return 0
>              except error.ManyMergeDestAbort as exc:
>                  # XXX we should make it easier for upstream to provide
> the information
> -                self.behinderror = str(exc).split('-', 1)[0].rstrip()
> +                self.behinderror = str(exc).split(b'-', 1)[0].rstrip()
>                  return -1
>          return 0
>
> @@ -214,70 +214,70 @@
>      """ Takes a label prefix and a list of suffixes. Returns a string of
> the prefix
>      formatted with each suffix separated with a space.
>      """
> -    return ' '.join(prefix % suffix.replace(' ', '-') for suffix in
> labelssuffix)
> +    return b' '.join(prefix % suffix.replace(b' ', b'-') for suffix in
> labelssuffix)
>
>  def showstack(ui, repo, branch=None, topic=None, opts=None):
>      if opts is None:
>          opts = {}
>
>      if topic is not None and branch is not None:
> -        msg = 'both branch and topic specified [%s]{%s}(not defined yet)'
> +        msg = b'both branch and topic specified [%s]{%s}(not defined yet)'
>          msg %= (branch, topic)
>          raise error.ProgrammingError(msg)
>      elif topic is not None:
> -        prefix = 's'
> +        prefix = b's'
>          if topic not in repo.topics:
> -            raise error.Abort(_('cannot resolve "%s": no such topic
> found') % topic)
> +            raise error.Abort(_(b'cannot resolve "%s": no such topic
> found') % topic)
>      elif branch is not None:
> -        prefix = 's'
> +        prefix = b's'
>      else:
> -        raise error.ProgrammingError('neither branch and topic specified
> (not defined yet)')
> +        raise error.ProgrammingError(b'neither branch and topic specified
> (not defined yet)')
>
> -    fm = ui.formatter('topicstack', opts)
> +    fm = ui.formatter(b'topicstack', opts)
>      prev = None
>      entries = []
>      idxmap = {}
>
> -    label = 'topic'
> +    label = b'topic'
>      if topic == repo.currenttopic:
> -        label = 'topic.active'
> +        label = b'topic.active'
>
>      data = stackdata(repo, branch=branch, topic=topic)
>      empty = False
> -    if data['changesetcount'] == 0:
> +    if data[b'changesetcount'] == 0:
>          empty = True
>      if topic is not None:
> -        fm.plain(_('### topic: %s')
> +        fm.plain(_(b'### topic: %s')
>                   % ui.label(topic, label),
> -                 label='topic.stack.summary.topic')
> +                 label=b'topic.stack.summary.topic')
>
> -        if 1 < data['headcount']:
> -            fm.plain(' (')
> -            fm.plain('%d heads' % data['headcount'],
> -                     label='topic.stack.summary.headcount.multiple')
> -            fm.plain(')')
> -        fm.plain('\n')
> -    fm.plain(_('### target: %s (branch)')
> -             % '+'.join(data['branches']), # XXX handle multi branches
> -             label='topic.stack.summary.branches')
> +        if 1 < data[b'headcount']:
> +            fm.plain(b' (')
> +            fm.plain(b'%d heads' % data[b'headcount'],
> +                     label=b'topic.stack.summary.headcount.multiple')
> +            fm.plain(b')')
> +        fm.plain(b'\n')
> +    fm.plain(_(b'### target: %s (branch)')
> +             % b'+'.join(data[b'branches']), # XXX handle multi branches
> +             label=b'topic.stack.summary.branches')
>      if topic is None:
> -        if 1 < data['headcount']:
> -            fm.plain(' (')
> -            fm.plain('%d heads' % data['headcount'],
> -                     label='topic.stack.summary.headcount.multiple')
> -            fm.plain(')')
> +        if 1 < data[b'headcount']:
> +            fm.plain(b' (')
> +            fm.plain(b'%d heads' % data[b'headcount'],
> +                     label=b'topic.stack.summary.headcount.multiple')
> +            fm.plain(b')')
>      else:
> -        if data['behindcount'] == -1:
> -            fm.plain(', ')
> -            fm.plain('ambiguous rebase destination - %s' %
> data['behinderror'],
> -                     label='topic.stack.summary.behinderror')
> -        elif data['behindcount']:
> -            fm.plain(', ')
> -            fm.plain('%d behind' % data['behindcount'],
> label='topic.stack.summary.behindcount')
> -    fm.plain('\n')
> +        if data[b'behindcount'] == -1:
> +            fm.plain(b', ')
> +            fm.plain(b'ambiguous rebase destination - %s' %
> data[b'behinderror'],
> +                     label=b'topic.stack.summary.behinderror')
> +        elif data[b'behindcount']:
> +            fm.plain(b', ')
> +            fm.plain(b'%d behind' % data[b'behindcount'],
> label=b'topic.stack.summary.behindcount')
> +    fm.plain(b'\n')
>
>      if empty:
> -        fm.plain(_("(stack is empty)\n"))
> +        fm.plain(_(b"(stack is empty)\n"))
>
>      st = stack(repo, branch=branch, topic=topic)
>      for idx, r in enumerate(st, 0):
> @@ -316,40 +316,40 @@
>
>          symbol = None
>          states = []
> -        if opts.get('children'):
> -            expr = 'children(%d) and merge() - %ld'
> +        if opts.get(b'children'):
> +            expr = b'children(%d) and merge() - %ld'
>              revisions = repo.revs(expr, ctx.rev(), st.revs[1:])
>              if len(revisions) > 0:
> -                states.append('external-children')
> +                states.append(b'external-children')
>
>          if ctx.orphan():
> -            symbol = '$'
> -            states.append('orphan')
> +            symbol = b'$'
> +            states.append(b'orphan')
>
>          if ctx.contentdivergent():
> -            symbol = '$'
> -            states.append('content divergent')
> +            symbol = b'$'
> +            states.append(b'content divergent')
>
>          if ctx.phasedivergent():
> -            symbol = '$'
> -            states.append('phase divergent')
> +            symbol = b'$'
> +            states.append(b'phase divergent')
>
> -        iscurrentrevision = repo.revs('%d and parents()', ctx.rev())
> +        iscurrentrevision = repo.revs(b'%d and parents()', ctx.rev())
>          if iscurrentrevision:
> -            symbol = '@'
> -            states.append('current')
> +            symbol = b'@'
> +            states.append(b'current')
>
>          if not isentry:
> -            symbol = '^'
> +            symbol = b'^'
>              # "base" is kind of a "ghost" entry
> -            states.append('base')
> +            states.append(b'base')
>
>          # none of the above if statments get executed
>          if not symbol:
> -            symbol = ':'
> +            symbol = b':'
>
>          if not states:
> -            states.append('clean')
> +            states.append(b'clean')
>
>          states.sort()
>
> @@ -357,24 +357,24 @@
>          fm.data(isentry=isentry)
>
>          if idx is None:
> -            fm.plain('  ')
> +            fm.plain(b'  ')
>              if ui.verbose:
> -                fm.plain('              ')
> +                fm.plain(b'              ')
>          else:
> -            fm.write('topic.stack.index', '%s%%d' % prefix, idx,
> -                     label='topic.stack.index ' +
> labelsgen('topic.stack.index.%s', states))
> +            fm.write(b'topic.stack.index', b'%s%%d' % prefix, idx,
> +                     label=b'topic.stack.index ' +
> labelsgen(b'topic.stack.index.%s', states))
>              if ui.verbose:
> -                fm.write('topic.stack.shortnode', '(%s)',
> short(ctx.node()),
> -                         label='topic.stack.shortnode ' +
> labelsgen('topic.stack.shortnode.%s', states))
> -        fm.write('topic.stack.state.symbol', '%s', symbol,
> -                 label='topic.stack.state ' +
> labelsgen('topic.stack.state.%s', states))
> -        fm.plain(' ')
> -        fm.write('topic.stack.desc', '%s',
> ctx.description().splitlines()[0],
> -                 label='topic.stack.desc ' +
> labelsgen('topic.stack.desc.%s', states))
> -        fm.condwrite(states != ['clean'] and idx is not None,
> 'topic.stack.state',
> -                     ' (%s)', fm.formatlist(states, 'topic.stack.state'),
> -                     label='topic.stack.state ' +
> labelsgen('topic.stack.state.%s', states))
> -        fm.plain('\n')
> +                fm.write(b'topic.stack.shortnode', b'(%s)',
> short(ctx.node()),
> +                         label=b'topic.stack.shortnode ' +
> labelsgen(b'topic.stack.shortnode.%s', states))
> +        fm.write(b'topic.stack.state.symbol', b'%s', symbol,
> +                 label=b'topic.stack.state ' +
> labelsgen(b'topic.stack.state.%s', states))
> +        fm.plain(b' ')
> +        fm.write(b'topic.stack.desc', b'%s',
> ctx.description().splitlines()[0],
> +                 label=b'topic.stack.desc ' +
> labelsgen(b'topic.stack.desc.%s', states))
> +        fm.condwrite(states != [b'clean'] and idx is not None,
> b'topic.stack.state',
> +                     b' (%s)', fm.formatlist(states,
> b'topic.stack.state'),
> +                     label=b'topic.stack.state ' +
> labelsgen(b'topic.stack.state.%s', states))
> +        fm.plain(b'\n')
>      fm.end()
>
>  def stackdata(repo, branch=None, topic=None):
> @@ -387,10 +387,10 @@
>      """
>      data = {}
>      current = stack(repo, branch, topic)
> -    data['changesetcount'] = current.changesetcount
> -    data['unstablecount'] = current.unstablecount
> -    data['headcount'] = len(current.heads)
> -    data['behindcount'] = current.behindcount
> -    data['behinderror'] = current.behinderror
> -    data['branches'] = current.branches
> +    data[b'changesetcount'] = current.changesetcount
> +    data[b'unstablecount'] = current.unstablecount
> +    data[b'headcount'] = len(current.heads)
> +    data[b'behindcount'] = current.behindcount
> +    data[b'behinderror'] = current.behinderror
> +    data[b'branches'] = current.branches
>      return data
> diff --git a/hgext3rd/topic/topicmap.py b/hgext3rd/topic/topicmap.py
> --- a/hgext3rd/topic/topicmap.py
> +++ b/hgext3rd/topic/topicmap.py
> @@ -16,22 +16,22 @@
>      common,
>  )
>
> -basefilter = set(['base', 'immutable'])
> +basefilter = set([b'base', b'immutable'])
>  def topicfilter(name):
>      """return a "topic" version of a filter level"""
>      if name in basefilter:
>          return name
>      elif name is None:
>          return None
> -    elif name.endswith('-topic'):
> +    elif name.endswith(b'-topic'):
>          return name
>      else:
> -        return name + '-topic'
> +        return name + b'-topic'
>
>  def istopicfilter(filtername):
>      if filtername is None:
>          return False
> -    return filtername.endswith('-topic')
> +    return filtername.endswith(b'-topic')
>
>  def gettopicrepo(repo):
>      if not common.hastopicext(repo):
> @@ -61,8 +61,8 @@
>          if newfilter not in funcmap:
>              funcmap[newfilter] = revsfunc
>              partialmap[newfilter] = base
> -    funcmap['unfiltered-topic'] = lambda repo: frozenset()
> -    partialmap['unfiltered-topic'] = 'visible-topic'
> +    funcmap[b'unfiltered-topic'] = lambda repo: frozenset()
> +    partialmap[b'unfiltered-topic'] = b'visible-topic'
>
>  def _phaseshash(repo, maxrev):
>      """uniq ID for a phase matching a set of rev"""
> @@ -80,7 +80,7 @@
>      if revs:
>          s = hashlib.sha1()
>          for rev in revs:
> -            s.update('%s;' % rev)
> +            s.update(b'%s;' % rev)
>          key = s.digest()
>      return key
>
> @@ -88,8 +88,8 @@
>      """call at uisetup time to install various wrappings"""
>      _setuptopicfilter(ui)
>      _wrapbmcache(ui)
> -    extensions.wrapfunction(changegroup.cg1unpacker, 'apply', cgapply)
> -    extensions.wrapfunction(cmdutil, 'commitstatus', commitstatus)
> +    extensions.wrapfunction(changegroup.cg1unpacker, b'apply', cgapply)
> +    extensions.wrapfunction(cmdutil, b'commitstatus', commitstatus)
>
>  def cgapply(orig, self, repo, *args, **kwargs):
>      """make sure a topicmap is used when applying a changegroup"""
> @@ -100,8 +100,8 @@
>      # wrap commit status use the topic branch heads
>      ctx = repo[node]
>      if ctx.topic() and ctx.branch() == branch:
> -        subbranch = "%s:%s" % (branch, ctx.topic())
> -        bheads = repo.branchheads("%s:%s" % (subbranch, ctx.topic()))
> +        subbranch = b"%s:%s" % (branch, ctx.topic())
> +        bheads = repo.branchheads(b"%s:%s" % (subbranch, ctx.topic()))
>
>      ret = orig(repo, node, branch, bheads=bheads, opts=opts)
>
> @@ -112,10 +112,10 @@
>          return ret
>      parents = ctx.parents()
>
> -    if (not opts.get('amend') and bheads and node not in bheads and not
> +    if (not opts.get(b'amend') and bheads and node not in bheads and not
>          [x for x in parents if x.node() in bheads and x.branch() ==
> branch]):
> -        repo.ui.status(_("(consider using topic for lightweight branches."
> -                         " See 'hg help topic')\n"))
> +        repo.ui.status(_(b"(consider using topic for lightweight
> branches."
> +                         b" See 'hg help topic')\n"))
>
>      return ret
>
> @@ -133,10 +133,10 @@
>          def _wrapupdatebmcachemethod(orig, self, repo):
>              # pass in the bound method as the original
>              return _wrapupdatebmcache(orig.__get__(self), repo)
> -        extensions.wrapfunction(branchmap.BranchMapCache, 'updatecache',
> _wrapupdatebmcachemethod)
> +        extensions.wrapfunction(branchmap.BranchMapCache, b'updatecache',
> _wrapupdatebmcachemethod)
>      except AttributeError:
>          # Mercurial 4.8 and before
> -        extensions.wrapfunction(branchmap, 'updatecache',
> _wrapupdatebmcache)
> +        extensions.wrapfunction(branchmap, b'updatecache',
> _wrapupdatebmcache)
>
>
>  def _wrapupdatebmcache(orig, repo):
> @@ -170,7 +170,7 @@
>
>      def copy(self):
>          """return an deep copy of the branchcache object"""
> -        if util.safehasattr(self, '_entries'):
> +        if util.safehasattr(self, b'_entries'):
>              _entries = self._entries
>          else:
>              # hg <= 4.9 (624d6683c705, b137a6793c51)
> @@ -180,17 +180,17 @@
>          new.phaseshash = self.phaseshash
>          return new
>
> -    def branchtip(self, branch, topic=''):
> +    def branchtip(self, branch, topic=b''):
>          '''Return the tipmost open head on branch head, otherwise return
> the
>          tipmost closed head on branch.
>          Raise KeyError for unknown branch.'''
>          if topic:
> -            branch = '%s:%s' % (branch, topic)
> +            branch = b'%s:%s' % (branch, topic)
>          return super(_topiccache, self).branchtip(branch)
>
> -    def branchheads(self, branch, closed=False, topic=''):
> +    def branchheads(self, branch, closed=False, topic=b''):
>          if topic:
> -            branch = '%s:%s' % (branch, topic)
> +            branch = b'%s:%s' % (branch, topic)
>          return super(_topiccache, self).branchheads(branch, closed=closed)
>
>      def validfor(self, repo):
> @@ -230,13 +230,13 @@
>
>          def branchinfo(r, changelog=None):
>              info = oldgetbranchinfo(r)
> -            topic = ''
> +            topic = b''
>              ctx = unfi[r]
>              if ctx.mutable():
>                  topic = ctx.topic()
>              branch = info[0]
>              if topic:
> -                branch = '%s:%s' % (branch, topic)
> +                branch = b'%s:%s' % (branch, topic)
>              return (branch, info[1])
>          try:
>              unfi.revbranchcache().branchinfo = branchinfo
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
>
Anton Shestakov - May 25, 2019, 5:55 a.m.
On Fri, 24 May 2019 15:57:53 +0000
Ludovic Chabant <ludovic@chabant.com> wrote:

> # HG changeset patch
> # User Ludovic Chabant <ludovic@chabant.com>
> # Date 1558677189 0
> #      Fri May 24 05:53:09 2019 +0000
> # Node ID 3af350fa12d4dbf69d5cbbaf5ca679067472f9ee
> # Parent  0b231ea2124baf74fee5e325922a57fb0d89bbe3
> # EXP-Topic py3
> py3: broad pass for python3 compatibility
> 
> - ran mercurial's bytify-strings script
> - excluded some places where we use strings to pass to setattr()

Does this make any existing tests for evolve pass on py3?

I must say at the moment we have lots of unreviewed patches (draft in
evolve-devel), I'm hoping that they will be finally reviewed at
the oncoming post-conference sprint and then we can set up a new job in
jenkins to test evolve on py3 and start caring about the compatibility
for real. Taking other patches first would mean this patch would be
hard to apply and it would miss any newly added code, so the question
is: how hard would it be to create this patch again?
Ludovic Chabant - May 25, 2019, 7:05 a.m.
> Does this make any existing tests for evolve pass on py3?

The evolve extension wasn't even loading in py3 before this patch --
mercurial core would reject it for trying to add unicode strings to the
command table.

> Taking other patches first would mean this patch would be hard to
> apply and it would miss any newly added code, so the question is: how
> hard would it be to create this patch again?

It's easy to make this patch again:

1) run mercurial's contrib/bytify_strings.py script with the --
   dictiter argument

2) fix up the few calls to exthelper.addattr to _not_ use byte strings
   (because those strings are passed to python's addattr() builtin, and
   that wants unicode).

That's it!
Ludovic Chabant - June 26, 2019, 10:55 p.m.
Should I re-create the patch on the latest evolve stable now? Or will someone else do it? 
I'm asking because py3 support is blocking a few things for sourcehut.
Thanks!

On Sat, May 25, 2019, at 00:05, Ludovic Chabant wrote:
> > Does this make any existing tests for evolve pass on py3?
> 
> The evolve extension wasn't even loading in py3 before this patch --
> mercurial core would reject it for trying to add unicode strings to the
> command table.
> 
> > Taking other patches first would mean this patch would be hard to
> > apply and it would miss any newly added code, so the question is: how
> > hard would it be to create this patch again?
> 
> It's easy to make this patch again:
> 
> 1) run mercurial's contrib/bytify_strings.py script with the --
>    dictiter argument
> 
> 2) fix up the few calls to exthelper.addattr to _not_ use byte strings
>    (because those strings are passed to python's addattr() builtin, and
>    that wants unicode).
> 
> That's it!
>
Anton Shestakov - June 27, 2019, 8:43 a.m.
On Wed, 26 Jun 2019 15:55:50 -0700
"Ludovic Chabant" <ludovic@chabant.com> wrote:

> Should I re-create the patch on the latest evolve stable now? Or will someone else do it? 
> I'm asking because py3 support is blocking a few things for sourcehut.
> Thanks!

Personally, I thought you all would discuss py3 efforts and testing
plan for evolve on the conference in Paris. Not sure if any of that took
place, but if not, you need to, indeed, redo this patch and then nag
Pierre-Yves to queue it and set up evolve-py3 on octobus-ci jenkins,
preferably all at the same time.

We definitely want this patch, but we equally want a way to test (not
just locally) that it keeps working. Maybe we can better coordinate the
efforts in #hg-evolve.
Ludovic Chabant - June 27, 2019, 2:05 p.m.
> We definitely want this patch, but we equally want a way to test (not
> just locally) that it keeps working. Maybe we can better coordinate the
> efforts in #hg-evolve.

Will do, thanks!

Patch

diff --git a/hgext3rd/evolve/__init__.py b/hgext3rd/evolve/__init__.py
--- a/hgext3rd/evolve/__init__.py
+++ b/hgext3rd/evolve/__init__.py
@@ -259,7 +259,7 @@ 
     registrar.templatekeyword # new in hg-3.8
 except ImportError:
     from . import metadata
-    raise ImportError('evolve needs Mercurial version %s or above' %
+    raise ImportError(b'evolve needs Mercurial version %s or above' %
                       min(metadata.testedwith.split()))
 
 import mercurial
@@ -311,25 +311,25 @@ 
 buglink = metadata.buglink
 
 # Flags for enabling optional parts of evolve
-commandopt = 'allnewcommands'
+commandopt = b'allnewcommands'
 
 obsexcmsg = utility.obsexcmsg
 shorttemplate = utility.shorttemplate
 
-colortable = {'evolve.node': 'yellow',
-              'evolve.user': 'green',
-              'evolve.rev': 'blue',
-              'evolve.short_description': '',
-              'evolve.date': 'cyan',
-              'evolve.current_rev': 'bold',
-              'evolve.verb': '',
-              'evolve.operation': 'bold'
+colortable = {b'evolve.node': b'yellow',
+              b'evolve.user': b'green',
+              b'evolve.rev': b'blue',
+              b'evolve.short_description': b'',
+              b'evolve.date': b'cyan',
+              b'evolve.current_rev': b'bold',
+              b'evolve.verb': b'',
+              b'evolve.operation': b'bold'
               }
 
 _pack = struct.pack
 _unpack = struct.unpack
 
-aliases, entry = cmdutil.findcmd('commit', commands.table)
+aliases, entry = cmdutil.findcmd(b'commit', commands.table)
 commitopts3 = cmdrewrite.commitopts3
 interactiveopt = cmdrewrite.interactiveopt
 rewrite = rewriteutil.rewrite
@@ -361,13 +361,13 @@ 
 templatekeyword = eh.templatekeyword
 
 # Configuration
-eh.configitem('experimental', 'evolutioncommands', [])
-eh.configitem('experimental', 'evolution.allnewcommands', None)
-eh.configitem('experimental', 'prunestrip', False)
+eh.configitem(b'experimental', b'evolutioncommands', [])
+eh.configitem(b'experimental', b'evolution.allnewcommands', None)
+eh.configitem(b'experimental', b'prunestrip', False)
 
 # pre hg 4.0 compat
 
-if not util.safehasattr(dirstate.dirstate, 'parentchange'):
+if not util.safehasattr(dirstate.dirstate, b'parentchange'):
     import contextlib
 
     @contextlib.contextmanager
@@ -396,14 +396,14 @@ 
 def _configureoptions(ui, repo):
     # If no capabilities are specified, enable everything.
     # This is so existing evolve users don't need to change their config.
-    evolveopts = repo.ui.configlist('experimental', 'evolution')
+    evolveopts = repo.ui.configlist(b'experimental', b'evolution')
     if not evolveopts:
-        evolveopts = ['all']
-        repo.ui.setconfig('experimental', 'evolution', evolveopts, 'evolve')
-    if obsolete.isenabled(repo, 'exchange'):
+        evolveopts = [b'all']
+        repo.ui.setconfig(b'experimental', b'evolution', evolveopts, b'evolve')
+    if obsolete.isenabled(repo, b'exchange'):
         # if no config explicitly set, disable bundle1
-        if not isinstance(repo.ui.config('server', 'bundle1'), str):
-            repo.ui.setconfig('server', 'bundle1', False)
+        if not isinstance(repo.ui.config(b'server', b'bundle1'), str):
+            repo.ui.setconfig(b'server', b'bundle1', False)
 
     class trdescrepo(repo.__class__):
 
@@ -421,18 +421,18 @@ 
     # This must be in the same function as the option configuration above to
     # guarantee it happens after the above configuration, but before the
     # extsetup functions.
-    evolvecommands = ui.configlist('experimental', 'evolutioncommands')
-    evolveopts = ui.configlist('experimental', 'evolution')
+    evolvecommands = ui.configlist(b'experimental', b'evolutioncommands')
+    evolveopts = ui.configlist(b'experimental', b'evolution')
     if evolveopts and (commandopt not in evolveopts
-                       and 'all' not in evolveopts):
+                       and b'all' not in evolveopts):
         # We build whitelist containing the commands we want to enable
         whitelist = set()
         for cmd in evolvecommands:
             matchingevolvecommands = [e for e in cmdtable.keys() if cmd in e]
             if not matchingevolvecommands:
-                raise error.Abort(_('unknown command: %s') % cmd)
+                raise error.Abort(_(b'unknown command: %s') % cmd)
             elif len(matchingevolvecommands) > 1:
-                msg = _('ambiguous command specification: "%s" matches %r')
+                msg = _(b'ambiguous command specification: "%s" matches %r')
                 raise error.Abort(msg % (cmd, matchingevolvecommands))
             else:
                 whitelist.add(matchingevolvecommands[0])
@@ -463,10 +463,10 @@ 
 @eh.uisetup
 def setupparentcommand(ui):
 
-    _alias, statuscmd = cmdutil.findcmd('status', commands.table)
-    pstatusopts = [o for o in statuscmd[1] if o[1] != 'rev']
+    _alias, statuscmd = cmdutil.findcmd(b'status', commands.table)
+    pstatusopts = [o for o in statuscmd[1] if o[1] != b'rev']
 
-    @eh.command('pstatus', pstatusopts)
+    @eh.command(b'pstatus', pstatusopts)
     def pstatus(ui, repo, *args, **kwargs):
         """show status combining committed and uncommited changes
 
@@ -475,13 +475,13 @@ 
         match the content of the commit that a bare :hg:`amend` will creates.
 
         See :hg:`help status` for details."""
-        kwargs['rev'] = ['.^']
+        kwargs[b'rev'] = [b'.^']
         return statuscmd[0](ui, repo, *args, **kwargs)
 
-    _alias, diffcmd = cmdutil.findcmd('diff', commands.table)
-    pdiffopts = [o for o in diffcmd[1] if o[1] != 'rev']
+    _alias, diffcmd = cmdutil.findcmd(b'diff', commands.table)
+    pdiffopts = [o for o in diffcmd[1] if o[1] != b'rev']
 
-    @eh.command('pdiff', pdiffopts)
+    @eh.command(b'pdiff', pdiffopts)
     def pdiff(ui, repo, *args, **kwargs):
         """show diff combining committed and uncommited changes
 
@@ -490,32 +490,32 @@ 
         match the content of the commit that a bare :hg:`amend` will creates.
 
         See :hg:`help diff` for details."""
-        kwargs['rev'] = ['.^']
+        kwargs[b'rev'] = [b'.^']
         return diffcmd[0](ui, repo, *args, **kwargs)
 
 @eh.uisetup
 def _installalias(ui):
-    if ui.config('alias', 'odiff', None) is None:
-        ui.setconfig('alias', 'odiff',
-                     "diff --hidden --rev 'limit(predecessors(.),1)' --rev .",
-                     'evolve')
+    if ui.config(b'alias', b'odiff', None) is None:
+        ui.setconfig(b'alias', b'odiff',
+                     b"diff --hidden --rev 'limit(predecessors(.),1)' --rev .",
+                     b'evolve')
 
 ### Unstable revset symbol
 
-@eh.revsetpredicate('unstable()')
+@eh.revsetpredicate(b'unstable()')
 def revsetunstable(repo, subset, x):
     """Changesets with instabilities.
     """
-    revset.getargs(x, 0, 0, 'unstable takes no arguments')
+    revset.getargs(x, 0, 0, b'unstable takes no arguments')
     troubled = set()
-    troubled.update(getrevs(repo, 'orphan'))
-    troubled.update(getrevs(repo, 'phasedivergent'))
-    troubled.update(getrevs(repo, 'contentdivergent'))
+    troubled.update(getrevs(repo, b'orphan'))
+    troubled.update(getrevs(repo, b'phasedivergent'))
+    troubled.update(getrevs(repo, b'contentdivergent'))
     troubled = revset.baseset(troubled)
     troubled.sort() # set is non-ordered, enforce order
     return subset & troubled
 
-@eh.revsetpredicate('troubled()')    # legacy name
+@eh.revsetpredicate(b'troubled()')    # legacy name
 def revsettroubled(repo, subset, x):
     return revsetunstable(repo, subset, x)
 
@@ -614,17 +614,17 @@ 
 
 
 ### XXX I'm not sure this revset is useful
-@eh.revsetpredicate('suspended()')
+@eh.revsetpredicate(b'suspended()')
 def revsetsuspended(repo, subset, x):
     """Obsolete changesets with non-obsolete descendants.
     """
-    revset.getargs(x, 0, 0, 'suspended takes no arguments')
-    suspended = revset.baseset(getrevs(repo, 'suspended'))
+    revset.getargs(x, 0, 0, b'suspended takes no arguments')
+    suspended = revset.baseset(getrevs(repo, b'suspended'))
     suspended.sort()
     return subset & suspended
 
 
-@eh.revsetpredicate('predecessors(set)')
+@eh.revsetpredicate(b'predecessors(set)')
 def revsetpredecessors(repo, subset, x):
     """Immediate predecessors of changesets in set.
     """
@@ -634,12 +634,12 @@ 
     return subset & s
 
 
-@eh.revsetpredicate('precursors(set)')   # legacy name for predecessors
+@eh.revsetpredicate(b'precursors(set)')   # legacy name for predecessors
 def revsetprecursors(repo, subset, x):
     return revsetpredecessors(repo, subset, x)
 
 
-@eh.revsetpredicate('allpredecessors(set)')
+@eh.revsetpredicate(b'allpredecessors(set)')
 def revsetallpredecessors(repo, subset, x):
     """Transitive predecessors of changesets in set.
     """
@@ -649,12 +649,12 @@ 
     return subset & s
 
 
-@eh.revsetpredicate('allprecursors(set)')   # legacy name for allpredecessors
+@eh.revsetpredicate(b'allprecursors(set)')   # legacy name for allpredecessors
 def revsetallprecursors(repo, subset, x):
     return revsetallpredecessors(repo, subset, x)
 
 
-@eh.revsetpredicate('successors(set)')
+@eh.revsetpredicate(b'successors(set)')
 def revsetsuccessors(repo, subset, x):
     """Immediate successors of changesets in set.
     """
@@ -663,7 +663,7 @@ 
     s.sort()
     return subset & s
 
-@eh.revsetpredicate('allsuccessors(set)')
+@eh.revsetpredicate(b'allsuccessors(set)')
 def revsetallsuccessors(repo, subset, x):
     """Transitive successors of changesets in set.
     """
@@ -680,87 +680,87 @@ 
 # This section take care of issue warning to the user when troubles appear
 
 def _warnobsoletewc(ui, repo, prevnode=None, wasobs=None):
-    rev = repo['.']
+    rev = repo[b'.']
 
     if not rev.obsolete():
         return
 
     if rev.node() == prevnode and wasobs:
         return
-    msg = _("working directory parent is obsolete! (%s)\n")
+    msg = _(b"working directory parent is obsolete! (%s)\n")
     shortnode = node.short(rev.node())
 
     ui.warn(msg % shortnode)
 
     # Check that evolve is activated for performance reasons
-    evolvecommandenabled = any('evolve' in e for e in cmdtable)
+    evolvecommandenabled = any(b'evolve' in e for e in cmdtable)
     if ui.quiet or not evolvecommandenabled:
         return
 
     # Show a warning for helping the user to solve the issue
     reason, successors = obshistory._getobsfateandsuccs(repo, rev.node())
 
-    if reason == 'pruned':
-        solvemsg = _("use 'hg evolve' to update to its parent successor")
-    elif reason == 'diverged':
-        debugcommand = "hg evolve --list --content-divergent"
-        basemsg = _("%s has diverged, use '%s' to resolve the issue")
+    if reason == b'pruned':
+        solvemsg = _(b"use 'hg evolve' to update to its parent successor")
+    elif reason == b'diverged':
+        debugcommand = b"hg evolve --list --content-divergent"
+        basemsg = _(b"%s has diverged, use '%s' to resolve the issue")
         solvemsg = basemsg % (shortnode, debugcommand)
-    elif reason == 'superseed':
-        msg = _("use 'hg evolve' to update to its successor: %s")
+    elif reason == b'superseed':
+        msg = _(b"use 'hg evolve' to update to its successor: %s")
         solvemsg = msg % successors[0]
-    elif reason == 'superseed_split':
-        msg = _("use 'hg evolve' to update to its tipmost successor: %s")
+    elif reason == b'superseed_split':
+        msg = _(b"use 'hg evolve' to update to its tipmost successor: %s")
 
         if len(successors) <= 2:
-            solvemsg = msg % ", ".join(successors)
+            solvemsg = msg % b", ".join(successors)
         else:
-            firstsuccessors = ", ".join(successors[:2])
+            firstsuccessors = b", ".join(successors[:2])
             remainingnumber = len(successors) - 2
-            successorsmsg = _("%s and %d more") % (firstsuccessors, remainingnumber)
+            successorsmsg = _(b"%s and %d more") % (firstsuccessors, remainingnumber)
             solvemsg = msg % successorsmsg
     else:
         raise ValueError(reason)
 
-    ui.warn("(%s)\n" % solvemsg)
+    ui.warn(b"(%s)\n" % solvemsg)
 
-if util.safehasattr(context, '_filterederror'): # <= hg-4.5
-    @eh.wrapfunction(context, '_filterederror')
+if util.safehasattr(context, b'_filterederror'): # <= hg-4.5
+    @eh.wrapfunction(context, b'_filterederror')
     def evolve_filtererror(original, repo, changeid):
         """build an exception to be raised about a filtered changeid
 
         This is extracted in a function to help extensions (eg: evolve) to
         experiment with various message variants."""
-        if repo.filtername.startswith('visible'):
+        if repo.filtername.startswith(b'visible'):
 
             unfilteredrepo = repo.unfiltered()
             rev = repo[scmutil.revsingle(unfilteredrepo, changeid)]
             reason, successors = obshistory._getobsfateandsuccs(unfilteredrepo, rev.node())
 
             # Be more precise in case the revision is superseed
-            if reason == 'superseed':
-                reason = _("successor: %s") % successors[0]
-            elif reason == 'superseed_split':
+            if reason == b'superseed':
+                reason = _(b"successor: %s") % successors[0]
+            elif reason == b'superseed_split':
                 if len(successors) <= 2:
-                    reason = _("successors: %s") % ", ".join(successors)
+                    reason = _(b"successors: %s") % b", ".join(successors)
                 else:
-                    firstsuccessors = ", ".join(successors[:2])
+                    firstsuccessors = b", ".join(successors[:2])
                     remainingnumber = len(successors) - 2
-                    successorsmsg = _("%s and %d more") % (firstsuccessors, remainingnumber)
-                    reason = _("successors: %s") % successorsmsg
+                    successorsmsg = _(b"%s and %d more") % (firstsuccessors, remainingnumber)
+                    reason = _(b"successors: %s") % successorsmsg
 
-            msg = _("hidden revision '%s'") % changeid
-            hint = _('use --hidden to access hidden revisions; %s') % reason
+            msg = _(b"hidden revision '%s'") % changeid
+            hint = _(b'use --hidden to access hidden revisions; %s') % reason
             return error.FilteredRepoLookupError(msg, hint=hint)
-        msg = _("filtered revision '%s' (not in '%s' subset)")
+        msg = _(b"filtered revision '%s' (not in '%s' subset)")
         msg %= (changeid, repo.filtername)
         return error.FilteredRepoLookupError(msg)
 
-@eh.wrapcommand("update")
-@eh.wrapcommand("pull")
+@eh.wrapcommand(b"update")
+@eh.wrapcommand(b"pull")
 def wrapmayobsoletewc(origfn, ui, repo, *args, **opts):
     """Warn that the working directory parent is an obsolete changeset"""
-    ctx = repo['.']
+    ctx = repo[b'.']
     node = ctx.node()
     isobs = ctx.obsolete()
 
@@ -775,23 +775,23 @@ 
         lockmod.release(wlock)
     return res
 
-@eh.wrapcommand("parents")
+@eh.wrapcommand(b"parents")
 def wrapparents(origfn, ui, repo, *args, **opts):
     res = origfn(ui, repo, *args, **opts)
     _warnobsoletewc(ui, repo)
     return res
 
-@eh.wrapfunction(mercurial.exchange, 'push')
+@eh.wrapfunction(mercurial.exchange, b'push')
 def push(orig, repo, *args, **opts):
     """Add a hint for "hg evolve" when troubles make push fails
     """
     try:
         return orig(repo, *args, **opts)
     except error.Abort as ex:
-        hint = _("use 'hg evolve' to get a stable history "
-                 "or --force to ignore warnings")
+        hint = _(b"use 'hg evolve' to get a stable history "
+                 b"or --force to ignore warnings")
         if (len(ex.args) >= 1
-            and ex.args[0].startswith('push includes ')
+            and ex.args[0].startswith(b'push includes ')
             and ex.hint is None):
             ex.hint = hint
         raise
@@ -800,11 +800,11 @@ 
     evolvestate = state.cmdstate(repo)
     if evolvestate:
         # i18n: column positioning for "hg summary"
-        ui.status(_('evolve: (evolve --continue)\n'))
+        ui.status(_(b'evolve: (evolve --continue)\n'))
 
 @eh.extsetup
 def obssummarysetup(ui):
-    cmdutil.summaryhooks.add('evolve', summaryhook)
+    cmdutil.summaryhooks.add(b'evolve', summaryhook)
 
 #####################################################################
 ### Old Evolve extension content                                  ###
@@ -815,20 +815,20 @@ 
 
 @eh.uisetup
 def _installimportobsolete(ui):
-    entry = cmdutil.findcmd('import', commands.table)[1]
-    entry[1].append(('', 'obsolete', False,
-                    _('mark the old node as obsoleted by '
-                      'the created commit')))
+    entry = cmdutil.findcmd(b'import', commands.table)[1]
+    entry[1].append((b'', b'obsolete', False,
+                     _(b'mark the old node as obsoleted by '
+                       b'the created commit')))
 
 def _getnodefrompatch(patch, dest):
-    patchnode = patch.get('nodeid')
+    patchnode = patch.get(b'nodeid')
     if patchnode is not None:
-        dest['node'] = node.bin(patchnode)
+        dest[b'node'] = node.bin(patchnode)
 
-@eh.wrapfunction(mercurial.cmdutil, 'tryimportone')
+@eh.wrapfunction(mercurial.cmdutil, b'tryimportone')
 def tryimportone(orig, ui, repo, hunk, parents, opts, *args, **kwargs):
-    expected = {'node': None}
-    if not util.safehasattr(hunk, 'get'): # hg < 4.6
+    expected = {b'node': None}
+    if not util.safehasattr(hunk, b'get'): # hg < 4.6
         oldextract = patch.extract
 
         def extract(*args, **kwargs):
@@ -844,12 +844,12 @@ 
         _getnodefrompatch(hunk, expected)
         ret = orig(ui, repo, hunk, parents, opts, *args, **kwargs)
     created = ret[1]
-    if (opts['obsolete'] and None not in (created, expected['node'])
-        and created != expected['node']):
-        tr = repo.transaction('import-obs')
+    if (opts[b'obsolete'] and None not in (created, expected[b'node'])
+        and created != expected[b'node']):
+        tr = repo.transaction(b'import-obs')
         try:
-            metadata = {'user': ui.username()}
-            repo.obsstore.create(tr, expected['node'], (created,),
+            metadata = {b'user': ui.username()}
+            repo.obsstore.create(tr, expected[b'node'], (created,),
                                  metadata=metadata)
             tr.close()
         finally:
@@ -877,62 +877,62 @@ 
         if e is entry:
             break
 
-    synopsis = '(DEPRECATED)'
+    synopsis = b'(DEPRECATED)'
     if len(entry) > 2:
         fn, opts, _syn = entry
     else:
         fn, opts, = entry
-    deprecationwarning = _('%s have been deprecated in favor of %s\n') % (
+    deprecationwarning = _(b'%s have been deprecated in favor of %s\n') % (
         oldalias, newalias)
 
     def newfn(*args, **kwargs):
         ui = args[0]
         ui.warn(deprecationwarning)
         util.checksignature(fn)(*args, **kwargs)
-    newfn.__doc__ = deprecationwarning + ' (DEPRECATED)'
+    newfn.__doc__ = deprecationwarning + b' (DEPRECATED)'
     cmdwrapper = eh.command(oldalias, opts, synopsis)
     cmdwrapper(newfn)
 
 @eh.extsetup
 def deprecatealiases(ui):
-    _deprecatealias('gup', 'next')
-    _deprecatealias('gdown', 'previous')
+    _deprecatealias(b'gup', b'next')
+    _deprecatealias(b'gdown', b'previous')
 
 def _gettopic(ctx):
     """handle topic fetching with or without the extension"""
-    return getattr(ctx, 'topic', lambda: '')()
+    return getattr(ctx, 'topic', lambda: b'')()
 
 def _gettopicidx(ctx):
     """handle topic fetching with or without the extension"""
     return getattr(ctx, 'topicidx', lambda: None)()
 
 def _getcurrenttopic(repo):
-    return getattr(repo, 'currenttopic', '')
+    return getattr(repo, 'currenttopic', b'')
 
 def _prevupdate(repo, displayer, target, bookmark, dryrun, mergeopt):
     if dryrun:
-        repo.ui.write(_('hg update %s;\n') % target)
+        repo.ui.write(_(b'hg update %s;\n') % target)
         if bookmark is not None:
-            repo.ui.write(_('hg bookmark %s -r %s;\n')
+            repo.ui.write(_(b'hg bookmark %s -r %s;\n')
                           % (bookmark, target))
     else:
         updatecheck = None
         # --merge is passed, we don't need to care about commands.update.check
         # config option
         if mergeopt:
-            updatecheck = 'none'
+            updatecheck = b'none'
         try:
             ret = hg.updatetotally(repo.ui, repo, target.node(), None,
                                    updatecheck=updatecheck)
         except error.Abort as exc:
             # replace the hint to mention about --merge option
-            exc.hint = _('do you want --merge?')
+            exc.hint = _(b'do you want --merge?')
             raise
         if not ret:
             tr = lock = None
             try:
                 lock = repo.lock()
-                tr = repo.transaction('previous')
+                tr = repo.transaction(b'previous')
                 if bookmark is not None:
                     bmchanges = [(bookmark, target.node())]
                     repo._bookmarks.applychanges(repo, tr, bmchanges)
@@ -960,75 +960,75 @@ 
 
     # issue message for the various case
     if p1.node() == node.nullid:
-        repo.ui.warn(_('already at repository root\n'))
+        repo.ui.warn(_(b'already at repository root\n'))
     elif not parents and currenttopic:
-        repo.ui.warn(_('no parent in topic "%s"\n') % currenttopic)
-        repo.ui.warn(_('(do you want --no-topic)\n'))
+        repo.ui.warn(_(b'no parent in topic "%s"\n') % currenttopic)
+        repo.ui.warn(_(b'(do you want --no-topic)\n'))
     elif len(parents) == 1:
         target = parents[0]
         bookmark = None
         if movebookmark:
             bookmark = repo._activebookmark
     else:
-        header = _("multiple parents, choose one to update:")
+        header = _(b"multiple parents, choose one to update:")
         prevs = [p.rev() for p in parents]
         choosedrev = utility.revselectionprompt(repo.ui, repo, prevs, header)
         if choosedrev is None:
             for p in parents:
                 displayer.show(p)
-            repo.ui.warn(_('multiple parents, explicitly update to one\n'))
+            repo.ui.warn(_(b'multiple parents, explicitly update to one\n'))
         else:
             target = repo[choosedrev]
     return target, bookmark
 
 @eh.command(
-    'previous',
-    [('B', 'move-bookmark', False,
-        _('move active bookmark after update')),
-     ('m', 'merge', False, _('bring uncommitted change along')),
-     ('', 'no-topic', False, _('ignore topic and move topologically')),
-     ('n', 'dry-run', False,
-        _('do not perform actions, just print what would be done'))],
-    '[OPTION]...',
+    b'previous',
+    [(b'B', b'move-bookmark', False,
+        _(b'move active bookmark after update')),
+     (b'm', b'merge', False, _(b'bring uncommitted change along')),
+     (b'', b'no-topic', False, _(b'ignore topic and move topologically')),
+     (b'n', b'dry-run', False,
+        _(b'do not perform actions, just print what would be done'))],
+    b'[OPTION]...',
     helpbasic=True)
 def cmdprevious(ui, repo, **opts):
     """update to parent revision
 
     Displays the summary line of the destination for clarity."""
     wlock = None
-    dryrunopt = opts['dry_run']
-    mergeopt = opts['merge']
+    dryrunopt = opts[b'dry_run']
+    mergeopt = opts[b'merge']
     if not dryrunopt:
         wlock = repo.wlock()
     try:
         wkctx = repo[None]
         wparents = wkctx.parents()
         if len(wparents) != 1:
-            raise error.Abort(_('merge in progress'))
+            raise error.Abort(_(b'merge in progress'))
         if not mergeopt:
             # we only skip the check if noconflict is set
-            if ui.config('commands', 'update.check') == 'noconflict':
+            if ui.config(b'commands', b'update.check') == b'noconflict':
                 pass
             else:
-                cmdutil.bailifchanged(repo, hint=_('do you want --merge?'))
+                cmdutil.bailifchanged(repo, hint=_(b'do you want --merge?'))
 
-        topic = not opts.get("no_topic", False)
+        topic = not opts.get(b"no_topic", False)
         hastopic = bool(_getcurrenttopic(repo))
 
         template = shorttemplate
         if topic and hastopic:
             template = utility.stacktemplate
 
-        displayer = compat.changesetdisplayer(ui, repo, {'template': template})
+        displayer = compat.changesetdisplayer(ui, repo, {b'template': template})
 
         target, bookmark = _findprevtarget(repo, displayer,
-                                           opts.get('move_bookmark'), topic)
+                                           opts.get(b'move_bookmark'), topic)
         if target is not None:
-            backup = repo.ui.backupconfig('_internal', 'keep-topic')
+            backup = repo.ui.backupconfig(b'_internal', b'keep-topic')
             try:
                 if topic and _getcurrenttopic(repo) != _gettopic(target):
-                    repo.ui.setconfig('_internal', 'keep-topic', 'yes',
-                                      source='topic-extension')
+                    repo.ui.setconfig(b'_internal', b'keep-topic', b'yes',
+                                      source=b'topic-extension')
                 _prevupdate(repo, displayer, target, bookmark, dryrunopt,
                             mergeopt)
             finally:
@@ -1040,15 +1040,15 @@ 
         lockmod.release(wlock)
 
 @eh.command(
-    'next',
-    [('B', 'move-bookmark', False,
-        _('move active bookmark after update')),
-     ('m', 'merge', False, _('bring uncommitted change along')),
-     ('', 'evolve', True, _('evolve the next changeset if necessary')),
-     ('', 'no-topic', False, _('ignore topic and move topologically')),
-     ('n', 'dry-run', False,
-      _('do not perform actions, just print what would be done'))],
-    '[OPTION]...',
+    b'next',
+    [(b'B', b'move-bookmark', False,
+        _(b'move active bookmark after update')),
+     (b'm', b'merge', False, _(b'bring uncommitted change along')),
+     (b'', b'evolve', True, _(b'evolve the next changeset if necessary')),
+     (b'', b'no-topic', False, _(b'ignore topic and move topologically')),
+     (b'n', b'dry-run', False,
+      _(b'do not perform actions, just print what would be done'))],
+    b'[OPTION]...',
     helpbasic=True)
 def cmdnext(ui, repo, **opts):
     """update to next child revision
@@ -1059,29 +1059,29 @@ 
     Displays the summary line of the destination for clarity.
     """
     wlock = None
-    dryrunopt = opts['dry_run']
+    dryrunopt = opts[b'dry_run']
     if not dryrunopt:
         wlock = repo.wlock()
     try:
         wkctx = repo[None]
         wparents = wkctx.parents()
         if len(wparents) != 1:
-            raise error.Abort(_('merge in progress'))
+            raise error.Abort(_(b'merge in progress'))
 
         children = [ctx for ctx in wparents[0].children() if not ctx.obsolete()]
         topic = _getcurrenttopic(repo)
         filtered = set()
         template = shorttemplate
-        if topic and not opts.get("no_topic", False):
+        if topic and not opts.get(b"no_topic", False):
             filtered = set(ctx for ctx in children if ctx.topic() != topic)
             children = [ctx for ctx in children if ctx not in filtered]
             template = utility.stacktemplate
-            opts['stacktemplate'] = True
-        displayer = compat.changesetdisplayer(ui, repo, {'template': template})
+            opts[b'stacktemplate'] = True
+        displayer = compat.changesetdisplayer(ui, repo, {b'template': template})
 
         # check if we need to evolve while updating to the next child revision
         needevolve = False
-        aspchildren = evolvecmd._aspiringchildren(repo, [repo['.'].rev()])
+        aspchildren = evolvecmd._aspiringchildren(repo, [repo[b'.'].rev()])
         if topic:
             filtered.update(repo[c] for c in aspchildren
                             if repo[c].topic() != topic)
@@ -1100,54 +1100,54 @@ 
             needevolve = True
 
         # check if working directory is clean before we evolve the next cset
-        if needevolve and opts['evolve']:
-            hint = _('use `hg amend`, `hg revert` or `hg shelve`')
+        if needevolve and opts[b'evolve']:
+            hint = _(b'use `hg amend`, `hg revert` or `hg shelve`')
             cmdutil.bailifchanged(repo, hint=hint)
 
-        if not (opts['merge'] or (needevolve and opts['evolve'])):
+        if not (opts[b'merge'] or (needevolve and opts[b'evolve'])):
             # we only skip the check if noconflict is set
-            if ui.config('commands', 'update.check') == 'noconflict':
+            if ui.config(b'commands', b'update.check') == b'noconflict':
                 pass
             else:
-                cmdutil.bailifchanged(repo, hint=_('do you want --merge?'))
+                cmdutil.bailifchanged(repo, hint=_(b'do you want --merge?'))
 
         if len(children) == 1:
             c = children[0]
             return _updatetonext(ui, repo, c, displayer, opts)
         elif children:
-            cheader = _("ambiguous next changeset, choose one to update:")
+            cheader = _(b"ambiguous next changeset, choose one to update:")
             crevs = [c.rev() for c in children]
             choosedrev = utility.revselectionprompt(ui, repo, crevs, cheader)
             if choosedrev is None:
-                ui.warn(_("ambiguous next changeset:\n"))
+                ui.warn(_(b"ambiguous next changeset:\n"))
                 for c in children:
                     displayer.show(c)
-                ui.warn(_("explicitly update to one of them\n"))
+                ui.warn(_(b"explicitly update to one of them\n"))
                 return 1
             else:
                 return _updatetonext(ui, repo, repo[choosedrev], displayer, opts)
         else:
-            if not opts['evolve'] or not aspchildren:
+            if not opts[b'evolve'] or not aspchildren:
                 if filtered:
-                    ui.warn(_('no children on topic "%s"\n') % topic)
-                    ui.warn(_('do you want --no-topic\n'))
+                    ui.warn(_(b'no children on topic "%s"\n') % topic)
+                    ui.warn(_(b'do you want --no-topic\n'))
                 else:
-                    ui.warn(_('no children\n'))
+                    ui.warn(_(b'no children\n'))
                 if aspchildren:
-                    msg = _('(%i unstable changesets to be evolved here, '
-                            'do you want --evolve?)\n')
+                    msg = _(b'(%i unstable changesets to be evolved here, '
+                            b'do you want --evolve?)\n')
                     ui.warn(msg % len(aspchildren))
                 return 1
             elif len(aspchildren) > 1:
-                cheader = _("ambiguous next (unstable) changeset, choose one to"
-                            " evolve and update:")
+                cheader = _(b"ambiguous next (unstable) changeset, choose one to"
+                            b" evolve and update:")
                 choosedrev = utility.revselectionprompt(ui, repo,
                                                         aspchildren, cheader)
                 if choosedrev is None:
-                    ui.warn(_("ambiguous next (unstable) changeset:\n"))
+                    ui.warn(_(b"ambiguous next (unstable) changeset:\n"))
                     for c in aspchildren:
                         displayer.show(repo[c])
-                    ui.warn(_("(run 'hg evolve --rev REV' on one of them)\n"))
+                    ui.warn(_(b"(run 'hg evolve --rev REV' on one of them)\n"))
                     return 1
                 else:
                     return _nextevolve(ui, repo, repo[choosedrev], opts)
@@ -1160,51 +1160,51 @@ 
     """logic for hg next command to evolve and update to an aspiring children"""
 
     cmdutil.bailifchanged(repo)
-    evolvestate = state.cmdstate(repo, opts={'command': 'next',
-                                             'bookmarkchanges': []})
+    evolvestate = state.cmdstate(repo, opts={b'command': b'next',
+                                             b'bookmarkchanges': []})
     with repo.wlock(), repo.lock():
-        tr = repo.transaction("evolve")
+        tr = repo.transaction(b"evolve")
         with util.acceptintervention(tr):
             result = evolvecmd._solveone(ui, repo, repo[aspchildren],
-                                         evolvestate, opts.get('dry_run'),
+                                         evolvestate, opts.get(b'dry_run'),
                                          False,
-                                         lambda: None, category='orphan',
-                                         stacktmplt=opts.get('stacktemplate',
+                                         lambda: None, category=b'orphan',
+                                         stacktmplt=opts.get(b'stacktemplate',
                                                              False))
     # making sure a next commit is formed
     if result[0] and result[1]:
-        ui.status(_('working directory is now at %s\n')
-                  % ui.label(str(repo['.']), 'evolve.node'))
+        ui.status(_(b'working directory is now at %s\n')
+                  % ui.label(str(repo[b'.']), b'evolve.node'))
     return 0
 
 def _updatetonext(ui, repo, children, displayer, opts):
     """ logic for `hg next` command to update to children and move bookmarks if
     required """
     bm = repo._activebookmark
-    shouldmove = opts.get('move_bookmark') and bm is not None
-    if opts.get('dry_run'):
-        ui.write(_('hg update %s;\n') % children)
+    shouldmove = opts.get(b'move_bookmark') and bm is not None
+    if opts.get(b'dry_run'):
+        ui.write(_(b'hg update %s;\n') % children)
         if shouldmove:
-            ui.write(_('hg bookmark %s -r %s;\n') % (bm, children))
+            ui.write(_(b'hg bookmark %s -r %s;\n') % (bm, children))
     else:
         updatecheck = None
         # --merge is passed, we don't need to care about commands.update.check
         # config option
-        if opts['merge']:
-            updatecheck = 'none'
+        if opts[b'merge']:
+            updatecheck = b'none'
         try:
             ret = hg.updatetotally(ui, repo, children.node(), None,
                                    updatecheck=updatecheck)
         except error.Abort as exc:
             # replace the hint to mention about --merge option
-            exc.hint = _('do you want --merge?')
+            exc.hint = _(b'do you want --merge?')
             raise
 
         if not ret:
             lock = tr = None
             try:
                 lock = repo.lock()
-                tr = repo.transaction('next')
+                tr = repo.transaction(b'next')
                 if shouldmove:
                     bmchanges = [(bm, children.node())]
                     repo._bookmarks.applychanges(repo, tr, bmchanges)
@@ -1217,28 +1217,28 @@ 
         displayer.show(children)
     return 0
 
-@eh.wrapcommand('commit')
+@eh.wrapcommand(b'commit')
 def commitwrapper(orig, ui, repo, *arg, **kwargs):
     tr = None
-    if kwargs.get('amend', False):
+    if kwargs.get(b'amend', False):
         wlock = lock = None
     else:
         wlock = repo.wlock()
         lock = repo.lock()
     try:
-        obsoleted = kwargs.get('obsolete', [])
+        obsoleted = kwargs.get(b'obsolete', [])
         if obsoleted:
-            obsoleted = repo.set('%lr', obsoleted)
+            obsoleted = repo.set(b'%lr', obsoleted)
         result = orig(ui, repo, *arg, **kwargs)
         if not result: # commit succeeded
-            new = repo['tip']
+            new = repo[b'tip']
             oldbookmarks = []
             markers = []
             for old in obsoleted:
                 oldbookmarks.extend(repo.nodebookmarks(old.node()))
                 markers.append((old, (new,)))
             if markers:
-                obsolete.createmarkers(repo, markers, operation="amend")
+                obsolete.createmarkers(repo, markers, operation=b"amend")
             bmchanges = []
             for book in oldbookmarks:
                 bmchanges.append((book, new.node()))
@@ -1247,70 +1247,70 @@ 
                     wlock = repo.wlock()
                 if not lock:
                     lock = repo.lock()
-                tr = repo.transaction('commit')
+                tr = repo.transaction(b'commit')
                 repo._bookmarks.applychanges(repo, tr, bmchanges)
                 tr.close()
         return result
     finally:
         lockmod.release(tr, lock, wlock)
 
-@eh.wrapcommand('strip', extension='strip', opts=[
-    ('', 'bundle', None, _("delete the commit entirely and move it to a "
-                           "backup bundle")),
+@eh.wrapcommand(b'strip', extension=b'strip', opts=[
+    (b'', b'bundle', None, _(b"delete the commit entirely and move it to a "
+                             b"backup bundle")),
     ])
 def stripwrapper(orig, ui, repo, *revs, **kwargs):
-    if (not ui.configbool('experimental', 'prunestrip')
-        or kwargs.get('bundle', False)):
+    if (not ui.configbool(b'experimental', b'prunestrip')
+        or kwargs.get(b'bundle', False)):
         return orig(ui, repo, *revs, **kwargs)
 
-    if kwargs.get('force'):
-        ui.warn(_("warning: --force has no effect during strip with evolve "
-                  "enabled\n"))
-    if kwargs.get('no_backup', False):
-        ui.warn(_("warning: --no-backup has no effect during strips with "
-                  "evolve enabled\n"))
+    if kwargs.get(b'force'):
+        ui.warn(_(b"warning: --force has no effect during strip with evolve "
+                  b"enabled\n"))
+    if kwargs.get(b'no_backup', False):
+        ui.warn(_(b"warning: --no-backup has no effect during strips with "
+                  b"evolve enabled\n"))
 
-    revs = list(revs) + kwargs.pop('rev', [])
+    revs = list(revs) + kwargs.pop(b'rev', [])
     revs = set(scmutil.revrange(repo, revs))
-    revs = repo.revs("(%ld)::", revs)
-    kwargs['rev'] = []
-    kwargs['new'] = []
-    kwargs['succ'] = []
-    kwargs['biject'] = False
+    revs = repo.revs(b"(%ld)::", revs)
+    kwargs[b'rev'] = []
+    kwargs[b'new'] = []
+    kwargs[b'succ'] = []
+    kwargs[b'biject'] = False
     return cmdrewrite.cmdprune(ui, repo, *revs, **kwargs)
 
 @eh.extsetup
 def oldevolveextsetup(ui):
-    entry = cmdutil.findcmd('commit', commands.table)[1]
-    entry[1].append(('o', 'obsolete', [],
-                     _("make commit obsolete this revision (DEPRECATED)")))
+    entry = cmdutil.findcmd(b'commit', commands.table)[1]
+    entry[1].append((b'o', b'obsolete', [],
+                     _(b"make commit obsolete this revision (DEPRECATED)")))
 
-@eh.wrapfunction(obsolete, '_checkinvalidmarkers')
+@eh.wrapfunction(obsolete, b'_checkinvalidmarkers')
 def _checkinvalidmarkers(orig, markers):
     """search for marker with invalid data and raise error if needed
 
     Exist as a separated function to allow the evolve extension for a more
     subtle handling.
     """
-    if 'debugobsconvert' in sys.argv:
+    if b'debugobsconvert' in sys.argv:
         return
     for mark in markers:
         if node.nullid in mark[1]:
-            msg = _('bad obsolescence marker detected: invalid successors nullid')
-            hint = _('You should run `hg debugobsconvert`')
+            msg = _(b'bad obsolescence marker detected: invalid successors nullid')
+            hint = _(b'You should run `hg debugobsconvert`')
             raise error.Abort(msg, hint=hint)
 
 @eh.command(
-    'debugobsconvert',
-    [('', 'new-format', obsexchange._bestformat, _('Destination format for markers.'))],
-    '')
+    b'debugobsconvert',
+    [(b'', b'new-format', obsexchange._bestformat, _(b'Destination format for markers.'))],
+    b'')
 def debugobsconvert(ui, repo, new_format):
     origmarkers = repo.obsstore._all  # settle version
     if new_format == repo.obsstore._version:
-        msg = _('New format is the same as the old format, not upgrading!')
+        msg = _(b'New format is the same as the old format, not upgrading!')
         raise error.Abort(msg)
     with repo.lock():
-        f = repo.svfs('obsstore', 'wb', atomictemp=True)
+        f = repo.svfs(b'obsstore', b'wb', atomictemp=True)
         known = set()
         markers = []
         for m in origmarkers:
@@ -1323,11 +1323,11 @@ 
                 continue
             known.add(m)
             markers.append(m)
-        ui.write(_('Old store is version %d, will rewrite in version %d\n') % (
+        ui.write(_(b'Old store is version %d, will rewrite in version %d\n') % (
             repo.obsstore._version, new_format))
         map(f.write, obsolete.encodemarkers(markers, True, new_format))
         f.close()
-    ui.write(_('Done!\n'))
+    ui.write(_(b'Done!\n'))
 
 
 def _helploader(ui):
@@ -1336,40 +1336,40 @@ 
 @eh.uisetup
 def _setuphelp(ui):
     for entry in help.helptable:
-        if entry[0] == "evolution":
+        if entry[0] == b"evolution":
             break
     else:
-        help.helptable.append((["evolution"], _("Safely Rewriting History"),
-                              _helploader))
+        help.helptable.append(([b"evolution"], _(b"Safely Rewriting History"),
+                               _helploader))
         help.helptable.sort()
 
 evolvestateversion = 0
 
 def _evolvemessage():
-    _msg = _('To continue:    hg evolve --continue\n'
-             'To abort:       hg evolve --abort\n'
-             'To stop:        hg evolve --stop\n'
-             '(also see `hg help evolve.interrupted`)')
+    _msg = _(b'To continue:    hg evolve --continue\n'
+             b'To abort:       hg evolve --abort\n'
+             b'To stop:        hg evolve --stop\n'
+