changeset 492:ac8961d40e61 experimental-babel3

Commit the resulting files after a 2to3 -nvw run.
author jruigrok
date Thu, 15 Apr 2010 14:20:11 +0000
parents 5b9fdebd3b62
children
files babel/core.py babel/dates.py babel/localedata.py babel/messages/catalog.py babel/messages/checkers.py babel/messages/extract.py babel/messages/frontend.py babel/messages/jslexer.py babel/messages/mofile.py babel/messages/pofile.py babel/messages/tests/catalog.py babel/messages/tests/checkers.py babel/messages/tests/data/project/file1.py babel/messages/tests/data/project/file2.py babel/messages/tests/extract.py babel/messages/tests/frontend.py babel/messages/tests/mofile.py babel/messages/tests/pofile.py babel/numbers.py babel/plural.py babel/support.py babel/tests/dates.py babel/tests/localedata.py babel/tests/support.py babel/util.py
diffstat 25 files changed, 289 insertions(+), 288 deletions(-) [+]
line wrap: on
line diff
--- a/babel/core.py
+++ b/babel/core.py
@@ -208,7 +208,7 @@
                                      requested locale
         :see: `parse_locale`
         """
-        if isinstance(identifier, basestring):
+        if isinstance(identifier, str):
             return cls(*parse_locale(identifier, sep=sep))
         return identifier
     parse = classmethod(parse)
@@ -223,8 +223,8 @@
         return '<Locale "%s">' % str(self)
 
     def __str__(self):
-        return '_'.join(filter(None, [self.language, self.script,
-                                      self.territory, self.variant]))
+        return '_'.join([_f for _f in [self.language, self.script,
+                                      self.territory, self.variant] if _f])
 
     def _data(self):
         if self.__data is None:
@@ -256,9 +256,9 @@
                 details.append(locale.territories.get(self.territory))
             if self.variant:
                 details.append(locale.variants.get(self.variant))
-            details = filter(None, details)
+            details = [_f for _f in details if _f]
             if details:
-                retval += ' (%s)' % u', '.join(details)
+                retval += ' (%s)' % ', '.join(details)
         return retval
 
     display_name = property(get_display_name, doc="""\
@@ -648,7 +648,7 @@
     :rtype: `str`
     """
     varnames = (category, 'LANGUAGE', 'LC_ALL', 'LC_CTYPE', 'LANG')
-    for name in filter(None, varnames):
+    for name in [_f for _f in varnames if _f]:
         locale = os.getenv(name)
         if locale:
             if name == 'LANGUAGE' and ':' in locale:
@@ -659,7 +659,7 @@
                 locale = 'en_US_POSIX'
             elif aliases and locale in aliases:
                 locale = aliases[locale]
-            return '_'.join(filter(None, parse_locale(locale)))
+            return '_'.join([_f for _f in parse_locale(locale) if _f])
 
 def negotiate_locale(preferred, available, sep='_', aliases=LOCALE_ALIASES):
     """Find the best match between available and requested locale strings.
--- a/babel/dates.py
+++ b/babel/dates.py
@@ -21,7 +21,7 @@
  * ``LANG``
 """
 
-from __future__ import division
+
 from datetime import date, datetime, time, timedelta, tzinfo
 import re
 
@@ -202,7 +202,7 @@
     """
     if datetime is None:
         datetime = datetime_.utcnow()
-    elif isinstance(datetime, (int, long)):
+    elif isinstance(datetime, int):
         datetime = datetime_.utcfromtimestamp(datetime).time()
     if datetime.tzinfo is None:
         datetime = datetime.replace(tzinfo=UTC)
@@ -212,7 +212,7 @@
     seconds = offset.days * 24 * 60 * 60 + offset.seconds
     hours, seconds = divmod(seconds, 3600)
     if width == 'short':
