Allow gertty to run in Py3K environments

In environments without py27, gertty was unable to run. This patch
addresses all the Py3K issues discovered when getting gertty running in
a py34-only environment.

Change-Id: I32a06f9768bdeaf8e95ddf9a9e54c79059fbaa2f
This commit is contained in:
Jay Pipes 2016-01-14 13:29:12 -05:00 committed by James E. Blair
parent 429668601b
commit 74877d2499
12 changed files with 52 additions and 42 deletions

View File

@ -18,16 +18,16 @@ import datetime
import dateutil import dateutil
import logging import logging
import os import os
import Queue
import re import re
import subprocess import subprocess
import sys import sys
import textwrap import textwrap
import threading import threading
import urlparse
import warnings import warnings
import webbrowser import webbrowser
from six.moves import queue
from six.moves.urllib import parse as urlparse
import sqlalchemy.exc import sqlalchemy.exc
import urwid import urwid
@ -253,7 +253,7 @@ class App(object):
unhandled_input=self.unhandledInput) unhandled_input=self.unhandledInput)
self.sync_pipe = self.loop.watch_pipe(self.refresh) 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.error_pipe = self.loop.watch_pipe(self._errorPipeInput)
self.logged_warnings = set() self.logged_warnings = set()
@ -347,7 +347,7 @@ class App(object):
interested = True interested = True
if hasattr(event, 'held_changed') and event.held_changed: if hasattr(event, 'held_changed') and event.held_changed:
invalidate = True invalidate = True
except Queue.Empty: except queue.Empty:
pass pass
if interested: if interested:
widget.refresh() widget.refresh()
@ -700,13 +700,13 @@ def version():
class PrintKeymapAction(argparse.Action): class PrintKeymapAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None): def __call__(self, parser, namespace, values, option_string=None):
for cmd in sorted(keymap.DEFAULT_KEYMAP.keys()): for cmd in sorted(keymap.DEFAULT_KEYMAP.keys()):
print cmd.replace(' ', '-') print(cmd.replace(' ', '-'))
sys.exit(0) sys.exit(0)
class PrintPaletteAction(argparse.Action): class PrintPaletteAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None): def __call__(self, parser, namespace, values, option_string=None):
for attr in sorted(palette.DEFAULT_PALETTE.keys()): for attr in sorted(palette.DEFAULT_PALETTE.keys()):
print attr print(attr)
sys.exit(0) sys.exit(0)
def main(): def main():

View File

@ -19,9 +19,10 @@ except:
pass pass
import re import re
import six
import urwid import urwid
import mywid from gertty import mywid
try: try:
OrderedDict = collections.OrderedDict OrderedDict = collections.OrderedDict
@ -30,7 +31,7 @@ except AttributeError:
class TextReplacement(object): class TextReplacement(object):
def __init__(self, config): def __init__(self, config):
if isinstance(config, basestring): if isinstance(config, six.string_types):
self.color = None self.color = None
self.text = config self.text = config
else: else:
@ -98,7 +99,7 @@ class CommentLink(object):
def run(self, app, chunks): def run(self, app, chunks):
ret = [] ret = []
for chunk in chunks: 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 don't currently support nested commentlinks; if
# we have something that isn't a string, just append # we have something that isn't a string, just append
# it to the output. # it to the output.

View File

@ -21,9 +21,9 @@ try:
import ordereddict import ordereddict
except: except:
pass pass
import urlparse
import yaml import yaml
from six.moves.urllib import parse as urlparse
import voluptuous as v import voluptuous as v
import gertty.commentlink import gertty.commentlink
@ -239,11 +239,11 @@ class Config(object):
def printSample(self): def printSample(self):
filename = 'share/gertty/examples' 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. If the file contains a password then permissions must be set to 0600.
Several sample configuration files were installed with Gertty and are Several sample configuration files were installed with Gertty and are
available in %s in the root of the installation. available in %s in the root of the installation.
For more information, please see the README. For more information, please see the README.
""" % (filename,) """ % (filename,))

View File

@ -20,6 +20,7 @@ import threading
import alembic import alembic
import alembic.config import alembic.config
import six
import sqlalchemy import sqlalchemy
from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, Boolean, DateTime, Text, UniqueConstraint from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, Boolean, DateTime, Text, UniqueConstraint
from sqlalchemy.schema import ForeignKey from sqlalchemy.schema import ForeignKey
@ -839,7 +840,7 @@ class DatabaseSession(object):
return None return None
def getRevisionsByParent(self, parent): def getRevisionsByParent(self, parent):
if isinstance(parent, basestring): if isinstance(parent, six.string_types):
parent = (parent,) parent = (parent,)
try: try:
return self.session().query(Revision).filter(Revision.parent.in_(parent)).all() return self.session().query(Revision).filter(Revision.parent.in_(parent)).all()

View File

