Bug 1390968: python-3 compatibility for python/**/*.py; r=Alex_Gaynor,gps
authorDustin J. Mitchell <dustin@mozilla.com>
Mon, 28 Aug 2017 21:31:30 +0000
changeset 377540 dfb510e198b8761964837f2bc404ec1bd985ffed
parent 377539 f6d1757da618997bb22bffa91a6b1ec6c7ad42b5
child 377541 70194da47f2518ca0476c2adc75d523a7546751a
push id32410
push userkwierso@gmail.com
push dateTue, 29 Aug 2017 22:38:06 +0000
treeherdermozilla-central@8f221407c600 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersAlex_Gaynor, gps
bugs1390968
milestone57.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1390968: python-3 compatibility for python/**/*.py; r=Alex_Gaynor,gps This passes `python3 -mcompileall`. Changes: * use `0o` prefix for octal literals * print as a function * except .. as * use six.reraise to replace a multi-argument raise statement * use six.string_types and six.moves.configparser * remove uses of `L` suffix for long integers MozReview-Commit-ID: KLaYRNHGpay
python/mach/mach/config.py
python/mach/setup.py
python/mozboot/mozboot/archlinux.py
python/mozboot/mozboot/windows.py
python/mozbuild/mozbuild/action/exe_7z_archive.py
python/mozbuild/mozbuild/action/explode_aar.py
python/mozbuild/mozbuild/action/output_searchplugins_list.py
python/mozbuild/mozbuild/action/tooltool.py
python/mozbuild/mozbuild/configure/check_debug_ranges.py
python/mozbuild/mozbuild/configure/libstdcxx.py
python/mozbuild/mozbuild/configure/lint_util.py
python/mozbuild/mozbuild/doctor.py
python/mozbuild/mozbuild/jar.py
python/mozbuild/mozbuild/preprocessor.py
python/mozbuild/mozbuild/test/test_util.py
python/mozbuild/mozbuild/util.py
python/mozbuild/mozpack/archive.py
python/mozbuild/mozpack/files.py
python/mozbuild/mozpack/mozjar.py
--- a/python/mach/mach/config.py
+++ b/python/mach/mach/config.py
@@ -14,24 +14,20 @@ ConfigProvider classes are associated wi
 settings are available.
 """
 
 from __future__ import absolute_import, unicode_literals
 
 import collections
 import os
 import sys
+import six
 from functools import wraps
-
-if sys.version_info[0] == 3:
-    from configparser import RawConfigParser, NoSectionError
-    str_type = str
-else:
-    from ConfigParser import RawConfigParser, NoSectionError
-    str_type = basestring
+from six.moves.configparser import RawConfigParser, NoSectionError
+from six import string_types as str_type
 
 
 class ConfigException(Exception):
     pass
 
 
 class ConfigType(object):
     """Abstract base class for config values."""
@@ -139,17 +135,17 @@ def reraise_attribute_error(func):
     raise AttributeError instead of KeyError.
     """
     @wraps(func)
     def _(*args, **kwargs):
         try:
             return func(*args, **kwargs)
         except KeyError:
             exc_class, exc, tb = sys.exc_info()
