changeset 8078:45bfab30d433

py3: add b'' annotations in some places where they will be needed later Mostly entirely trivial adding of b prefix that is a ignored for py2 ... and also a bit of related trivial reformatting/refactorings.
author Mads Kiilerich <mads@kiilerich.com>
date Sat, 28 Dec 2019 20:25:59 +0100
parents effd091203ae
children 88e0d0c0c208
files kallithea/config/app_cfg.py kallithea/controllers/compare.py kallithea/controllers/pullrequests.py kallithea/lib/diffs.py kallithea/lib/hooks.py kallithea/lib/ssh.py kallithea/lib/utils.py kallithea/lib/vcs/backends/git/changeset.py kallithea/lib/vcs/backends/git/inmemory.py kallithea/lib/vcs/backends/git/repository.py kallithea/lib/vcs/backends/git/workdir.py kallithea/lib/vcs/backends/hg/changeset.py kallithea/lib/vcs/backends/hg/inmemory.py kallithea/lib/vcs/backends/hg/repository.py kallithea/lib/vcs/backends/hg/ssh.py kallithea/lib/vcs/subprocessio.py kallithea/model/pull_request.py kallithea/model/scm.py kallithea/tests/api/api_base.py kallithea/tests/base.py kallithea/tests/fixture.py kallithea/tests/functional/test_admin_auth_settings.py kallithea/tests/functional/test_admin_gists.py kallithea/tests/vcs/test_git.py kallithea/tests/vcs/test_hg.py kallithea/tests/vcs/test_inmemchangesets.py kallithea/tests/vcs/test_nodes.py kallithea/tests/vcs/test_repository.py
diffstat 28 files changed, 134 insertions(+), 133 deletions(-) [+]
line wrap: on
line diff
--- a/kallithea/config/app_cfg.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/config/app_cfg.py	Sat Dec 28 20:25:59 2019 +0100
@@ -162,7 +162,7 @@
 
     load_rcextensions(root_path=config['here'])
 
-    repos_path = make_ui().configitems('paths')[0][1]
+    repos_path = make_ui().configitems(b'paths')[0][1]
     config['base_path'] = repos_path
     set_app_settings(config)
 
--- a/kallithea/controllers/compare.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/controllers/compare.py	Sat Dec 28 20:25:59 2019 +0100
@@ -108,20 +108,26 @@
                 hgrepo = other_repo._repo
 
             ancestors = [hgrepo[ancestor].hex() for ancestor in
-                         hgrepo.revs("id(%s) & ::id(%s)", other_rev, org_rev)]
+                         hgrepo.revs(b"id(%s) & ::id(%s)", other_rev, org_rev)]
             if ancestors:
                 log.debug("shortcut found: %s is already an ancestor of %s", other_rev, org_rev)
             else:
                 log.debug("no shortcut found: %s is not an ancestor of %s", other_rev, org_rev)
                 ancestors = [hgrepo[ancestor].hex() for ancestor in
-                             hgrepo.revs("heads(::id(%s) & ::id(%s))", org_rev, other_rev)] # FIXME: expensive!
+                             hgrepo.revs(b"heads(::id(%s) & ::id(%s))", org_rev, other_rev)] # FIXME: expensive!
 
-            other_revs = hgrepo.revs("ancestors(id(%s)) and not ancestors(id(%s)) and not id(%s)",
-                                     other_rev, org_rev, org_rev)
-            other_changesets = [other_repo.get_changeset(rev) for rev in other_revs]
-            org_revs = hgrepo.revs("ancestors(id(%s)) and not ancestors(id(%s)) and not id(%s)",
-                                   org_rev, other_rev, other_rev)
-            org_changesets = [org_repo.get_changeset(hgrepo[rev].hex()) for rev in org_revs]
+            other_changesets = [
+                other_repo.get_changeset(rev)
+                for rev in hgrepo.revs(
+                    b"ancestors(id(%s)) and not ancestors(id(%s)) and not id(%s)",
+                     other_rev, org_rev, org_rev)
+            ]
+            org_changesets = [
+                org_repo.get_changeset(hgrepo[rev].hex())
+                for rev in hgrepo.revs(
+                    b"ancestors(id(%s)) and not ancestors(id(%s)) and not id(%s)",
+                    org_rev, other_rev, other_rev)
+            ]
 
         elif alias == 'git':
             if org_repo != other_repo:
--- a/kallithea/controllers/pullrequests.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/controllers/pullrequests.py	Sat Dec 28 20:25:59 2019 +0100
@@ -97,7 +97,7 @@
             # including branches of children could be nice too
             peerbranches = set()
             for i in repo._repo.revs(
-                "sort(parents(branch(id(%s)) and merge()) - branch(id(%s)), -rev)",
+                b"sort(parents(branch(id(%s)) and merge()) - branch(id(%s)), -rev)",
                 branch_rev, branch_rev
             ):
                 for abranch in repo.get_changeset(i).branches:
--- a/kallithea/lib/diffs.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/lib/diffs.py	Sat Dec 28 20:25:59 2019 +0100
@@ -236,7 +236,7 @@
     context = context or 3
     submodules = [o for o in [filenode_new, filenode_old] if isinstance(o, SubModuleNode)]
     if submodules:
-        return ''
+        return b''
 
     for filenode in (filenode_old, filenode_new):
         if not isinstance(filenode, FileNode):
@@ -261,7 +261,7 @@
                                      ignore_whitespace=ignore_whitespace, context=context)
     except MemoryError:
         h.flash('MemoryError: Diff is too big', category='error')
