diff --git a/babel.cfg b/babel.cfg
deleted file mode 100644
index efceab8..0000000
--- a/babel.cfg
+++ /dev/null
@@ -1 +0,0 @@
-[python: **.py]
diff --git a/openstack-common.conf b/openstack-common.conf
deleted file mode 100644
index 8225869..0000000
--- a/openstack-common.conf
+++ /dev/null
@@ -1,7 +0,0 @@
-[DEFAULT]
-
-# The list of modules to copy from oslo-incubator.git
-module=install_venv_common
-
-# The base module to hold the copy of openstack.common
-base=reviewstats
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index c3b7d7e..3185b59 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,8 +1,6 @@
 paramiko
-pbr>=0.5.21,<1.0
+pbr>=2.0,!=2.1.0
 prettytable
-Babel>=1.3
 pytz>=2010h
 requests>=2.2.0,!=2.4.0
-six>=1.7.0
 PyYAML>=3.1.0
diff --git a/reviewstats/cmd/bugstats.py b/reviewstats/cmd/bugstats.py
index 2f2e200..9a1c6ac 100644
--- a/reviewstats/cmd/bugstats.py
+++ b/reviewstats/cmd/bugstats.py
@@ -139,8 +139,8 @@ class Listener(object):
             closed in the period, and bug tags present on any critical bugs.
         """
         for period in self.periods:
-            yield ([period[0].strftime('%Y-%m-%d')] +
-                   period[1:-1] + [','.join(period[-1])])
+            yield ([period[0].strftime('%Y-%m-%d')]
+                   + period[1:-1] + [','.join(period[-1])])
 
 
 def main():
diff --git a/reviewstats/cmd/openreviews.py b/reviewstats/cmd/openreviews.py
index 7f99474..69b2427 100755
--- a/reviewstats/cmd/openreviews.py
+++ b/reviewstats/cmd/openreviews.py
@@ -21,8 +21,6 @@ import logging
 import optparse
 import sys
 
-import six
-
 from reviewstats import utils
 
 
@@ -176,7 +174,7 @@ def print_stats_txt(stats, f=sys.stdout):
             print_item_txt(item, level)
 
     def print_item_txt(item, level):
-        if isinstance(item, six.text_type):
+        if isinstance(item, str):
             f.write('%s\n' % item.encode('utf-8'))
         elif isinstance(item, list):
             print_list_txt(item, level + 1)
@@ -205,7 +203,7 @@ def print_stats_html(stats, f=sys.stdout):
             f.write('</%s>\n' % ('ul' if level == 1 else 'ol'))
 
     def print_item_html(item, level):
-        if isinstance(item, six.text_type):
+        if isinstance(item, str):
             f.write('%s' % item.encode('utf-8'))
         elif isinstance(item, list):
             print_list_html(item, level + 1)
diff --git a/reviewstats/cmd/reviewers.py b/reviewstats/cmd/reviewers.py
index 7bc0409..b230cf7 100755
--- a/reviewstats/cmd/reviewers.py
+++ b/reviewstats/cmd/reviewers.py
@@ -80,8 +80,9 @@ def process_patchset(project, patchset, reviewers, ts, options):
         reviewer = review['by'].get('username', 'unknown')
         set_defaults(reviewer, reviewers)
 
-        if (review['type'] == 'Approved' or
-                (review['type'] == 'Workflow' and int(review['value']) > 0)):
+        if (review['type'] == 'Approved'
+            or (review['type'] == 'Workflow'
+                and int(review['value']) > 0)):
             cur = reviewers[reviewer]['votes']['A']
             reviewers[reviewer]['votes']['A'] = cur + 1
         elif review['type'] != 'Workflow':
@@ -210,8 +211,8 @@ def write_pretty(reviewer_data, file_obj, options, reviewers, projects,
          '(%.1f/day)\n')
         % (options.days, change_stats['wip'],
            float(change_stats['wip']) / options.days))
-    queue_growth = (change_stats['created'] - change_stats['merged'] -
-                    change_stats['abandoned'] - change_stats['wip'])
+    queue_growth = (change_stats['created'] - change_stats['merged']
+                    - change_stats['abandoned'] - change_stats['wip'])
     file_obj.write(
         ('  Queue growth in the last %d days: %d '
          '(%.1f/day)\n')
diff --git a/reviewstats/cmd/reviews_for_bugs.py b/reviewstats/cmd/reviews_for_bugs.py
index 7c2f458..163f86b 100755
--- a/reviewstats/cmd/reviews_for_bugs.py
+++ b/reviewstats/cmd/reviews_for_bugs.py
@@ -58,7 +58,7 @@ def main():
     milestones = {}
 
     changes = utils.get_changes(projects, args.user, args.key, only_open=True)
-    bug_regex = re.compile('bug/(\d+)')
+    bug_regex = re.compile(r'bug/(\d+)')
     for change in changes:
         if 'topic' not in change:
             continue
diff --git a/reviewstats/utils.py b/reviewstats/utils.py
index 8d1327c..633cb15 100644
--- a/reviewstats/utils.py
+++ b/reviewstats/utils.py
@@ -18,18 +18,18 @@
 
 import glob
 import gzip
+import io
 import json
 import logging
 import os
+import pickle
 import time
+import urllib
 import yaml
 
 import paramiko
 import requests
 import requests.auth
-from six.moves import cPickle as pickle
-from six.moves import cStringIO
-from six.moves import urllib
 
 LOG = logging.getLogger(__name__)
 
@@ -59,7 +59,7 @@ def get_remote_data(address, datatype='json'):
         data += chunk
 
     if remote_data.info().get('Content-Encoding') == 'gzip':
-        buf = cStringIO.StringIO(data)
+        buf = io.StringIO(data)
         f = gzip.GzipFile(fileobj=buf)
         data = f.read()
 
@@ -143,9 +143,9 @@ def projects_q(project):
     .. _Searching Changes:
         https://review.openstack.org/Documentation/user-search.html
     """