@ -21,6 +21,7 @@ import re
import git import git
import gitdb import gitdb
import six
OLD = 0 OLD = 0
NEW = 1 NEW = 1
@ -83,14 +84,14 @@ class CommitContext(object):
commit.authored_date, commit.author_tz_offset) commit.authored_date, commit.author_tz_offset)
commit_date = self.decorateGitTime( commit_date = self.decorateGitTime(
commit.committed_date, commit.committer_tz_offset) commit.committed_date, commit.committer_tz_offset)
if type(author.email) is unicode: if isinstance(author.email, six.text_type):
author_email = author.email author_email = author.email
else: else:
author_email = unicode(author.email, 'utf8') author_email = six.u(author.email)
if type(committer.email) is unicode: if isinstance(committer.email, six.text_type):
committer_email = committer.email committer_email = committer.email
else: else:
committer_email = unicode(committer.email, 'utf8') committer_email = six.u(committer.email)
return [u"Parent: %s\n" % parentsha, return [u"Parent: %s\n" % parentsha,
u"Author: %s <%s>\n" % (author.name, author_email), u"Author: %s <%s>\n" % (author.name, author_email),
u"AuthorDate: %s\n" % author_date, u"AuthorDate: %s\n" % author_date,
@ -181,8 +182,9 @@ class DiffFile(object):
def finalize(self): def finalize(self):
if not self.current_chunk: if not self.current_chunk:
return return
self.current_chunk.lines = zip(self.current_chunk.oldlines, self.current_chunk.lines = list(
self.current_chunk.newlines) six.moves.zip(self.current_chunk.oldlines,
self.current_chunk.newlines))
if not self.chunks: if not self.chunks:
self.current_chunk.first = True self.current_chunk.first = True
else: else:
@ -407,7 +409,11 @@ class Repo(object):
oldchunk = [] oldchunk = []
newchunk = [] newchunk = []
prev_key = '' 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): for i, line in enumerate(diff_lines):
last_line = (i == len(diff_lines)-1) last_line = (i == len(diff_lines)-1)
if line.startswith('---'): if line.startswith('---'):

View File

@ -175,7 +175,7 @@ FORMAT_SUBS = (
(re.compile('ctrl '), 'CTRL-'), (re.compile('ctrl '), 'CTRL-'),
(re.compile('meta '), 'META-'), (re.compile('meta '), 'META-'),
(re.compile('f(\d+)'), 'F\\1'), (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): def formatKey(key):

View File

@ -74,11 +74,11 @@ if __name__ == '__main__':
token = lexer.token() token = lexer.token()
if not token: if not token:
break break
print token print(token)
app = Dummy() app = Dummy()
app.config = Dummy() app.config = Dummy()
app.config.username = 'bob' app.config.username = 'bob'
search = SearchCompiler(app.config.username) search = SearchCompiler(app.config.username)
x = search.parse(query) x = search.parse(query)
print x print(x)

View File

@ -20,8 +20,7 @@ from sqlalchemy.sql.expression import and_, or_, not_, select, func
import gertty.db import gertty.db
import gertty.search import gertty.search
from gertty.search.tokenizer import tokens # NOQA
from tokenizer import tokens # NOQA
def SearchParser(): def SearchParser():
precedence = ( # NOQA precedence = ( # NOQA

View File

@ -13,6 +13,7 @@
# under the License. # under the License.
import ply.lex as lex import ply.lex as lex
import six
operators = { operators = {
'age': 'OP_AGE', 'age': 'OP_AGE',
@ -59,7 +60,7 @@ tokens = [
'USTRING', 'USTRING',
#'REGEX', #'REGEX',
#'SHA', #'SHA',
] + operators.values() ] + list(operators.values())
def SearchTokenizer(): def SearchTokenizer():
t_LPAREN = r'\(' # NOQA t_LPAREN = r'\(' # NOQA
@ -110,7 +111,7 @@ def SearchTokenizer():
def t_USTRING(t): def t_USTRING(t):
r'([^\s\(\)!-][^\s\(\)!]*)' r'([^\s\(\)!-][^\s\(\)!]*)'
t.value=t.value.decode("string-escape") t.value = six.b(t.value).decode("unicode_escape")
return t return t
def t_newline(t): def t_newline(t):
@ -118,7 +119,7 @@ def SearchTokenizer():
t.lexer.lineno += len(t.value) t.lexer.lineno += len(t.value)
def t_error(t): def t_error(t):
print "Illegal character '%s'" % t.value[0] print("Illegal character '%s'" % t.value[0])
t.lexer.skip(1) t.lexer.skip(1)
return lex.lex() return lex.lex()

View File

@ -20,11 +20,8 @@ import math
import os import os
import re import re
import threading import threading
import urllib
import urlparse
import json import json
import time import time
import Queue
import datetime import datetime
import dateutil.parser import dateutil.parser
@ -34,6 +31,9 @@ except:
pass pass
import requests import requests
import requests.utils import requests.utils
import six
from six.moves import queue
from six.moves.urllib import parse as urlparse
import gertty.version import gertty.version
from gertty import gitrepo from gertty import gitrepo
@ -262,7 +262,7 @@ class SyncProjectBranchesTask(Task):
def run(self, sync): def run(self, sync):
app = sync.app 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() remote_branches = set()
for x in remote: for x in remote:
m = self.branch_re.match(x['ref']) m = self.branch_re.match(x['ref'])
@ -598,8 +598,8 @@ class SyncChangeTask(Task):
ref = remote_revision['fetch']['http']['ref'] ref = remote_revision['fetch']['http']['ref']
url = list(urlparse.urlsplit(sync.app.config.url + change.project.name)) url = list(urlparse.urlsplit(sync.app.config.url + change.project.name))
url[1] = '%s:%s@%s' % ( url[1] = '%s:%s@%s' % (
urllib.quote_plus(sync.app.config.username), urlparse.quote_plus(sync.app.config.username),
urllib.quote_plus(sync.app.config.password), url[1]) urlparse.quote_plus(sync.app.config.password), url[1])
url = urlparse.urlunsplit(url) url = urlparse.urlunsplit(url)
elif 'ssh' in remote_revision['fetch']: elif 'ssh' in remote_revision['fetch']:
ref = remote_revision['fetch']['ssh']['ref'] ref = remote_revision['fetch']['ssh']['ref']
@ -1251,7 +1251,7 @@ class PruneChangeTask(Task):
change.project.name, change_ref)) change.project.name, change_ref))
try: try:
repo.deleteRef(change_ref) repo.deleteRef(change_ref)
except OSError, e: except OSError as e:
if e.errno not in [errno.EISDIR, errno.EPERM]: if e.errno not in [errno.EISDIR, errno.EPERM]:
raise raise
session.delete(change) session.delete(change)
@ -1283,7 +1283,7 @@ class Sync(object):
self.app = app self.app = app
self.log = logging.getLogger('gertty.sync') self.log = logging.getLogger('gertty.sync')
self.queue = MultiQueue([HIGH_PRIORITY, NORMAL_PRIORITY, LOW_PRIORITY]) self.queue = MultiQueue([HIGH_PRIORITY, NORMAL_PRIORITY, LOW_PRIORITY])
self.result_queue = Queue.Queue() self.result_queue = queue.Queue()
self.session = requests.Session() self.session = requests.Session()
if self.app.config.auth_type == 'basic': if self.app.config.auth_type == 'basic':
authclass = requests.auth.HTTPBasicAuth authclass = requests.auth.HTTPBasicAuth
@ -1335,14 +1335,14 @@ class Sync(object):
try: try:
task.run(self) task.run(self)
task.complete(True) task.complete(True)
except requests.ConnectionError, e: except requests.ConnectionError as e:
self.log.warning("Offline due to: %s" % (e,)) self.log.warning("Offline due to: %s" % (e,))
if not self.offline: if not self.offline:
self.submitTask(GetVersionTask(HIGH_PRIORITY)) self.submitTask(GetVersionTask(HIGH_PRIORITY))
self.submitTask(UploadReviewsTask(HIGH_PRIORITY)) self.submitTask(UploadReviewsTask(HIGH_PRIORITY))
self.offline = True self.offline = True
self.app.status.update(offline=True, refresh=False) self.app.status.update(offline=True, refresh=False)
os.write(pipe, 'refresh\n') os.write(pipe, six.b('refresh\n'))
time.sleep(30) time.sleep(30)
return task return task
except Exception: except Exception:
@ -1353,7 +1353,7 @@ class Sync(object):
self.app.status.update(offline=False, refresh=False) self.app.status.update(offline=False, refresh=False)
for r in task.results: for r in task.results:
self.result_queue.put(r) self.result_queue.put(r)
os.write(pipe, 'refresh\n') os.write(pipe, six.b('refresh\n'))
return None return None
def url(self, path): def url(self, path):

View File

@ -15,8 +15,8 @@
import datetime import datetime
import logging import logging
import urlparse
from six.moves.urllib import parse as urlparse
import urwid import urwid
from gertty import gitrepo from gertty import gitrepo

View File

@ -15,6 +15,8 @@
import datetime import datetime
import logging import logging
import six
import urwid import urwid
from gertty import keymap from gertty import keymap
@ -360,7 +362,7 @@ class ChangeListView(urwid.WidgetWrap):
return (ret, prefixes) return (ret, prefixes)
def clearChangeList(self): 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.listbox.body.remove(value)
self.change_rows = {} self.change_rows = {}
@ -575,7 +577,7 @@ class ChangeListView(urwid.WidgetWrap):
view = view_change.ChangeView(self.app, change_key) view = view_change.ChangeView(self.app, change_key)
self.app.changeScreen(view) self.app.changeScreen(view)
except gertty.view.DisplayError as e: except gertty.view.DisplayError as e:
self.app.error(e.message) self.app.error(str(e))
def openReview(self, rows): def openReview(self, rows):
dialog = view_change.ReviewDialog(self.app, rows[0].current_revision_key) dialog = view_change.ReviewDialog(self.app, rows[0].current_revision_key)