-        return ''
+        return b''
 
 
 NEW_FILENODE = 1
@@ -279,7 +279,7 @@
     mentioned in the diff together with a dict of meta information that
     can be used to render it in a HTML template.
     """
-    _diff_git_re = re.compile('^diff --git', re.MULTILINE)
+    _diff_git_re = re.compile(b'^diff --git', re.MULTILINE)
 
     def __init__(self, diff, vcs='hg', diff_limit=None, inline_diff=True):
         """
@@ -480,7 +480,7 @@
     return _escape_re.sub(substitute, safe_unicode(string))
 
 
-_git_header_re = re.compile(r"""
+_git_header_re = re.compile(br"""
     ^diff[ ]--git[ ]a/(?P<a_path>.+?)[ ]b/(?P<b_path>.+?)\n
     (?:^old[ ]mode[ ](?P<old_mode>\d+)\n
        ^new[ ]mode[ ](?P<new_mode>\d+)(?:\n|$))?
@@ -497,7 +497,7 @@
 """, re.VERBOSE | re.MULTILINE)
 
 
-_hg_header_re = re.compile(r"""
+_hg_header_re = re.compile(br"""
     ^diff[ ]--git[ ]a/(?P<a_path>.+?)[ ]b/(?P<b_path>.+?)\n
     (?:^old[ ]mode[ ](?P<old_mode>\d+)\n
        ^new[ ]mode[ ](?P<new_mode>\d+)(?:\n|$))?
@@ -542,7 +542,7 @@
     rest = diff_chunk[match.end():]
     if rest and _header_next_check.match(rest):
         raise Exception('cannot parse %s diff header: %r followed by %r' % (vcs, diff_chunk[:match.end()], rest[:1000]))
-    diff_lines = (_escaper(m.group(0)) for m in re.finditer(r'.*\n|.+$', rest)) # don't split on \r as str.splitlines do
+    diff_lines = (_escaper(m.group(0)) for m in re.finditer(br'.*\n|.+$', rest)) # don't split on \r as str.splitlines do
     return meta_info, diff_lines
 
 
--- a/kallithea/lib/hooks.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/lib/hooks.py	Sat Dec 28 20:25:59 2019 +0100
@@ -110,7 +110,7 @@
     cahes! The function should perhaps be renamed.
     """
     _h = binascii.hexlify
-    revs = [_h(repo[r].node()) for r in revrange(repo, [node + ':' + node_last])]
+    revs = [_h(repo[r].node()) for r in revrange(repo, [b'%s:%s' % (node, node_last)])]
     process_pushed_raw_ids(revs)
     return 0
 
@@ -363,8 +363,9 @@
             if push_ref['old_rev'] == EmptyChangeset().raw_id:
                 # update the symbolic ref if we push new repo
                 if scm_repo.is_empty():
-                    scm_repo._repo.refs.set_symbolic_ref('HEAD',
-                                        'refs/heads/%s' % push_ref['name'])
+                    scm_repo._repo.refs.set_symbolic_ref(
+                        b'HEAD',
+                        b'refs/heads/%s' % push_ref['name'])
 
                 # build exclude list without the ref
                 cmd = ['for-each-ref', '--format=%(refname)', 'refs/heads/*']
--- a/kallithea/lib/ssh.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/lib/ssh.py	Sat Dec 28 20:25:59 2019 +0100
@@ -88,8 +88,8 @@
     except TypeError:
         raise SshKeyParseError(_("Incorrect SSH key - failed to decode base64 part %r") % keyvalue)
 
-    if not decoded.startswith('\x00\x00\x00' + chr(len(keytype)) + str(keytype) + '\x00'):
-        raise SshKeyParseError(_("Incorrect SSH key - base64 part is not %r as claimed but %r") % (str(keytype), str(decoded[4:].split('\0', 1)[0])))
+    if not decoded.startswith(b'\x00\x00\x00' + chr(len(keytype)) + str(keytype) + b'\x00'):
+        raise SshKeyParseError(_("Incorrect SSH key - base64 part is not %r as claimed but %r") % (str(keytype), str(decoded[4:].split(b'\0', 1)[0])))
 
     return keytype, decoded, comment
 
--- a/kallithea/lib/utils.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/lib/utils.py	Sat Dec 28 20:25:59 2019 +0100
@@ -337,21 +337,21 @@
     sa = meta.Session()
     for ui_ in sa.query(Ui).all():
         if ui_.ui_active:
-            ui_val = '' if ui_.ui_value is None else safe_str(ui_.ui_value)
+            ui_val = b'' if ui_.ui_value is None else safe_str(ui_.ui_value)
             log.debug('config from db: [%s] %s=%r', ui_.ui_section,
                       ui_.ui_key, ui_val)
             baseui.setconfig(safe_str(ui_.ui_section), safe_str(ui_.ui_key),
                              ui_val)
 
     # force set push_ssl requirement to False, Kallithea handles that
-    baseui.setconfig('web', 'push_ssl', False)
-    baseui.setconfig('web', 'allow_push', '*')
+    baseui.setconfig(b'web', b'push_ssl', False)
+    baseui.setconfig(b'web', b'allow_push', b'*')
     # prevent interactive questions for ssh password / passphrase
-    ssh = baseui.config('ui', 'ssh', default='ssh')
-    baseui.setconfig('ui', 'ssh', '%s -oBatchMode=yes -oIdentitiesOnly=yes' % ssh)
+    ssh = baseui.config(b'ui', b'ssh', default=b'ssh')
+    baseui.setconfig(b'ui', b'ssh', b'%s -oBatchMode=yes -oIdentitiesOnly=yes' % ssh)
     # push / pull hooks
-    baseui.setconfig('hooks', 'changegroup.kallithea_log_push_action', 'python:kallithea.lib.hooks.log_push_action')
-    baseui.setconfig('hooks', 'outgoing.kallithea_log_pull_action', 'python:kallithea.lib.hooks.log_pull_action')
+    baseui.setconfig(b'hooks', b'changegroup.kallithea_log_push_action', b'python:kallithea.lib.hooks.log_push_action')
+    baseui.setconfig(b'hooks', b'outgoing.kallithea_log_pull_action', b'python:kallithea.lib.hooks.log_pull_action')
 
     if repo_path is not None:
         hgrc_path = os.path.join(repo_path, '.hg', 'hgrc')
--- a/kallithea/lib/vcs/backends/git/changeset.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/lib/vcs/backends/git/changeset.py	Sat Dec 28 20:25:59 2019 +0100
@@ -244,7 +244,7 @@
         # Only used to feed diffstat
         rev1 = self.parents[0] if self.parents else self.repository.EMPTY_CHANGESET
         rev2 = self
-        return ''.join(self.repository.get_diff(rev1, rev2,
+        return b''.join(self.repository.get_diff(rev1, rev2,
                                     ignore_whitespace=ignore_whitespace,
                                     context=context))
 
@@ -418,7 +418,7 @@
                 obj_path = name
             if objects.S_ISGITLINK(stat):
                 root_tree = self.repository._repo[self._tree_id]
-                cf = ConfigFile.from_file(BytesIO(self.repository._repo.get_object(root_tree['.gitmodules'][1]).data))
+                cf = ConfigFile.from_file(BytesIO(self.repository._repo.get_object(root_tree[b'.gitmodules'][1]).data))
                 url = cf.get(('submodule', obj_path), 'url')
                 dirnodes.append(SubModuleNode(obj_path, url=url, changeset=id,
                                               alias=als))
@@ -457,7 +457,7 @@
             _GL = lambda m: m and objects.S_ISGITLINK(m)
             if _GL(self._stat_modes.get(path)):
                 tree = self.repository._repo[self._tree_id]
-                cf = ConfigFile.from_file(BytesIO(self.repository._repo.get_object(tree['.gitmodules'][1]).data))
+                cf = ConfigFile.from_file(BytesIO(self.repository._repo.get_object(tree[b'.gitmodules'][1]).data))
                 url = cf.get(('submodule', path), 'url')
                 node = SubModuleNode(path, url=url, changeset=id_,
                                      alias=self.repository.alias)
--- a/kallithea/lib/vcs/backends/git/inmemory.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/lib/vcs/backends/git/inmemory.py	Sat Dec 28 20:25:59 2019 +0100
@@ -39,7 +39,7 @@
         repo = self.repository._repo
         object_store = repo.object_store
 
-        ENCODING = "UTF-8"  # TODO: should probably be kept in sync with safe_unicode/safe_bytes and vcs/conf/settings.py DEFAULT_ENCODINGS
+        ENCODING = b"UTF-8"  # TODO: should probably be kept in sync with safe_unicode/safe_bytes and vcs/conf/settings.py DEFAULT_ENCODINGS
 
         # Create tree and populates it with blobs
         commit_tree = self.parents[0] and repo[self.parents[0]._commit.tree] or \
@@ -47,7 +47,7 @@
         for node in self.added + self.changed:
             # Compute subdirs if needed
             dirpath, nodename = posixpath.split(node.path)
-            dirnames = safe_str(dirpath).split('/') if dirpath else []
+            dirnames = safe_str(dirpath).split(b'/') if dirpath else []
             parent = commit_tree
             ancestors = [('', parent)]
 
@@ -100,7 +100,7 @@
             for tree in new_trees:
                 object_store.add_object(tree)
         for node in self.removed:
-            paths = node.path.split('/')
+            paths = node.path.split(b'/')
             tree = commit_tree
             trees = [tree]
             # Traverse deep into the forest...
@@ -146,10 +146,9 @@
 
         object_store.add_object(commit)
 
-        ref = 'refs/heads/%s' % branch
+        # Update vcs repository object & recreate dulwich repo
+        ref = b'refs/heads/%s' % branch
         repo.refs[ref] = commit.id
-
-        # Update vcs repository object & recreate dulwich repo
         self.repository.revisions.append(commit.id)
         # invalidate parsed refs after commit
         self.repository._parsed_refs = self.repository._get_parsed_refs()
--- a/kallithea/lib/vcs/backends/git/repository.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/lib/vcs/backends/git/repository.py	Sat Dec 28 20:25:59 2019 +0100
@@ -123,8 +123,8 @@
             raise RepositoryError(msg)
 
         try:
-            stdout = ''.join(p.output)
-            stderr = ''.join(p.error)
+            stdout = b''.join(p.output)
+            stderr = b''.join(p.error)
         finally:
             p.close()
         # TODO: introduce option to make commands fail if they have any stderr output?
@@ -170,12 +170,12 @@
         handlers = []
         url_obj = hg_url(url)
         test_uri, authinfo = url_obj.authinfo()
-        url_obj.passwd = '*****'
-        cleaned_uri = str(url_obj)
-
         if not test_uri.endswith('info/refs'):
             test_uri = test_uri.rstrip('/') + '/info/refs'
 
+        url_obj.passwd = b'*****'
+        cleaned_uri = str(url_obj)
+
         if authinfo:
             # create a password manager
             passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
@@ -252,7 +252,7 @@
     def _get_all_revisions2(self):
         # alternate implementation using dulwich
         includes = [x[1][0] for x in self._parsed_refs.iteritems()
-                    if x[1][1] != 'T']
+                    if x[1][1] != b'T']
         return [c.commit.id for c in self._repo.get_walker(include=includes)]
 
     def _get_revision(self, revision):
@@ -282,7 +282,7 @@
 
             # get by branch/tag name
             _ref_revision = self._parsed_refs.get(revision)
-            if _ref_revision:  # and _ref_revision[1] in ['H', 'RH', 'T']:
+            if _ref_revision:  # and _ref_revision[1] in [b'H', b'RH', b'T']:
                 return _ref_revision[0]
 
             if revision in self.revisions:
@@ -355,9 +355,7 @@
 
     @LazyProperty
     def description(self):
-        undefined_description = u'unknown'
-        _desc = self._repo.get_description()
-        return safe_unicode(_desc or undefined_description)
+        return safe_unicode(self._repo.get_description() or b'unknown')
 
     @LazyProperty
     def contact(self):
@@ -370,7 +368,7 @@
             return {}
         sortkey = lambda ctx: ctx[0]
         _branches = [(x[0], x[1][0])
-                     for x in self._parsed_refs.iteritems() if x[1][1] == 'H']
+                     for x in self._parsed_refs.iteritems() if x[1][1] == b'H']
         return OrderedDict(sorted(_branches, key=sortkey, reverse=False))
 
     @LazyProperty
@@ -387,7 +385,7 @@
 
         sortkey = lambda ctx: ctx[0]
         _tags = [(x[0], x[1][0])
-                 for x in self._parsed_refs.iteritems() if x[1][1] == 'T']
+                 for x in self._parsed_refs.iteritems() if x[1][1] == b'T']
         return OrderedDict(sorted(_tags, key=sortkey, reverse=True))
 
     def tag(self, name, user, revision=None, message=None, date=None,
@@ -408,7 +406,7 @@
         changeset = self.get_changeset(revision)
         message = message or "Added tag %s for commit %s" % (name,
             changeset.raw_id)
-        self._repo.refs["refs/tags/%s" % name] = changeset._commit.id
+        self._repo.refs[b"refs/tags/%s" % name] = changeset._commit.id
 
         self._parsed_refs = self._get_parsed_refs()
         self.tags = self._get_tags()
@@ -451,15 +449,15 @@
         # cache the property
         _repo = self._repo
         refs = _repo.get_refs()
-        keys = [('refs/heads/', 'H'),
-                ('refs/remotes/origin/', 'RH'),
-                ('refs/tags/', 'T')]
+        keys = [(b'refs/heads/', b'H'),
+                (b'refs/remotes/origin/', b'RH'),
+                (b'refs/tags/', b'T')]
         _refs = {}
         for ref, sha in refs.iteritems():
             for k, type_ in keys:
                 if ref.startswith(k):
                     _key = ref[len(k):]
-                    if type_ == 'T':
+                    if type_ == b'T':
                         obj = _repo.get_object(sha)
                         if isinstance(obj, Tag):
                             sha = _repo.get_object(sha).object[1]
@@ -472,10 +470,10 @@
         heads = {}
 
         for key, val in refs.items():
-            for ref_key in ['refs/heads/', 'refs/remotes/origin/']:
+            for ref_key in [b'refs/heads/', b'refs/remotes/origin/']:
                 if key.startswith(ref_key):
                     n = key[len(ref_key):]
-                    if n not in ['HEAD']:
+                    if n not in [b'HEAD']:
                         heads[n] = val
 
         return heads if reverse else dict((y, x) for x, y in heads.iteritems())
@@ -627,9 +625,9 @@
         # If we used 'show' command, strip first few lines (until actual diff
         # starts)
         if rev1 == self.EMPTY_CHANGESET:
-            parts = stdout.split('\ndiff ', 1)
+            parts = stdout.split(b'\ndiff ', 1)
             if len(parts) > 1:
-                stdout = 'diff ' + parts[1]
+                stdout = b'diff ' + parts[1]
         return stdout
 
     @LazyProperty
--- a/kallithea/lib/vcs/backends/git/workdir.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/lib/vcs/backends/git/workdir.py	Sat Dec 28 20:25:59 2019 +0100
@@ -7,7 +7,7 @@
 class GitWorkdir(BaseWorkdir):
 
     def get_branch(self):
-        headpath = self.repository._repo.refs.refpath('HEAD')
+        headpath = self.repository._repo.refs.refpath(b'HEAD')
         try:
             content = open(headpath).read()
             match = re.match(r'^ref: refs/heads/(?P<branch>.+)\n$', content)
@@ -20,7 +20,7 @@
             raise RepositoryError("Couldn't compute workdir's branch")
 
     def get_changeset(self):
-        wk_dir_id = self.repository._repo.refs.as_dict().get('HEAD')
+        wk_dir_id = self.repository._repo.refs.as_dict().get(b'HEAD')
         return self.repository.get_changeset(wk_dir_id)
 
     def checkout_branch(self, branch=None):
--- a/kallithea/lib/vcs/backends/hg/changeset.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/lib/vcs/backends/hg/changeset.py	Sat Dec 28 20:25:59 2019 +0100
@@ -194,7 +194,7 @@
 
     def diff(self):
         # Only used to feed diffstat
-        return ''.join(self._ctx.diff())
+        return b''.join(self._ctx.diff())
 
     def _fix_path(self, path):
         """
@@ -236,7 +236,7 @@
         Returns stat mode of the file at the given ``path``.
         """
         fctx = self._get_filectx(path)
-        if 'x' in fctx.flags():
+        if b'x' in fctx.flags():
             return 0o100755
         else:
             return 0o100644
--- a/kallithea/lib/vcs/backends/hg/inmemory.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/lib/vcs/backends/hg/inmemory.py	Sat Dec 28 20:25:59 2019 +0100
@@ -36,7 +36,7 @@
 
         if branch is None:
             branch = MercurialRepository.DEFAULT_BRANCH_NAME
-        kwargs['branch'] = branch
+        kwargs[b'branch'] = branch
 
         def filectxfn(_repo, memctx, path):
             """
@@ -79,7 +79,7 @@
 
         commit_ctx = memctx(repo=self.repository._repo,
             parents=parents,
-            text='',
+            text=b'',
             files=self.get_paths(),
             filectxfn=filectxfn,
             user=author,
--- a/kallithea/lib/vcs/backends/hg/repository.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/lib/vcs/backends/hg/repository.py	Sat Dec 28 20:25:59 2019 +0100
@@ -221,8 +221,7 @@
         ))
 
     def _get_all_revisions(self):
-
-        return [self._repo[x].hex() for x in self._repo.filtered('visible').changelog.revs()]
+        return [self._repo[x].hex() for x in self._repo.filtered(b'visible').changelog.revs()]
 
     def get_diff(self, rev1, rev2, path='', ignore_whitespace=False,
                   context=3):
@@ -262,7 +261,7 @@
         else:
             file_filter = None
 
-        return ''.join(patch.diff(self._repo, rev1, rev2, match=file_filter,
+        return b''.join(patch.diff(self._repo, rev1, rev2, match=file_filter,
                           opts=diffopts(git=True,
                                         showfunc=True,
                                         ignorews=ignore_whitespace,
@@ -280,23 +279,23 @@
         when the return code is non 200
         """
         # check first if it's not an local url
-        if os.path.isdir(url) or url.startswith('file:'):
+        if os.path.isdir(url) or url.startswith(b'file:'):
             return True
 
-        if url.startswith('ssh:'):
+        if url.startswith(b'ssh:'):
             # in case of invalid uri or authentication issues, sshpeer will
             # throw an exception.
-            sshpeer.instance(repoui or ui.ui(), url, False).lookup('tip')
+            sshpeer.instance(repoui or ui.ui(), url, False).lookup(b'tip')
             return True
 
         url_prefix = None
-        if '+' in url[:url.find('://')]:
-            url_prefix, url = url.split('+', 1)
+        if b'+' in url[:url.find(b'://')]:
+            url_prefix, url = url.split(b'+', 1)
 
         handlers = []
         url_obj = hg_url(url)
         test_uri, authinfo = url_obj.authinfo()
-        url_obj.passwd = '*****'
+        url_obj.passwd = b'*****'
         cleaned_uri = str(url_obj)
 
         if authinfo:
@@ -328,7 +327,7 @@
         if not url_prefix: # skip svn+http://... (and git+... too)
             # now check if it's a proper hg repo
             try:
-                httppeer.instance(repoui or ui.ui(), url, False).lookup('tip')
+                httppeer.instance(repoui or ui.ui(), url, False).lookup(b'tip')
             except Exception as e:
                 raise urllib2.URLError(
                     "url [%s] does not look like an hg repo org_exc: %s"
@@ -374,15 +373,13 @@
 
     @LazyProperty
     def description(self):
-        undefined_description = u'unknown'
-        _desc = self._repo.ui.config('web', 'description', None, untrusted=True)
-        return safe_unicode(_desc or undefined_description)
+        _desc = self._repo.ui.config(b'web', b'description', None, untrusted=True)
+        return safe_unicode(_desc or b'unknown')
 
     @LazyProperty
     def contact(self):
-        undefined_contact = u'Unknown'
         return safe_unicode(get_contact(self._repo.ui.config)
-                            or undefined_contact)
+                            or b'Unknown')
 
     @LazyProperty
     def last_change(self):
@@ -413,7 +410,7 @@
             raise EmptyRepositoryError("There are no changesets yet")
 
         if revision in [-1, None]:
-            revision = 'tip'
+            revision = b'tip'
         elif isinstance(revision, unicode):
             revision = safe_bytes(revision)
 
@@ -461,13 +458,13 @@
         return self._get_revision(revision)
 
     def _get_archives(self, archive_name='tip'):
-        allowed = self.baseui.configlist("web", "allow_archive",
+        allowed = self.baseui.configlist(b"web", b"allow_archive",
                                          untrusted=True)
-        for i in [('zip', '.zip'), ('gz', '.tar.gz'), ('bz2', '.tar.bz2')]:
-            if i[0] in allowed or self._repo.ui.configbool("web",
-                                                           "allow" + i[0],
+        for name, ext in [(b'zip', '.zip'), (b'gz', '.tar.gz'), (b'bz2', '.tar.bz2')]:
+            if name in allowed or self._repo.ui.configbool(b"web",
+                                                           b"allow" + name,
                                                            untrusted=True):
-                yield {"type": i[0], "extension": i[1], "node": archive_name}
+                yield {"type": name, "extension": ext, "node": archive_name}
 
     def _get_url(self, url):
         """
@@ -525,18 +522,18 @@
         # filter branches
         filter_ = []
         if branch_name:
-            filter_.append('branch("%s")' % safe_str(branch_name))
+            filter_.append(b'branch("%s")' % safe_str(branch_name))
         if start_date:
-            filter_.append('date(">%s")' % start_date)
+            filter_.append(b'date(">%s")' % start_date)
         if end_date:
-            filter_.append('date("<%s")' % end_date)
+            filter_.append(b'date("<%s")' % end_date)
         if filter_ or max_revisions:
             if filter_:
-                revspec = ' and '.join(filter_)
+                revspec = b' and '.join(filter_)
             else:
-                revspec = 'all()'
+                revspec = b'all()'
             if max_revisions:
-                revspec = 'limit(%s, %s)' % (revspec, max_revisions)
+                revspec = b'limit(%s, %d)' % (revspec, max_revisions)
             revisions = scmutil.revrange(self._repo, [revspec])
         else:
             revisions = self.revisions
--- a/kallithea/lib/vcs/backends/hg/ssh.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/lib/vcs/backends/hg/ssh.py	Sat Dec 28 20:25:59 2019 +0100
@@ -58,8 +58,8 @@
         # Note: we want a repo with config based on .hg/hgrc and can thus not use self.db_repo.scm_instance._repo.ui
         baseui = make_ui(repo_path=self.db_repo.repo_full_path)
         if not self.allow_push:
-            baseui.setconfig('hooks', 'pretxnopen._ssh_reject', 'python:kallithea.lib.hooks.rejectpush')
-            baseui.setconfig('hooks', 'prepushkey._ssh_reject', 'python:kallithea.lib.hooks.rejectpush')
+            baseui.setconfig(b'hooks', b'pretxnopen._ssh_reject', b'python:kallithea.lib.hooks.rejectpush')
+            baseui.setconfig(b'hooks', b'prepushkey._ssh_reject', b'python:kallithea.lib.hooks.rejectpush')
 
         repo = hg.repository(baseui, safe_str(self.db_repo.repo_full_path))
         log.debug("Starting Mercurial sshserver for %s", self.db_repo.repo_full_path)
--- a/kallithea/lib/vcs/subprocessio.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/lib/vcs/subprocessio.py	Sat Dec 28 20:25:59 2019 +0100
@@ -367,11 +367,11 @@
             and returncode != 0
         ): # and it failed
             bg_out.stop()
-            out = ''.join(bg_out)
+            out = b''.join(bg_out)
             bg_err.stop()
-            err = ''.join(bg_err)
-            if (err.strip() == 'fatal: The remote end hung up unexpectedly' and
-                out.startswith('0034shallow ')
+            err = b''.join(bg_err)
+            if (err.strip() == b'fatal: The remote end hung up unexpectedly' and
+                out.startswith(b'0034shallow ')
             ):
                 # hack inspired by https://github.com/schacon/grack/pull/7
                 bg_out = iter([out])
--- a/kallithea/model/pull_request.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/model/pull_request.py	Sat Dec 28 20:25:59 2019 +0100
@@ -261,7 +261,7 @@
 
         if self.org_repo.scm_instance.alias == 'git':
             # create a ref under refs/pull/ so that commits don't get garbage-collected
-            self.org_repo.scm_instance._repo["refs/pull/%d/head" % pr.pull_request_id] = safe_str(self.org_rev)
+            self.org_repo.scm_instance._repo[b"refs/pull/%d/head" % pr.pull_request_id] = safe_str(self.org_rev)
 
         # reset state to under-review
         from kallithea.model.changeset_status import ChangesetStatusModel
--- a/kallithea/model/scm.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/model/scm.py	Sat Dec 28 20:25:59 2019 +0100
@@ -716,11 +716,11 @@
         if not os.path.isdir(loc):
             os.makedirs(loc)
 
-        tmpl_post = "#!%s\n" % self._get_git_hook_interpreter()
+        tmpl_post = b"#!%s\n" % self._get_git_hook_interpreter()
         tmpl_post += pkg_resources.resource_string(
             'kallithea', os.path.join('config', 'post_receive_tmpl.py')
         )
-        tmpl_pre = "#!%s\n" % self._get_git_hook_interpreter()
+        tmpl_pre = b"#!%s\n" % self._get_git_hook_interpreter()
         tmpl_pre += pkg_resources.resource_string(
             'kallithea', os.path.join('config', 'pre_receive_tmpl.py')
         )
@@ -750,7 +750,7 @@
                 log.debug('writing %s hook file !', h_type)
                 try:
                     with open(_hook_file, 'wb') as f:
-                        tmpl = tmpl.replace('_TMPL_', kallithea.__version__)
+                        tmpl = tmpl.replace(b'_TMPL_', kallithea.__version__)
                         f.write(tmpl)
                     os.chmod(_hook_file, 0o755)
                 except IOError as e:
--- a/kallithea/tests/api/api_base.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/tests/api/api_base.py	Sat Dec 28 20:25:59 2019 +0100
@@ -2509,8 +2509,8 @@
             "revisions": self.TEST_PR_REVISIONS,
         }
         self._compare_ok(random_id, expected,
-                         given=re.sub(r"\d\d\d\d\-\d\d\-\d\dT\d\d\:\d\d\:\d\d",
-                                      "2000-01-01T00:00:00", response.body))
+                         given=re.sub(br"\d\d\d\d\-\d\d\-\d\dT\d\d\:\d\d\:\d\d",
+                                      b"2000-01-01T00:00:00", response.body))
 
     def test_api_close_pullrequest(self):
         pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, u'close test')
--- a/kallithea/tests/base.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/tests/base.py	Sat Dec 28 20:25:59 2019 +0100
@@ -156,7 +156,7 @@
                                   'password': password,
                                   '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
-        if 'Invalid username or password' in response.body:
+        if b'Invalid username or password' in response.body:
             pytest.fail('could not login using %s %s' % (username, password))
 
         assert response.status == '302 Found'
--- a/kallithea/tests/fixture.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/tests/fixture.py	Sat Dec 28 20:25:59 2019 +0100
@@ -423,7 +423,7 @@
 
 
 def failing_test_hook(ui, repo, **kwargs):
-    ui.write("failing_test_hook failed\n")
+    ui.write(b"failing_test_hook failed\n")
     return 1
 
 
@@ -432,5 +432,5 @@
 
 
 def passing_test_hook(ui, repo, **kwargs):
-    ui.write("passing_test_hook succeeded\n")
+    ui.write(b"passing_test_hook succeeded\n")
     return 0
--- a/kallithea/tests/functional/test_admin_auth_settings.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/tests/functional/test_admin_auth_settings.py	Sat Dec 28 20:25:59 2019 +0100
@@ -219,7 +219,7 @@
             url=url(controller='admin/my_account', action='my_account'),
             extra_environ={'REMOTE_USER': 'john'},
         )
-        assert 'Log Out' not in response.normal_body
+        assert b'Log Out' not in response.normal_body
 
     def test_crowd_save_settings(self):
         self.log_user()
--- a/kallithea/tests/functional/test_admin_gists.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/tests/functional/test_admin_gists.py	Sat Dec 28 20:25:59 2019 +0100
@@ -158,14 +158,14 @@
         gist = _create_gist('gist-show-me', content='GIST CONTENT')
         response = self.app.get(url('formatted_gist',
                                     gist_id=gist.gist_access_id, format='raw'))
-        assert response.body == 'GIST CONTENT'
+        assert response.body == b'GIST CONTENT'
 
     def test_show_as_raw_individual_file(self):
         gist = _create_gist('gist-show-me-raw', content='GIST BODY')
         response = self.app.get(url('formatted_gist_file',
                                     gist_id=gist.gist_access_id, format='raw',
                                     revision='tip', f_path='gist-show-me-raw'))
-        assert response.body == 'GIST BODY'
+        assert response.body == b'GIST BODY'
 
     def test_edit(self):
         response = self.app.get(url('edit_gist', gist_id=1))
--- a/kallithea/tests/vcs/test_git.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/tests/vcs/test_git.py	Sat Dec 28 20:25:59 2019 +0100
@@ -229,7 +229,7 @@
     def test_changeset10(self):
 
         chset10 = self.repo.get_changeset(self.repo.revisions[9])
-        readme = """===
+        readme = b"""===
 VCS
 ===
 
@@ -649,11 +649,11 @@
 
     def test_paths_slow_traversing(self):
         cs = self.repo.get_changeset()
-        assert cs.get_node('foobar').get_node('static').get_node('js').get_node('admin').get_node('base.js').content == 'base'
+        assert cs.get_node('foobar').get_node('static').get_node('js').get_node('admin').get_node('base.js').content == b'base'
 
     def test_paths_fast_traversing(self):
         cs = self.repo.get_changeset()
-        assert cs.get_node('foobar/static/js/admin/base.js').content == 'base'
+        assert cs.get_node('foobar/static/js/admin/base.js').content == b'base'
 
     def test_workdir_get_branch(self):
         self.repo.run_git_command(['checkout', '-b', 'production'])
--- a/kallithea/tests/vcs/test_hg.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/tests/vcs/test_hg.py	Sat Dec 28 20:25:59 2019 +0100
@@ -219,7 +219,7 @@
     def test_changeset10(self):
 
         chset10 = self.repo.get_changeset(10)
-        readme = """===
+        readme = b"""===
 VCS
 ===
 
--- a/kallithea/tests/vcs/test_inmemchangesets.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/tests/vcs/test_inmemchangesets.py	Sat Dec 28 20:25:59 2019 +0100
@@ -82,8 +82,8 @@
         changeset = self.imc.commit(u'Initial', u'joe.doe@example.com')
         assert isinstance(changeset.get_node('foo'), DirNode)
         assert isinstance(changeset.get_node('foo/bar'), DirNode)
-        assert changeset.get_node('foo/bar/image.png').content == '\0'
-        assert changeset.get_node('foo/README.txt').content == 'readme!'
+        assert changeset.get_node('foo/bar/image.png').content == b'\0'
+        assert changeset.get_node('foo/README.txt').content == b'readme!'
 
         # commit some more files again
         to_add = [
@@ -95,11 +95,11 @@
         ]
         self.imc.add(*to_add)
         changeset = self.imc.commit(u'Another', u'joe.doe@example.com')
-        changeset.get_node('foo/bar/foobaz/bar').content == 'foo'
-        changeset.get_node('foo/bar/another/bar').content == 'foo'
-        changeset.get_node('foo/baz.txt').content == 'foo'
-        changeset.get_node('foobar/foobaz/file').content == 'foo'
-        changeset.get_node('foobar/barbaz').content == 'foo'
+        changeset.get_node('foo/bar/foobaz/bar').content == b'foo'
+        changeset.get_node('foo/bar/another/bar').content == b'foo'
+        changeset.get_node('foo/baz.txt').content == b'foo'
+        changeset.get_node('foobar/foobaz/file').content == b'foo'
+        changeset.get_node('foobar/barbaz').content == b'foo'
 
     def test_add_non_ascii_files(self):
         rev_count = len(self.repo.revisions)
@@ -154,7 +154,7 @@
         newtip = self.repo.get_changeset()
         assert tip != newtip
         assert tip.id != newtip.id
-        assert newtip.get_node('foo/bar/baz').content == 'My **changed** content'
+        assert newtip.get_node('foo/bar/baz').content == b'My **changed** content'
 
     def test_change_non_ascii(self):
         to_add = [
@@ -181,8 +181,8 @@
         assert tip != newtip
         assert tip.id != newtip.id
 
-        assert newtip.get_node('żółwik/zwierzątko').content == 'My **changed** content'
-        assert newtip.get_node('żółwik/zwierzątko_uni').content == 'My **changed** content'
+        assert newtip.get_node('żółwik/zwierzątko').content == b'My **changed** content'
+        assert newtip.get_node('żółwik/zwierzątko_uni').content == b'My **changed** content'
 
     def test_change_raise_empty_repository(self):
         node = FileNode('foobar')
--- a/kallithea/tests/vcs/test_nodes.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/tests/vcs/test_nodes.py	Sat Dec 28 20:25:59 2019 +0100
@@ -158,10 +158,10 @@
         tar_node = FileNode('test.tar.gz')
 
         my_node2 = FileNode('myfile2')
-        my_node2._content = 'foobar'
+        my_node2._content = b'foobar'
 
         my_node3 = FileNode('myfile3')
-        my_node3._content = '\0foobar'
+        my_node3._content = b'\0foobar'
 
         assert py_node.mimetype == mimetypes.guess_type(py_node.name)[0]
         assert py_node.get_mimetype() == mimetypes.guess_type(py_node.name)
--- a/kallithea/tests/vcs/test_repository.py	Sat Dec 28 23:09:48 2019 +0100
+++ b/kallithea/tests/vcs/test_repository.py	Sat Dec 28 20:25:59 2019 +0100
@@ -110,7 +110,7 @@
 
     def test_initial_commit_diff(self):
         initial_rev = self.repo.revisions[0]
-        assert self.repo.get_diff(self.repo.EMPTY_CHANGESET, initial_rev) == r'''diff --git a/foobar b/foobar
+        assert self.repo.get_diff(self.repo.EMPTY_CHANGESET, initial_rev) == br'''diff --git a/foobar b/foobar
 new file mode 100644
 index 0000000000000000000000000000000000000000..f6ea0495187600e7b2288c8ac19c5886383a4632
 --- /dev/null
@@ -130,7 +130,7 @@
 
     def test_second_changeset_diff(self):
         revs = self.repo.revisions
-        assert self.repo.get_diff(revs[0], revs[1]) == r'''diff --git a/foobar b/foobar
+        assert self.repo.get_diff(revs[0], revs[1]) == br'''diff --git a/foobar b/foobar
 index f6ea0495187600e7b2288c8ac19c5886383a4632..389865bb681b358c9b102d79abd8d5f941e96551 100644
 --- a/foobar
 +++ b/foobar
@@ -151,7 +151,7 @@
 
     def test_third_changeset_diff(self):
         revs = self.repo.revisions
-        assert self.repo.get_diff(revs[1], revs[2]) == r'''diff --git a/foobar b/foobar
+        assert self.repo.get_diff(revs[1], revs[2]) == br'''diff --git a/foobar b/foobar
 deleted file mode 100644
 index 389865bb681b358c9b102d79abd8d5f941e96551..0000000000000000000000000000000000000000
 --- a/foobar
@@ -173,7 +173,7 @@
 
     def test_fourth_changeset_diff(self):
         revs = self.repo.revisions
-        assert self.repo.get_diff(revs[2], revs[3]) == r'''diff --git a/README{ b/README{
+        assert self.repo.get_diff(revs[2], revs[3]) == br'''diff --git a/README{ b/README{
 new file mode 100644
 index 0000000000000000000000000000000000000000..cdc0c1b5d234feedb37bbac19cd1b6442061102d
 --- /dev/null
@@ -189,7 +189,7 @@
 
     def test_initial_commit_diff(self):
         initial_rev = self.repo.revisions[0]
-        assert self.repo.get_diff(self.repo.EMPTY_CHANGESET, initial_rev) == r'''diff --git a/foobar b/foobar
+        assert self.repo.get_diff(self.repo.EMPTY_CHANGESET, initial_rev) == br'''diff --git a/foobar b/foobar
 new file mode 100644
 --- /dev/null
 +++ b/foobar
@@ -207,7 +207,7 @@
 
     def test_second_changeset_diff(self):
         revs = self.repo.revisions
-        assert self.repo.get_diff(revs[0], revs[1]) == r'''diff --git a/foobar b/foobar
+        assert self.repo.get_diff(revs[0], revs[1]) == br'''diff --git a/foobar b/foobar
 --- a/foobar
 +++ b/foobar
 @@ -1,1 +1,1 @@
@@ -226,7 +226,7 @@
 
     def test_third_changeset_diff(self):
         revs = self.repo.revisions
-        assert self.repo.get_diff(revs[1], revs[2]) == r'''diff --git a/foobar b/foobar
+        assert self.repo.get_diff(revs[1], revs[2]) == br'''diff --git a/foobar b/foobar
 deleted file mode 100644
 --- a/foobar
 +++ /dev/null
@@ -246,7 +246,7 @@
 
     def test_fourth_changeset_diff(self):
         revs = self.repo.revisions
-        assert self.repo.get_diff(revs[2], revs[3]) == r'''diff --git a/README{ b/README{
+        assert self.repo.get_diff(revs[2], revs[3]) == br'''diff --git a/README{ b/README{
 new file mode 100644
 --- /dev/null
 +++ b/README{