-            raise AttributeError().__class__, exc, tb
+            six.reraise(AttributeError().__class__, exc, tb)
     return _
 
 
 class ConfigSettings(collections.Mapping):
     """Interface for configuration settings.
 
     This is the main interface to the configuration.
 
--- a/python/mach/setup.py
+++ b/python/mach/setup.py
@@ -27,12 +27,13 @@ setup(
         'Development Status :: 3 - Alpha',
         'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)',
         'Natural Language :: English',
     ],
     install_requires=[
         'blessings',
         'mozfile',
         'mozprocess',
+        'six',
     ],
     tests_require=['mock'],
 )
 
--- a/python/mozboot/mozboot/archlinux.py
+++ b/python/mozboot/mozboot/archlinux.py
@@ -70,17 +70,17 @@ class ArchlinuxBootstrapper(StyloInstall
         # See comment about 32 bit binaries and multilib below.
         'multilib/lib32-libstdc++5',
         'multilib/lib32-ncurses',
         'multilib/lib32-readline',
         'multilib/lib32-zlib',
     ]
 
     def __init__(self, version, dist_id, **kwargs):
-        print 'Using an experimental bootstrapper for Archlinux.'
+        print('Using an experimental bootstrapper for Archlinux.')
         BaseBootstrapper.__init__(self, **kwargs)
 
     def install_system_packages(self):
         self.pacman_install(*self.SYSTEM_PACKAGES)
 
     def install_browser_packages(self):
         self.ensure_browser_packages()
 
--- a/python/mozboot/mozboot/windows.py
+++ b/python/mozboot/mozboot/windows.py
@@ -40,17 +40,17 @@ class WindowsBootstrapper(BaseBootstrapp
         if 'MOZ_WINDOWS_BOOTSTRAP' not in os.environ or os.environ['MOZ_WINDOWS_BOOTSTRAP'] != '1':
             raise NotImplementedError('Bootstrap support for Windows is under development. For now, use MozillaBuild '
                                       'to set up a build environment on Windows. If you are testing Windows Bootstrap support, '
                                       'try `export MOZ_WINDOWS_BOOTSTRAP=1`')
         BaseBootstrapper.__init__(self, **kwargs)
         if not self.which('pacman'):
             raise NotImplementedError('The Windows bootstrapper only works with msys2 with pacman. Get msys2 at '
                                       'http://msys2.github.io/')
-        print 'Using an experimental bootstrapper for Windows.'
+        print('Using an experimental bootstrapper for Windows.')
 
     def which(self, name):
         return BaseBootstrapper.which(self, name + '.exe')
 
     def install_system_packages(self):
         self.pacman_install(*self.SYSTEM_PACKAGES)
 
     def upgrade_mercurial(self, current):
--- a/python/mozbuild/mozbuild/action/exe_7z_archive.py
+++ b/python/mozbuild/mozbuild/action/exe_7z_archive.py
@@ -18,17 +18,17 @@ def archive_exe(pkg_dir, tagfile, sfx_pa
             shutil.move(pkg_dir, 'core')
         subprocess.check_call(['upx', '--best', '-o', mozpath.join(tmpdir, '7zSD.sfx'), sfx_package])
 
         subprocess.check_call(['7z', 'a', '-r', '-t7z', mozpath.join(tmpdir, 'app.7z'), '-mx', '-m0=BCJ2', '-m1=LZMA:d25', '-m2=LZMA:d19', '-m3=LZMA:d19', '-mb0:1', '-mb0s1:2', '-mb0s2:3'])
 
         with open(package, 'wb') as o:
             for i in [mozpath.join(tmpdir, '7zSD.sfx'), tagfile, mozpath.join(tmpdir, 'app.7z')]:
                 shutil.copyfileobj(open(i, 'rb'), o)
-        os.chmod(package, 0755)
+        os.chmod(package, 0o0755)
     finally:
         if pkg_dir:
             shutil.move('core', pkg_dir)
         shutil.rmtree(tmpdir)
 
 def main(args):
     if len(args) != 4:
         print('Usage: exe_7z_archive.py <pkg_dir> <tagfile> <sfx_package> <package>',
--- a/python/mozbuild/mozbuild/action/explode_aar.py
+++ b/python/mozbuild/mozbuild/action/explode_aar.py
@@ -39,17 +39,17 @@ def explode(aar, destdir):
         jar = mozpath.join(finder.base, name + '-' + p)
         os.rename(mozpath.join(finder.base, p), jar)
 
     # Frequently assets/ is present but empty.  Protect against meaningless
     # changes to the AAR files by deleting empty assets/ directories.
     assets = mozpath.join(destdir, 'assets')
     try:
         os.rmdir(assets)
-    except OSError, e:
+    except OSError as e:
         if e.errno in (errno.ENOTEMPTY, errno.ENOENT):
             pass
         else:
             raise
 
     return True
 
 
--- a/python/mozbuild/mozbuild/action/output_searchplugins_list.py
+++ b/python/mozbuild/mozbuild/action/output_searchplugins_list.py
@@ -23,9 +23,9 @@ else:
 # Get additional engines from regionOverrides
 for region, overrides in searchinfo["regionOverrides"].iteritems():
   for originalengine, replacement in overrides.iteritems():
     if originalengine in engines:
       # We add the engine because we still need the original
       engines.add(replacement)
 
 # join() will take an iterable, not just a list.
-print '\n'.join(engines)
+print('\n'.join(engines))
--- a/python/mozbuild/mozbuild/action/tooltool.py
+++ b/python/mozbuild/mozbuild/action/tooltool.py
@@ -367,19 +367,19 @@ def list_manifest(manifest_file):
         manifest = open_manifest(manifest_file)
     except InvalidManifest as e:
         log.error("failed to load manifest file at '%s': %s" % (
             manifest_file,
             str(e),
         ))
         return False
     for f in manifest.file_records:
-        print "%s\t%s\t%s" % ("P" if f.present() else "-",
+        print("%s\t%s\t%s" % ("P" if f.present() else "-",
                               "V" if f.present() and f.validate() else "-",
-                              f.filename)
+                              f.filename))
     return True
 
 
 def validate_manifest(manifest_file):
     """I validate that all files in a manifest are present and valid but
     don't fetch or delete them if they aren't"""
     try:
         manifest = open_manifest(manifest_file)
@@ -669,17 +669,17 @@ def fetch_files(manifest_file, base_urls
 
             # if I am using a cache and a new file has just been retrieved from a
             # remote location, I need to update the cache as well
             if cache_folder:
                 log.info("Updating local cache %s..." % cache_folder)
                 try:
                     if not os.path.exists(cache_folder):
                         log.info("Creating cache in %s..." % cache_folder)
-                        os.makedirs(cache_folder, 0700)
+                        os.makedirs(cache_folder, 0o0700)
                     shutil.copy(os.path.join(os.getcwd(), localfile.filename),
                                 os.path.join(cache_folder, localfile.digest))
                     log.info("Local cache %s updated with %s" % (cache_folder,
                                                                  localfile.filename))
                     touch(os.path.join(cache_folder, localfile.digest))
                 except (OSError, IOError):
                     log.warning('Impossible to add file %s to cache folder %s' %
                                 (localfile.filename, cache_folder), exc_info=True)
--- a/python/mozbuild/mozbuild/configure/check_debug_ranges.py
+++ b/python/mozbuild/mozbuild/configure/check_debug_ranges.py
@@ -54,9 +54,9 @@ def main(bin, compilation_unit):
     range = get_range_for(compilation_unit, debug_info[0])
     if range is not None:
         return get_range_length(range, debug_ranges[0])
 
     return -1
 
 
 if __name__ == '__main__':
-    print main(*sys.argv[1:])
+    print(main(*sys.argv[1:]))
--- a/python/mozbuild/mozbuild/configure/libstdcxx.py
+++ b/python/mozbuild/mozbuild/configure/libstdcxx.py
@@ -71,11 +71,11 @@ def find_version(e):
     p = subprocess.Popen(['readelf', '-V', libstdcxx], stdout=subprocess.PIPE)
     versions = [parse_readelf_line(x)
                 for x in p.stdout.readlines() if 'Name: GLIBCXX' in x]
     last_version = sorted(versions, cmp = cmp_ver)[-1]
     return encode_ver(last_version)
 
 if __name__ == '__main__':
     cxx_env = os.environ['CXX']
-    print 'MOZ_LIBSTDCXX_TARGET_VERSION=%s' % find_version(cxx_env)
+    print('MOZ_LIBSTDCXX_TARGET_VERSION=%s' % find_version(cxx_env))
     host_cxx_env = os.environ.get('HOST_CXX', cxx_env)
-    print 'MOZ_LIBSTDCXX_HOST_VERSION=%s' % find_version(host_cxx_env)
+    print('MOZ_LIBSTDCXX_HOST_VERSION=%s' % find_version(host_cxx_env))
--- a/python/mozbuild/mozbuild/configure/lint_util.py
+++ b/python/mozbuild/mozbuild/configure/lint_util.py
@@ -25,17 +25,17 @@ def disassemble_as_iter(co):
         op = ord(c)
         opname = dis.opname[op]
         i += 1;
         if op >= dis.HAVE_ARGUMENT:
             arg = ord(code[i]) + ord(code[i + 1]) * 256 + extended_arg
             extended_arg = 0
             i += 2
             if op == dis.EXTENDED_ARG:
-                extended_arg = arg * 65536L
+                extended_arg = arg * 65536
                 continue
             if op in dis.hasconst:
                 yield opname, co.co_consts[arg]
             elif op in dis.hasname:
                 yield opname, co.co_names[arg]
             elif op in dis.hasjrel:
                 yield opname, i + arg
             elif op in dis.haslocal:
--- a/python/mozbuild/mozbuild/doctor.py
+++ b/python/mozbuild/mozbuild/doctor.py
@@ -207,17 +207,17 @@ class Doctor(object):
                     if not choice:
                         return {'status': 'BAD, NOT FIXED',
                                 'desc': 'lastaccess enabled systemwide'}
                     try:
                         command = 'fsutil behavior set disablelastaccess 1'.split(' ')
                         fsutil_output = subprocess.check_output(command)
                         status = 'GOOD, FIXED'
                         desc = 'lastaccess disabled systemwide'
-                    except subprocess.CalledProcessError, e:
+                    except subprocess.CalledProcessError as e:
                         desc = 'lastaccess enabled systemwide'
                         if e.output.find('denied') != -1:
                             status = 'BAD, FIX DENIED'
                             denied = True
                         else:
                             status = 'BAD, NOT FIXED'
                 else:
                     status = 'BAD, FIXABLE'
--- a/python/mozbuild/mozbuild/jar.py
+++ b/python/mozbuild/mozbuild/jar.py
@@ -367,17 +367,17 @@ class JarMaker(object):
 
         jarfile = os.path.join(jardir, jarinfo.base, jarinfo.name)
         jf = None
         if self.outputFormat == 'jar':
             # jar
             jarfilepath = jarfile + '.jar'
             try:
                 os.makedirs(os.path.dirname(jarfilepath))
-            except OSError, error:
+            except OSError as error:
                 if error.errno != errno.EEXIST:
                     raise
             jf = ZipFile(jarfilepath, 'a', lock=True)
             outHelper = self.OutputHelper_jar(jf)
         else:
             outHelper = getattr(self, 'OutputHelper_'
                                 + self.outputFormat)(jarfile)
 
@@ -509,44 +509,44 @@ class JarMaker(object):
             return getModTime(os.path.join(self.basepath, aPath))
 
         def getOutput(self, name):
             out = self.ensureDirFor(name)
 
             # remove previous link or file
             try:
                 os.remove(out)
-            except OSError, e:
+            except OSError as e:
                 if e.errno != errno.ENOENT:
                     raise
             return open(out, 'wb')
 
         def ensureDirFor(self, name):
             out = os.path.join(self.basepath, name)
             outdir = os.path.dirname(out)
             if not os.path.isdir(outdir):
                 try:
                     os.makedirs(outdir)
-                except OSError, error:
+                except OSError as error:
                     if error.errno != errno.EEXIST:
                         raise
             return out
 
     class OutputHelper_symlink(OutputHelper_flat):
         '''Subclass of OutputHelper_flat that provides a helper for
         creating a symlink including creating the parent directories.
         '''
 
         def symlink(self, src, dest):
             out = self.ensureDirFor(dest)
 
             # remove previous link or file
             try:
                 os.remove(out)
-            except OSError, e:
+            except OSError as e:
                 if e.errno != errno.ENOENT:
                     raise
             if sys.platform != 'win32':
                 os.symlink(src, out)
             else:
                 # On Win32, use ctypes to create a hardlink
                 rv = CreateHardLink(out, src, None)
                 if rv == 0:
--- a/python/mozbuild/mozbuild/preprocessor.py
+++ b/python/mozbuild/mozbuild/preprocessor.py
@@ -51,17 +51,17 @@ class Expression:
         Create a new expression with this string.
         The expression will already be parsed into an Abstract Syntax Tree.
         """
         self.content = expression_string
         self.offset = 0
         self.__ignore_whitespace()
         self.e = self.__get_logical_or()
         if self.content:
-            raise Expression.ParseError, self
+            raise Expression.ParseError(self)
 
     def __get_logical_or(self):
         """
         Production: and_cond ( '||' expression ) ?
         """
         if not len(self.content):
             return None
         rv = Expression.__AST("logical_op")
@@ -152,17 +152,17 @@ class Expression:
             if word_len:
                 value = int(self.content[:word_len])
                 rv = Expression.__ASTLeaf('int', value)
             else:
                 word_len = re.match('\w*', self.content).end()
                 if word_len:
                     rv = Expression.__ASTLeaf('string', self.content[:word_len])
                 else:
-                    raise Expression.ParseError, self
+                    raise Expression.ParseError(self)
         self.__strip(word_len)
         self.__ignore_whitespace()
         return rv
 
     def __ignore_whitespace(self):
         ws_len = re.match('\s*', self.content).end()
         self.__strip(ws_len)
         return
@@ -191,17 +191,17 @@ class Expression:
         # Helper function to evaluate __get_logical_and and __get_logical_or results
         def eval_logical_op(tok):
             left = opmap[tok[0].type](tok[0])
             right = opmap[tok[2].type](tok[2])
             if tok[1].value == '&&':
                 return left and right
             elif tok[1].value == '||':
                 return left or right
-            raise Expression.ParseError, self
+            raise Expression.ParseError(self)
 
         # Mapping from token types to evaluator functions
         # Apart from (non-)equality, all these can be simple lambda forms.
         opmap = {
           'logical_op': eval_logical_op,
           'equality': eval_equality,
           'not': lambda tok: not opmap[tok[0].type](tok[0]),
           'string': lambda tok: context[tok.value],
--- a/python/mozbuild/mozbuild/test/test_util.py
+++ b/python/mozbuild/mozbuild/test/test_util.py
@@ -105,17 +105,17 @@ class TestFileAvoidWrite(unittest.TestCa
             self.assertEqual(open('file', 'r').read(), 'foobar')
 
         class MyMockedOpen(MockedOpen):
             '''MockedOpen extension to raise an exception if something
             attempts to write in an opened file.
             '''
             def __call__(self, name, mode):
                 if 'w' in mode:
-                    raise Exception, 'Unexpected open with write mode'
+                    raise Exception('Unexpected open with write mode')
                 return MockedOpen.__call__(self, name, mode)
 
         with MyMockedOpen({'file': 'content'}):
             # Validate that MyMockedOpen works as intended
             file = FileAvoidWrite('file')
             file.write('foobar')
             self.assertRaises(Exception, file.close)
 
--- a/python/mozbuild/mozbuild/util.py
+++ b/python/mozbuild/mozbuild/util.py
@@ -147,17 +147,17 @@ class ReadOnlyDefaultDict(ReadOnlyDict):
 
 
 def ensureParentDir(path):
     """Ensures the directory parent to the given file exists."""
     d = os.path.dirname(path)
     if d and not os.path.exists(path):
         try:
             os.makedirs(d)
-        except OSError, error:
+        except OSError as error:
             if error.errno != errno.EEXIST:
                 raise
 
 
 def mkdir(path, not_indexed=False):
     """Ensure a directory exists.
 
     If ``not_indexed`` is True, an attribute is set that disables content
--- a/python/mozbuild/mozpack/archive.py
+++ b/python/mozbuild/mozpack/archive.py
@@ -1,17 +1,16 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import absolute_import
 
 import bz2
 import gzip
-import io
 import stat
 import tarfile
 
 from .files import (
     BaseFile, File,
 )
 
 # 2016-01-01T00:00:00+0000
@@ -32,17 +31,17 @@ def create_tar_from_files(fp, files):
     FUTURE accept a filename argument (or create APIs to write files)
     """
     with tarfile.open(name='', mode='w', fileobj=fp, dereference=True) as tf:
         for archive_path, f in sorted(files.items()):
             if not isinstance(f, BaseFile):
                 f = File(f)
 
             ti = tarfile.TarInfo(archive_path)
-            ti.mode = f.mode or 0644
+            ti.mode = f.mode or 0o0644
             ti.type = tarfile.REGTYPE
 
             if not ti.isreg():
                 raise ValueError('not a regular file: %s' % f)
 
             # Disallow setuid and setgid bits. This is an arbitrary restriction.
             # However, since we set uid/gid to root:root, setuid and setgid
             # would be a glaring security hole if the archive were
--- a/python/mozbuild/mozpack/files.py
+++ b/python/mozbuild/mozpack/files.py
@@ -140,23 +140,23 @@ class BaseFile(object):
         return False
 
     @staticmethod
     def normalize_mode(mode):
         # Normalize file mode:
         # - keep file type (e.g. S_IFREG)
         ret = stat.S_IFMT(mode)
         # - expand user read and execute permissions to everyone
-        if mode & 0400:
-            ret |= 0444
-        if mode & 0100:
-            ret |= 0111
-        # - keep user write permissions
-        if mode & 0200:
-            ret |= 0200
+        if mode & 0o0400:
+            ret |= 0o0444
+        if mode & 0o0100:
+            ret |= 0o0111
+         # - keep user write permissions
+        if mode & 0o0200:
+            ret |= 0o0200
         # - leave away sticky bit, setuid, setgid
         return ret
 
     def copy(self, dest, skip_if_older=True):
         '''
         Copy the BaseFile content to the destination given as a string or a
         Dest instance. Avoids replacing existing files if the BaseFile content
         matches that of the destination, or in case of plain files, if the
--- a/python/mozbuild/mozpack/mozjar.py
+++ b/python/mozbuild/mozpack/mozjar.py
@@ -396,17 +396,17 @@ class JarReader(object):
             # Creator host system. 0 is MSDOS, 3 is Unix
             host = entry['creator_version'] >> 8
             # External attributes values depend on host above. On Unix the
             # higher bits are the stat.st_mode value. On MSDOS, the lower bits
             # are the FAT attributes.
             xattr = entry['external_attr']
             # Skip directories
             if (host == 0 and xattr & 0x10) or (host == 3 and
-                                                xattr & (040000 << 16)):
+                                                xattr & (0o040000 << 16)):
                 continue
             entries[entry['filename']] = entry
             if entry['offset'] < preload:
                 self._last_preloaded = entry['filename']
         self._entries = entries
         return entries
 
     @property
@@ -633,17 +633,17 @@ class JarWriter(object):
                                      type(data))
         # Fill a central directory entry for this new member.
         entry = JarCdirEntry()
         entry['creator_version'] = 20
         if mode is not None:
             # Set creator host system (upper byte of creator_version)
             # to 3 (Unix) so mode is honored when there is one.
             entry['creator_version'] |= 3 << 8
-            entry['external_attr'] = (mode & 0xFFFF) << 16L
+            entry['external_attr'] = (mode & 0xFFFF) << 16
         if deflater.compressed:
             entry['min_version'] = 20  # Version 2.0 supports deflated streams
             entry['general_flag'] = 2  # Max compression
             entry['compression'] = deflater.compress
         else:
             entry['min_version'] = 10  # Version 1.0 for stored streams
             entry['general_flag'] = 0
             entry['compression'] = JAR_STORED