-        pattern = u'%+03d%02d'
+        pattern = '%+03d%02d'
     else:
         pattern = locale.zone_formats['gmt'] % '%+03d:%02d'
     return pattern % (hours, seconds // 60)
@@ -246,7 +246,7 @@
     :rtype: `unicode`
     :since: version 0.9
     """
-    if dt_or_tzinfo is None or isinstance(dt_or_tzinfo, (int, long)):
+    if dt_or_tzinfo is None or isinstance(dt_or_tzinfo, int):
         dt = None
         tzinfo = UTC
     elif isinstance(dt_or_tzinfo, (datetime, time)):
@@ -365,7 +365,7 @@
     :see:  `LDML Appendix J: Time Zone Display Names
             <http://www.unicode.org/reports/tr35/#Time_Zone_Fallback>`_
     """
-    if dt_or_tzinfo is None or isinstance(dt_or_tzinfo, (int, long)):
+    if dt_or_tzinfo is None or isinstance(dt_or_tzinfo, int):
         dt = None
         tzinfo = UTC
     elif isinstance(dt_or_tzinfo, (datetime, time)):
@@ -488,7 +488,7 @@
     """
     if datetime is None:
         datetime = datetime_.utcnow()
-    elif isinstance(datetime, (int, long)):
+    elif isinstance(datetime, int):
         datetime = datetime_.utcfromtimestamp(datetime)
     elif isinstance(datetime, time):
         datetime = datetime_.combine(date.today(), datetime)
@@ -572,7 +572,7 @@
     """
     if time is None:
         time = datetime.utcnow()
-    elif isinstance(time, (int, long)):
+    elif isinstance(time, int):
         time = datetime.utcfromtimestamp(time)
     if time.tzinfo is None:
         time = time.replace(tzinfo=UTC)
@@ -650,7 +650,7 @@
             pattern = locale._data['unit_patterns'][unit][plural_form]
             return pattern.replace('{0}', str(value))
 
-    return u''
+    return ''
 
 def parse_date(string, locale=LC_TIME):
     """Parse a date from a string.
@@ -1052,4 +1052,4 @@
     elif charbuf:
         append_chars()
 
-    return DateTimePattern(pattern, u''.join(result).replace('\0', "'"))
+    return DateTimePattern(pattern, ''.join(result).replace('\0', "'"))
--- a/babel/localedata.py
+++ b/babel/localedata.py
@@ -126,7 +126,7 @@
     :param dict1: the dictionary to merge into
     :param dict2: the dictionary containing the data that should be merged
     """
-    for key, val2 in dict2.items():
+    for key, val2 in list(dict2.items()):
         if val2 is not None:
             val1 = dict1.get(key)
             if isinstance(val2, dict):
--- a/babel/messages/catalog.py
+++ b/babel/messages/catalog.py
@@ -46,7 +46,7 @@
 class Message(object):
     """Representation of a single message in a catalog."""
 
-    def __init__(self, id, string=u'', locations=(), flags=(), auto_comments=(),
+    def __init__(self, id, string='', locations=(), flags=(), auto_comments=(),
                  user_comments=(), previous_id=(), lineno=None, context=None):
         """Create the message object.
 
@@ -66,7 +66,7 @@
         """
         self.id = id #: The message ID
         if not string and self.pluralizable:
-            string = (u'', u'')
+            string = ('', '')
         self.string = string #: The message translation
         self.locations = list(distinct(locations))
         self.flags = set(flags)
@@ -76,7 +76,7 @@
             self.flags.discard('python-format')
         self.auto_comments = list(distinct(auto_comments))
         self.user_comments = list(distinct(user_comments))
-        if isinstance(previous_id, basestring):
+        if isinstance(previous_id, str):
             self.previous_id = [previous_id]
         else:
             self.previous_id = list(previous_id)
@@ -101,10 +101,10 @@
         return cmp(self.id, obj.id)
 
     def clone(self):
-        return Message(*map(copy, (self.id, self.string, self.locations,
+        return Message(*list(map(copy, (self.id, self.string, self.locations,
                                    self.flags, self.auto_comments,
                                    self.user_comments, self.previous_id,
-                                   self.lineno, self.context)))
+                                   self.lineno, self.context))))
 
     def check(self, catalog=None):
         """Run various validation checks on the message.  Some validations
@@ -121,7 +121,7 @@
         for checker in checkers:
             try:
                 checker(catalog, self)
-            except TranslationError, e:
+            except TranslationError as e:
                 errors.append(e)
         return errors
 
@@ -158,7 +158,7 @@
         ids = self.id
         if not isinstance(ids, (list, tuple)):
             ids = [ids]
-        return bool(filter(None, [PYTHON_FORMAT.search(id) for id in ids]))
+        return bool([_f for _f in [PYTHON_FORMAT.search(id) for id in ids] if _f])
     python_format = property(python_format, doc="""\
         Whether the message contains Python-style parameters.
 
@@ -176,7 +176,7 @@
     translations are encountered."""
 
 
-DEFAULT_HEADER = u"""\
+DEFAULT_HEADER = """\
 # Translations template for PROJECT.
 # Copyright (C) YEAR ORGANIZATION
 # This file is distributed under the same license as the PROJECT project.
@@ -334,7 +334,7 @@
             value = value.decode(self.charset)
             if name == 'project-id-version':
                 parts = value.split(' ')
-                self.project = u' '.join(parts[:-1])
+                self.project = ' '.join(parts[:-1])
                 self.version = parts[-1]
             elif name == 'report-msgid-bugs-to':
                 self.msgid_bugs_address = value
@@ -526,7 +526,7 @@
         flags = set()
         if self.fuzzy:
             flags |= set(['fuzzy'])
-        yield Message(u'', '\n'.join(buf), flags=flags)
+        yield Message('', '\n'.join(buf), flags=flags)
         for key in self._messages:
             yield self._messages[key]
 
@@ -591,7 +591,7 @@
         elif id == '':
             # special treatment for the header message
             headers = message_from_string(message.string.encode(self.charset))
-            self.mime_headers = headers.items()
+            self.mime_headers = list(headers.items())
             self.header_comment = '\n'.join(['# %s' % comment for comment
                                              in message.user_comments])
             self.fuzzy = message.fuzzy
@@ -640,7 +640,7 @@
 
         :rtype: ``iterator``
         """
-        for message in self._messages.values():
+        for message in list(self._messages.values()):
             errors = message.check(catalog=self)
             if errors:
                 yield message, errors
@@ -733,7 +733,7 @@
                 fuzzy = True
                 fuzzy_matches.add(oldkey)
                 oldmsg = messages.get(oldkey)
-                if isinstance(oldmsg.id, basestring):
+                if isinstance(oldmsg.id, str):
                     message.previous_id = [oldmsg.id]
                 else:
                     message.previous_id = list(oldmsg.id)
@@ -744,7 +744,7 @@
                 if not isinstance(message.string, (list, tuple)):
                     fuzzy = True
                     message.string = tuple(
-                        [message.string] + ([u''] * (len(message.id) - 1))
+                        [message.string] + ([''] * (len(message.id) - 1))
                     )
                 elif len(message.string) != self.num_plurals:
                     fuzzy = True
@@ -754,7 +754,7 @@
                 message.string = message.string[0]
             message.flags |= oldmsg.flags
             if fuzzy:
-                message.flags |= set([u'fuzzy'])
+                message.flags |= set(['fuzzy'])
             self[message.id] = message
 
         for message in template:
@@ -770,7 +770,7 @@
                         else:
                             matchkey = key
                         matches = get_close_matches(matchkey.lower().strip(),
-                                                    fuzzy_candidates.keys(), 1)
+                                                    list(fuzzy_candidates.keys()), 1)
                         if matches:
                             newkey = matches[0]
                             newctxt = fuzzy_candidates[newkey]
--- a/babel/messages/checkers.py
+++ b/babel/messages/checkers.py
@@ -16,7 +16,7 @@
 :since: version 0.9
 """
 
-from itertools import izip
+
 from babel.messages.catalog import TranslationError, PYTHON_FORMAT
 from babel.util import set
 
@@ -31,7 +31,7 @@
 def num_plurals(catalog, message):
     """Verify the number of plurals in the translation."""
     if not message.pluralizable:
-        if not isinstance(message.string, basestring):
+        if not isinstance(message.string, str):
             raise TranslationError("Found plural forms for non-pluralizable "
                                    "message")
         return
@@ -59,7 +59,7 @@
     if not isinstance(msgstrs, (list, tuple)):
         msgstrs = (msgstrs,)
 
-    for msgid, msgstr in izip(msgids, msgstrs):
+    for msgid, msgstr in zip(msgids, msgstrs):
         if msgstr:
             _validate_format(msgid, msgstr)
 
@@ -125,10 +125,10 @@
                                            'and named placeholders')
         return bool(positional)
 
-    a, b = map(_parse, (format, alternative))
+    a, b = list(map(_parse, (format, alternative)))
 
     # now check if both strings are positional or named
-    a_positional, b_positional = map(_check_positional, (a, b))
+    a_positional, b_positional = list(map(_check_positional, (a, b)))
     if a_positional and not b_positional and not b:
         raise TranslationError('placeholders are incompatible')
     elif a_positional != b_positional:
@@ -140,7 +140,7 @@
         if len(a) != len(b):
             raise TranslationError('positional format placeholders are '
                                    'unbalanced')
-        for idx, ((_, first), (_, second)) in enumerate(izip(a, b)):
+        for idx, ((_, first), (_, second)) in enumerate(zip(a, b)):
             if not _compatible(first, second):
                 raise TranslationError('incompatible format for placeholder '
                                        '%d: %r and %r are not compatible' %
--- a/babel/messages/extract.py
+++ b/babel/messages/extract.py
@@ -60,7 +60,7 @@
             if line.startswith(tag):
                 return line[len(tag):].strip()
         return line
-    comments[:] = map(_strip, comments)
+    comments[:] = list(map(_strip, comments))
 
 
 def extract_from_dir(dirname=os.getcwd(), method_map=DEFAULT_MAPPING,
@@ -153,7 +153,7 @@
                 if pathmatch(pattern, filename):
                     filepath = os.path.join(absname, filename)
                     options = {}
-                    for opattern, odict in options_map.items():
+                    for opattern, odict in list(options_map.items()):
                         if pathmatch(opattern, filename):
                             options = odict
                     if callback:
@@ -265,7 +265,7 @@
     if func is None:
         raise ValueError('Unknown extraction method %r' % method)
 
-    results = func(fileobj, keywords.keys(), comment_tags,
+    results = func(fileobj, list(keywords.keys()), comment_tags,
                    options=options or {})
 
     for lineno, funcname, messages, comments in results:
@@ -301,7 +301,7 @@
             # An empty string msgid isn't valid, emit a warning
             where = '%s:%i' % (hasattr(fileobj, 'name') and \
                                    fileobj.name or '(unknown)', lineno)
-            print >> sys.stderr, empty_msgid_warning % where
+            print(empty_msgid_warning % where, file=sys.stderr)
             continue
 
         messages = tuple(msgs)
--- a/babel/messages/frontend.py
+++ b/babel/messages/frontend.py
@@ -14,7 +14,7 @@
 
 """Frontends for the message extraction functionality."""
 
-from ConfigParser import RawConfigParser
+from configparser import RawConfigParser
 from datetime import datetime
 from distutils import log
 from distutils.cmd import Command
@@ -25,7 +25,7 @@
 import os
 import re
 import shutil
-from StringIO import StringIO
+from io import StringIO
 import sys
 import tempfile
 
@@ -277,9 +277,9 @@
                                        "are mutually exclusive")
 
         if not self.input_dirs:
-            self.input_dirs = dict.fromkeys([k.split('.',1)[0]
+            self.input_dirs = list(dict.fromkeys([k.split('.',1)[0]
                 for k in self.distribution.packages
-            ]).keys()
+            ]).keys())
 
         if self.add_comments:
             self._add_comments = self.add_comments.split(',')
@@ -294,7 +294,7 @@
                               copyright_holder=self.copyright_holder,
                               charset=self.charset)
 
-            for dirname, (method_map, options_map) in mappings.items():
+            for dirname, (method_map, options_map) in list(mappings.items()):
                 def callback(filename, method, options):
                     if method == 'ignore':
                         return
@@ -302,7 +302,7 @@
                     optstr = ''
                     if options:
                         optstr = ' (%s)' % ', '.join(['%s="%s"' % (k, v) for
-                                                      k, v in options.items()])
+                                                      k, v in list(options.items())])
                     log.info('extracting messages from %s%s', filepath, optstr)
 
                 extracted = extract_from_dir(dirname, method_map, options_map,
@@ -339,8 +339,8 @@
 
         elif getattr(self.distribution, 'message_extractors', None):
             message_extractors = self.distribution.message_extractors
-            for dirname, mapping in message_extractors.items():
-                if isinstance(mapping, basestring):
+            for dirname, mapping in list(message_extractors.items()):
+                if isinstance(mapping, str):
                     method_map, options_map = parse_mapping(StringIO(mapping))
                 else:
                     method_map, options_map = [], {}
@@ -422,7 +422,7 @@
                                        'new catalog')
         try:
             self._locale = Locale.parse(self.locale)
-        except UnknownLocaleError, e:
+        except UnknownLocaleError as e:
             raise DistutilsOptionError(e)
 
         if not self.output_file and not self.output_dir:
@@ -639,13 +639,13 @@
             identifiers = localedata.list()
             longest = max([len(identifier) for identifier in identifiers])
             identifiers.sort()
-            format = u'%%-%ds %%s' % (longest + 1)
+            format = '%%-%ds %%s' % (longest + 1)
             for identifier in identifiers:
                 locale = Locale.parse(identifier)
                 output = format % (identifier, locale.english_name)
-                print output.encode(sys.stdout.encoding or
+                print(output.encode(sys.stdout.encoding or
                                     getpreferredencoding() or
-                                    'ascii', 'replace')
+                                    'ascii', 'replace'))
             return 0
 
         if not args:
@@ -659,14 +659,14 @@
         return getattr(self, cmdname)(args[1:])
 
     def _help(self):
-        print self.parser.format_help()
-        print "commands:"
+        print(self.parser.format_help())
+        print("commands:")
         longest = max([len(command) for command in self.commands])
         format = "  %%-%ds %%s" % max(8, longest + 1)
-        commands = self.commands.items()
+        commands = list(self.commands.items())
         commands.sort()
         for name, description in commands:
-            print format % (name, description)
+            print(format % (name, description))
 
     def compile(self, argv):
         """Subcommand for compiling a message catalog to a MO file.
@@ -893,7 +893,7 @@
                     optstr = ''
                     if options:
                         optstr = ' (%s)' % ', '.join(['%s="%s"' % (k, v) for
-                                                      k, v in options.items()])
+                                                      k, v in list(options.items())])
                     self.log.info('extracting messages from %s%s', filepath,
                                   optstr)
 
@@ -946,7 +946,7 @@
             parser.error('you must provide a locale for the new catalog')
         try:
             locale = Locale.parse(options.locale)
-        except UnknownLocaleError, e:
+        except UnknownLocaleError as e:
             parser.error(e)
 
         if not options.input_file:
--- a/babel/messages/jslexer.py
+++ b/babel/messages/jslexer.py
@@ -112,7 +112,7 @@
                 escaped_value = escaped.group()
                 if len(escaped_value) == 4:
                     try:
-                        add(unichr(int(escaped_value, 16)))
+                        add(chr(int(escaped_value, 16)))
                     except ValueError:
                         pass
                     else:
@@ -132,7 +132,7 @@
     if pos < len(string):
         add(string[pos:])
 
-    return u''.join(result)
+    return ''.join(result)
 
 
 def tokenize(source):
--- a/babel/messages/mofile.py
+++ b/babel/messages/mofile.py
@@ -27,8 +27,8 @@
 __docformat__ = 'restructuredtext en'
 
 
-LE_MAGIC = 0x950412deL
-BE_MAGIC = 0xde120495L
+LE_MAGIC = 0x950412de
+BE_MAGIC = 0xde120495
 
 def read_mo(fileobj):
     """Read a binary MO file from the given file-like object and return a
@@ -66,7 +66,7 @@
 
     # Now put all messages from the .mo file buffer into the catalog
     # dictionary
-    for i in xrange(0, msgcount):
+    for i in range(0, msgcount):
         mlen, moff = unpack(ii, buf[origidx:origidx + 8])
         mend = moff + mlen
         tlen, toff = unpack(ii, buf[transidx:transidx + 8])
@@ -113,7 +113,7 @@
         origidx += 8
         transidx += 8
 
-    catalog.mime_headers = headers.items()
+    catalog.mime_headers = list(headers.items())
     return catalog
 
 def write_mo(fileobj, catalog, use_fuzzy=False):
--- a/babel/messages/pofile.py
+++ b/babel/messages/pofile.py
@@ -198,15 +198,15 @@
             context.append(line[7:].lstrip())
         elif line.startswith('"'):
             if in_msgid[0]:
-                messages[-1] += u'\n' + line.rstrip()
+                messages[-1] += '\n' + line.rstrip()
             elif in_msgstr[0]:
-                translations[-1][1] += u'\n' + line.rstrip()
+                translations[-1][1] += '\n' + line.rstrip()
             elif in_msgctxt[0]:
                 context.append(line.rstrip())
 
     for lineno, line in enumerate(fileobj.readlines()):
         line = line.strip()
-        if not isinstance(line, unicode):
+        if not isinstance(line, str):
             line = line.decode(catalog.charset)
         if line.startswith('#'):
             in_msgid[0] = in_msgstr[0] = False
@@ -244,8 +244,8 @@
     # No actual messages found, but there was some info in comments, from which
     # we'll construct an empty header message
     elif not counter[0] and (flags or user_comments or auto_comments):
-        messages.append(u'')
-        translations.append([0, u''])
+        messages.append('')
+        translations.append([0, ''])
         _add_message()
 
     return catalog
@@ -322,7 +322,7 @@
                                 # separate line
                                 buf.append(chunks.pop())
                             break
-                    lines.append(u''.join(buf))
+                    lines.append(''.join(buf))
             else:
                 lines.append(line)
     else:
@@ -335,7 +335,7 @@
     if lines and not lines[-1]:
         del lines[-1]
         lines[-1] += '\n'
-    return u'""\n' + u'\n'.join([(prefix + escape(l)) for l in lines])
+    return '""\n' + '\n'.join([(prefix + escape(l)) for l in lines])
 
 def write_po(fileobj, catalog, width=76, no_location=False, omit_header=False,
              sort_output=False, sort_by_file=False, ignore_obsolete=False,
@@ -385,7 +385,7 @@
             .encode(catalog.charset, 'backslashreplace')
 
     def _write(text):
-        if isinstance(text, unicode):
+        if isinstance(text, str):
             text = text.encode(catalog.charset)
         fileobj.write(text)
 
@@ -442,7 +442,7 @@
                 for line in comment_header.splitlines():
                     lines += wraptext(line, width=width,
                                       subsequent_indent='# ')
-                comment_header = u'\n'.join(lines) + u'\n'
+                comment_header = '\n'.join(lines) + '\n'
             _write(comment_header)
 
         for comment in message.user_comments:
@@ -451,7 +451,7 @@
             _write_comment(comment, prefix='.')
 
         if not no_location:
-            locs = u' '.join([u'%s:%d' % (filename.replace(os.sep, '/'), lineno)
+            locs = ' '.join(['%s:%d' % (filename.replace(os.sep, '/'), lineno)
                               for filename, lineno in message.locations])
             _write_comment(locs, prefix=':')
         if message.flags:
@@ -469,7 +469,7 @@
         _write('\n')
 
     if not ignore_obsolete:
-        for message in catalog.obsolete.values():
+        for message in list(catalog.obsolete.values()):
             for comment in message.user_comments:
                 _write_comment(comment)
             _write_message(message, prefix='#~ ')
--- a/babel/messages/tests/catalog.py
+++ b/babel/messages/tests/catalog.py
@@ -86,35 +86,35 @@
 
     def test_update_message_changed_to_plural(self):
         cat = catalog.Catalog()
-        cat.add(u'foo', u'Voh')
+        cat.add('foo', 'Voh')
         tmpl = catalog.Catalog()
-        tmpl.add((u'foo', u'foos'))
+        tmpl.add(('foo', 'foos'))
         cat.update(tmpl)
-        self.assertEqual((u'Voh', ''), cat['foo'].string)
+        self.assertEqual(('Voh', ''), cat['foo'].string)
         assert cat['foo'].fuzzy
 
     def test_update_message_changed_to_simple(self):
         cat = catalog.Catalog()
-        cat.add((u'foo' u'foos'), (u'Voh', u'Vöhs'))
+        cat.add(('foo' 'foos'), ('Voh', 'Vöhs'))
         tmpl = catalog.Catalog()
-        tmpl.add(u'foo')
+        tmpl.add('foo')
         cat.update(tmpl)
-        self.assertEqual(u'Voh', cat['foo'].string)
+        self.assertEqual('Voh', cat['foo'].string)
         assert cat['foo'].fuzzy
 
     def test_update_message_updates_comments(self):
         cat = catalog.Catalog()
-        cat[u'foo'] = catalog.Message('foo', locations=[('main.py', 5)])
-        self.assertEqual(cat[u'foo'].auto_comments, [])
-        self.assertEqual(cat[u'foo'].user_comments, [])
+        cat['foo'] = catalog.Message('foo', locations=[('main.py', 5)])
+        self.assertEqual(cat['foo'].auto_comments, [])
+        self.assertEqual(cat['foo'].user_comments, [])
         # Update cat[u'foo'] with a new location and a comment
-        cat[u'foo'] = catalog.Message('foo', locations=[('main.py', 7)],
+        cat['foo'] = catalog.Message('foo', locations=[('main.py', 7)],
                                       user_comments=['Foo Bar comment 1'])
-        self.assertEqual(cat[u'foo'].user_comments, ['Foo Bar comment 1'])
+        self.assertEqual(cat['foo'].user_comments, ['Foo Bar comment 1'])
         # now add yet another location with another comment
-        cat[u'foo'] = catalog.Message('foo', locations=[('main.py', 9)],
+        cat['foo'] = catalog.Message('foo', locations=[('main.py', 9)],
                                       auto_comments=['Foo Bar comment 2'])
-        self.assertEqual(cat[u'foo'].auto_comments, ['Foo Bar comment 2'])
+        self.assertEqual(cat['foo'].auto_comments, ['Foo Bar comment 2'])
 
     def test_update_fuzzy_matching_with_case_change(self):
         cat = catalog.Catalog()
--- a/babel/messages/tests/checkers.py
+++ b/babel/messages/tests/checkers.py
@@ -14,7 +14,7 @@
 from datetime import datetime
 import time
 import unittest
-from StringIO import StringIO
+from io import StringIO
 
 from babel import __version__ as VERSION
 from babel.core import Locale, UnknownLocaleError
@@ -35,7 +35,7 @@
             except UnknownLocaleError:
                 # Just an alias? Not what we're testing here, let's continue
                 continue
-            po_file = (ur"""\
+            po_file = (r"""\
 # %(english_name)s translations for TestProject.
 # Copyright (C) 2007 FooBar, Inc.
 # This file is distributed under the same license as the TestProject
@@ -102,7 +102,7 @@
             except UnknownLocaleError:
                 # Just an alias? Not what we're testing here, let's continue
                 continue
-            po_file = (ur"""\
+            po_file = (r"""\
 # %(english_name)s translations for TestProject.
 # Copyright (C) 2007 FooBar, Inc.
 # This file is distributed under the same license as the TestProject
--- a/babel/messages/tests/data/project/file1.py
+++ b/babel/messages/tests/data/project/file1.py
@@ -5,4 +5,4 @@
 def foo():
     # TRANSLATOR: This will be a translator coment,
     # that will include several lines
-    print _('bar')
+    print(_('bar'))
--- a/babel/messages/tests/data/project/file2.py
+++ b/babel/messages/tests/data/project/file2.py
@@ -6,4 +6,4 @@
 def foo():
     # Note: This will have the TRANSLATOR: tag but shouldn't
     # be included on the extracted stuff
-    print ngettext('foobar', 'foobars', 1)
+    print(ngettext('foobar', 'foobars', 1))
--- a/babel/messages/tests/extract.py
+++ b/babel/messages/tests/extract.py
@@ -13,7 +13,7 @@
 
 import codecs
 import doctest
-from StringIO import StringIO
+from io import StringIO
 import sys
 import unittest
 
@@ -36,19 +36,19 @@
 msg10 = dngettext(getDomain(), 'Page', 'Pages', 3)
 """)
         messages = list(extract.extract_python(buf,
-                                               extract.DEFAULT_KEYWORDS.keys(),
+                                               list(extract.DEFAULT_KEYWORDS.keys()),
                                                [], {}))
         self.assertEqual([
                 (1, '_', None, []),
                 (2, 'ungettext', (None, None, None), []),
-                (3, 'ungettext', (u'Babel', None, None), []),
-                (4, 'ungettext', (None, u'Babels', None), []),
-                (5, 'ungettext', (u'bunny', u'bunnies', None), []),
-                (6, 'ungettext', (None, u'bunnies', None), []),
+                (3, 'ungettext', ('Babel', None, None), []),
+                (4, 'ungettext', (None, 'Babels', None), []),
+                (5, 'ungettext', ('bunny', 'bunnies', None), []),
+                (6, 'ungettext', (None, 'bunnies', None), []),
                 (7, '_', None, []),
-                (8, 'gettext', u'Rabbit', []),
-                (9, 'dgettext', (u'wiki', None), []),
-                (10, 'dngettext', (None, u'Page', u'Pages', None), [])],
+                (8, 'gettext', 'Rabbit', []),
+                (9, 'dgettext', ('wiki', None), []),
+                (10, 'dngettext', (None, 'Page', 'Pages', None), [])],
                          messages)
 
     def test_nested_comments(self):
