diff --git a/gertty/app.py b/gertty/app.py index 0ce0367..b72f006 100644 --- a/gertty/app.py +++ b/gertty/app.py @@ -18,16 +18,16 @@ import datetime import dateutil import logging import os -import Queue import re import subprocess import sys import textwrap import threading -import urlparse import warnings import webbrowser +from six.moves import queue +from six.moves.urllib import parse as urlparse import sqlalchemy.exc import urwid @@ -253,7 +253,7 @@ class App(object): unhandled_input=self.unhandledInput) self.sync_pipe = self.loop.watch_pipe(self.refresh) - self.error_queue = Queue.Queue() + self.error_queue = queue.Queue() self.error_pipe = self.loop.watch_pipe(self._errorPipeInput) self.logged_warnings = set() @@ -347,7 +347,7 @@ class App(object): interested = True if hasattr(event, 'held_changed') and event.held_changed: invalidate = True - except Queue.Empty: + except queue.Empty: pass if interested: widget.refresh() @@ -700,13 +700,13 @@ def version(): class PrintKeymapAction(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): for cmd in sorted(keymap.DEFAULT_KEYMAP.keys()): - print cmd.replace(' ', '-') + print(cmd.replace(' ', '-')) sys.exit(0) class PrintPaletteAction(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): for attr in sorted(palette.DEFAULT_PALETTE.keys()): - print attr + print(attr) sys.exit(0) def main(): diff --git a/gertty/commentlink.py b/gertty/commentlink.py index 6ab9de4..2804e6e 100644 --- a/gertty/commentlink.py +++ b/gertty/commentlink.py @@ -19,9 +19,10 @@ except: pass import re +import six import urwid -import mywid +from gertty import mywid try: OrderedDict = collections.OrderedDict @@ -30,7 +31,7 @@ except AttributeError: class TextReplacement(object): def __init__(self, config): - if isinstance(config, basestring): + if isinstance(config, six.string_types): self.color = None self.text = config else: @@ -98,7 +99,7 @@ class CommentLink(object): def run(self, app, chunks): ret = [] for chunk in chunks: - if not isinstance(chunk, basestring): + if not isinstance(chunk, six.string_types): # We don't currently support nested commentlinks; if # we have something that isn't a string, just append # it to the output. diff --git a/gertty/config.py b/gertty/config.py index 97b10f7..51296ad 100644 --- a/gertty/config.py +++ b/gertty/config.py @@ -21,9 +21,9 @@ try: import ordereddict except: pass -import urlparse import yaml +from six.moves.urllib import parse as urlparse import voluptuous as v import gertty.commentlink @@ -239,11 +239,11 @@ class Config(object): def printSample(self): filename = 'share/gertty/examples' - print """Gertty requires a configuration file at ~/.gertty.yaml + print("""Gertty requires a configuration file at ~/.gertty.yaml If the file contains a password then permissions must be set to 0600. Several sample configuration files were installed with Gertty and are available in %s in the root of the installation. For more information, please see the README. -""" % (filename,) +""" % (filename,)) diff --git a/gertty/db.py b/gertty/db.py index b6eefe6..4a92e31 100644 --- a/gertty/db.py +++ b/gertty/db.py @@ -20,6 +20,7 @@ import threading import alembic import alembic.config +import six import sqlalchemy from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, Boolean, DateTime, Text, UniqueConstraint from sqlalchemy.schema import ForeignKey @@ -839,7 +840,7 @@ class DatabaseSession(object): return None def getRevisionsByParent(self, parent): - if isinstance(parent, basestring): + if isinstance(parent, six.string_types): parent = (parent,) try: return self.session().query(Revision).filter(Revision.parent.in_(parent)).all() diff --git a/gertty/gitrepo.py b/gertty/gitrepo.py index 59e4616..cda4e2c 100644 --- a/gertty/gitrepo.py +++ b/gertty/gitrepo.py @@ -21,6 +21,7 @@ import re import git import gitdb +import six OLD = 0 NEW = 1 @@ -83,14 +84,14 @@ class CommitContext(object): commit.authored_date, commit.author_tz_offset) commit_date = self.decorateGitTime( commit.committed_date, commit.committer_tz_offset) - if type(author.email) is unicode: + if isinstance(author.email, six.text_type): author_email = author.email else: - author_email = unicode(author.email, 'utf8') - if type(committer.email) is unicode: + author_email = six.u(author.email) + if isinstance(committer.email, six.text_type): committer_email = committer.email else: - committer_email = unicode(committer.email, 'utf8') + committer_email = six.u(committer.email) return [u"Parent: %s\n" % parentsha, u"Author: %s <%s>\n" % (author.name, author_email), u"AuthorDate: %s\n" % author_date, @@ -181,8 +182,9 @@ class DiffFile(object): def finalize(self): if not self.current_chunk: return - self.current_chunk.lines = zip(self.current_chunk.oldlines, - self.current_chunk.newlines) + self.current_chunk.lines = list( + six.moves.zip(self.current_chunk.oldlines, + self.current_chunk.newlines)) if not self.chunks: self.current_chunk.first = True else: @@ -407,7 +409,11 @@ class Repo(object): oldchunk = [] newchunk = [] prev_key = '' - diff_lines = diff_context.diff.split('\n') + if isinstance(diff_context.diff, six.string_types): + diff_text = six.b(diff_context.diff).decode('utf-8') + else: + diff_text = diff_context.diff.decode('utf-8') + diff_lines = diff_text.split('\n') for i, line in enumerate(diff_lines): last_line = (i == len(diff_lines)-1) if line.startswith('---'): diff --git a/gertty/keymap.py b/gertty/keymap.py index b482c66..0173d84 100644 --- a/gertty/keymap.py +++ b/gertty/keymap.py @@ -175,7 +175,7 @@ FORMAT_SUBS = ( (re.compile('ctrl '), 'CTRL-'), (re.compile('meta '), 'META-'), (re.compile('f(\d+)'), 'F\\1'), - (re.compile('([a-z][a-z]+)'), lambda x: string.upper(x.group(1))), + (re.compile('([a-z][a-z]+)'), lambda x: x.group(1).upper()), ) def formatKey(key): diff --git a/gertty/search/__init__.py b/gertty/search/__init__.py index 0073f31..6a689b5 100644 --- a/gertty/search/__init__.py +++ b/gertty/search/__init__.py @@ -74,11 +74,11 @@ if __name__ == '__main__': token = lexer.token() if not token: break - print token + print(token) app = Dummy() app.config = Dummy() app.config.username = 'bob' search = SearchCompiler(app.config.username) x = search.parse(query) - print x + print(x) diff --git a/gertty/search/parser.py b/gertty/search/parser.py index 9548908..a4d315a 100644 --- a/gertty/search/parser.py +++ b/gertty/search/parser.py @@ -20,8 +20,7 @@ from sqlalchemy.sql.expression import and_, or_, not_, select, func import gertty.db import gertty.search - -from tokenizer import tokens # NOQA +from gertty.search.tokenizer import tokens # NOQA def SearchParser(): precedence = ( # NOQA diff --git a/gertty/search/tokenizer.py b/gertty/search/tokenizer.py index 01a8a09..c9aaa3c 100644 --- a/gertty/search/tokenizer.py +++ b/gertty/search/tokenizer.py @@ -13,6 +13,7 @@ # under the License. import ply.lex as lex +import six operators = { 'age': 'OP_AGE', @@ -59,7 +60,7 @@ tokens = [ 'USTRING', #'REGEX', #'SHA', - ] + operators.values() + ] + list(operators.values()) def SearchTokenizer(): t_LPAREN = r'\(' # NOQA @@ -110,7 +111,7 @@ def SearchTokenizer(): def t_USTRING(t): r'([^\s\(\)!-][^\s\(\)!]*)' - t.value=t.value.decode("string-escape") + t.value = six.b(t.value).decode("unicode_escape") return t def t_newline(t): @@ -118,7 +119,7 @@ def SearchTokenizer(): t.lexer.lineno += len(t.value) def t_error(t): - print "Illegal character '%s'" % t.value[0] + print("Illegal character '%s'" % t.value[0]) t.lexer.skip(1) return lex.lex() diff --git a/gertty/sync.py b/gertty/sync.py index 78075ab..e8e4c5c 100644 --- a/gertty/sync.py +++ b/gertty/sync.py @@ -20,11 +20,8 @@ import math import os import re import threading -import urllib -import urlparse import json import time -import Queue import datetime import dateutil.parser @@ -34,6 +31,9 @@ except: pass import requests import requests.utils +import six +from six.moves import queue +from six.moves.urllib import parse as urlparse import gertty.version from gertty import gitrepo @@ -262,7 +262,7 @@ class SyncProjectBranchesTask(Task): def run(self, sync): app = sync.app - remote = sync.get('projects/%s/branches/' % urllib.quote_plus(self.project_name)) + remote = sync.get('projects/%s/branches/' % urlparse.quote_plus(self.project_name)) remote_branches = set() for x in remote: m = self.branch_re.match(x['ref']) @@ -598,8 +598,8 @@ class SyncChangeTask(Task): ref = remote_revision['fetch']['http']['ref'] url = list(urlparse.urlsplit(sync.app.config.url + change.project.name)) url[1] = '%s:%s@%s' % ( - urllib.quote_plus(sync.app.config.username), - urllib.quote_plus(sync.app.config.password), url[1]) + urlparse.quote_plus(sync.app.config.username), + urlparse.quote_plus(sync.app.config.password), url[1]) url = urlparse.urlunsplit(url) elif 'ssh' in remote_revision['fetch']: ref = remote_revision['fetch']['ssh']['ref'] @@ -1251,7 +1251,7 @@ class PruneChangeTask(Task): change.project.name, change_ref)) try: repo.deleteRef(change_ref) - except OSError, e: + except OSError as e: if e.errno not in [errno.EISDIR, errno.EPERM]: raise session.delete(change) @@ -1283,7 +1283,7 @@ class Sync(object): self.app = app self.log = logging.getLogger('gertty.sync') self.queue = MultiQueue([HIGH_PRIORITY, NORMAL_PRIORITY, LOW_PRIORITY]) - self.result_queue = Queue.Queue() + self.result_queue = queue.Queue() self.session = requests.Session() if self.app.config.auth_type == 'basic': authclass = requests.auth.HTTPBasicAuth @@ -1335,14 +1335,14 @@ class Sync(object): try: task.run(self) task.complete(True) - except requests.ConnectionError, e: + except requests.ConnectionError as e: self.log.warning("Offline due to: %s" % (e,)) if not self.offline: self.submitTask(GetVersionTask(HIGH_PRIORITY)) self.submitTask(UploadReviewsTask(HIGH_PRIORITY)) self.offline = True self.app.status.update(offline=True, refresh=False) - os.write(pipe, 'refresh\n') + os.write(pipe, six.b('refresh\n')) time.sleep(30) return task except Exception: @@ -1353,7 +1353,7 @@ class Sync(object): self.app.status.update(offline=False, refresh=False) for r in task.results: self.result_queue.put(r) - os.write(pipe, 'refresh\n') + os.write(pipe, six.b('refresh\n')) return None def url(self, path): diff --git a/gertty/view/change.py b/gertty/view/change.py index a95284b..312ed9a 100644 --- a/gertty/view/change.py +++ b/gertty/view/change.py @@ -15,8 +15,8 @@ import datetime import logging -import urlparse +from six.moves.urllib import parse as urlparse import urwid from gertty import gitrepo diff --git a/gertty/view/change_list.py b/gertty/view/change_list.py index 55fc8f7..9152e78 100644 --- a/gertty/view/change_list.py +++ b/gertty/view/change_list.py @@ -15,6 +15,8 @@ import datetime import logging + +import six import urwid from gertty import keymap @@ -360,7 +362,7 @@ class ChangeListView(urwid.WidgetWrap): return (ret, prefixes) def clearChangeList(self): - for key, value in self.change_rows.iteritems(): + for key, value in six.iteritems(self.change_rows): self.listbox.body.remove(value) self.change_rows = {} @@ -575,7 +577,7 @@ class ChangeListView(urwid.WidgetWrap): view = view_change.ChangeView(self.app, change_key) self.app.changeScreen(view) except gertty.view.DisplayError as e: - self.app.error(e.message) + self.app.error(str(e)) def openReview(self, rows): dialog = view_change.ReviewDialog(self.app, rows[0].current_revision_key)