-    return ('(' +
-            ' OR '.join(['project:' + p for p in project['subprojects']]) +
-            ')')
+    return ('('
+            + ' OR '.join(['project:' + p for p in project['subprojects']])
+            + ')')
 
 
 def get_changes(projects, ssh_user, ssh_key, only_open=False, stable='',
@@ -321,8 +321,9 @@ def patch_set_approved(patch_set):
     """
     approvals = patch_set.get('approvals', [])
     for review in approvals:
-        if (review['type'] == 'Approved' or
-                (review['type'] == 'Workflow' and int(review['value']) > 0)):
+        if (review['type'] == 'Approved'
+            or (review['type'] == 'Workflow'
+                and int(review['value']) > 0)):
             return True
     return False
 
diff --git a/setup.cfg b/setup.cfg
index df06f43..2e2e3d5 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -20,20 +20,6 @@ classifier =
 packages =
     reviewstats
 
-[compile_catalog]
-directory = reviewstats/locale
-domain = reviewstats
-
-[update_catalog]
-domain = reviewstats
-output_dir = reviewstats/locale
-input_file = reviewstats/locale/reviewstats.pot
-
-[extract_messages]
-keywords = _ gettext ngettext l_ lazy_gettext
-mapping_file = babel.cfg
-output_file = reviewstats/locale/reviewstats.pot
-
 [entry_points]
 console_scripts =
     bugstats = reviewstats.cmd.bugstats:main
diff --git a/test-requirements.txt b/test-requirements.txt
index ed50606..75ffdac 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -1,4 +1,4 @@
-hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
+hacking>=3.1.0,<=3.2.0 # Apache-2.0
 
 coverage>=3.6
 fixtures>=0.3.14
diff --git a/tests/test_reviewers.py b/tests/test_reviewers.py
index becf6d0..f2f3de5 100644
--- a/tests/test_reviewers.py
+++ b/tests/test_reviewers.py
@@ -12,10 +12,9 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
+import io
 import unittest
 
-import six
-
 import reviewstats.cmd.reviewers
 
 
@@ -27,7 +26,7 @@ class ReviewersCSVTestCase(unittest.TestCase):
         options = Options()
         options.csv_rows = 10
         reviewer_data = [('', '', '', '')] * 100
-        sio = six.StringIO()
+        sio = io.StringIO()
 
         reviewstats.cmd.reviewers.write_csv(reviewer_data, sio, options, {},
                                             {}, {}, {})
diff --git a/tox.ini b/tox.ini
index 4498790..51846ea 100644
--- a/tox.ini
+++ b/tox.ini
@@ -40,6 +40,8 @@ commands =
 show-source = True
 # E126: from PEP8 upstream, 'most folk agree that its bad'.
 # E128: like E126.
-ignore = E123,E125,E126,E128,H803
+# E741 ambiguous variable name 'l'
+# W503 line break before binary operator
+ignore = E123,E125,E126,E128,E741,W503,H803
 builtins = _
 exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build