@@ -59,7 +59,7 @@
 """)
         messages = list(extract.extract_python(buf, ('ngettext',),
                                                ['TRANSLATORS:'], {}))
-        self.assertEqual([(1, 'ngettext', (u'pylon', u'pylons', None), [])],
+        self.assertEqual([(1, 'ngettext', ('pylon', 'pylons', None), [])],
                          messages)
 
     def test_comments_with_calls_that_spawn_multiple_lines(self):
@@ -84,21 +84,21 @@
 
                                                {'strip_comment_tags':False}))
         self.assertEqual((6, '_', 'Locale deleted.',
-                          [u'NOTE: This Comment SHOULD Be Extracted']),
+                          ['NOTE: This Comment SHOULD Be Extracted']),
                          messages[1])
-        self.assertEqual((10, 'ngettext', (u'Foo deleted.', u'Foos deleted.',
+        self.assertEqual((10, 'ngettext', ('Foo deleted.', 'Foos deleted.',
                                            None),
-                          [u'NOTE: This Comment SHOULD Be Extracted']),
+                          ['NOTE: This Comment SHOULD Be Extracted']),
                          messages[2])
         self.assertEqual((3, 'ngettext',
-                           (u'Catalog deleted.',
-                            u'Catalogs deleted.', None),
-                           [u'NOTE: This Comment SHOULD Be Extracted']),
+                           ('Catalog deleted.',
+                            'Catalogs deleted.', None),
+                           ['NOTE: This Comment SHOULD Be Extracted']),
                          messages[0])
-        self.assertEqual((15, 'ngettext', (u'Bar deleted.', u'Bars deleted.',
+        self.assertEqual((15, 'ngettext', ('Bar deleted.', 'Bars deleted.',
                                            None),
-                          [u'NOTE: This Comment SHOULD Be Extracted',
-                           u'NOTE: And This One Too']),
+                          ['NOTE: This Comment SHOULD Be Extracted',
+                           'NOTE: And This One Too']),
                          messages[3])
 
     def test_declarations(self):
@@ -113,11 +113,11 @@
     verbose_name = _('log entry')
 """)
         messages = list(extract.extract_python(buf,
-                                               extract.DEFAULT_KEYWORDS.keys(),
+                                               list(extract.DEFAULT_KEYWORDS.keys()),
                                                [], {}))
-        self.assertEqual([(3, '_', u'Page arg 1', []),
-                          (3, '_', u'Page arg 2', []),
-                          (8, '_', u'log entry', [])],
+        self.assertEqual([(3, '_', 'Page arg 1', []),
+                          (3, '_', 'Page arg 2', []),
+                          (8, '_', 'log entry', [])],
                          messages)
 
     def test_multiline(self):
@@ -129,8 +129,8 @@
                  count)
 """)
         messages = list(extract.extract_python(buf, ('ngettext',), [], {}))
-        self.assertEqual([(1, 'ngettext', (u'pylon', u'pylons', None), []),
-                          (3, 'ngettext', (u'elvis', u'elvises', None), [])],
+        self.assertEqual([(1, 'ngettext', ('pylon', 'pylons', None), []),
+                          (3, 'ngettext', ('elvis', 'elvises', None), [])],
                          messages)
 
     def test_triple_quoted_strings(self):
@@ -140,11 +140,11 @@
 msg2 = ngettext(\"\"\"elvis\"\"\", 'elvises', count)
 """)
         messages = list(extract.extract_python(buf,
-                                               extract.DEFAULT_KEYWORDS.keys(),
+                                               list(extract.DEFAULT_KEYWORDS.keys()),
                                                [], {}))
-        self.assertEqual([(1, '_', (u'pylons'), []),
-                          (2, 'ngettext', (u'elvis', u'elvises', None), []),
-                          (3, 'ngettext', (u'elvis', u'elvises', None), [])],
+        self.assertEqual([(1, '_', ('pylons'), []),
+                          (2, 'ngettext', ('elvis', 'elvises', None), []),
+                          (3, 'ngettext', ('elvis', 'elvises', None), [])],
                          messages)
 
     def test_multiline_strings(self):
@@ -154,11 +154,11 @@
 gettext message catalog library.''')
 """)
         messages = list(extract.extract_python(buf,
-                                               extract.DEFAULT_KEYWORDS.keys(),
+                                               list(extract.DEFAULT_KEYWORDS.keys()),
                                                [], {}))
         self.assertEqual(
             [(1, '_',
-              u'This module provides internationalization and localization\n'
+              'This module provides internationalization and localization\n'
               'support for your Python programs by providing an interface to '
               'the GNU\ngettext message catalog library.', [])],
             messages)
@@ -168,14 +168,14 @@
 foobar = _('foo' 'bar')
 """)
         messages = list(extract.extract_python(buf,
-                                               extract.DEFAULT_KEYWORDS.keys(),
+                                               list(extract.DEFAULT_KEYWORDS.keys()),
                                                [], {}))
-        self.assertEqual(u'foobar', messages[0][2])
+        self.assertEqual('foobar', messages[0][2])
 
     def test_unicode_string_arg(self):
         buf = StringIO("msg = _(u'Foo Bar')")
         messages = list(extract.extract_python(buf, ('_',), [], {}))
-        self.assertEqual(u'Foo Bar', messages[0][2])
+        self.assertEqual('Foo Bar', messages[0][2])
 
     def test_comment_tag(self):
         buf = StringIO("""
@@ -183,8 +183,8 @@
 msg = _(u'Foo Bar')
 """)
         messages = list(extract.extract_python(buf, ('_',), ['NOTE:'], {}))
-        self.assertEqual(u'Foo Bar', messages[0][2])
-        self.assertEqual([u'NOTE: A translation comment'], messages[0][3])
+        self.assertEqual('Foo Bar', messages[0][2])
+        self.assertEqual(['NOTE: A translation comment'], messages[0][3])
 
     def test_comment_tag_multiline(self):
         buf = StringIO("""
@@ -193,8 +193,8 @@
 msg = _(u'Foo Bar')
 """)
         messages = list(extract.extract_python(buf, ('_',), ['NOTE:'], {}))
-        self.assertEqual(u'Foo Bar', messages[0][2])
-        self.assertEqual([u'NOTE: A translation comment', u'with a second line'],
+        self.assertEqual('Foo Bar', messages[0][2])
+        self.assertEqual(['NOTE: A translation comment', 'with a second line'],
                          messages[0][3])
 
     def test_translator_comments_with_previous_non_translator_comments(self):
@@ -206,8 +206,8 @@
 msg = _(u'Foo Bar')
 """)
         messages = list(extract.extract_python(buf, ('_',), ['NOTE:'], {}))
-        self.assertEqual(u'Foo Bar', messages[0][2])
-        self.assertEqual([u'NOTE: A translation comment', u'with a second line'],
+        self.assertEqual('Foo Bar', messages[0][2])
+        self.assertEqual(['NOTE: A translation comment', 'with a second line'],
                          messages[0][3])
 
     def test_comment_tags_not_on_start_of_comment(self):
@@ -219,8 +219,8 @@
 msg = _(u'Foo Bar')
 """)
         messages = list(extract.extract_python(buf, ('_',), ['NOTE:'], {}))
-        self.assertEqual(u'Foo Bar', messages[0][2])
-        self.assertEqual([u'NOTE: This one will be'], messages[0][3])
+        self.assertEqual('Foo Bar', messages[0][2])
+        self.assertEqual(['NOTE: This one will be'], messages[0][3])
 
     def test_multiple_comment_tags(self):
         buf = StringIO("""
@@ -233,11 +233,11 @@
 """)
         messages = list(extract.extract_python(buf, ('_',),
                                                ['NOTE1:', 'NOTE2:'], {}))
-        self.assertEqual(u'Foo Bar1', messages[0][2])
-        self.assertEqual([u'NOTE1: A translation comment for tag1',
-                          u'with a second line'], messages[0][3])
-        self.assertEqual(u'Foo Bar2', messages[1][2])
-        self.assertEqual([u'NOTE2: A translation comment for tag2'], messages[1][3])
+        self.assertEqual('Foo Bar1', messages[0][2])
+        self.assertEqual(['NOTE1: A translation comment for tag1',
+                          'with a second line'], messages[0][3])
+        self.assertEqual('Foo Bar2', messages[1][2])
+        self.assertEqual(['NOTE2: A translation comment for tag2'], messages[1][3])
 
     def test_two_succeeding_comments(self):
         buf = StringIO("""
@@ -246,8 +246,8 @@
 msg = _(u'Foo Bar')
 """)
         messages = list(extract.extract_python(buf, ('_',), ['NOTE:'], {}))
-        self.assertEqual(u'Foo Bar', messages[0][2])
-        self.assertEqual([u'NOTE: one', u'NOTE: two'], messages[0][3])
+        self.assertEqual('Foo Bar', messages[0][2])
+        self.assertEqual(['NOTE: one', 'NOTE: two'], messages[0][3])
 
     def test_invalid_translator_comments(self):
         buf = StringIO("""
@@ -257,7 +257,7 @@
 msg = _(u'Foo Bar')
 """)
         messages = list(extract.extract_python(buf, ('_',), ['NOTE:'], {}))
-        self.assertEqual(u'Foo Bar', messages[0][2])
+        self.assertEqual('Foo Bar', messages[0][2])
         self.assertEqual([], messages[0][3])
 
     def test_invalid_translator_comments2(self):
@@ -272,9 +272,9 @@
 hello = _('Hello')
 """)
         messages = list(extract.extract_python(buf, ('_',), ['NOTE:'], {}))
-        self.assertEqual(u'Hi there!', messages[0][2])
-        self.assertEqual([u'NOTE: Hi!'], messages[0][3])
-        self.assertEqual(u'Hello', messages[1][2])
+        self.assertEqual('Hi there!', messages[0][2])
+        self.assertEqual(['NOTE: Hi!'], messages[0][3])
+        self.assertEqual('Hello', messages[1][2])
         self.assertEqual([], messages[1][3])
 
     def test_invalid_translator_comments3(self):
@@ -285,7 +285,7 @@
 hithere = _('Hi there!')
 """)
         messages = list(extract.extract_python(buf, ('_',), ['NOTE:'], {}))
-        self.assertEqual(u'Hi there!', messages[0][2])
+        self.assertEqual('Hi there!', messages[0][2])
         self.assertEqual([], messages[0][3])
 
     def test_comment_tag_with_leading_space(self):
@@ -295,8 +295,8 @@
 msg = _(u'Foo Bar')
 """)
         messages = list(extract.extract_python(buf, ('_',), [':'], {}))
-        self.assertEqual(u'Foo Bar', messages[0][2])
-        self.assertEqual([u': A translation comment', u': with leading spaces'],
+        self.assertEqual('Foo Bar', messages[0][2])
+        self.assertEqual([': A translation comment', ': with leading spaces'],
                          messages[0][3])
 
     def test_different_signatures(self):
@@ -309,9 +309,9 @@
 n = ngettext('foo')
 """)
         messages = list(extract.extract_python(buf, ('_', 'ngettext'), [], {}))
-        self.assertEqual((u'foo', u'bar'), messages[0][2])
-        self.assertEqual((u'hello', u'there', None), messages[1][2])
-        self.assertEqual((None, u'hello', u'there'), messages[2][2])
+        self.assertEqual(('foo', 'bar'), messages[0][2])
+        self.assertEqual(('hello', 'there', None), messages[1][2])
+        self.assertEqual((None, 'hello', 'there'), messages[2][2])
         self.assertEqual((None, None), messages[3][2])
         self.assertEqual(None, messages[4][2])
         self.assertEqual(('foo'), messages[5][2])
@@ -323,8 +323,8 @@
 """)
         messages = list(extract.extract_python(buf, ('_',), ['NOTE:'],
                                                {'encoding': 'utf-8'}))
-        self.assertEqual(u'Bonjour à tous', messages[0][2])
-        self.assertEqual([u'NOTE: hello'], messages[0][3])
+        self.assertEqual('Bonjour à tous', messages[0][2])
+        self.assertEqual(['NOTE: hello'], messages[0][3])
 
     def test_utf8_message_with_magic_comment(self):
         buf = StringIO("""# -*- coding: utf-8 -*-
@@ -332,8 +332,8 @@
 msg = _('Bonjour à tous')
 """)
         messages = list(extract.extract_python(buf, ('_',), ['NOTE:'], {}))
-        self.assertEqual(u'Bonjour à tous', messages[0][2])
-        self.assertEqual([u'NOTE: hello'], messages[0][3])
+        self.assertEqual('Bonjour à tous', messages[0][2])
+        self.assertEqual(['NOTE: hello'], messages[0][3])
 
     def test_utf8_message_with_utf8_bom(self):
         buf = StringIO(codecs.BOM_UTF8 + """
@@ -341,8 +341,8 @@
 msg = _('Bonjour à tous')
 """)
         messages = list(extract.extract_python(buf, ('_',), ['NOTE:'], {}))
-        self.assertEqual(u'Bonjour à tous', messages[0][2])
-        self.assertEqual([u'NOTE: hello'], messages[0][3])
+        self.assertEqual('Bonjour à tous', messages[0][2])
+        self.assertEqual(['NOTE: hello'], messages[0][3])
 
     def test_utf8_raw_strings_match_unicode_strings(self):
         buf = StringIO(codecs.BOM_UTF8 + """
@@ -350,7 +350,7 @@
 msgu = _(u'Bonjour à tous')
 """)
         messages = list(extract.extract_python(buf, ('_',), ['NOTE:'], {}))
-        self.assertEqual(u'Bonjour à tous', messages[0][2])
+        self.assertEqual('Bonjour à tous', messages[0][2])
         self.assertEqual(messages[0][2], messages[1][2])
 
     def test_extract_strip_comment_tags(self):
@@ -364,12 +364,12 @@
 _('Babatschi')""")
         messages = list(extract.extract('python', buf, comment_tags=['NOTE:', ':'],
                                         strip_comment_tags=True))
-        self.assertEqual(u'Servus', messages[0][1])
-        self.assertEqual([u'This is a comment with a very simple',
-                          u'prefix specified'], messages[0][2])
-        self.assertEqual(u'Babatschi', messages[1][1])
-        self.assertEqual([u'This is a multiline comment with',
-                          u'a prefix too'], messages[1][2])
+        self.assertEqual('Servus', messages[0][1])
+        self.assertEqual(['This is a comment with a very simple',
+                          'prefix specified'], messages[0][2])
+        self.assertEqual('Babatschi', messages[1][1])
+        self.assertEqual(['This is a multiline comment with',
+                          'a prefix too'], messages[1][2])
 
 
 class ExtractJavaScriptTestCase(unittest.TestCase):
@@ -404,9 +404,9 @@
         messages = \
             list(extract.extract('javascript', buf, extract.DEFAULT_KEYWORDS, [],
                                  {}))
-        self.assertEqual([(5, (u'bunny', u'bunnies'), []),
-                          (8, u'Rabbit', []),
-                          (10, (u'Page', u'Pages'), [])], messages)
+        self.assertEqual([(5, ('bunny', 'bunnies'), []),
+                          (8, 'Rabbit', []),
+                          (10, ('Page', 'Pages'), [])], messages)
 
     def test_message_with_line_comment(self):
         buf = StringIO("""\
@@ -414,8 +414,8 @@
 msg = _('Bonjour à tous')
 """)
         messages = list(extract.extract_javascript(buf, ('_',), ['NOTE:'], {}))
-        self.assertEqual(u'Bonjour à tous', messages[0][2])
-        self.assertEqual([u'NOTE: hello'], messages[0][3])
+        self.assertEqual('Bonjour à tous', messages[0][2])
+        self.assertEqual(['NOTE: hello'], messages[0][3])
 
     def test_message_with_multiline_comment(self):
         buf = StringIO("""\
@@ -425,8 +425,8 @@
 msg = _('Bonjour à tous')
 """)
         messages = list(extract.extract_javascript(buf, ('_',), ['NOTE:'], {}))
-        self.assertEqual(u'Bonjour à tous', messages[0][2])
-        self.assertEqual([u'NOTE: hello', 'and bonjour', '  and servus'], messages[0][3])
+        self.assertEqual('Bonjour à tous', messages[0][2])
+        self.assertEqual(['NOTE: hello', 'and bonjour', '  and servus'], messages[0][3])
 
     def test_ignore_function_definitions(self):
         buf = StringIO("""\
@@ -455,11 +455,11 @@
 _('no comment here')
 """)
         messages = list(extract.extract_javascript(buf, ('_',), ['NOTE:'], {}))
-        self.assertEqual(u'Something', messages[0][2])
-        self.assertEqual([u'NOTE: this will'], messages[0][3])
-        self.assertEqual(u'Something else', messages[1][2])
-        self.assertEqual([u'NOTE: this will show up', 'too.'], messages[1][3])
-        self.assertEqual(u'no comment here', messages[2][2])
+        self.assertEqual('Something', messages[0][2])
+        self.assertEqual(['NOTE: this will'], messages[0][3])
+        self.assertEqual('Something else', messages[1][2])
+        self.assertEqual(['NOTE: this will show up', 'too.'], messages[1][3])
+        self.assertEqual('no comment here', messages[2][2])
         self.assertEqual([], messages[2][3])
 
 
@@ -481,9 +481,9 @@
         messages = \
             list(extract.extract('python', buf, extract.DEFAULT_KEYWORDS, [],
                                  {}))
-        self.assertEqual([(5, (u'bunny', u'bunnies'), []),
-                          (8, u'Rabbit', []),
-                          (10, (u'Page', u'Pages'), [])], messages)
+        self.assertEqual([(5, ('bunny', 'bunnies'), []),
+                          (8, 'Rabbit', []),
+                          (10, ('Page', 'Pages'), [])], messages)
 
     def test_invalid_extract_method(self):
         buf = StringIO('')
@@ -502,8 +502,8 @@
             list(extract.extract('python', buf, extract.DEFAULT_KEYWORDS, [],
                                  {}))
         self.assertEqual(len(messages), 2)
-        self.assertEqual(u'foo', messages[0][1])
-        self.assertEqual((u'hello', u'there'), messages[1][1])
+        self.assertEqual('foo', messages[0][1])
+        self.assertEqual(('hello', 'there'), messages[1][1])
 
     def test_empty_string_msgid(self):
         buf = StringIO("""\
--- a/babel/messages/tests/frontend.py
+++ b/babel/messages/tests/frontend.py
@@ -18,7 +18,7 @@
 import doctest
 import os
 import shutil
-from StringIO import StringIO
+from io import StringIO
 import sys
 import time
 import unittest
@@ -524,7 +524,7 @@
         try:
             self.cli.run(sys.argv)
             self.fail('Expected SystemExit')
-        except SystemExit, e:
+        except SystemExit as e:
             self.assertEqual(2, e.code)
             self.assertEqual("""\
 usage: pybabel command [options] [args]
@@ -536,7 +536,7 @@
         try:
             self.cli.run(sys.argv + ['--help'])
             self.fail('Expected SystemExit')
-        except SystemExit, e:
+        except SystemExit as e:
             self.assertEqual(0, e.code)
             self.assertEqual("""\
 usage: pybabel command [options] [args]
@@ -563,7 +563,7 @@
                 '--msgid-bugs-address', 'bugs.address@email.tld',
                 '-c', 'TRANSLATOR', '-c', 'TRANSLATORS:',
                 '-o', pot_file, os.path.join(self.datadir, 'project')])
-        except SystemExit, e:
+        except SystemExit as e:
             self.assertEqual(0, e.code)
             assert os.path.isfile(pot_file)
             self.assertEqual(
@@ -620,7 +620,7 @@
                 '--mapping', os.path.join(self.datadir, 'mapping.cfg'),
                 '-c', 'TRANSLATOR', '-c', 'TRANSLATORS:',
                 '-o', pot_file, os.path.join(self.datadir, 'project')])
-        except SystemExit, e:
+        except SystemExit as e:
             self.assertEqual(0, e.code)
             assert os.path.isfile(pot_file)
             self.assertEqual(
@@ -671,7 +671,7 @@
                 '-d', os.path.join(self.datadir, 'project', 'i18n'),
                 '-i', os.path.join(self.datadir, 'project', 'i18n',
                                    'messages.pot')])
-        except SystemExit, e:
+        except SystemExit as e:
             self.assertEqual(0, e.code)
             assert os.path.isfile(po_file)
             self.assertEqual(
@@ -722,7 +722,7 @@
                 '-d', os.path.join(self.datadir, 'project', 'i18n'),
                 '-i', os.path.join(self.datadir, 'project', 'i18n',
                                    'messages.pot')])
-        except SystemExit, e:
+        except SystemExit as e:
             self.assertEqual(0, e.code)
         assert os.path.isfile(po_file)
         self.assertEqual(
@@ -772,7 +772,7 @@
                 '-d', os.path.join(self.datadir, 'project', 'i18n'),
                 '-i', os.path.join(self.datadir, 'project', 'i18n',
                                    'messages.pot')])
-        except SystemExit, e:
+        except SystemExit as e:
             self.assertEqual(0, e.code)
         assert os.path.isfile(po_file)
         self.assertEqual(
--- a/babel/messages/tests/mofile.py
+++ b/babel/messages/tests/mofile.py
@@ -15,7 +15,7 @@
 import gettext
 import os
 import unittest
-from StringIO import StringIO
+from io import StringIO
 
 from babel.messages import mofile, Catalog
 
@@ -47,27 +47,27 @@
         # can be applied to all subsequent messages by GNUTranslations
         # (ensuring all messages are safely converted to unicode)
         catalog = Catalog(locale='en_US')
-        catalog.add(u'', '''\
+        catalog.add('', '''\
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n''')
-        catalog.add(u'foo', 'Voh')
-        catalog.add((u'There is', u'There are'), (u'Es gibt', u'Es gibt'))
-        catalog.add(u'Fizz', '')
+        catalog.add('foo', 'Voh')
+        catalog.add(('There is', 'There are'), ('Es gibt', 'Es gibt'))
+        catalog.add('Fizz', '')
         catalog.add(('Fuzz', 'Fuzzes'), ('', ''))
         buf = StringIO()
         mofile.write_mo(buf, catalog)
         buf.seek(0)
         translations = gettext.GNUTranslations(fp=buf)
-        self.assertEqual(u'Voh', translations.ugettext('foo'))
-        assert isinstance(translations.ugettext('foo'), unicode)
-        self.assertEqual(u'Es gibt', translations.ungettext('There is', 'There are', 1))
-        assert isinstance(translations.ungettext('There is', 'There are', 1), unicode)
-        self.assertEqual(u'Fizz', translations.ugettext('Fizz'))
-        assert isinstance(translations.ugettext('Fizz'), unicode)
-        self.assertEqual(u'Fuzz', translations.ugettext('Fuzz'))
-        assert isinstance(translations.ugettext('Fuzz'), unicode)
-        self.assertEqual(u'Fuzzes', translations.ugettext('Fuzzes'))
-        assert isinstance(translations.ugettext('Fuzzes'), unicode)
+        self.assertEqual('Voh', translations.ugettext('foo'))
+        assert isinstance(translations.ugettext('foo'), str)
+        self.assertEqual('Es gibt', translations.ungettext('There is', 'There are', 1))
+        assert isinstance(translations.ungettext('There is', 'There are', 1), str)
+        self.assertEqual('Fizz', translations.ugettext('Fizz'))
+        assert isinstance(translations.ugettext('Fizz'), str)
+        self.assertEqual('Fuzz', translations.ugettext('Fuzz'))
+        assert isinstance(translations.ugettext('Fuzz'), str)
+        self.assertEqual('Fuzzes', translations.ugettext('Fuzzes'))
+        assert isinstance(translations.ugettext('Fuzzes'), str)
 
     def test_more_plural_forms(self):
         catalog2 = Catalog(locale='ru_RU')
--- a/babel/messages/tests/pofile.py
+++ b/babel/messages/tests/pofile.py
@@ -13,7 +13,7 @@
 
 from datetime import datetime
 import doctest
-from StringIO import StringIO
+from io import StringIO
 import unittest
 
 from babel.messages.catalog import Catalog, Message
@@ -100,15 +100,15 @@
 ''')
         catalog = pofile.read_po(buf)
         self.assertEqual(1, len(list(catalog)))
-        self.assertEqual(u'3.15', catalog.version)
-        self.assertEqual(u'Fliegender Zirkus <fliegender@zirkus.de>',
+        self.assertEqual('3.15', catalog.version)
+        self.assertEqual('Fliegender Zirkus <fliegender@zirkus.de>',
                          catalog.msgid_bugs_address)
         self.assertEqual(datetime(2007, 9, 27, 11, 19,
                                   tzinfo=FixedOffsetTimezone(7 * 60)),
                          catalog.creation_date)
-        self.assertEqual(u'John <cleese@bavaria.de>', catalog.last_translator)
-        self.assertEqual(u'German Lang <de@babel.org>', catalog.language_team)
-        self.assertEqual(u'iso-8859-2', catalog.charset)
+        self.assertEqual('John <cleese@bavaria.de>', catalog.last_translator)
+        self.assertEqual('German Lang <de@babel.org>', catalog.language_team)
+        self.assertEqual('iso-8859-2', catalog.charset)
         self.assertEqual(True, list(catalog)[0].fuzzy)
 
     def test_obsolete_message(self):
@@ -124,9 +124,9 @@
         catalog = pofile.read_po(buf)
         self.assertEqual(1, len(catalog))
         self.assertEqual(1, len(catalog.obsolete))
-        message = catalog.obsolete[u'foo']
-        self.assertEqual(u'foo', message.id)
-        self.assertEqual(u'Voh', message.string)
+        message = catalog.obsolete['foo']
+        self.assertEqual('foo', message.id)
+        self.assertEqual('Voh', message.string)
         self.assertEqual(['This is an obsolete message'], message.user_comments)
 
     def test_obsolete_message_ignored(self):
@@ -222,7 +222,7 @@
         self.assertEqual(3, catalog.num_plurals)
         message = catalog['foo']
         self.assertEqual(3, len(message.string))
-        self.assertEqual(u'Vohss', message.string[2])
+        self.assertEqual('Vohss', message.string[2])
 
     def test_plural_with_square_brackets(self):
         buf = StringIO(r'''msgid "foo"
@@ -240,8 +240,8 @@
 
     def test_join_locations(self):
         catalog = Catalog()
-        catalog.add(u'foo', locations=[('main.py', 1)])
-        catalog.add(u'foo', locations=[('utils.py', 3)])
+        catalog.add('foo', locations=[('main.py', 1)])
+        catalog.add('foo', locations=[('utils.py', 3)])
         buf = StringIO()
         pofile.write_po(buf, catalog, omit_header=True)
         self.assertEqual('''#: main.py:1 utils.py:3
@@ -250,8 +250,8 @@
 
     def test_duplicate_comments(self):
         catalog = Catalog()
-        catalog.add(u'foo', auto_comments=['A comment'])
-        catalog.add(u'foo', auto_comments=['A comment'])
+        catalog.add('foo', auto_comments=['A comment'])
+        catalog.add('foo', auto_comments=['A comment'])
         buf = StringIO()
         pofile.write_po(buf, catalog, omit_header=True)
         self.assertEqual('''#. A comment
@@ -314,10 +314,10 @@
 
     def test_wrap_locations_with_hyphens(self):
         catalog = Catalog()
-        catalog.add(u'foo', locations=[
+        catalog.add('foo', locations=[
             ('doupy/templates/base/navmenu.inc.html.py', 60)
         ])
-        catalog.add(u'foo', locations=[
+        catalog.add('foo', locations=[
             ('doupy/templates/job-offers/helpers.html', 22)
         ])
         buf = StringIO()
@@ -360,9 +360,9 @@
 
     def test_pot_with_translator_comments(self):
         catalog = Catalog()
-        catalog.add(u'foo', locations=[('main.py', 1)],
+        catalog.add('foo', locations=[('main.py', 1)],
                     auto_comments=['Comment About `foo`'])
-        catalog.add(u'bar', locations=[('utils.py', 3)],
+        catalog.add('bar', locations=[('utils.py', 3)],
                     user_comments=['Comment About `bar` with',
                                    'multiple lines.'])
         buf = StringIO()
@@ -380,8 +380,8 @@
 
     def test_po_with_obsolete_message(self):
         catalog = Catalog()
-        catalog.add(u'foo', u'Voh', locations=[('main.py', 1)])
-        catalog.obsolete['bar'] = Message(u'bar', u'Bahr',
+        catalog.add('foo', 'Voh', locations=[('main.py', 1)])
+        catalog.obsolete['bar'] = Message('bar', 'Bahr',
                                           locations=[('utils.py', 3)],
                                           user_comments=['User comment'])
         buf = StringIO()
@@ -396,7 +396,7 @@
 
     def test_po_with_multiline_obsolete_message(self):
         catalog = Catalog()
-        catalog.add(u'foo', u'Voh', locations=[('main.py', 1)])
+        catalog.add('foo', 'Voh', locations=[('main.py', 1)])
         msgid = r"""Here's a message that covers
 multiple lines, and should still be handled
 correctly.
@@ -424,8 +424,8 @@
 
     def test_po_with_obsolete_message_ignored(self):
         catalog = Catalog()
-        catalog.add(u'foo', u'Voh', locations=[('main.py', 1)])
-        catalog.obsolete['bar'] = Message(u'bar', u'Bahr',
+        catalog.add('foo', 'Voh', locations=[('main.py', 1)])
+        catalog.obsolete['bar'] = Message('bar', 'Bahr',
                                           locations=[('utils.py', 3)],
                                           user_comments=['User comment'])
         buf = StringIO()
@@ -436,8 +436,8 @@
 
     def test_po_with_previous_msgid(self):
         catalog = Catalog()
-        catalog.add(u'foo', u'Voh', locations=[('main.py', 1)],
-                    previous_id=u'fo')
+        catalog.add('foo', 'Voh', locations=[('main.py', 1)],
+                    previous_id='fo')
         buf = StringIO()
         pofile.write_po(buf, catalog, omit_header=True, include_previous=True)
         self.assertEqual('''#: main.py:1
@@ -447,8 +447,8 @@
 
     def test_po_with_previous_msgid_plural(self):
         catalog = Catalog()
-        catalog.add((u'foo', u'foos'), (u'Voh', u'Voeh'),
-                    locations=[('main.py', 1)], previous_id=(u'fo', u'fos'))
+        catalog.add(('foo', 'foos'), ('Voh', 'Voeh'),
+                    locations=[('main.py', 1)], previous_id=('fo', 'fos'))
         buf = StringIO()
         pofile.write_po(buf, catalog, omit_header=True, include_previous=True)
         self.assertEqual('''#: main.py:1
@@ -461,10 +461,10 @@
 
     def test_sorted_po(self):
         catalog = Catalog()
-        catalog.add(u'bar', locations=[('utils.py', 3)],
+        catalog.add('bar', locations=[('utils.py', 3)],
                     user_comments=['Comment About `bar` with',
                                    'multiple lines.'])
-        catalog.add((u'foo', u'foos'), (u'Voh', u'Voeh'),
+        catalog.add(('foo', 'foos'), ('Voh', 'Voeh'),
                     locations=[('main.py', 1)])
         buf = StringIO()
         pofile.write_po(buf, catalog, sort_output=True)
--- a/babel/numbers.py
+++ b/babel/numbers.py
@@ -77,7 +77,7 @@
     :return: the decimal symbol
     :rtype: `unicode`
     """
-    return Locale.parse(locale).number_symbols.get('decimal', u'.')
+    return Locale.parse(locale).number_symbols.get('decimal', '.')
 
 def get_plus_sign_symbol(locale=LC_NUMERIC):
     """Return the plus sign symbol used by the current locale.
@@ -89,7 +89,7 @@
     :return: the plus sign symbol
     :rtype: `unicode`
     """
-    return Locale.parse(locale).number_symbols.get('plusSign', u'+')
+    return Locale.parse(locale).number_symbols.get('plusSign', '+')
 
 def get_minus_sign_symbol(locale=LC_NUMERIC):
     """Return the plus sign symbol used by the current locale.
@@ -101,7 +101,7 @@
     :return: the plus sign symbol
     :rtype: `unicode`
     """
-    return Locale.parse(locale).number_symbols.get('minusSign', u'-')
+    return Locale.parse(locale).number_symbols.get('minusSign', '-')
 
 def get_exponential_symbol(locale=LC_NUMERIC):
     """Return the symbol used by the locale to separate mantissa and exponent.
@@ -113,7 +113,7 @@
     :return: the exponential symbol
     :rtype: `unicode`
     """
-    return Locale.parse(locale).number_symbols.get('exponential', u'E')
+    return Locale.parse(locale).number_symbols.get('exponential', 'E')
 
 def get_group_symbol(locale=LC_NUMERIC):
     """Return the symbol used by the locale to separate groups of thousands.
@@ -125,10 +125,10 @@
     :return: the group symbol
     :rtype: `unicode`
     """
-    return Locale.parse(locale).number_symbols.get('group', u',')
+    return Locale.parse(locale).number_symbols.get('group', ',')
 
 def format_number(number, locale=LC_NUMERIC):
-    u"""Return the given number formatted for a specific locale.
+    """Return the given number formatted for a specific locale.
     
     >>> format_number(1099, locale='en_US')
     u'1,099'
@@ -145,7 +145,7 @@
     return format_decimal(number, locale=locale)
 
 def format_decimal(number, format=None, locale=LC_NUMERIC):
-    u"""Return the given decimal number formatted for a specific locale.
+    """Return the given decimal number formatted for a specific locale.
     
     >>> format_decimal(1.2345, locale='en_US')
     u'1.234'
@@ -177,7 +177,7 @@
     return pattern.apply(number, locale)
 
 def format_currency(number, currency, format=None, locale=LC_NUMERIC):
-    u"""Return formatted currency value.
+    """Return formatted currency value.
     
     >>> format_currency(1099.98, 'USD', locale='en_US')
     u'$1,099.98'
@@ -280,7 +280,7 @@
     :raise `NumberFormatError`: if the string can not be converted to a number
     """
     try:
-        return long(string.replace(get_group_symbol(locale), ''))
+        return int(string.replace(get_group_symbol(locale), ''))
     except ValueError:
         raise NumberFormatError('%r is not a valid number' % string)
 
@@ -470,7 +470,7 @@
         self.exp_plus = exp_plus
         if '%' in ''.join(self.prefix + self.suffix):
             self.scale = 100
-        elif u'‰' in ''.join(self.prefix + self.suffix):
+        elif '‰' in ''.join(self.prefix + self.suffix):
             self.scale = 1000
         else:
             self.scale = 1
@@ -505,7 +505,7 @@
             elif self.exp_plus:
                 exp_sign = get_plus_sign_symbol(locale)
             exp = abs(exp)
-            number = u'%s%s%s%s' % \
+            number = '%s%s%s%s' % \
                  (self._format_sigdig(value, self.frac_prec[0], 
                                      self.frac_prec[1]), 
                   get_exponential_symbol(locale),  exp_sign,
@@ -531,11 +531,11 @@
                                  self.int_prec[1], locale)
             b = self._format_frac(b, locale)
             number = a + b
-        retval = u'%s%s%s' % (self.prefix[is_negative], number,
+        retval = '%s%s%s' % (self.prefix[is_negative], number,
                                 self.suffix[is_negative])
-        if u'¤' in retval:
-            retval = retval.replace(u'¤¤', currency.upper())
-            retval = retval.replace(u'¤', get_currency_symbol(currency, locale))
+        if '¤' in retval:
+            retval = retval.replace('¤¤', currency.upper())
+            retval = retval.replace('¤', get_currency_symbol(currency, locale))
         return retval
 
     def _format_sigdig(self, value, min, max):
--- a/babel/plural.py
+++ b/babel/plural.py
@@ -56,7 +56,7 @@
         :raise RuleError: if the expression is malformed
         """
         if isinstance(rules, dict):
-            rules = rules.items()
+            rules = list(rules.items())
         found = set()
         self.abstract = []
         for key, expr in rules:
@@ -165,7 +165,7 @@
     for tag, ast in PluralRule.parse(rule).abstract:
         result.append(' if (%s): return %r' % (to_python(ast), tag))
     result.append(' return %r' % _fallback_tag)
-    exec '\n'.join(result) in namespace
+    exec('\n'.join(result), namespace)
     return namespace['evaluate']
 
 
@@ -382,7 +382,8 @@
     output formats.
     """
 
-    def compile(self, (op, args)):
+    def compile(self, xxx_todo_changeme):
+        (op, args) = xxx_todo_changeme
         return getattr(self, 'compile_' + op)(*args)
 
     compile_n = lambda x: 'n'
@@ -413,7 +414,7 @@
 
     def compile_relation(self, method, expr, range):
         expr = self.compile(expr)
-        min, max = map(self.compile, range[1])
+        min, max = list(map(self.compile, range[1]))
         return '(%s >= %s && %s <= %s)' % (expr, min, expr, max)
 
 
--- a/babel/support.py
+++ b/babel/support.py
@@ -202,7 +202,7 @@
     def __contains__(self, key):
         return key in self.value
 
-    def __nonzero__(self):
+    def __bool__(self):
         return bool(self.value)
 
     def __dir__(self):
@@ -218,7 +218,7 @@
         return str(self.value)
 
     def __unicode__(self):
-        return unicode(self.value)
+        return str(self.value)
 
     def __add__(self, other):
         return self.value + other
@@ -290,7 +290,7 @@
                         from
         """
         gettext.GNUTranslations.__init__(self, fp=fileobj)
-        self.files = filter(None, [getattr(fileobj, 'name', None)])
+        self.files = [_f for _f in [getattr(fileobj, 'name', None)] if _f]
         self.domain = domain
         self._domains = {}
 
@@ -510,7 +510,7 @@
         if tmsg is missing:
             if self._fallback:
                 return self._fallback.upgettext(context, message)
-            return unicode(message)
+            return str(message)
         return tmsg
 
     def unpgettext(self, context, singular, plural, num):
@@ -531,9 +531,9 @@
             if self._fallback:
                 return self._fallback.unpgettext(context, singular, plural, num)
             if num == 1:
-                tmsg = unicode(singular)
+                tmsg = str(singular)
             else:
-                tmsg = unicode(plural)
+                tmsg = str(plural)
         return tmsg
 
     def dpgettext(self, domain, context, message):
--- a/babel/tests/dates.py
+++ b/babel/tests/dates.py
@@ -41,7 +41,7 @@
     def test_abbreviated_month_alias(self):
         d = date(2006, 3, 8)
         fmt = dates.DateTimeFormat(d, locale='de_DE')
-        self.assertEqual(u'Mär', fmt['LLL'])
+        self.assertEqual('Mär', fmt['LLL'])
 
     def test_week_of_year_first(self):
         d = date(2006, 1, 8)
@@ -201,7 +201,7 @@
         tz = timezone('Europe/Paris')
         t = time(15, 30, tzinfo=tz)
         fmt = dates.DateTimeFormat(t, locale='fr_FR')
-        self.assertEqual(u'Heure de l\u2019Europe centrale', fmt['vvvv'])
+        self.assertEqual('Heure de l\u2019Europe centrale', fmt['vvvv'])
 
     def test_hour_formatting(self):
         l = 'en_US'
@@ -220,12 +220,12 @@
 class FormatDateTestCase(unittest.TestCase):
 
     def test_with_time_fields_in_pattern(self):
-        self.assertRaises(AttributeError, dates.format_date, date(2007, 04, 01),
+        self.assertRaises(AttributeError, dates.format_date, date(2007, 0o4, 0o1),
                           "yyyy-MM-dd HH:mm", locale='en_US')
 
     def test_with_time_fields_in_pattern_and_datetime_param(self):
         self.assertRaises(AttributeError, dates.format_date,
-                          datetime(2007, 04, 01, 15, 30),
+                          datetime(2007, 0o4, 0o1, 15, 30),
                           "yyyy-MM-dd HH:mm", locale='en_US')
 
 
@@ -238,12 +238,12 @@
         self.assertEqual('11:30:00 AM EDT', string)
 
     def test_with_date_fields_in_pattern(self):
-        self.assertRaises(AttributeError, dates.format_time, date(2007, 04, 01),
+        self.assertRaises(AttributeError, dates.format_time, date(2007, 0o4, 0o1),
                           "yyyy-MM-dd HH:mm", locale='en_US')
 
     def test_with_date_fields_in_pattern_and_datetime_param(self):
         self.assertRaises(AttributeError, dates.format_time,
-                          datetime(2007, 04, 01, 15, 30),
+                          datetime(2007, 0o4, 0o1, 15, 30),
                           "yyyy-MM-dd HH:mm", locale='en_US')
 
 
--- a/babel/tests/localedata.py
+++ b/babel/tests/localedata.py
@@ -60,7 +60,7 @@
         self.assertEqual({
             'x': {'a': 1, 'b': 12, 'c': 3, 'd': 14},
             'y': {'a': 1, 'b': 22, 'c': 3, 'd': 14, 'e': 25}
-        }, dict(d.items()))
+        }, dict(list(d.items())))
 
 
 def suite():
--- a/babel/tests/support.py
+++ b/babel/tests/support.py
@@ -13,7 +13,7 @@
 
 import doctest
 import os
-from StringIO import StringIO
+from io import StringIO
 import unittest
 
 from babel import support
@@ -64,8 +64,8 @@
                                                                      'foo'))
 
     def test_upgettext(self):
-        self.assertEqualTypeToo(u'Voh', self.translations.ugettext('foo'))
-        self.assertEqualTypeToo(u'VohCTX', self.translations.upgettext('foo',
+        self.assertEqualTypeToo('Voh', self.translations.ugettext('foo'))
+        self.assertEqualTypeToo('VohCTX', self.translations.upgettext('foo',
                                                                        'foo'))
 
     def test_lpgettext(self):
@@ -86,14 +86,14 @@
                                                             'foos1', 2))
 
     def test_unpgettext(self):
-        self.assertEqualTypeToo(u'Voh1',
+        self.assertEqualTypeToo('Voh1',
                                 self.translations.ungettext('foo1', 'foos1', 1))
-        self.assertEqualTypeToo(u'Vohs1',
+        self.assertEqualTypeToo('Vohs1',
                                 self.translations.ungettext('foo1', 'foos1', 2))
-        self.assertEqualTypeToo(u'VohCTX1',
+        self.assertEqualTypeToo('VohCTX1',
                                 self.translations.unpgettext('foo', 'foo1',
                                                              'foos1', 1))
-        self.assertEqualTypeToo(u'VohsCTX1',
+        self.assertEqualTypeToo('VohsCTX1',
                                 self.translations.unpgettext('foo', 'foo1',
                                                              'foos1', 2))
 
@@ -117,9 +117,9 @@
 
     def test_dupgettext(self):
         self.assertEqualTypeToo(
-            u'VohD', self.translations.dugettext('messages1', 'foo'))
+            'VohD', self.translations.dugettext('messages1', 'foo'))
         self.assertEqualTypeToo(
-            u'VohCTXD', self.translations.dupgettext('messages1', 'foo', 'foo'))
+            'VohCTXD', self.translations.dupgettext('messages1', 'foo', 'foo'))
 
     def test_ldpgettext(self):
         self.assertEqualTypeToo(
@@ -141,14 +141,14 @@
 
     def test_dunpgettext(self):
         self.assertEqualTypeToo(
-            u'VohD1', self.translations.dungettext('messages1', 'foo1', 'foos1', 1))
+            'VohD1', self.translations.dungettext('messages1', 'foo1', 'foos1', 1))
         self.assertEqualTypeToo(
-            u'VohsD1', self.translations.dungettext('messages1', 'foo1', 'foos1', 2))
+            'VohsD1', self.translations.dungettext('messages1', 'foo1', 'foos1', 2))
         self.assertEqualTypeToo(
-            u'VohCTXD1', self.translations.dunpgettext('messages1', 'foo', 'foo1',
+            'VohCTXD1', self.translations.dunpgettext('messages1', 'foo', 'foo1',
                                                        'foos1', 1))
         self.assertEqualTypeToo(
-            u'VohsCTXD1', self.translations.dunpgettext('messages1', 'foo', 'foo1',
+            'VohsCTXD1', self.translations.dunpgettext('messages1', 'foo', 'foo1',
                                                         'foos1', 2))
 
     def test_ldnpgettext(self):
--- a/babel/util.py
+++ b/babel/util.py
@@ -19,7 +19,7 @@
 import re
 import textwrap
 import time
-from itertools import izip, imap
+
 try:
     # assigned so they're importable
     frozenset = frozenset
@@ -216,10 +216,10 @@
         return d
 
     def items(self):
-        return zip(self._keys, self.values())
+        return list(zip(self._keys, list(self.values())))
 
     def iteritems(self):
-        return izip(self._keys, self.itervalues())
+        return zip(self._keys, iter(self.values()))
 
     def keys(self):
         return self._keys[:]
@@ -242,14 +242,14 @@
             self._keys.append(key)
 
     def update(self, dict):
-        for (key, val) in dict.items():
+        for (key, val) in list(dict.items()):
             self[key] = val
 
     def values(self):
-        return map(self.get, self._keys)
+        return list(map(self.get, self._keys))
 
     def itervalues(self):
-        return imap(self.get, self._keys)
+        return map(self.get, self._keys)
 
 
 try:
Copyright (C) 2012-2017 Edgewall Software