diff options
Diffstat (limited to 'user')
-rw-r--r-- | user/thunderbird/APKBUILD | 34 | ||||
-rw-r--r-- | user/thunderbird/python3.patch | 10079 |
2 files changed, 10110 insertions, 3 deletions
diff --git a/user/thunderbird/APKBUILD b/user/thunderbird/APKBUILD index f516c34be..6b5c8b8fd 100644 --- a/user/thunderbird/APKBUILD +++ b/user/thunderbird/APKBUILD @@ -1,7 +1,7 @@ # Contributor: A. Wilcox <awilfox@adelielinux.org> # Maintainer: A. Wilcox <awilfox@adelielinux.org> pkgname=thunderbird -pkgver=52.6.0 +pkgver=52.9.0 pkgrel=0 pkgdesc="Email client from Mozilla" url="https://www.mozilla.org/thunderbird/" @@ -13,7 +13,7 @@ depends="" # system-libs # actual deps makedepends=" - autoconf2.13 debianutils-which perl python2 + autoconf2.13 ncurses-dev perl cmd:which alsa-lib-dev bzip2-dev icu-dev libevent-dev libffi-dev libpng-dev libjpeg-turbo-dev libvpx-dev nspr-dev nss-dev pulseaudio-dev zlib-dev @@ -41,6 +41,28 @@ somask="liblgpllibs.so libxul.so" _tbirddir=/usr/lib/${pkgname}-${pkgver} +unpack() { + default_unpack + # just ripped from Firefox's APKBUILD... + [ -z $SKIP_PYTHON ] || return 0 + msg "Killing all remaining hope for humanity and building Python 2..." + cd "$srcdir" + [ -d python ] && rm -r python + mkdir python + cd python + # 19:39 <+solar> just make the firefox build process build its own py2 copy + curl -O https://www.python.org/ftp/python/2.7.15/Python-2.7.15.tar.xz + tar xJf Python-2.7.15.tar.xz + cd Python-2.7.15 + # 20:03 <calvin> TheWilfox: there's always violence + ./configure --prefix="$srcdir/python" + make -j $JOBS + # 6 tests failed: + # test__locale test_os test_posix test_re test_strptime test_time + # make test + make -j $JOBS install +} + prepare() { default_prepare cp "$srcdir"/stab.h "$builddir"/mozilla/toolkit/crashreporter/google-breakpad/src/ @@ -48,6 +70,10 @@ prepare() { echo "ac_add_options --enable-optimize=\"$CFLAGS\"" >> "$builddir"/mozconfig echo "ac_add_options --host=\"$CHOST\"" >> "$builddir"/mozconfig echo "ac_add_options --target=\"$CTARGET\"" >> "$builddir"/mozconfig + # too much memory + if [ -z "$JOBS" -o $JOBS -gt 32 ]; then + echo "mk_add_options MOZ_MAKE_FLAGS=\"-j32\"" >> "$builddir"/mozconfig + fi } build() { @@ -59,11 +85,13 @@ build() { export LDFLAGS="$LDFLAGS -Wl,-rpath,${_tbirddir}" export USE_SHORT_LIBNAME=1 + export PATH="$srcdir/python/bin:$PATH" ./mozilla/mach build } package() { cd "$builddir" + export PATH="$srcdir/python/bin:$PATH" DESTDIR="$pkgdir" ./mozilla/mach install install -D -m644 "$srcdir"/thunderbird.desktop \ "$pkgdir"/usr/share/applications/thunderbird.desktop @@ -80,7 +108,7 @@ dev() { mv "$pkgdir"/usr/share/idl "$subpkgdir"/usr/share } -sha512sums="80742c95ed61d1cb2e72b71bb23bdd211a40240ab4393e9f028a38f902547372084a8f56445e2394484be088a7b9801405f3d6618fb2742601cc968bf34427f0 thunderbird-52.6.0.source.tar.xz +sha512sums="2142ba7cc04f48a9ffa17ad8f3a0d761f90416c9e6a7066be662a09b19846f13f0fb9669356ccbbf576744a83143cd659c28ce034679c4d6377004f428932dc1 thunderbird-52.9.0.source.tar.xz 000b4403bfac4a6192ebe36a734ef3e464f3bdd3bc797e87bc487b4d9d93cd4b41137d82726617205e39f7aedf8bf2dfb11645db24a8b0b0137a141c9133f151 mozconfig 9b11ba43f1f3fe9cda69b6b92e2073ea5165a47e30084537f396ceb8fb63573c4eb057251644837504aa4546183dc8f77fbb24f1450b6a15a1386f29180deefc bad-google-code.patch 2f52fcd7c42f8e12c955e05aa12449aa486c5347d2a7406ff0dada66f64079152b18c3f65c43410df372e871488f17889bc337ced37d0b76305afdbcb55cb580 fix-seccomp-bpf.patch diff --git a/user/thunderbird/python3.patch b/user/thunderbird/python3.patch new file mode 100644 index 000000000..2a4835fb7 --- /dev/null +++ b/user/thunderbird/python3.patch @@ -0,0 +1,10079 @@ +--- thunderbird-52.9.0/mozilla/python/mozbuild/dumbmake/dumbmake.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/dumbmake/dumbmake.py (refactored) +@@ -2,7 +2,7 @@ + # 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, unicode_literals ++ + + from collections import OrderedDict + from itertools import groupby +@@ -36,7 +36,7 @@ + deps = {} + + for i, (indent, target) in enumerate(pairs): +- if not deps.has_key(target): ++ if target not in deps: + deps[target] = [] + + for j in range(i+1, len(pairs)): +@@ -68,7 +68,7 @@ + del all_targets[dependency] + all_targets[dependency] = True + +- return all_targets.keys() ++ return list(all_targets.keys()) + + def get_components(path): + """Take a path and return all the components of the path.""" +@@ -114,7 +114,7 @@ + make_dirs[make_dir] = True + + all_components = [] +- for make_dir in make_dirs.iterkeys(): ++ for make_dir in make_dirs.keys(): + all_components.extend(get_components(make_dir)) + + for i in all_dependencies(*all_components, dependency_map=dependency_map): +--- thunderbird-52.9.0/mozilla/python/mozbuild/dumbmake/test/test_dumbmake.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/dumbmake/test/test_dumbmake.py (refactored) +@@ -1,7 +1,7 @@ + # 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 unicode_literals ++ + + import unittest + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/android_version_code.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/android_version_code.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function ++ + + import argparse + import math +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/artifacts.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/artifacts.py (refactored) +@@ -40,7 +40,7 @@ + ''' + + +-from __future__ import absolute_import, print_function, unicode_literals ++ + + import collections + import functools +@@ -57,7 +57,7 @@ + import subprocess + import tarfile + import tempfile +-import urlparse ++import urllib.parse + import zipfile + + import pylru +@@ -183,7 +183,7 @@ + + with JarWriter(file=processed_filename, optimize=False, compress_level=5) as writer: + reader = JarReader(filename) +- for filename, entry in reader.entries.iteritems(): ++ for filename, entry in reader.entries.items(): + for pattern, (src_prefix, dest_prefix) in self.test_artifact_patterns: + if not mozpath.match(filename, pattern): + continue +@@ -552,7 +552,7 @@ + + def print_cache(self): + with self: +- for item in self._cache.items(): ++ for item in list(self._cache.items()): + self.log(logging.INFO, 'artifact', + {'item': item}, + '{item}') +@@ -565,7 +565,7 @@ + # We use the persisted LRU caches to our advantage. The first item is + # most recent. + with self: +- item = next(self._cache.items(), None) ++ item = next(list(self._cache.items()), None) + if item is not None: + (name, args, sorted_kwargs), result = item + self.print_last_item(args, sorted_kwargs, result) +@@ -593,10 +593,10 @@ + 'changeset={changeset}&version=2&tipsonly=1') + req = requests.get(cset_url_tmpl.format(tree=tree, changeset=revision), + headers={'Accept': 'application/json'}) +- if req.status_code not in range(200, 300): ++ if req.status_code not in list(range(200, 300)): + raise ValueError + result = req.json() +- [found_pushid] = result['pushes'].keys() ++ [found_pushid] = list(result['pushes'].keys()) + return int(found_pushid) + + @cachedmethod(operator.attrgetter('_cache')) +@@ -609,7 +609,7 @@ + headers={'Accept': 'application/json'}) + result = req.json() + return [ +- p['changesets'][-1] for p in result['pushes'].values() ++ p['changesets'][-1] for p in list(result['pushes'].values()) + ] + + class TaskCache(CacheManager): +@@ -847,7 +847,7 @@ + + candidate_pushheads = collections.defaultdict(list) + +- for tree, pushid in found_pushids.iteritems(): ++ for tree, pushid in found_pushids.items(): + end = pushid + start = pushid - NUM_PUSHHEADS_TO_QUERY_PER_PARENT + +@@ -1052,7 +1052,7 @@ + """ + if source and os.path.isfile(source): + return self.install_from_file(source, distdir) +- elif source and urlparse.urlparse(source).scheme: ++ elif source and urllib.parse.urlparse(source).scheme: + return self.install_from_url(source, distdir) + else: + if source is None and 'MOZ_ARTIFACT_REVISION' in os.environ: +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/base.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/base.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + import json + import logging +@@ -482,7 +482,7 @@ + for flag in flags: + if flag == '-j': + try: +- flag = flags.next() ++ flag = next(flags) + except StopIteration: + break + try: +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/config_status.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/config_status.py (refactored) +@@ -6,7 +6,7 @@ + # drop-in replacement for autoconf 2.13's config.status, with features + # borrowed from autoconf > 2.5, and additional features. + +-from __future__ import absolute_import, print_function ++ + + import logging + import os +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/doctor.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/doctor.py (refactored) +@@ -2,7 +2,7 @@ + # 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 os + import subprocess +@@ -83,7 +83,7 @@ + valid = False + while not valid and limit > 0: + try: +- choice = strtobool(raw_input(prompt + '[Y/N]\n')) ++ choice = strtobool(input(prompt + '[Y/N]\n')) + valid = True + except ValueError: + print("ERROR! Please enter a valid option!") +@@ -103,11 +103,11 @@ + if status == 'SKIPPED': + continue + self.results.append(result) +- print('%s...\t%s\n' % ( ++ print(('%s...\t%s\n' % ( + result.get('desc', ''), + status + ) +- ).expandtabs(40) ++ ).expandtabs(40)) + + @property + def platform(self): +@@ -212,7 +212,7 @@ + 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' +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/dotproperties.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/dotproperties.py (refactored) +@@ -5,7 +5,7 @@ + # This file contains utility functions for reading .properties files, like + # region.properties. + +-from __future__ import absolute_import, unicode_literals ++ + + import codecs + import re +@@ -14,7 +14,7 @@ + if sys.version_info[0] == 3: + str_type = str + else: +- str_type = basestring ++ str_type = str + + class DotProperties: + r'''A thin representation of a key=value .properties file.''' +@@ -52,7 +52,7 @@ + if not prefix.endswith('.'): + prefix = prefix + '.' + indexes = [] +- for k, v in self._properties.iteritems(): ++ for k, v in self._properties.items(): + if not k.startswith(prefix): + continue + key = k[len(prefix):] +@@ -73,7 +73,7 @@ + if not prefix.endswith('.'): + prefix = prefix + '.' + +- D = dict((k[len(prefix):], v) for k, v in self._properties.iteritems() ++ D = dict((k[len(prefix):], v) for k, v in self._properties.items() + if k.startswith(prefix) and '.' not in k[len(prefix):]) + + for required_key in required_keys: +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/html_build_viewer.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/html_build_viewer.py (refactored) +@@ -4,16 +4,16 @@ + + # This module contains code for running an HTTP server to view build info. + +-from __future__ import absolute_import, unicode_literals + +-import BaseHTTPServer ++ ++import http.server + import json + import os + + import requests + + +-class HTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler): ++class HTTPHandler(http.server.BaseHTTPRequestHandler): + def do_GET(self): + s = self.server.wrapper + p = self.path +@@ -92,7 +92,7 @@ + self.doc_root = doc_root + self.json_files = {} + +- self.server = BaseHTTPServer.HTTPServer((address, port), HTTPHandler) ++ self.server = http.server.HTTPServer((address, port), HTTPHandler) + self.server.wrapper = self + self.do_shutdown = False + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/jar.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/jar.py (refactored) +@@ -8,7 +8,7 @@ + See the documentation for jar.mn on MDC for further details on the format. + ''' + +-from __future__ import absolute_import ++ + + import sys + import os +@@ -17,7 +17,7 @@ + import logging + from time import localtime + from MozZipFile import ZipFile +-from cStringIO import StringIO ++from io import StringIO + from collections import defaultdict + + from mozbuild.preprocessor import Preprocessor +@@ -302,9 +302,9 @@ + '''updateManifest replaces the % in the chrome registration entries + with the given chrome base path, and updates the given manifest file. + ''' +- myregister = dict.fromkeys(map(lambda s: s.replace('%', +- chromebasepath), register)) +- addEntriesToListFile(manifestPath, myregister.iterkeys()) ++ myregister = dict.fromkeys([s.replace('%', ++ chromebasepath) for s in register]) ++ addEntriesToListFile(manifestPath, iter(myregister.keys())) + + def makeJar(self, infile, jardir): + '''makeJar is the main entry point to JarMaker. +@@ -322,7 +322,7 @@ + elif self.relativesrcdir: + self.localedirs = \ + self.generateLocaleDirs(self.relativesrcdir) +- if isinstance(infile, basestring): ++ if isinstance(infile, str): + logging.info('processing ' + infile) + self.sourcedirs.append(_normpath(os.path.dirname(infile))) + pp = self.pp.clone() +@@ -372,7 +372,7 @@ + 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) +@@ -514,7 +514,7 @@ + # 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') +@@ -525,7 +525,7 @@ + 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 +@@ -541,7 +541,7 @@ + # 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': +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/mach_commands.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/mach_commands.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + import argparse + import errno +@@ -136,7 +136,7 @@ + # terminal is a blessings.Terminal. + self._t = terminal + self._fh = sys.stdout +- self.tiers = monitor.tiers.tier_status.viewitems() ++ self.tiers = monitor.tiers.tier_status.items() + + def clear(self): + """Removes the footer from the current terminal.""" +@@ -802,7 +802,7 @@ + dirpath = None + + type_counts = database.type_counts(dirpath) +- sorted_counts = sorted(type_counts.iteritems(), ++ sorted_counts = sorted(iter(type_counts.items()), + key=operator.itemgetter(1)) + + total = 0 +@@ -957,7 +957,7 @@ + processes[i].run() + + exit_code = 0 +- for process in processes.values(): ++ for process in list(processes.values()): + status = process.wait() + if status: + exit_code = status +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/makeutil.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/makeutil.py (refactored) +@@ -2,7 +2,7 @@ + # 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 os + import re +@@ -66,7 +66,7 @@ + self._list = [] + self._set = set() + +- def __nonzero__(self): ++ def __bool__(self): + return bool(self._set) + + def __iter__(self): +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/milestone.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/milestone.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + import argparse + import os +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/mozconfig.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/mozconfig.py (refactored) +@@ -2,7 +2,7 @@ + # 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, unicode_literals ++ + + import filecmp + import os +@@ -306,7 +306,7 @@ + + # Environment variables also appear as shell variables, but that's + # uninteresting duplication of information. Filter them out. +- filt = lambda x, y: {k: v for k, v in x.items() if k not in y} ++ filt = lambda x, y: {k: v for k, v in list(x.items()) if k not in y} + result['vars'] = diff_vars( + filt(parsed['vars_before'], parsed['env_before']), + filt(parsed['vars_after'], parsed['env_after']) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/mozinfo.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/mozinfo.py (refactored) +@@ -5,7 +5,7 @@ + # This module produces a JSON file that provides basic build info and + # configuration metadata. + +-from __future__ import absolute_import ++ + + import os + import re +@@ -154,7 +154,7 @@ + and what keys are produced. + """ + build_conf = build_dict(config, env) +- if isinstance(file, basestring): ++ if isinstance(file, str): + file = open(file, 'wb') + + json.dump(build_conf, file, sort_keys=True, indent=4) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/preprocessor.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/preprocessor.py (refactored) +@@ -27,7 +27,8 @@ + import re + from optparse import OptionParser + import errno +-from makeutil import Makefile ++from .makeutil import Makefile ++from functools import reduce + + # hack around win32 mangling our line endings + # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65443 +@@ -56,7 +57,7 @@ + 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): + """ +@@ -157,7 +158,7 @@ + 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 +@@ -196,7 +197,7 @@ + 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. +@@ -230,7 +231,7 @@ + def __repr__(self): + return self.value.__repr__() + +- class ParseError(StandardError): ++ class ParseError(Exception): + """ + Error raised when parsing fails. + It has two members, offset and content, which give the offset of the +@@ -278,7 +279,7 @@ + self.context = Context() + for k,v in {'FILE': '', + 'LINE': 0, +- 'DIRECTORY': os.path.abspath('.')}.iteritems(): ++ 'DIRECTORY': os.path.abspath('.')}.items(): + self.context[k] = v + self.actionLevel = 0 + self.disableLevel = 0 +@@ -292,21 +293,21 @@ + self.cmds = {} + for cmd, level in {'define': 0, + 'undef': 0, +- 'if': sys.maxint, +- 'ifdef': sys.maxint, +- 'ifndef': sys.maxint, ++ 'if': sys.maxsize, ++ 'ifdef': sys.maxsize, ++ 'ifndef': sys.maxsize, + 'else': 1, + 'elif': 1, + 'elifdef': 1, + 'elifndef': 1, +- 'endif': sys.maxint, ++ 'endif': sys.maxsize, + 'expand': 0, + 'literal': 0, + 'filter': 0, + 'unfilter': 0, + 'include': 0, + 'includesubst': 0, +- 'error': 0}.iteritems(): ++ 'error': 0}.items(): + self.cmds[cmd] = (level, getattr(self, 'do_' + cmd)) + self.out = sys.stdout + self.setMarker(marker) +@@ -469,7 +470,7 @@ + raise Preprocessor.Error(self, "--depend doesn't work with stdout", + None) + try: +- from makeutil import Makefile ++ from .makeutil import Makefile + except: + raise Preprocessor.Error(self, "--depend requires the " + "mozbuild.makeutil module", None) +@@ -684,7 +685,7 @@ + current = dict(self.filters) + for f in filters: + current[f] = getattr(self, 'filter_' + f) +- filterNames = current.keys() ++ filterNames = list(current.keys()) + filterNames.sort() + self.filters = [(fn, current[fn]) for fn in filterNames] + return +@@ -694,7 +695,7 @@ + for f in filters: + if f in current: + del current[f] +- filterNames = current.keys() ++ filterNames = list(current.keys()) + filterNames.sort() + self.filters = [(fn, current[fn]) for fn in filterNames] + return +@@ -739,7 +740,7 @@ + args can either be a file name, or a file-like object. + Files should be opened, and will be closed after processing. + """ +- isName = type(args) == str or type(args) == unicode ++ isName = type(args) == str or type(args) == str + oldCheckLineNumbers = self.checkLineNumbers + self.checkLineNumbers = False + if isName: +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/pythonutil.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/pythonutil.py (refactored) +@@ -2,7 +2,7 @@ + # 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 os + import sys +@@ -11,7 +11,7 @@ + def iter_modules_in_path(*paths): + paths = [os.path.abspath(os.path.normcase(p)) + os.sep + for p in paths] +- for name, module in sys.modules.items(): ++ for name, module in list(sys.modules.items()): + if not hasattr(module, '__file__'): + continue + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/shellutil.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/shellutil.py (refactored) +@@ -15,7 +15,7 @@ + # which matches the pattern and captures it in a named match group. + # The group names and patterns are given as arguments. + all_tokens = '|'.join('(?P<%s>%s)' % (name, value) +- for name, value in tokens.iteritems()) ++ for name, value in tokens.items()) + nonescaped = r'(?<!\\)(?:%s)' % all_tokens + + # The final pattern matches either the above pattern, or an escaped +@@ -96,7 +96,7 @@ + self.cline = self.cline[m.end():] + + match = {name: value +- for name, value in m.groupdict().items() if value} ++ for name, value in list(m.groupdict().items()) if value} + if 'quote' in match: + # " or ' start a quoted string + if match['quote'] == '"': +@@ -144,7 +144,7 @@ + self._push(self.cline[:m.start()]) + self.cline = self.cline[m.end():] + match = {name: value +- for name, value in m.groupdict().items() if value} ++ for name, value in list(m.groupdict().items()) if value} + if 'quote' in match: + # a double quote ends the quoted string, so go back to + # unquoted parsing +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/sphinx.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/sphinx.py (refactored) +@@ -2,7 +2,7 @@ + # 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 importlib + import os +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/testing.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/testing.py (refactored) +@@ -2,9 +2,9 @@ + # 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, unicode_literals +- +-import cPickle as pickle ++ ++ ++import pickle as pickle + import os + import sys + +@@ -62,7 +62,7 @@ + if test_defaults: + with open(test_defaults, 'rb') as fh: + defaults = pickle.load(fh) +- for path, tests in test_data.items(): ++ for path, tests in list(test_data.items()): + for metadata in tests: + if defaults: + manifest = metadata['manifest'] +@@ -303,7 +303,7 @@ + WEB_PLATFORM_TESTS_FLAVORS = ('web-platform-tests',) + + def all_test_flavors(): +- return ([v[0] for v in TEST_MANIFESTS.values()] + ++ return ([v[0] for v in list(TEST_MANIFESTS.values())] + + list(REFTEST_FLAVORS) + + list(WEB_PLATFORM_TESTS_FLAVORS) + + ['python']) +@@ -445,7 +445,7 @@ + only a few tests need to be run. + """ + flavor_info = {flavor: (root, prefix, install) +- for (flavor, root, prefix, install) in TEST_MANIFESTS.values()} ++ for (flavor, root, prefix, install) in list(TEST_MANIFESTS.values())} + objdir_dest = mozpath.join(topobjdir, tests_root) + + converter = SupportFilesConverter() +@@ -527,7 +527,7 @@ + paths_file = os.path.join(context.config.topsrcdir, "testing", + "web-platform", "tests", "tools", "localpaths.py") + _globals = {"__file__": paths_file} +- execfile(paths_file, _globals) ++ exec(compile(open(paths_file).read(), paths_file, 'exec'), _globals) + import manifest as wptmanifest + finally: + sys.path = old_path +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/util.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/util.py (refactored) +@@ -5,7 +5,7 @@ + # This file contains miscellaneous utility functions that don't belong anywhere + # in particular. + +-from __future__ import absolute_import, unicode_literals, print_function ++ + + import argparse + import collections +@@ -36,7 +36,7 @@ + if sys.version_info[0] == 3: + str_type = str + else: +- str_type = basestring ++ str_type = str + + if sys.platform == 'win32': + _kernel32 = ctypes.windll.kernel32 +@@ -78,7 +78,7 @@ + return h.hexdigest() + + +-class EmptyValue(unicode): ++class EmptyValue(str): + """A dummy type that behaves like an empty string and sequence. + + This type exists in order to support +@@ -92,7 +92,7 @@ + class ReadOnlyNamespace(object): + """A class for objects with immutable attributes set at initialization.""" + def __init__(self, **kwargs): +- for k, v in kwargs.iteritems(): ++ for k, v in kwargs.items(): + super(ReadOnlyNamespace, self).__setattr__(k, v) + + def __delattr__(self, key): +@@ -152,7 +152,7 @@ + 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 + +@@ -224,7 +224,7 @@ + self.mode = mode + + def write(self, buf): +- if isinstance(buf, unicode): ++ if isinstance(buf, str): + buf = buf.encode('utf-8') + BytesIO.write(self, buf) + +@@ -381,7 +381,7 @@ + def __add__(self, other): + # Allow None and EmptyValue is a special case because it makes undefined + # variable references in moz.build behave better. +- other = [] if isinstance(other, (types.NoneType, EmptyValue)) else other ++ other = [] if isinstance(other, (type(None), EmptyValue)) else other + if not isinstance(other, list): + raise ValueError('Only lists can be appended to lists.') + +@@ -390,7 +390,7 @@ + return new_list + + def __iadd__(self, other): +- other = [] if isinstance(other, (types.NoneType, EmptyValue)) else other ++ other = [] if isinstance(other, (type(None), EmptyValue)) else other + if not isinstance(other, list): + raise ValueError('Only lists can be appended to lists.') + +@@ -542,14 +542,14 @@ + functions below. + """ + assert isinstance(flags, dict) +- assert all(isinstance(v, type) for v in flags.values()) ++ assert all(isinstance(v, type) for v in list(flags.values())) + + class Flags(object): +- __slots__ = flags.keys() ++ __slots__ = list(flags.keys()) + _flags = flags + + def update(self, **kwargs): +- for k, v in kwargs.iteritems(): ++ for k, v in kwargs.items(): + setattr(self, k, v) + + def __getattr__(self, name): +@@ -1080,14 +1080,14 @@ + # issue. So we do a little dance to filter it out ourselves. + dummy_fill_value = ("dummy",) + def filter_out_dummy(iterable): +- return itertools.ifilter(lambda x: x != dummy_fill_value, ++ return filter(lambda x: x != dummy_fill_value, + iterable) + + # From the itertools documentation, slightly modified: + def grouper(n, iterable): + "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" + args = [iter(iterable)] * n +- return itertools.izip_longest(fillvalue=dummy_fill_value, *args) ++ return itertools.zip_longest(fillvalue=dummy_fill_value, *args) + + for i, unified_group in enumerate(grouper(files_per_unified_file, + files)): +@@ -1104,7 +1104,7 @@ + [(1,2), (3,4), (5,6)] + ''' + i = iter(iterable) +- return itertools.izip_longest(i, i) ++ return itertools.zip_longest(i, i) + + + VARIABLES_RE = re.compile('\$\((\w+)\)') +@@ -1122,7 +1122,7 @@ + value = variables.get(name) + if not value: + continue +- if not isinstance(value, types.StringTypes): ++ if not isinstance(value, (str,)): + value = ' '.join(value) + result += value + return result +@@ -1149,7 +1149,7 @@ + pass + + +-class EnumString(unicode): ++class EnumString(str): + '''A string type that only can have a limited set of values, similarly to + an Enum, and can only be compared against that set of values. + +@@ -1185,19 +1185,18 @@ + # quoting could be done with either ' or ". + if c == "'": + return "\\'" +- return unicode(c.encode('unicode_escape')) ++ return str(c.encode('unicode_escape')) + + # Mapping table between raw characters below \x80 and their escaped + # counterpart, when they differ + _INDENTED_REPR_TABLE = { + c: e +- for c, e in map(lambda x: (x, _escape_char(x)), +- map(unichr, range(128))) ++ for c, e in [(x, _escape_char(x)) for x in list(map(chr, list(range(128))))] + if c != e + } + # Regexp matching all characters to escape. + _INDENTED_REPR_RE = re.compile( +- '([' + ''.join(_INDENTED_REPR_TABLE.values()) + ']+)') ++ '([' + ''.join(list(_INDENTED_REPR_TABLE.values())) + ']+)') + + + def indented_repr(o, indent=4): +@@ -1223,7 +1222,7 @@ + elif isinstance(o, bytes): + yield 'b' + yield repr(o) +- elif isinstance(o, unicode): ++ elif isinstance(o, str): + yield "'" + # We want a readable string (non escaped unicode), but some + # special characters need escaping (e.g. \n, \t, etc.) +@@ -1253,11 +1252,11 @@ + if isinstance(obj, dict): + return { + encode(k, encoding): encode(v, encoding) +- for k, v in obj.iteritems() ++ for k, v in obj.items() + } + if isinstance(obj, bytes): + return obj +- if isinstance(obj, unicode): ++ if isinstance(obj, str): + return obj.encode(encoding) + if isinstance(obj, Iterable): + return [encode(i, encoding) for i in obj] +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/vendor_rust.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/vendor_rust.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + from distutils.version import LooseVersion + import logging +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/virtualenv.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/virtualenv.py (refactored) +@@ -5,7 +5,7 @@ + # This file contains code for populating the virtualenv environment for + # Mozilla's build system. It is typically called as part of configure. + +-from __future__ import absolute_import, print_function, unicode_literals ++ + + import distutils.sysconfig + import os +@@ -461,8 +461,8 @@ + and call .ensure() and .activate() to make the virtualenv active. + """ + +- execfile(self.activate_path, dict(__file__=self.activate_path)) +- if isinstance(os.environ['PATH'], unicode): ++ exec(compile(open(self.activate_path).read(), self.activate_path, 'exec'), dict(__file__=self.activate_path)) ++ if isinstance(os.environ['PATH'], str): + os.environ['PATH'] = os.environ['PATH'].encode('utf-8') + + def install_pip_package(self, package): +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/buildlist.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/buildlist.py (refactored) +@@ -7,7 +7,7 @@ + + Usage: buildlist.py <filename> <entry> [<entry> ...] + ''' +-from __future__ import absolute_import, print_function ++ + + import sys + import os +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/cl.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/cl.py (refactored) +@@ -2,7 +2,7 @@ + # 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 ctypes + import os +@@ -55,7 +55,7 @@ + break + + if target is None: +- print >>sys.stderr, "No target set" ++ print("No target set", file=sys.stderr) + return 1 + + # Assume the source file is the last argument +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/dump_env.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/dump_env.py (refactored) +@@ -6,5 +6,5 @@ + # native paths printed on Windows so that these paths can be incorporated + # into Python configure's environment. + import os +-for key, value in os.environ.items(): +- print('%s=%s' % (key, value)) ++for key, value in list(os.environ.items()): ++ print(('%s=%s' % (key, value))) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/explode_aar.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/explode_aar.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + import argparse + import errno +@@ -44,7 +44,7 @@ + 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: +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/file_generate.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/file_generate.py (refactored) +@@ -6,7 +6,7 @@ + # the arguments that can be used to generate the output file, call the + # script's |main| method with appropriate arguments. + +-from __future__ import absolute_import, print_function ++ + + import argparse + import imp +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/generate_suggestedsites.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/generate_suggestedsites.py (refactored) +@@ -26,7 +26,7 @@ + directory e.g. raw/suggestedsites.json, raw-pt-rBR/suggestedsites.json. + ''' + +-from __future__ import absolute_import, print_function ++ + + import argparse + import copy +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/generate_symbols_file.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/generate_symbols_file.py (refactored) +@@ -2,12 +2,12 @@ + # 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, print_function, unicode_literals ++ + + import argparse + import buildconfig + import os +-from StringIO import StringIO ++from io import StringIO + from mozbuild.preprocessor import Preprocessor + from mozbuild.util import DefinesAction + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/jar_maker.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/jar_maker.py (refactored) +@@ -2,7 +2,7 @@ + # 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 sys + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/make_dmg.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/make_dmg.py (refactored) +@@ -2,7 +2,7 @@ + # 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 print_function ++ + + from mozbuild.base import MozbuildObject + from mozpack import dmg +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/output_searchplugins_list.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/output_searchplugins_list.py (refactored) +@@ -18,4 +18,4 @@ + else: + engines = searchinfo["default"]["visibleDefaultEngines"] + +-print '\n'.join(engines) ++print('\n'.join(engines)) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/package_fennec_apk.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/package_fennec_apk.py (refactored) +@@ -6,7 +6,7 @@ + Script to produce an Android package (.apk) for Fennec. + ''' + +-from __future__ import absolute_import, print_function ++ + + import argparse + import buildconfig +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/preprocessor.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/preprocessor.py (refactored) +@@ -2,7 +2,7 @@ + # 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 sys + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/process_define_files.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/process_define_files.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + import argparse + import os +@@ -55,7 +55,7 @@ + 'CONFIGURE_DEFINE_FILE') + defines = '\n'.join(sorted( + '#define %s %s' % (name, val) +- for name, val in config.defines.iteritems() ++ for name, val in config.defines.items() + if name not in config.non_global_defines)) + l = l[:m.start('cmd') - 1] \ + + defines + l[m.end('name'):] +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/process_install_manifest.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/process_install_manifest.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + import argparse + import os +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/test_archive.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/test_archive.py (refactored) +@@ -8,7 +8,7 @@ + # It is defined inline because this was easiest to make test archive + # generation faster. + +-from __future__ import absolute_import, print_function, unicode_literals ++ + + import argparse + import itertools +@@ -433,7 +433,7 @@ + # "common" is our catch all archive and it ignores things from other archives. + # Verify nothing sneaks into ARCHIVE_FILES without a corresponding exclusion + # rule in the "common" archive. +-for k, v in ARCHIVE_FILES.items(): ++for k, v in list(ARCHIVE_FILES.items()): + # Skip mozharness because it isn't staged. + if k in ('common', 'mozharness'): + continue +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/webidl.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/webidl.py (refactored) +@@ -2,7 +2,7 @@ + # 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 sys + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/xpccheck.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/xpccheck.py (refactored) +@@ -8,7 +8,7 @@ + Usage: xpccheck.py <directory> [<directory> ...] + ''' + +-from __future__ import absolute_import ++ + + import sys + import os +@@ -40,7 +40,7 @@ + break + + if not found: +- print >>sys.stderr, "TEST-UNEXPECTED-FAIL | xpccheck | test %s is missing from test manifest %s!" % (name, os.path.join(directory, 'xpcshell.ini')) ++ print("TEST-UNEXPECTED-FAIL | xpccheck | test %s is missing from test manifest %s!" % (name, os.path.join(directory, 'xpcshell.ini')), file=sys.stderr) + sys.exit(1) + + def verifyIniFile(initests, directory): +@@ -60,12 +60,12 @@ + break + + if not found: +- print >>sys.stderr, "TEST-UNEXPECTED-FAIL | xpccheck | found %s in xpcshell.ini and not in directory '%s'" % (name, directory) ++ print("TEST-UNEXPECTED-FAIL | xpccheck | found %s in xpcshell.ini and not in directory '%s'" % (name, directory), file=sys.stderr) + sys.exit(1) + + def main(argv): + if len(argv) < 2: +- print >>sys.stderr, "Usage: xpccheck.py <topsrcdir> <directory> [<directory> ...]" ++ print("Usage: xpccheck.py <topsrcdir> <directory> [<directory> ...]", file=sys.stderr) + sys.exit(1) + + topsrcdir = argv[0] +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/xpidl-process.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/xpidl-process.py (refactored) +@@ -7,7 +7,7 @@ + # input IDL file(s). It's purpose is to directly support the build + # system. The API will change to meet the needs of the build system. + +-from __future__ import absolute_import ++ + + import argparse + import os +@@ -58,7 +58,7 @@ + + # TODO use FileAvoidWrite once it supports binary mode. + xpt_path = os.path.join(xpt_dir, '%s.xpt' % module) +- xpt_link(xpts.values()).write(xpt_path) ++ xpt_link(list(xpts.values())).write(xpt_path) + + rule.add_targets([xpt_path]) + if deps_dir: +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/zip.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/action/zip.py (refactored) +@@ -5,7 +5,7 @@ + # This script creates a zip file, but will also strip any binaries + # it finds before adding them to the zip. + +-from __future__ import absolute_import ++ + + from mozpack.files import FileFinder + from mozpack.copier import Jarrer +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/android_eclipse.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/android_eclipse.py (refactored) +@@ -2,7 +2,7 @@ + # 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, unicode_literals ++ + + import itertools + import os +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/base.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/base.py (refactored) +@@ -2,7 +2,7 @@ + # 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, unicode_literals ++ + + from abc import ( + ABCMeta, +@@ -30,15 +30,13 @@ + from mozbuild.base import ExecutionSummary + + +-class BuildBackend(LoggingMixin): ++class BuildBackend(LoggingMixin, metaclass=ABCMeta): + """Abstract base class for build backends. + + A build backend is merely a consumer of the build configuration (the output + of the frontend processing). It does something with said data. What exactly + is the discretion of the specific implementation. + """ +- +- __metaclass__ = ABCMeta + + def __init__(self, environment): + assert isinstance(environment, ConfigEnvironment) +@@ -252,7 +250,7 @@ + srcdir = mozpath.dirname(obj.input_path) + pp.context.update({ + k: ' '.join(v) if isinstance(v, list) else v +- for k, v in obj.config.substs.iteritems() ++ for k, v in obj.config.substs.items() + }) + pp.context.update( + top_srcdir=obj.topsrcdir, +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/common.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/common.py (refactored) +@@ -2,9 +2,9 @@ + # 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, unicode_literals +- +-import cPickle as pickle ++ ++ ++import pickle as pickle + import itertools + import json + import os +@@ -194,11 +194,11 @@ + def add_defaults(self, manifest): + if not hasattr(manifest, 'manifest_defaults'): + return +- for sub_manifest, defaults in manifest.manifest_defaults.items(): ++ for sub_manifest, defaults in list(manifest.manifest_defaults.items()): + self.manifest_defaults[sub_manifest] = defaults + + def add_installs(self, obj, topsrcdir): +- for src, (dest, _) in obj.installs.iteritems(): ++ for src, (dest, _) in obj.installs.items(): + key = src[len(topsrcdir)+1:] + self.installs_by_path[key].append((src, dest)) + for src, pat, dest in obj.pattern_installs: +@@ -379,7 +379,7 @@ + + path = mozpath.join(self.environment.topobjdir, 'test-installs.pkl') + with self._write_file(path, mode='rb') as fh: +- pickle.dump({k: v for k, v in self._test_manager.installs_by_path.items() ++ pickle.dump({k: v for k, v in list(self._test_manager.installs_by_path.items()) + if k in self._test_manager.deferred_installs}, + fh, + protocol=2) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/configenvironment.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/configenvironment.py (refactored) +@@ -2,7 +2,7 @@ + # 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 os + import sys +@@ -17,7 +17,7 @@ + + + if sys.version_info.major == 2: +- text_type = unicode ++ text_type = str + else: + text_type = str + +@@ -176,7 +176,7 @@ + except UnicodeDecodeError: + return v.decode('utf-8', 'replace') + +- for k, v in self.substs.items(): ++ for k, v in list(self.substs.items()): + if not isinstance(v, StringTypes): + if isinstance(v, Iterable): + type(v)(decode(i) for i in v) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/cpp_eclipse.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/cpp_eclipse.py (refactored) +@@ -2,7 +2,7 @@ + # 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 errno + import random +@@ -218,12 +218,12 @@ + cproject_header = cproject_header.replace('@MACH_COMMAND@', os.path.join(self.environment.topsrcdir, 'mach')) + fh.write(cproject_header) + +- for path, defines in self._paths_to_defines.items(): ++ for path, defines in list(self._paths_to_defines.items()): + folderinfo = CPROJECT_TEMPLATE_FOLDER_INFO_HEADER + folderinfo = folderinfo.replace('@FOLDER_ID@', str(random.randint(1000000, 99999999999))) + folderinfo = folderinfo.replace('@FOLDER_NAME@', 'tree/' + path) + fh.write(folderinfo) +- for k, v in defines.items(): ++ for k, v in list(defines.items()): + define = ET.Element('listOptionValue') + define.set('builtIn', 'false') + define.set('value', str(k) + "=" + str(v)) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/fastermake.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/fastermake.py (refactored) +@@ -2,7 +2,7 @@ + # 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, unicode_literals, print_function ++ + + from mozbuild.backend.base import PartialBackend + from mozbuild.backend.common import CommonBackend +@@ -130,12 +130,12 @@ + if value is not None: + mk.add_statement('%s = %s' % (var, value)) + +- install_manifests_bases = self._install_manifests.keys() ++ install_manifests_bases = list(self._install_manifests.keys()) + + # Add information for chrome manifest generation + manifest_targets = [] + +- for target, entries in self._manifest_entries.iteritems(): ++ for target, entries in self._manifest_entries.items(): + manifest_targets.append(target) + install_target = mozpath.basedir(target, install_manifests_bases) + self._install_manifests[install_target].add_content( +@@ -144,16 +144,16 @@ + + # Add information for install manifests. + mk.add_statement('INSTALL_MANIFESTS = %s' +- % ' '.join(self._install_manifests.keys())) ++ % ' '.join(list(self._install_manifests.keys()))) + + # Add dependencies we infered: +- for target, deps in self._dependencies.iteritems(): ++ for target, deps in self._dependencies.items(): + mk.create_rule([target]).add_dependencies( + '$(TOPOBJDIR)/%s' % d for d in deps) + + mk.add_statement('include $(TOPSRCDIR)/config/faster/rules.mk') + +- for base, install_manifest in self._install_manifests.iteritems(): ++ for base, install_manifest in self._install_manifests.items(): + with self._write_file( + mozpath.join(self.environment.topobjdir, 'faster', + 'install_%s' % base.replace('/', '_'))) as fh: +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/mach_commands.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/mach_commands.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + import argparse + import os +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/recursivemake.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/recursivemake.py (refactored) +@@ -2,7 +2,7 @@ + # 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, unicode_literals ++ + + import logging + import os +@@ -12,7 +12,7 @@ + defaultdict, + namedtuple, + ) +-from StringIO import StringIO ++from io import StringIO + from itertools import chain + + from mozpack.manifests import ( +@@ -74,6 +74,7 @@ + ) + from ..makeutil import Makefile + from mozbuild.shellutil import quote as shell_quote ++from functools import reduce + + MOZBUILD_VARIABLES = [ + b'ANDROID_APK_NAME', +@@ -214,7 +215,7 @@ + self.fh.write(buf) + + def write_once(self, buf): +- if isinstance(buf, unicode): ++ if isinstance(buf, str): + buf = buf.encode('utf-8') + if b'\n' + buf not in self.fh.getvalue(): + self.write(buf) +@@ -283,8 +284,8 @@ + Helper function to call a filter from compute_dependencies and + traverse. + """ +- return filter(current, self._traversal.get(current, +- self.SubDirectories())) ++ return list(filter(current, self._traversal.get(current, ++ self.SubDirectories()))) + + def compute_dependencies(self, filter=None): + """ +@@ -638,7 +639,7 @@ + convenience variables, and the other dependency definitions for a + hopefully proper directory traversal. + """ +- for tier, no_skip in self._no_skip.items(): ++ for tier, no_skip in list(self._no_skip.items()): + self.log(logging.DEBUG, 'fill_root_mk', { + 'number': len(no_skip), 'tier': tier + }, 'Using {number} directories during {tier}') +@@ -684,7 +685,7 @@ + for tier, filter in filters: + main, all_deps = \ + self._traversal.compute_dependencies(filter) +- for dir, deps in all_deps.items(): ++ for dir, deps in list(all_deps.items()): + if deps is not None or (dir in self._idl_dirs \ + and tier == 'export'): + rule = root_deps_mk.create_rule(['%s/%s' % (dir, tier)]) +@@ -697,7 +698,7 @@ + rule.add_dependencies('%s/%s' % (d, tier) for d in main) + + all_compile_deps = reduce(lambda x,y: x|y, +- self._compile_graph.values()) if self._compile_graph else set() ++ list(self._compile_graph.values())) if self._compile_graph else set() + compile_roots = set(self._compile_graph.keys()) - all_compile_deps + + rule = root_deps_mk.create_rule(['recurse_compile']) +@@ -839,7 +840,7 @@ + self._fill_root_mk() + + # Make the master test manifest files. +- for flavor, t in self._test_manifests.items(): ++ for flavor, t in list(self._test_manifests.items()): + install_prefix, manifests = t + manifest_stem = mozpath.join(install_prefix, '%s.ini' % flavor) + self._write_master_test_manifest(mozpath.join( +@@ -945,7 +946,7 @@ + for p in ('Makefile', 'backend.mk', '.deps/.mkdir.done'): + build_files.add_optional_exists(p) + +- for idl in manager.idls.values(): ++ for idl in list(manager.idls.values()): + self._install_manifests['dist_idl'].add_symlink(idl['source'], + idl['basename']) + self._install_manifests['dist_include'].add_optional_exists('%s.h' +@@ -992,7 +993,7 @@ + + interfaces_manifests = [] + dist_dir = mozpath.join(self.environment.topobjdir, 'dist') +- for manifest, entries in manager.interface_manifests.items(): ++ for manifest, entries in list(manager.interface_manifests.items()): + interfaces_manifests.append(mozpath.join('$(DEPTH)', manifest)) + for xpt in sorted(entries): + registered_xpt_files.add(mozpath.join( +@@ -1052,7 +1053,7 @@ + # Don't allow files to be defined multiple times unless it is allowed. + # We currently allow duplicates for non-test files or test files if + # the manifest is listed as a duplicate. +- for source, (dest, is_test) in obj.installs.items(): ++ for source, (dest, is_test) in list(obj.installs.items()): + try: + self._install_manifests['_test_files'].add_symlink(source, dest) + except ValueError: +@@ -1386,7 +1387,7 @@ + man_dir = mozpath.join(self.environment.topobjdir, '_build_manifests', + dest) + +- for k, manifest in manifests.items(): ++ for k, manifest in list(manifests.items()): + with self._write_file(mozpath.join(man_dir, k)) as fh: + manifest.write(fileobj=fh) + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/tup.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/tup.py (refactored) +@@ -2,7 +2,7 @@ + # 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, unicode_literals ++ + + import os + +@@ -253,7 +253,7 @@ + backend_file = self._get_backend_file('xpcom/xpidl') + backend_file.export_shell() + +- for module, data in sorted(manager.modules.iteritems()): ++ for module, data in sorted(manager.modules.items()): + dest, idls = data + cmd = [ + '$(PYTHON_PATH)', +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/visualstudio.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/visualstudio.py (refactored) +@@ -5,7 +5,7 @@ + # This file contains a build backend for generating Visual Studio project + # files. + +-from __future__ import absolute_import, unicode_literals ++ + + import errno + import os +@@ -218,7 +218,7 @@ + includes = [os.path.normpath(i) for i in includes] + + defines = [] +- for k, v in self._paths_to_defines.get(path, {}).items(): ++ for k, v in list(self._paths_to_defines.get(path, {}).items()): + if v is True: + defines.append(k) + else: +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/codecoverage/chrome_map.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/codecoverage/chrome_map.py (refactored) +@@ -5,7 +5,7 @@ + from collections import defaultdict + import json + import os +-import urlparse ++import urllib.parse + + from mach.config import ConfigSettings + from mach.logging import LoggingManager +@@ -42,7 +42,7 @@ + if isinstance(entry, (ManifestChrome, ManifestResource)): + if isinstance(entry, ManifestResource): + dest = entry.target +- url = urlparse.urlparse(dest) ++ url = urllib.parse.urlparse(dest) + if not url.scheme: + dest = mozpath.normpath(mozpath.join(entry.base, dest)) + if url.scheme == 'file': +@@ -99,7 +99,7 @@ + chrome_mapping = self.manifest_handler.chrome_mapping + overrides = self.manifest_handler.overrides + json.dump([ +- {k: list(v) for k, v in chrome_mapping.iteritems()}, ++ {k: list(v) for k, v in chrome_mapping.items()}, + overrides, + self._install_mapping, + ], fh, sort_keys=True, indent=2) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/codecoverage/packager.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/codecoverage/packager.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function ++ + + import argparse + import sys +@@ -12,7 +12,7 @@ + + def package_gcno_tree(root, output_file): + # XXX JarWriter doesn't support unicode strings, see bug 1056859 +- if isinstance(root, unicode): ++ if isinstance(root, str): + root = root.encode('utf-8') + + finder = FileFinder(root) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/compilation/codecomplete.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/compilation/codecomplete.py (refactored) +@@ -4,7 +4,7 @@ + + # This modules provides functionality for dealing with code completion. + +-from __future__ import absolute_import ++ + + import os + +@@ -59,5 +59,5 @@ + # Drop the first flag since that is the pathname of the compiler. + flags = (shell_split(build_vars[cc]) + shell_split(build_vars[name]))[1:] + +- print(' '.join(shell_quote(arg) +- for arg in util.sanitize_cflags(flags))) ++ print((' '.join(shell_quote(arg) ++ for arg in util.sanitize_cflags(flags)))) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/compilation/database.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/compilation/database.py (refactored) +@@ -118,7 +118,7 @@ + + db = [] + +- for (directory, filename), cmd in self._db.iteritems(): ++ for (directory, filename), cmd in self._db.items(): + env = self._envs[directory] + cmd = list(cmd) + cmd.append(filename) +@@ -151,7 +151,7 @@ + a = expand_variables(a, variables).split() + if not a: + continue +- if isinstance(a, types.StringTypes): ++ if isinstance(a, (str,)): + c.append(a) + else: + c.extend(a) +@@ -216,7 +216,7 @@ + value = cenv.substs.get(name) + if not value: + return +- if isinstance(value, types.StringTypes): ++ if isinstance(value, (str,)): + value = value.split() + db.extend(value) + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/compilation/warnings.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/compilation/warnings.py (refactored) +@@ -4,7 +4,7 @@ + + # This modules provides functionality for dealing with compiler warnings. + +-from __future__ import absolute_import, unicode_literals ++ + + import errno + import json +@@ -123,18 +123,18 @@ + + def __len__(self): + i = 0 +- for value in self._files.values(): ++ for value in list(self._files.values()): + i += len(value['warnings']) + + return i + + def __iter__(self): +- for value in self._files.values(): ++ for value in list(self._files.values()): + for warning in value['warnings']: + yield warning + + def __contains__(self, item): +- for value in self._files.values(): ++ for value in list(self._files.values()): + for warning in value['warnings']: + if warning == item: + return True +@@ -144,7 +144,7 @@ + @property + def warnings(self): + """All the CompilerWarning instances in this database.""" +- for value in self._files.values(): ++ for value in list(self._files.values()): + for w in value['warnings']: + yield w + +@@ -152,7 +152,7 @@ + """Returns a mapping of warning types to their counts.""" + + types = {} +- for value in self._files.values(): ++ for value in list(self._files.values()): + for warning in value['warnings']: + if dirpath and not mozpath.normsep(warning['filename']).startswith(dirpath): + continue +@@ -210,7 +210,7 @@ + """ + + # Need to calculate up front since we are mutating original object. +- filenames = self._files.keys() ++ filenames = list(self._files.keys()) + for filename in filenames: + if not os.path.exists(filename): + del self._files[filename] +@@ -229,10 +229,10 @@ + obj = {'files': {}} + + # All this hackery because JSON can't handle sets. +- for k, v in self._files.iteritems(): ++ for k, v in self._files.items(): + obj['files'][k] = {} + +- for k2, v2 in v.iteritems(): ++ for k2, v2 in v.items(): + normalized = v2 + + if k2 == 'warnings': +@@ -249,8 +249,8 @@ + self._files = obj['files'] + + # Normalize data types. +- for filename, value in self._files.iteritems(): +- for k, v in value.iteritems(): ++ for filename, value in self._files.items(): ++ for k, v in value.items(): + if k != 'warnings': + continue + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/__init__.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/__init__.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + import inspect + import logging +@@ -193,7 +193,7 @@ + for b in ('None', 'False', 'True', 'int', 'bool', 'any', 'all', 'len', + 'list', 'tuple', 'set', 'dict', 'isinstance', 'getattr', + 'hasattr', 'enumerate', 'range', 'zip') +- }, __import__=forbidden_import, str=unicode) ++ }, __import__=forbidden_import, str=str) + + # Expose a limited set of functions from os.path + OS = ReadOnlyNamespace(path=ReadOnlyNamespace(**{ +@@ -333,7 +333,7 @@ + if path: + self.include_file(path) + +- for option in self._options.itervalues(): ++ for option in self._options.values(): + # All options must be referenced by some @depends function + if option not in self._seen: + raise ConfigureError( +@@ -437,7 +437,7 @@ + value = PositiveOptionValue() + elif value is False or value == (): + value = NegativeOptionValue() +- elif isinstance(value, types.StringTypes): ++ elif isinstance(value, (str,)): + value = PositiveOptionValue((value,)) + elif isinstance(value, tuple): + value = PositiveOptionValue(value) +@@ -477,7 +477,7 @@ + return value + + def _dependency(self, arg, callee_name, arg_name=None): +- if isinstance(arg, types.StringTypes): ++ if isinstance(arg, (str,)): + prefix, name, values = Option.split_option(arg) + if values != (): + raise ConfigureError("Option must not contain an '='") +@@ -541,7 +541,7 @@ + ''' + when = self._normalize_when(kwargs.get('when'), 'option') + args = [self._resolve(arg) for arg in args] +- kwargs = {k: self._resolve(v) for k, v in kwargs.iteritems() ++ kwargs = {k: self._resolve(v) for k, v in kwargs.items() + if k != 'when'} + option = Option(*args, **kwargs) + if when: +@@ -622,7 +622,7 @@ + with self.only_when_impl(when): + what = self._resolve(what) + if what: +- if not isinstance(what, types.StringTypes): ++ if not isinstance(what, (str,)): + raise TypeError("Unexpected type: '%s'" % type(what).__name__) + self.include_file(what) + +@@ -640,7 +640,7 @@ + (k[:-len('_impl')], getattr(self, k)) + for k in dir(self) if k.endswith('_impl') and k != 'template_impl' + ) +- glob.update((k, v) for k, v in self.iteritems() if k not in glob) ++ glob.update((k, v) for k, v in self.items() if k not in glob) + + # Any function argument to the template must be prepared to be sandboxed. + # If the template itself returns a function (in which case, it's very +@@ -664,7 +664,7 @@ + def wrapper(*args, **kwargs): + args = [maybe_prepare_function(arg) for arg in args] + kwargs = {k: maybe_prepare_function(v) +- for k, v in kwargs.iteritems()} ++ for k, v in kwargs.items()} + ret = template(*args, **kwargs) + if isfunction(ret): + # We can't expect the sandboxed code to think about all the +@@ -696,7 +696,7 @@ + for value, required in ( + (_import, True), (_from, False), (_as, False)): + +- if not isinstance(value, types.StringTypes) and ( ++ if not isinstance(value, (str,)) and ( + required or value is not None): + raise TypeError("Unexpected type: '%s'" % type(value).__name__) + if value is not None and not self.RE_MODULE.match(value): +@@ -759,7 +759,7 @@ + name = self._resolve(name, need_help_dependency=False) + if name is None: + return +- if not isinstance(name, types.StringTypes): ++ if not isinstance(name, (str,)): + raise TypeError("Unexpected type: '%s'" % type(name).__name__) + if name in data: + raise ConfigureError( +@@ -849,7 +849,7 @@ + if isinstance(possible_reasons[0], Option): + reason = possible_reasons[0] + if not reason and (isinstance(value, (bool, tuple)) or +- isinstance(value, types.StringTypes)): ++ isinstance(value, (str,))): + # A reason can be provided automatically when imply_option + # is called with an immediate value. + _, filename, line, _, _, _ = inspect.stack()[1] +@@ -884,10 +884,10 @@ + if not inspect.isfunction(func): + raise TypeError("Unexpected type: '%s'" % type(func).__name__) + if func in self._prepared_functions: +- return func, func.func_globals ++ return func, func.__globals__ + + glob = SandboxedGlobal( +- (k, v) for k, v in func.func_globals.iteritems() ++ (k, v) for k, v in func.__globals__.items() + if (inspect.isfunction(v) and v not in self._templates) or ( + inspect.isclass(v) and issubclass(v, Exception)) + ) +@@ -908,20 +908,20 @@ + # Note this is not entirely bullet proof (if the value is e.g. a list, + # the list contents could have changed), but covers the bases. + closure = None +- if func.func_closure: ++ if func.__closure__: + def makecell(content): + def f(): + content +- return f.func_closure[0] ++ return f.__closure__[0] + + closure = tuple(makecell(cell.cell_contents) +- for cell in func.func_closure) ++ for cell in func.__closure__) + + new_func = wraps(func)(types.FunctionType( +- func.func_code, ++ func.__code__, + glob, + func.__name__, +- func.func_defaults, ++ func.__defaults__, + closure + )) + @wraps(new_func) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/check_debug_ranges.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/check_debug_ranges.py (refactored) +@@ -6,7 +6,7 @@ + # to a given compilation unit. This is used as a helper to find a bug in some + # versions of GNU ld. + +-from __future__ import absolute_import ++ + + import subprocess + import sys +@@ -59,4 +59,4 @@ + + + if __name__ == '__main__': +- print main(*sys.argv[1:]) ++ print(main(*sys.argv[1:])) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/constants.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/constants.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + from mozbuild.util import EnumString + from collections import OrderedDict +@@ -56,7 +56,7 @@ + 'x86_64': 64, + } + +-CPU = EnumString.subclass(*CPU_bitness.keys()) ++CPU = EnumString.subclass(*list(CPU_bitness.keys())) + + Endianness = EnumString.subclass( + 'big', +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/help.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/help.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + import os + from mozbuild.configure.options import Option +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/libstdcxx.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/libstdcxx.py (refactored) +@@ -13,7 +13,7 @@ + # will be used from shell, we just print the two assignments and evaluate + # them from shell. + +-from __future__ import absolute_import ++ + + import os + import subprocess +@@ -76,6 +76,6 @@ + + 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)) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/lint.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/lint.py (refactored) +@@ -2,9 +2,9 @@ + # 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, print_function, unicode_literals + +-from StringIO import StringIO ++ ++from io import StringIO + from . import ( + CombinedDependsFunction, + ConfigureError, +@@ -42,7 +42,7 @@ + # - don't use @imports + # - don't have a closure + # - don't use global variables +- if func in self._imports or func.func_closure: ++ if func in self._imports or func.__closure__: + return True + for op, arg in disassemble_as_iter(func): + if op in ('LOAD_GLOBAL', 'STORE_GLOBAL'): +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/lint_util.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/lint_util.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + import dis + import inspect +@@ -12,9 +12,9 @@ + # returns an iterator. + def disassemble_as_iter(co): + if inspect.ismethod(co): +- co = co.im_func ++ co = co.__func__ + if inspect.isfunction(co): +- co = co.func_code ++ co = co.__code__ + code = co.co_code + n = len(code) + i = 0 +@@ -30,7 +30,7 @@ + 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] +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/options.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/options.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + import os + import sys +@@ -12,7 +12,7 @@ + + def istupleofstrings(obj): + return isinstance(obj, tuple) and len(obj) and all( +- isinstance(o, types.StringTypes) for o in obj) ++ isinstance(o, (str,)) for o in obj) + + + class OptionValue(tuple): +@@ -71,7 +71,7 @@ + in the form of a tuple for when values are given to the option (in the form + --option=value[,value2...]. + ''' +- def __nonzero__(self): ++ def __bool__(self): + return True + + +@@ -96,7 +96,7 @@ + if format_data: + message = message.format(**format_data) + super(ConflictingOptionError, self).__init__(message) +- for k, v in format_data.iteritems(): ++ for k, v in format_data.items(): + setattr(self, k, v) + + +@@ -132,7 +132,7 @@ + 'At least an option name or an environment variable name must ' + 'be given') + if name: +- if not isinstance(name, types.StringTypes): ++ if not isinstance(name, (str,)): + raise InvalidOptionError('Option must be a string') + if not name.startswith('--'): + raise InvalidOptionError('Option must start with `--`') +@@ -141,7 +141,7 @@ + if not name.islower(): + raise InvalidOptionError('Option must be all lowercase') + if env: +- if not isinstance(env, types.StringTypes): ++ if not isinstance(env, (str,)): + raise InvalidOptionError( + 'Environment variable name must be a string') + if not env.isupper(): +@@ -151,8 +151,8 @@ + isinstance(nargs, int) and nargs >= 0): + raise InvalidOptionError( + "nargs must be a positive integer, '?', '*' or '+'") +- if (not isinstance(default, types.StringTypes) and +- not isinstance(default, (bool, types.NoneType)) and ++ if (not isinstance(default, (str,)) and ++ not isinstance(default, (bool, type(None))) and + not istupleofstrings(default)): + raise InvalidOptionError( + 'default must be a bool, a string or a tuple of strings') +@@ -224,7 +224,7 @@ + ', '.join("'%s'" % c for c in choices)) + elif has_choices: + maxargs = self.maxargs +- if len(choices) < maxargs and maxargs != sys.maxint: ++ if len(choices) < maxargs and maxargs != sys.maxsize: + raise InvalidOptionError('Not enough `choices` for `nargs`') + self.choices = choices + self.help = help +@@ -238,7 +238,7 @@ + where prefix is one of 'with', 'without', 'enable' or 'disable'. + The '=values' part is optional. Values are separated with commas. + ''' +- if not isinstance(option, types.StringTypes): ++ if not isinstance(option, (str,)): + raise InvalidOptionError('Option must be a string') + + elements = option.split('=', 1) +@@ -291,7 +291,7 @@ + def maxargs(self): + if isinstance(self.nargs, int): + return self.nargs +- return 1 if self.nargs == '?' else sys.maxint ++ return 1 if self.nargs == '?' else sys.maxsize + + def _validate_nargs(self, num): + minargs, maxargs = self.minargs, self.maxargs +@@ -485,5 +485,5 @@ + + def __iter__(self): + for d in (self._args, self._extra_args): +- for arg, pos in d.itervalues(): ++ for arg, pos in d.values(): + yield arg +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/util.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/util.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + import codecs + import itertools +@@ -52,7 +52,7 @@ + + def __cmp__(self, other): + # LooseVersion checks isinstance(StringType), so work around it. +- if isinstance(other, unicode): ++ if isinstance(other, str): + other = other.encode('ascii') + return LooseVersion.__cmp__(self, other) + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/controller/building.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/controller/building.py (refactored) +@@ -2,7 +2,7 @@ + # 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, unicode_literals ++ + + import getpass + import json +@@ -108,7 +108,7 @@ + """ + o = [] + +- for tier, state in self.tiers.items(): ++ for tier, state in list(self.tiers.items()): + t_entry = dict( + name=tier, + start=state['begin_time'], +@@ -643,8 +643,8 @@ + + return '\n'.join(lines) + +- def __nonzero__(self): +- relative_values = [v for k, v in self._values.items() ++ def __bool__(self): ++ relative_values = [v for k, v in list(self._values.items()) + if k not in self.ABSOLUTE_KEYS] + return (all(v >= 0 for v in relative_values) and + any(v > 0 for v in relative_values)) +@@ -666,8 +666,8 @@ + """Install test files.""" + + if self.is_clobber_needed(): +- print(INSTALL_TESTS_CLOBBER.format( +- clobber_file=os.path.join(self.topobjdir, 'CLOBBER'))) ++ print((INSTALL_TESTS_CLOBBER.format( ++ clobber_file=os.path.join(self.topobjdir, 'CLOBBER')))) + sys.exit(1) + + if not test_objs: +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/controller/clobber.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/controller/clobber.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function ++ + + r'''This module contains code for managing clobbering of the tree.''' + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/context.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/context.py (refactored) +@@ -14,7 +14,7 @@ + contain, you've come to the right place. + """ + +-from __future__ import absolute_import, unicode_literals ++ + + import os + +@@ -234,15 +234,15 @@ + This function is transactional: if setitem fails for one of the values, + the context is not updated at all.""" + if isinstance(iterable, dict): +- iterable = iterable.items() ++ iterable = list(iterable.items()) + + update = {} +- for key, value in itertools.chain(iterable, kwargs.items()): ++ for key, value in itertools.chain(iterable, list(kwargs.items())): + stored_type = self._validate(key, value) + # Don't create an instance of stored_type if coercion is needed, + # until all values are validated. + update[key] = (value, stored_type) +- for key, (value, stored_type) in update.items(): ++ for key, (value, stored_type) in list(update.items()): + if not isinstance(value, stored_type): + update[key] = stored_type(value) + else: +@@ -297,7 +297,7 @@ + self.update(value) + + +-class FinalTargetValue(ContextDerivedValue, unicode): ++class FinalTargetValue(ContextDerivedValue, str): + def __new__(cls, context, value=""): + if not value: + value = 'dist/' +@@ -307,7 +307,7 @@ + value += 'bin' + if context['DIST_SUBDIR']: + value += '/' + context['DIST_SUBDIR'] +- return unicode.__new__(cls, value) ++ return str.__new__(cls, value) + + + def Enum(*values): +@@ -355,7 +355,7 @@ + cls = SourcePath + return super(PathMeta, cls).__call__(context, value) + +-class Path(ContextDerivedValue, unicode): ++class Path(ContextDerivedValue, str, metaclass=PathMeta): + """Stores and resolves a source path relative to a given context + + This class is used as a backing type for some of the sandbox variables. +@@ -366,7 +366,6 @@ + - '!objdir/relative/paths' + - '%/filesystem/absolute/paths' + """ +- __metaclass__ = PathMeta + + def __new__(cls, context, value=None): + return super(Path, cls).__new__(cls, value) +@@ -386,7 +385,7 @@ + def __cmp__(self, other): + if isinstance(other, Path) and self.srcdir != other.srcdir: + return cmp(self.full_path, other.full_path) +- return cmp(unicode(self), other) ++ return cmp(str(self), other) + + # __cmp__ is not enough because unicode has __eq__, __ne__, etc. defined + # and __cmp__ is only used for those when they don't exist. +@@ -544,7 +543,7 @@ + __slots__ = tuple([name for name, _ in fields]) + + def __init__(self, context): +- for fname, ftype in self._fields.items(): ++ for fname, ftype in list(self._fields.items()): + if issubclass(ftype, ContextDerivedValue): + setattr(self, fname, self._fields[fname](context)) + else: +@@ -614,8 +613,8 @@ + return _TypedListWithAction + + WebPlatformTestManifest = TypedNamedTuple("WebPlatformTestManifest", +- [("manifest_path", unicode), +- ("test_root", unicode)]) ++ [("manifest_path", str), ++ ("test_root", str)]) + ManifestparserManifestList = OrderedListWithAction(read_manifestparser_manifest) + ReftestManifestList = OrderedListWithAction(read_reftest_manifest) + WptManifestList = TypedListWithAction(WebPlatformTestManifest, read_wpt_manifest) +@@ -623,12 +622,12 @@ + OrderedSourceList = ContextDerivedTypedList(SourcePath, StrictOrderingOnAppendList) + OrderedTestFlavorList = TypedList(Enum(*all_test_flavors()), + StrictOrderingOnAppendList) +-OrderedStringList = TypedList(unicode, StrictOrderingOnAppendList) ++OrderedStringList = TypedList(str, StrictOrderingOnAppendList) + DependentTestsEntry = ContextDerivedTypedRecord(('files', OrderedSourceList), + ('tags', OrderedStringList), + ('flavors', OrderedTestFlavorList)) + BugzillaComponent = TypedNamedTuple('BugzillaComponent', +- [('product', unicode), ('component', unicode)]) ++ [('product', str), ('component', str)]) + + + class Files(SubContext): +@@ -764,7 +763,7 @@ + self.test_tags |= other.test_tags + self.test_flavors |= other.test_flavors + +- for k, v in other.items(): ++ for k, v in list(other.items()): + if k == 'IMPACTED_TESTS': + self.test_files |= set(mozpath.relpath(e.full_path, e.context.config.topsrcdir) + for e in v.files) +@@ -818,7 +817,7 @@ + + bug_components = Counter() + +- for f in files.values(): ++ for f in list(files.values()): + bug_component = f.get('BUG_COMPONENT') + if bug_component: + bug_components[bug_component] += 1 +@@ -889,11 +888,11 @@ + file. + """), + +- 'ANDROID_APK_NAME': (unicode, unicode, ++ 'ANDROID_APK_NAME': (str, str, + """The name of an Android APK file to generate. + """), + +- 'ANDROID_APK_PACKAGE': (unicode, unicode, ++ 'ANDROID_APK_PACKAGE': (str, str, + """The name of the Android package to generate R.java for, like org.mozilla.gecko. + """), + +@@ -962,7 +961,7 @@ + """), + + 'GENERATED_FILES': (StrictOrderingOnAppendListWithFlagsFactory({ +- 'script': unicode, ++ 'script': str, + 'inputs': list }), list, + """Generic generated files. + +@@ -1107,7 +1106,7 @@ + """Like ``OBJDIR_FILES``, with preprocessing. Use sparingly. + """), + +- 'FINAL_LIBRARY': (unicode, unicode, ++ 'FINAL_LIBRARY': (str, str, + """Library in which the objects of the current directory will be linked. + + This variable contains the name of a library, defined elsewhere with +@@ -1158,7 +1157,7 @@ + """A list of python unit tests. + """), + +- 'HOST_LIBRARY_NAME': (unicode, unicode, ++ 'HOST_LIBRARY_NAME': (str, str, + """Name of target library generated when cross compiling. + """), + +@@ -1176,7 +1175,7 @@ + libraries that link into this library via FINAL_LIBRARY. + """), + +- 'LIBRARY_NAME': (unicode, unicode, ++ 'LIBRARY_NAME': (str, str, + """The code name of the library generated for a directory. + + By default STATIC_LIBRARY_NAME and SHARED_LIBRARY_NAME take this name. +@@ -1188,7 +1187,7 @@ + ``example/components/xpcomsample.lib`` on Windows. + """), + +- 'SHARED_LIBRARY_NAME': (unicode, unicode, ++ 'SHARED_LIBRARY_NAME': (str, str, + """The name of the static library generated for a directory, if it needs to + differ from the library code name. + +@@ -1202,7 +1201,7 @@ + Implies FORCE_SHARED_LIB. + """), + +- 'STATIC_LIBRARY_NAME': (unicode, unicode, ++ 'STATIC_LIBRARY_NAME': (str, str, + """The name of the static library generated for a directory, if it needs to + differ from the library code name. + +@@ -1238,37 +1237,37 @@ + + This variable contains a list of system libaries to link against. + """), +- 'RCFILE': (unicode, unicode, ++ 'RCFILE': (str, str, + """The program .rc file. + + This variable can only be used on Windows. + """), + +- 'RESFILE': (unicode, unicode, ++ 'RESFILE': (str, str, + """The program .res file. + + This variable can only be used on Windows. + """), + +- 'RCINCLUDE': (unicode, unicode, ++ 'RCINCLUDE': (str, str, + """The resource script file to be included in the default .res file. + + This variable can only be used on Windows. + """), + +- 'DEFFILE': (unicode, unicode, ++ 'DEFFILE': (str, str, + """The program .def (module definition) file. + + This variable can only be used on Windows. + """), + +- 'LD_VERSION_SCRIPT': (unicode, unicode, ++ 'LD_VERSION_SCRIPT': (str, str, + """The linker version script for shared libraries. + + This variable can only be used on Linux. + """), + +- 'SYMBOLS_FILE': (Path, unicode, ++ 'SYMBOLS_FILE': (Path, str, + """A file containing a list of symbols to export from a shared library. + + The given file contains a list of symbols to be exported, and is +@@ -1323,7 +1322,7 @@ + ``BIN_SUFFIX``, the name will remain unchanged. + """), + +- 'SONAME': (unicode, unicode, ++ 'SONAME': (str, str, + """The soname of the shared object currently being linked + + soname is the "logical name" of a shared object, often used to provide +@@ -1379,7 +1378,7 @@ + ``GENERATED_FILES``. + """), + +- 'PROGRAM' : (unicode, unicode, ++ 'PROGRAM' : (str, str, + """Compiled executable name. + + If the configuration token ``BIN_SUFFIX`` is set, its value will be +@@ -1387,7 +1386,7 @@ + ``BIN_SUFFIX``, ``PROGRAM`` will remain unchanged. + """), + +- 'HOST_PROGRAM' : (unicode, unicode, ++ 'HOST_PROGRAM' : (str, str, + """Compiled host executable name. + + If the configuration token ``HOST_BIN_SUFFIX`` is set, its value will be +@@ -1425,7 +1424,7 @@ + files. + """), + +- 'XPIDL_MODULE': (unicode, unicode, ++ 'XPIDL_MODULE': (str, str, + """XPCOM Interface Definition Module Name. + + This is the name of the ``.xpt`` file that is created by linking +@@ -1576,14 +1575,14 @@ + """), + + # The following variables are used to control the target of installed files. +- 'XPI_NAME': (unicode, unicode, ++ 'XPI_NAME': (str, str, + """The name of an extension XPI to generate. + + When this variable is present, the results of this directory will end up + being packaged into an extension instead of the main dist/bin results. + """), + +- 'DIST_SUBDIR': (unicode, unicode, ++ 'DIST_SUBDIR': (str, str, + """The name of an alternate directory to install files to. + + When this variable is present, the results of this directory will end up +@@ -1591,7 +1590,7 @@ + otherwise be placed. + """), + +- 'FINAL_TARGET': (FinalTargetValue, unicode, ++ 'FINAL_TARGET': (FinalTargetValue, str, + """The name of the directory to install targets to. + + The directory is relative to the top of the object directory. The +@@ -1622,7 +1621,7 @@ + + 'GYP_DIRS': (StrictOrderingOnAppendListWithFlagsFactory({ + 'variables': dict, +- 'input': unicode, ++ 'input': str, + 'sandbox_vars': dict, + 'non_unified_sources': StrictOrderingOnAppendList, + }), list, +@@ -1799,7 +1798,7 @@ + } + + # Sanity check: we don't want any variable above to have a list as storage type. +-for name, (storage_type, input_types, docs) in VARIABLES.items(): ++for name, (storage_type, input_types, docs) in list(VARIABLES.items()): + if storage_type == list: + raise RuntimeError('%s has a "list" storage type. Use "List" instead.' + % name) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/data.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/data.py (refactored) +@@ -15,7 +15,7 @@ + structures. + """ + +-from __future__ import absolute_import, unicode_literals ++ + + from mozbuild.util import StrictOrderingOnAppendList + from mozpack.chrome.manifest import ManifestEntry +@@ -186,7 +186,7 @@ + self.defines = defines + + def get_defines(self): +- for define, value in self.defines.iteritems(): ++ for define, value in self.defines.items(): + if value is True: + yield('-D%s' % define) + elif value is False: +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/emitter.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/emitter.py (refactored) +@@ -2,7 +2,7 @@ + # 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, unicode_literals ++ + + import itertools + import logging +@@ -120,8 +120,8 @@ + # arguments. This gross hack works around the problem until we + # rid ourselves of 2.6. + self.info = {} +- for k, v in mozinfo.info.items(): +- if isinstance(k, unicode): ++ for k, v in list(mozinfo.info.items()): ++ if isinstance(k, str): + k = k.encode('ascii') + self.info[k] = v + +@@ -197,7 +197,7 @@ + + def _emit_libs_derived(self, contexts): + # First do FINAL_LIBRARY linkage. +- for lib in (l for libs in self._libs.values() for l in libs): ++ for lib in (l for libs in list(self._libs.values()) for l in libs): + if not isinstance(lib, (StaticLibrary, RustLibrary)) or not lib.link_into: + continue + if lib.link_into not in self._libs: +@@ -257,12 +257,12 @@ + lib.link_into == outerlib.basename): + propagate_defines(lib, defines) + +- for lib in (l for libs in self._libs.values() for l in libs): ++ for lib in (l for libs in list(self._libs.values()) for l in libs): + if isinstance(lib, Library): + propagate_defines(lib, lib.lib_defines) + yield lib + +- for obj in self._binaries.values(): ++ for obj in list(self._binaries.values()): + yield obj + + LIBRARY_NAME_VAR = { +@@ -321,7 +321,7 @@ + libs[key] = l + if key not in libs: + libs[key] = l +- candidates = libs.values() ++ candidates = list(libs.values()) + if force_static and not candidates: + if dir: + raise SandboxValidationError( +@@ -383,9 +383,9 @@ + + def _verify_deps(self, context, crate_dir, crate_name, dependencies, description='Dependency'): + """Verify that a crate's dependencies all specify local paths.""" +- for dep_crate_name, values in dependencies.iteritems(): ++ for dep_crate_name, values in dependencies.items(): + # A simple version number. +- if isinstance(values, (str, unicode)): ++ if isinstance(values, str): + raise SandboxValidationError( + '%s %s of crate %s does not list a path' % (description, dep_crate_name, crate_name), + context) +@@ -463,7 +463,7 @@ + ' in [profile.%s] section') % (libname, profile_name), + context) + +- dependencies = set(config.get('dependencies', {}).iterkeys()) ++ dependencies = set(config.get('dependencies', {}).keys()) + + return RustLibrary(context, libname, cargo_file, crate_type, + dependencies, **static_args) +@@ -738,7 +738,7 @@ + assert not gen_sources['UNIFIED_SOURCES'] + + no_pgo = context.get('NO_PGO') +- no_pgo_sources = [f for f, flags in all_flags.iteritems() ++ no_pgo_sources = [f for f, flags in all_flags.items() + if flags.no_pgo] + if no_pgo: + if no_pgo_sources: +@@ -765,7 +765,7 @@ + + # The inverse of the above, mapping suffixes to their canonical suffix. + canonicalized_suffix_map = {} +- for suffix, alternatives in suffix_map.iteritems(): ++ for suffix, alternatives in suffix_map.items(): + alternatives.add(suffix) + for a in alternatives: + canonicalized_suffix_map[a] = suffix +@@ -786,7 +786,7 @@ + # a directory with mixed C and C++ source, but it's not that important. + cxx_sources = defaultdict(bool) + +- for variable, (klass, gen_klass, suffixes) in varmap.items(): ++ for variable, (klass, gen_klass, suffixes) in list(varmap.items()): + allowed_suffixes = set().union(*[suffix_map[s] for s in suffixes]) + + # First ensure that we haven't been given filetypes that we don't +@@ -812,7 +812,7 @@ + obj = cls(*arglist) + yield obj + +- for f, flags in all_flags.iteritems(): ++ for f, flags in all_flags.items(): + if flags.flags: + ext = mozpath.splitext(f)[1] + yield PerSourceFlag(context, f, flags.flags) +@@ -958,7 +958,7 @@ + for obj in self._handle_linkables(context, passthru, generated_files): + yield obj + +- generated_files.update(['%s%s' % (k, self.config.substs.get('BIN_SUFFIX', '')) for k in self._binaries.keys()]) ++ generated_files.update(['%s%s' % (k, self.config.substs.get('BIN_SUFFIX', '')) for k in list(self._binaries.keys())]) + + components = [] + for var, cls in ( +@@ -1055,10 +1055,10 @@ + for obj in self._process_jar_manifests(context): + yield obj + +- for name, jar in context.get('JAVA_JAR_TARGETS', {}).items(): ++ for name, jar in list(context.get('JAVA_JAR_TARGETS', {}).items()): + yield ContextWrapped(context, jar) + +- for name, data in context.get('ANDROID_ECLIPSE_PROJECT_TARGETS', {}).items(): ++ for name, data in list(context.get('ANDROID_ECLIPSE_PROJECT_TARGETS', {}).items()): + yield ContextWrapped(context, data) + + if context.get('USE_YASM') is True: +@@ -1127,7 +1127,7 @@ + script = mozpath.join(mozpath.dirname(mozpath.dirname(__file__)), + 'action', 'process_define_files.py') + yield GeneratedFile(context, script, 'process_define_file', +- unicode(path), ++ str(path), + [Path(context, path + '.in')]) + + generated_files = context.get('GENERATED_FILES') +@@ -1170,7 +1170,7 @@ + yield GeneratedFile(context, script, method, outputs, inputs) + + def _process_test_manifests(self, context): +- for prefix, info in TEST_MANIFESTS.items(): ++ for prefix, info in list(TEST_MANIFESTS.items()): + for path, manifest in context.get('%s_MANIFESTS' % prefix, []): + for obj in self._process_test_manifest(context, info, path, manifest): + yield obj +@@ -1261,7 +1261,7 @@ + + process_support_files(test) + +- for path, m_defaults in mpmanifest.manifest_defaults.items(): ++ for path, m_defaults in list(mpmanifest.manifest_defaults.items()): + process_support_files(m_defaults) + + # We also copy manifests into the output directory, +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/gyp_reader.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/gyp_reader.py (refactored) +@@ -2,7 +2,7 @@ + # 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, unicode_literals ++ + + import gyp + import sys +@@ -69,7 +69,7 @@ + + + def encode(value): +- if isinstance(value, unicode): ++ if isinstance(value, str): + return value.encode('utf-8') + return value + +@@ -87,7 +87,7 @@ + # gyp expects plain str instead of unicode. The frontend code gives us + # unicode strings, so convert them. + path = encode(path) +- str_vars = dict((name, encode(value)) for name, value in vars.items()) ++ str_vars = dict((name, encode(value)) for name, value in list(vars.items())) + + params = { + b'parallel': False, +@@ -222,7 +222,7 @@ + if not f: + continue + # the result may be a string or a list. +- if isinstance(f, types.StringTypes): ++ if isinstance(f, (str,)): + context[var].append(f) + else: + context[var].extend(f) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/mach_commands.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/mach_commands.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + from collections import defaultdict + import os +@@ -105,13 +105,13 @@ + """ + components = defaultdict(set) + try: +- for p, m in self._get_files_info(paths, rev=rev).items(): ++ for p, m in list(self._get_files_info(paths, rev=rev).items()): + components[m.get('BUG_COMPONENT')].add(p) + except InvalidPathException as e: + print(e.message) + return 1 + +- for component, files in sorted(components.items(), key=lambda x: (x is None, x)): ++ for component, files in sorted(list(components.items()), key=lambda x: (x is None, x)): + print('%s :: %s' % (component.product, component.component) if component else 'UNKNOWN') + for f in sorted(files): + print(' %s' % f) +@@ -139,7 +139,7 @@ + help='Paths whose data to query') + def file_info_test_deps(self, paths, rev=None): + try: +- for p, m in self._get_files_info(paths, rev=rev).items(): ++ for p, m in list(self._get_files_info(paths, rev=rev).items()): + print('%s:' % mozpath.relpath(p, self.topsrcdir)) + if m.test_files: + print('\tTest file patterns:') +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/reader.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/reader.py (refactored) +@@ -16,7 +16,7 @@ + It does this by examining specific variables populated during execution. + """ + +-from __future__ import absolute_import, print_function, unicode_literals ++ + + import ast + import inspect +@@ -80,11 +80,12 @@ + ) + + from mozbuild.base import ExecutionSummary ++from functools import reduce + + + if sys.version_info.major == 2: +- text_type = unicode +- type_type = types.TypeType ++ text_type = str ++ type_type = type + else: + text_type = str + type_type = type +@@ -126,7 +127,7 @@ + b'JS_STANDALONE': b'1', + }) + udict = {} +- for k, v in self.substs.items(): ++ for k, v in list(self.substs.items()): + if isinstance(v, str): + udict[k.decode('utf-8')] = v.decode('utf-8') + else: +@@ -338,7 +339,7 @@ + raise Exception('`template` is a function decorator. You must ' + 'use it as `@template` preceding a function declaration.') + +- name = func.func_name ++ name = func.__name__ + + if name in self.templates: + raise KeyError( +@@ -417,7 +418,7 @@ + klass = self._context.__class__ + self._context.__class__ = TemplateContext + # The sandbox will do all the necessary checks for these merges. +- for key, value in context.items(): ++ for key, value in list(context.items()): + if isinstance(value, dict): + self[key].update(value) + elif isinstance(value, (list, HierarchicalStringList)): +@@ -434,10 +435,10 @@ + + class TemplateFunction(object): + def __init__(self, func, sandbox): +- self.path = func.func_code.co_filename +- self.name = func.func_name +- +- code = func.func_code ++ self.path = func.__code__.co_filename ++ self.name = func.__name__ ++ ++ code = func.__code__ + firstlineno = code.co_firstlineno + lines = sandbox._current_source.splitlines(True) + lines = inspect.getblock(lines[firstlineno - 1:]) +@@ -476,8 +477,8 @@ + compile(func_ast, self.path, 'exec'), + glob, + self.name, +- func.func_defaults, +- func.func_closure, ++ func.__defaults__, ++ func.__closure__, + ) + func() + +@@ -491,11 +492,11 @@ + '__builtins__': sandbox._builtins + } + func = types.FunctionType( +- self._func.func_code, ++ self._func.__code__, + glob, + self.name, +- self._func.func_defaults, +- self._func.func_closure ++ self._func.__defaults__, ++ self._func.__closure__ + ) + sandbox.exec_function(func, args, kwargs, self.path, + becomes_current_path=False) +@@ -511,7 +512,7 @@ + def visit_Str(self, node): + # String nodes we got from the AST parser are str, but we want + # unicode literals everywhere, so transform them. +- node.s = unicode(node.s) ++ node.s = str(node.s) + return node + + def visit_Name(self, node): +@@ -644,7 +645,7 @@ + + for l in traceback.format_exception(type(self.other), self.other, + self.trace): +- s.write(unicode(l)) ++ s.write(str(l)) + + return s.getvalue() + +@@ -794,7 +795,7 @@ + s.write(' %s\n' % inner.args[2]) + s.write('\n') + close_matches = difflib.get_close_matches(inner.args[2], +- VARIABLES.keys(), 2) ++ list(VARIABLES.keys()), 2) + if close_matches: + s.write('Maybe you meant %s?\n' % ' or '.join(close_matches)) + s.write('\n') +@@ -1196,7 +1197,7 @@ + + recurse_info[d][key] = dict(sandbox.metadata[key]) + +- for path, child_metadata in recurse_info.items(): ++ for path, child_metadata in list(recurse_info.items()): + child_path = path.join('moz.build').full_path + + # Ensure we don't break out of the topsrcdir. We don't do realpath +@@ -1288,7 +1289,7 @@ + # There is room to improve this code (and the code in + # _find_relevant_mozbuilds) to better handle multiple files in the same + # directory. Bug 1136966 tracks. +- for path, mbpaths in relevants.items(): ++ for path, mbpaths in list(relevants.items()): + path_mozbuilds[path] = [mozpath.join(topsrcdir, p) for p in mbpaths] + + for i, mbpath in enumerate(mbpaths[0:-1]): +@@ -1325,7 +1326,7 @@ + all_contexts.append(context) + + result = {} +- for path, paths in path_mozbuilds.items(): ++ for path, paths in list(path_mozbuilds.items()): + result[path] = reduce(lambda x, y: x + y, (contexts[p] for p in paths), []) + + return result, all_contexts +@@ -1352,7 +1353,7 @@ + + r = {} + +- for path, ctxs in paths.items(): ++ for path, ctxs in list(paths.items()): + flags = Files(Context()) + + for ctx in ctxs: +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/sandbox.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/sandbox.py (refactored) +@@ -17,7 +17,7 @@ + user-friendly error messages in the case of errors. + """ + +-from __future__ import absolute_import, unicode_literals ++ + + import os + import sys +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/common.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/common.py (refactored) +@@ -2,7 +2,7 @@ + # 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 unicode_literals ++ + + from mach.logging import LoggingManager + +@@ -36,7 +36,7 @@ + }, **extra_substs) + + self.substs_unicode = ReadOnlyDict({k.decode('utf-8'): v.decode('utf-8', +- 'replace') for k, v in self.substs.items()}) ++ 'replace') for k, v in list(self.substs.items())}) + + self.defines = self.substs + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_base.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_base.py (refactored) +@@ -2,7 +2,7 @@ + # 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 unicode_literals ++ + + import json + import os +@@ -12,7 +12,7 @@ + import tempfile + import unittest + +-from cStringIO import StringIO ++from io import StringIO + from mozfile.mozfile import NamedTemporaryFile + + from mozunit import main +@@ -93,7 +93,7 @@ + mozconfig = os.path.join(d, 'mozconfig') + with open(mozconfig, 'wt') as fh: + fh.write('mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/foo/@CONFIG_GUESS@') +- print('Wrote mozconfig %s' % mozconfig) ++ print(('Wrote mozconfig %s' % mozconfig)) + + topobjdir = os.path.join(d, 'foo', guess) + os.makedirs(topobjdir) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_containers.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_containers.py (refactored) +@@ -152,7 +152,7 @@ + + self.assertEqual(test['foo'], 1) + +- self.assertEqual(test.keys(), ['foo', 'bar' ]) ++ self.assertEqual(list(test.keys()), ['foo', 'bar' ]) + + def test_defaults(self): + test = OrderedDefaultDict(bool, {'foo': 1 }) +@@ -161,7 +161,7 @@ + + self.assertEqual(test['qux'], False) + +- self.assertEqual(test.keys(), ['foo', 'qux' ]) ++ self.assertEqual(list(test.keys()), ['foo', 'qux' ]) + + + class TestKeyedDefaultDict(unittest.TestCase): +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_dotproperties.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_dotproperties.py (refactored) +@@ -1,11 +1,11 @@ + # -*- coding: utf-8 -*- + +-from __future__ import unicode_literals ++ + + import os + import unittest + +-from StringIO import StringIO ++from io import StringIO + + import mozpack.path as mozpath + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_expression.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_expression.py (refactored) +@@ -25,8 +25,8 @@ + + def test_in(self): + """test 'var in context' to not fall for fallback""" +- self.assert_('FAIL' in self.c) +- self.assert_('PASS' not in self.c) ++ self.assertTrue('FAIL' in self.c) ++ self.assertTrue('PASS' not in self.c) + + class TestExpression(unittest.TestCase): + """ +@@ -48,16 +48,16 @@ + + def test_not(self): + """Test for the ! operator""" +- self.assert_(Expression('!0').evaluate(self.c)) +- self.assert_(not Expression('!1').evaluate(self.c)) ++ self.assertTrue(Expression('!0').evaluate(self.c)) ++ self.assertTrue(not Expression('!1').evaluate(self.c)) + + def test_equals(self): + """ Test for the == operator""" +- self.assert_(Expression('FAIL == PASS').evaluate(self.c)) ++ self.assertTrue(Expression('FAIL == PASS').evaluate(self.c)) + + def test_notequals(self): + """ Test for the != operator""" +- self.assert_(Expression('FAIL != 1').evaluate(self.c)) ++ self.assertTrue(Expression('FAIL != 1').evaluate(self.c)) + + def test_logical_and(self): + """ Test for the && operator""" +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_jarmaker.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_jarmaker.py (refactored) +@@ -2,14 +2,14 @@ + # 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 print_function ++ + import unittest + + import os, sys, os.path, time, inspect + from filecmp import dircmp + from tempfile import mkdtemp + from shutil import rmtree, copy2 +-from StringIO import StringIO ++from io import StringIO + from zipfile import ZipFile + import mozunit + +@@ -117,12 +117,12 @@ + """Helper to report rich results on difference between two directories. + """ + def _fillDiff(self, dc, rv, basepath="{0}"): +- rv['right_only'] += map(lambda l: basepath.format(l), dc.right_only) +- rv['left_only'] += map(lambda l: basepath.format(l), dc.left_only) +- rv['diff_files'] += map(lambda l: basepath.format(l), dc.diff_files) +- rv['funny'] += map(lambda l: basepath.format(l), dc.common_funny) +- rv['funny'] += map(lambda l: basepath.format(l), dc.funny_files) +- for subdir, _dc in dc.subdirs.iteritems(): ++ rv['right_only'] += [basepath.format(l) for l in dc.right_only] ++ rv['left_only'] += [basepath.format(l) for l in dc.left_only] ++ rv['diff_files'] += [basepath.format(l) for l in dc.diff_files] ++ rv['funny'] += [basepath.format(l) for l in dc.common_funny] ++ rv['funny'] += [basepath.format(l) for l in dc.funny_files] ++ for subdir, _dc in dc.subdirs.items(): + self._fillDiff(_dc, rv, basepath.format(subdir + "/{0}")) + def allResults(self, left, right): + rv = {'right_only':[], 'left_only':[], +@@ -295,7 +295,7 @@ + ('hoge', 'foo', '2'): ('qux', 'foo', '2'), + ('hoge', 'baz'): ('qux', 'baz'), + } +- for dest, src in expected_symlinks.iteritems(): ++ for dest, src in expected_symlinks.items(): + srcpath = os.path.join(self.srcdir, *src) + destpath = os.path.join(self.builddir, 'chrome', 'test', 'dir', + *dest) +@@ -317,7 +317,7 @@ + def test_en_US(self): + jm = self.jm + jm.makeJar(self.fake_empty_file, '/NO_OUTPUT_REQUIRED') +- self.assertEquals(jm.localedirs, ++ self.assertEqual(jm.localedirs, + [ + os.path.join(os.path.abspath('/TOPSOURCEDIR'), + 'browser/locales', 'en-US') +@@ -326,13 +326,13 @@ + jm = self.jm + jm.l10nbase = '/L10N_BASE' + jm.makeJar(self.fake_empty_file, '/NO_OUTPUT_REQUIRED') +- self.assertEquals(jm.localedirs, [os.path.join('/L10N_BASE', 'browser')]) ++ self.assertEqual(jm.localedirs, [os.path.join('/L10N_BASE', 'browser')]) + def test_l10n_merge(self): + jm = self.jm + jm.l10nbase = '/L10N_BASE' + jm.l10nmerge = '/L10N_MERGE' + jm.makeJar(self.fake_empty_file, '/NO_OUTPUT_REQUIRED') +- self.assertEquals(jm.localedirs, ++ self.assertEqual(jm.localedirs, + [os.path.join('/L10N_MERGE', 'browser'), + os.path.join('/L10N_BASE', 'browser'), + os.path.join(os.path.abspath('/TOPSOURCEDIR'), +@@ -346,7 +346,7 @@ + ''') + jarcontents.name = 'override.mn' + jm.makeJar(jarcontents, '/NO_OUTPUT_REQUIRED') +- self.assertEquals(jm.localedirs, ++ self.assertEqual(jm.localedirs, + [ + os.path.join(os.path.abspath('/TOPSOURCEDIR'), + 'dom/locales', 'en-US') +@@ -360,7 +360,7 @@ + ''') + jarcontents.name = 'override.mn' + jm.makeJar(jarcontents, '/NO_OUTPUT_REQUIRED') +- self.assertEquals(jm.localedirs, [os.path.join('/L10N_BASE', 'dom')]) ++ self.assertEqual(jm.localedirs, [os.path.join('/L10N_BASE', 'dom')]) + + + if __name__ == '__main__': +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_line_endings.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_line_endings.py (refactored) +@@ -1,6 +1,6 @@ + import unittest + +-from StringIO import StringIO ++from io import StringIO + import os + import sys + import os.path +@@ -30,17 +30,17 @@ + def testMac(self): + self.createFile(['\x0D']*3) + self.pp.do_include(self.tempnam) +- self.assertEquals(self.pp.out.getvalue(), 'a\nb\nc\n') ++ self.assertEqual(self.pp.out.getvalue(), 'a\nb\nc\n') + + def testUnix(self): + self.createFile(['\x0A']*3) + self.pp.do_include(self.tempnam) +- self.assertEquals(self.pp.out.getvalue(), 'a\nb\nc\n') ++ self.assertEqual(self.pp.out.getvalue(), 'a\nb\nc\n') + + def testWindows(self): + self.createFile(['\x0D\x0A']*3) + self.pp.do_include(self.tempnam) +- self.assertEquals(self.pp.out.getvalue(), 'a\nb\nc\n') ++ self.assertEqual(self.pp.out.getvalue(), 'a\nb\nc\n') + + if __name__ == '__main__': + mozunit.main() +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_makeutil.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_makeutil.py (refactored) +@@ -11,7 +11,7 @@ + from mozunit import main + import os + import unittest +-from StringIO import StringIO ++from io import StringIO + + + class TestMakefile(unittest.TestCase): +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_mozconfig.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_mozconfig.py (refactored) +@@ -2,7 +2,7 @@ + # 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 unicode_literals ++ + + import os + import unittest +@@ -480,9 +480,9 @@ + + self.assertTrue(e.exception.message.startswith( + 'Evaluation of your mozconfig exited with an error')) +- self.assertEquals(e.exception.path, ++ self.assertEqual(e.exception.path, + mozconfig.name.replace(os.sep, '/')) +- self.assertEquals(e.exception.output, ['hello world']) ++ self.assertEqual(e.exception.output, ['hello world']) + + + if __name__ == '__main__': +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_mozinfo.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_mozinfo.py (refactored) +@@ -8,7 +8,7 @@ + import tempfile + import unittest + +-from StringIO import StringIO ++from io import StringIO + + import mozunit + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_preprocessor.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_preprocessor.py (refactored) +@@ -4,7 +4,7 @@ + + import unittest + +-from StringIO import StringIO ++from io import StringIO + import os + import shutil + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_pythonutil.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_pythonutil.py (refactored) +@@ -12,7 +12,7 @@ + def test_iter_modules_in_path(self): + mozbuild_path = os.path.normcase(os.path.dirname(os.path.dirname(__file__))) + paths = list(iter_modules_in_path(mozbuild_path)) +- self.assertEquals(sorted(paths), [ ++ self.assertEqual(sorted(paths), [ + os.path.join(os.path.abspath(mozbuild_path), '__init__.py'), + os.path.join(os.path.abspath(mozbuild_path), 'pythonutil.py'), + os.path.join(os.path.abspath(mozbuild_path), 'test', 'test_pythonutil.py'), +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_testing.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_testing.py (refactored) +@@ -2,9 +2,9 @@ + # 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 unicode_literals +- +-import cPickle as pickle ++ ++ ++import pickle as pickle + import os + import shutil + import tempfile +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_util.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/test_util.py (refactored) +@@ -3,7 +3,7 @@ + # 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 unicode_literals ++ + + import itertools + import hashlib +@@ -110,7 +110,7 @@ + ''' + 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'}): +@@ -432,7 +432,7 @@ + self.assertEqual(len(l), 0) + original = ['a', 'b', 'c'] + l = ListWithAction(['a', 'b', 'c'], action=self.action) +- expected = map(self.action, original) ++ expected = list(map(self.action, original)) + self.assertSameList(expected, l) + + with self.assertRaises(ValueError): +@@ -445,7 +445,7 @@ + l = ListWithAction(action=self.action) + original = ['a', 'b'] + l.extend(original) +- expected = map(self.action, original) ++ expected = list(map(self.action, original)) + self.assertSameList(expected, l) + + with self.assertRaises(ValueError): +@@ -455,7 +455,7 @@ + l = ListWithAction(action=self.action) + original = ['a', 'b'] + l[:] = original +- expected = map(self.action, original) ++ expected = list(map(self.action, original)) + self.assertSameList(expected, l) + + with self.assertRaises(ValueError): +@@ -465,7 +465,7 @@ + l = ListWithAction(action=self.action) + original = ['a', 'b'] + l2 = l + original +- expected = map(self.action, original) ++ expected = list(map(self.action, original)) + self.assertSameList(expected, l2) + + with self.assertRaises(ValueError): +@@ -475,7 +475,7 @@ + l = ListWithAction(action=self.action) + original = ['a', 'b'] + l += original +- expected = map(self.action, original) ++ expected = list(map(self.action, original)) + self.assertSameList(expected, l) + + with self.assertRaises(ValueError): +@@ -524,7 +524,7 @@ + + def test_strict_ordering_on_append_list_with_flags_factory_extend(self): + FooList = StrictOrderingOnAppendListWithFlagsFactory({ +- 'foo': bool, 'bar': unicode ++ 'foo': bool, 'bar': str + }) + foo = FooList(['a', 'b', 'c']) + foo['a'].foo = True +@@ -532,7 +532,7 @@ + + # Don't allow extending lists with different flag definitions. + BarList = StrictOrderingOnAppendListWithFlagsFactory({ +- 'foo': unicode, 'baz': bool ++ 'foo': str, 'baz': bool + }) + bar = BarList(['d', 'e', 'f']) + bar['d'].foo = 'foo' +@@ -752,9 +752,9 @@ + + class TypedTestStrictOrderingOnAppendList(unittest.TestCase): + def test_init(self): +- class Unicode(unicode): ++ class Unicode(str): + def __init__(self, other): +- if not isinstance(other, unicode): ++ if not isinstance(other, str): + raise ValueError() + super(Unicode, self).__init__(other) + +@@ -776,14 +776,14 @@ + + class TestTypedNamedTuple(unittest.TestCase): + def test_simple(self): +- FooBar = TypedNamedTuple('FooBar', [('foo', unicode), ('bar', int)]) ++ FooBar = TypedNamedTuple('FooBar', [('foo', str), ('bar', int)]) + + t = FooBar(foo='foo', bar=2) +- self.assertEquals(type(t), FooBar) +- self.assertEquals(t.foo, 'foo') +- self.assertEquals(t.bar, 2) +- self.assertEquals(t[0], 'foo') +- self.assertEquals(t[1], 2) ++ self.assertEqual(type(t), FooBar) ++ self.assertEqual(t.foo, 'foo') ++ self.assertEqual(t.bar, 2) ++ self.assertEqual(t[0], 'foo') ++ self.assertEqual(t[1], 2) + + FooBar('foo', 2) + +@@ -796,7 +796,7 @@ + # arguments. + t1 = ('foo', 3) + t2 = FooBar(t1) +- self.assertEquals(type(t2), FooBar) ++ self.assertEqual(type(t2), FooBar) + self.assertEqual(FooBar(t1), FooBar('foo', 3)) + + +@@ -871,18 +871,18 @@ + CompilerType = EnumString.subclass('msvc', 'gcc', 'clang', 'clang-cl') + + type = CompilerType('msvc') +- self.assertEquals(type, 'msvc') +- self.assertNotEquals(type, 'gcc') +- self.assertNotEquals(type, 'clang') +- self.assertNotEquals(type, 'clang-cl') ++ self.assertEqual(type, 'msvc') ++ self.assertNotEqual(type, 'gcc') ++ self.assertNotEqual(type, 'clang') ++ self.assertNotEqual(type, 'clang-cl') + self.assertIn(type, ('msvc', 'clang-cl')) + self.assertNotIn(type, ('gcc', 'clang')) + + with self.assertRaises(EnumStringComparisonError): +- self.assertEquals(type, 'foo') ++ self.assertEqual(type, 'foo') + + with self.assertRaises(EnumStringComparisonError): +- self.assertNotEquals(type, 'foo') ++ self.assertNotEqual(type, 'foo') + + with self.assertRaises(EnumStringComparisonError): + self.assertIn(type, ('foo', 'gcc')) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/action/test_buildlist.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/action/test_buildlist.py (refactored) +@@ -38,11 +38,11 @@ + lines = [line.rstrip() for line in f.readlines()] + f.close() + for line in lines: +- self.assert_(len(l) > 0, ++ self.assertTrue(len(l) > 0, + "ran out of expected lines! (expected '{0}', got '{1}')" + .format(l, lines)) + self.assertEqual(line, l.pop(0)) +- self.assert_(len(l) == 0, ++ self.assertTrue(len(l) == 0, + "not enough lines in file! (expected '{0}'," + " got '{1}'".format(l, lines)) + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/action/test_generate_browsersearch.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/action/test_generate_browsersearch.py (refactored) +@@ -3,7 +3,7 @@ + # Any copyright is dedicated to the Public Domain. + # http://creativecommons.org/publicdomain/zero/1.0/ + +-from __future__ import unicode_literals ++ + + import json + import os +@@ -43,8 +43,8 @@ + + def test_valid_unicode(self): + o = self._test_one('valid-zh-CN') +- self.assertEquals(o['default'], '百度') +- self.assertEquals(o['engines'], ['百度', 'Google']) ++ self.assertEqual(o['default'], '百度') ++ self.assertEqual(o['engines'], ['百度', 'Google']) + + def test_invalid_unicode(self): + with self.assertRaises(UnicodeDecodeError): +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/action/test_package_fennec_apk.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/action/test_package_fennec_apk.py (refactored) +@@ -3,7 +3,7 @@ + # Any copyright is dedicated to the Public Domain. + # http://creativecommons.org/publicdomain/zero/1.0/ + +-from __future__ import unicode_literals ++ + + import os + import unittest +@@ -41,14 +41,14 @@ + root_files=[data('root_file.txt')]) + + # omni.ja ends up in assets/omni.ja. +- self.assertEquals(jarrer['assets/omni.ja'].open().read().strip(), 'omni.ja') ++ self.assertEqual(jarrer['assets/omni.ja'].open().read().strip(), 'omni.ja') + + # Everything else is in place. + for name in ('classes.dex', + 'assets/asset.txt', + 'lib/lib.txt', + 'root_file.txt'): +- self.assertEquals(jarrer[name].open().read().strip(), name) ++ self.assertEqual(jarrer[name].open().read().strip(), name) + + def test_inputs(self): + # Language repacks take updated resources from an ap_ and pack them +@@ -57,8 +57,8 @@ + # overrides the first. + jarrer = package(inputs=[data('input2.apk'), data('input1.ap_')]) + +- files1 = JarReader(data('input1.ap_')).entries.keys() +- files2 = JarReader(data('input2.apk')).entries.keys() ++ files1 = list(JarReader(data('input1.ap_')).entries.keys()) ++ files2 = list(JarReader(data('input2.apk')).entries.keys()) + for name in files2: + self.assertTrue(name in files1 or + jarrer[name].open().read().startswith('input2/')) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/backend/common.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/backend/common.py (refactored) +@@ -2,7 +2,7 @@ + # 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 unicode_literals ++ + + import os + import unittest +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/backend/test_android_eclipse.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/backend/test_android_eclipse.py (refactored) +@@ -2,7 +2,7 @@ + # 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 unicode_literals ++ + + import json + import os +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/backend/test_build.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/backend/test_build.py (refactored) +@@ -2,7 +2,7 @@ + # 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 unicode_literals, print_function ++ + + import buildconfig + import os +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/backend/test_configenvironment.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/backend/test_configenvironment.py (refactored) +@@ -3,7 +3,7 @@ + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + + import os, posixpath +-from StringIO import StringIO ++from io import StringIO + import unittest + from mozunit import main, MockedOpen + +@@ -29,7 +29,7 @@ + self.substs = ReadOnlyDict(d) + + d = dict(self.substs_unicode) +- d[u'top_srcdir'] = top_srcdir.decode('utf-8') ++ d['top_srcdir'] = top_srcdir.decode('utf-8') + self.substs_unicode = ReadOnlyDict(d) + + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/backend/test_recursivemake.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/backend/test_recursivemake.py (refactored) +@@ -2,9 +2,9 @@ + # 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 unicode_literals +- +-import cPickle as pickle ++ ++ ++import pickle as pickle + import json + import os + import unittest +@@ -331,7 +331,7 @@ + ], + } + +- for var, val in expected.items(): ++ for var, val in list(expected.items()): + # print("test_variable_passthru[%s]" % (var)) + found = [str for str in lines if str.startswith(var)] + self.assertEqual(found, val) +@@ -370,7 +370,7 @@ + ], + } + +- for var, val in expected.items(): ++ for var, val in list(expected.items()): + found = [str for str in lines if str.startswith(var)] + self.assertEqual(found, val) + +@@ -544,7 +544,7 @@ + + # This is not the most robust test in the world, but it gets the job + # done. +- entries = [e for e in m._dests.keys() if '**' in e] ++ entries = [e for e in list(m._dests.keys()) if '**' in e] + self.assertEqual(len(entries), 1) + self.assertIn('support/**', entries[0]) + +@@ -562,7 +562,7 @@ + set(['child/test_sub.js', + 'child/data/**', + 'child/another-file.sjs'])) +- for key in test_installs.keys(): ++ for key in list(test_installs.keys()): + self.assertIn(key, test_installs) + + test_files_manifest = mozpath.join(env.topobjdir, +@@ -576,7 +576,7 @@ + # Then, synthesize one from the test-installs.pkl file. This should + # allow us to re-create a subset of the above. + synthesized_manifest = InstallManifest() +- for item, installs in test_installs.items(): ++ for item, installs in list(test_installs.items()): + for install_info in installs: + if len(install_info) == 3: + synthesized_manifest.add_pattern_symlink(*install_info) +@@ -584,7 +584,7 @@ + synthesized_manifest.add_symlink(*install_info) + + self.assertEqual(len(synthesized_manifest), 3) +- for item, info in synthesized_manifest._dests.items(): ++ for item, info in list(synthesized_manifest._dests.items()): + self.assertIn(item, m) + self.assertEqual(info, m._dests[item]) + +@@ -758,7 +758,7 @@ + expected[mozpath.join(env.topobjdir, 'final-target')] = [ + 'FINAL_TARGET = $(DEPTH)/random-final-target' + ] +- for key, expected_rules in expected.iteritems(): ++ for key, expected_rules in expected.items(): + backend_path = mozpath.join(key, 'backend.mk') + lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:]] + found = [str for str in lines if +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/backend/test_visualstudio.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/backend/test_visualstudio.py (refactored) +@@ -2,7 +2,7 @@ + # 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 unicode_literals ++ + + from xml.dom.minidom import parse + import os +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/common.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/common.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + import copy + import errno +@@ -16,7 +16,7 @@ + from mozbuild.util import ReadOnlyNamespace + from mozpack import path as mozpath + +-from StringIO import StringIO ++from io import StringIO + from which import WhichError + + from buildconfig import ( +@@ -78,10 +78,10 @@ + self._search_path = environ.get('PATH', '').split(os.pathsep) + + self._subprocess_paths = { +- mozpath.abspath(k): v for k, v in paths.iteritems() if v ++ mozpath.abspath(k): v for k, v in paths.items() if v + } + +- paths = paths.keys() ++ paths = list(paths.keys()) + + environ = dict(environ) + if 'CONFIG_SHELL' not in environ: +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/lint.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/lint.py (refactored) +@@ -2,11 +2,11 @@ + # 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, print_function, unicode_literals ++ + + import os + import unittest +-from StringIO import StringIO ++from io import StringIO + from mozunit import main + from buildconfig import ( + topobjdir, +@@ -42,9 +42,7 @@ + return type.__new__(mcs, name, bases, attrs) + + +-class Lint(unittest.TestCase): +- __metaclass__ = LintMeta +- ++class Lint(unittest.TestCase, metaclass=LintMeta): + def setUp(self): + self._curdir = os.getcwd() + os.chdir(topobjdir) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_checks_configure.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_checks_configure.py (refactored) +@@ -2,9 +2,9 @@ + # 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, print_function, unicode_literals +- +-from StringIO import StringIO ++ ++ ++from io import StringIO + import os + import sys + import textwrap +@@ -447,7 +447,7 @@ + checking for a... %s + ''' % self.OTHER_A)) + +- dirs = map(mozpath.dirname, (self.OTHER_A, self.KNOWN_A)) ++ dirs = list(map(mozpath.dirname, (self.OTHER_A, self.KNOWN_A))) + config, out, status = self.get_result(textwrap.dedent('''\ + check_prog("A", ("known-a",), paths=["%s"]) + ''' % os.pathsep.join(dirs))) +@@ -457,7 +457,7 @@ + checking for a... %s + ''' % self.OTHER_A)) + +- dirs = map(mozpath.dirname, (self.KNOWN_A, self.KNOWN_B)) ++ dirs = list(map(mozpath.dirname, (self.KNOWN_A, self.KNOWN_B))) + config, out, status = self.get_result(textwrap.dedent('''\ + check_prog("A", ("known-a",), paths=["%s", "%s"]) + ''' % (os.pathsep.join(dirs), self.OTHER_A))) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_compile_checks.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_compile_checks.py (refactored) +@@ -2,14 +2,14 @@ + # 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, print_function, unicode_literals ++ + + import os + import textwrap + import unittest + import mozpack.path as mozpath + +-from StringIO import StringIO ++from io import StringIO + + from buildconfig import topsrcdir + from common import ConfigureTestSandbox +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_configure.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_configure.py (refactored) +@@ -2,9 +2,9 @@ + # 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, print_function, unicode_literals +- +-from StringIO import StringIO ++ ++ ++from io import StringIO + import os + import sys + import textwrap +@@ -43,7 +43,7 @@ + + if '--help' in options: + return out.getvalue(), config +- self.assertEquals('', out.getvalue()) ++ self.assertEqual('', out.getvalue()) + return config + + def moz_configure(self, source): +@@ -55,7 +55,7 @@ + def test_defaults(self): + config = self.get_config() + self.maxDiff = None +- self.assertEquals({ ++ self.assertEqual({ + 'CHOICES': NegativeOptionValue(), + 'DEFAULTED': PositiveOptionValue(('not-simple',)), + 'IS_GCC': NegativeOptionValue(), +@@ -71,9 +71,9 @@ + def test_help(self): + help, config = self.get_config(['--help'], prog='configure') + +- self.assertEquals({}, config) ++ self.assertEqual({}, config) + self.maxDiff = None +- self.assertEquals( ++ self.assertEqual( + 'Usage: configure [options]\n' + '\n' + 'Options: [defaults in brackets after descriptions]\n' +@@ -109,7 +109,7 @@ + ): + self.assertNotIn('ENABLED_SIMPLE', config) + self.assertIn('SIMPLE', config) +- self.assertEquals(NegativeOptionValue(), config['SIMPLE']) ++ self.assertEqual(NegativeOptionValue(), config['SIMPLE']) + + for config in ( + self.get_config(['--enable-simple']), +@@ -117,7 +117,7 @@ + ): + self.assertIn('ENABLED_SIMPLE', config) + self.assertIn('SIMPLE', config) +- self.assertEquals(PositiveOptionValue(), config['SIMPLE']) ++ self.assertEqual(PositiveOptionValue(), config['SIMPLE']) + self.assertIs(config['SIMPLE'], config['ENABLED_SIMPLE']) + + # --enable-simple doesn't take values. +@@ -135,7 +135,7 @@ + env={'MOZ_WITH_ENV': '1'}), + ): + self.assertIn('WITH_ENV', config) +- self.assertEquals(NegativeOptionValue(), config['WITH_ENV']) ++ self.assertEqual(NegativeOptionValue(), config['WITH_ENV']) + + for config in ( + self.get_config(['--enable-with-env']), +@@ -145,7 +145,7 @@ + env={'MOZ_WITH_ENV': ''}), + ): + self.assertIn('WITH_ENV', config) +- self.assertEquals(PositiveOptionValue(), config['WITH_ENV']) ++ self.assertEqual(PositiveOptionValue(), config['WITH_ENV']) + + with self.assertRaises(InvalidOptionError): + self.get_config(['--enable-with-env=value']) +@@ -160,23 +160,23 @@ + self.get_config(['--enable-values', '--disable-values']), + ): + self.assertIn(name, config) +- self.assertEquals(NegativeOptionValue(), config[name]) ++ self.assertEqual(NegativeOptionValue(), config[name]) + + for config in ( + self.get_config(['--enable-values']), + self.get_config(['--disable-values', '--enable-values']), + ): + self.assertIn(name, config) +- self.assertEquals(PositiveOptionValue(), config[name]) ++ self.assertEqual(PositiveOptionValue(), config[name]) + + config = self.get_config(['--enable-values=foo']) + self.assertIn(name, config) +- self.assertEquals(PositiveOptionValue(('foo',)), config[name]) ++ self.assertEqual(PositiveOptionValue(('foo',)), config[name]) + + config = self.get_config(['--enable-values=foo,bar']) + self.assertIn(name, config) + self.assertTrue(config[name]) +- self.assertEquals(PositiveOptionValue(('foo', 'bar')), config[name]) ++ self.assertEqual(PositiveOptionValue(('foo', 'bar')), config[name]) + + def test_values2(self): + self.test_values('VALUES2') +@@ -187,12 +187,12 @@ + def test_returned_default(self): + config = self.get_config(['--enable-simple']) + self.assertIn('DEFAULTED', config) +- self.assertEquals( ++ self.assertEqual( + PositiveOptionValue(('simple',)), config['DEFAULTED']) + + config = self.get_config(['--disable-simple']) + self.assertIn('DEFAULTED', config) +- self.assertEquals( ++ self.assertEqual( + PositiveOptionValue(('not-simple',)), config['DEFAULTED']) + + def test_returned_choices(self): +@@ -200,13 +200,13 @@ + config = self.get_config( + ['--enable-values=alpha', '--returned-choices=%s' % val]) + self.assertIn('CHOICES', config) +- self.assertEquals(PositiveOptionValue((val,)), config['CHOICES']) ++ self.assertEqual(PositiveOptionValue((val,)), config['CHOICES']) + + for val in ('0', '1', '2'): + config = self.get_config( + ['--enable-values=numeric', '--returned-choices=%s' % val]) + self.assertIn('CHOICES', config) +- self.assertEquals(PositiveOptionValue((val,)), config['CHOICES']) ++ self.assertEqual(PositiveOptionValue((val,)), config['CHOICES']) + + with self.assertRaises(InvalidOptionError): + self.get_config(['--enable-values=numeric', +@@ -218,12 +218,12 @@ + def test_included(self): + config = self.get_config(env={'CC': 'gcc'}) + self.assertIn('IS_GCC', config) +- self.assertEquals(config['IS_GCC'], True) ++ self.assertEqual(config['IS_GCC'], True) + + config = self.get_config( + ['--enable-include=extra.configure', '--extra']) + self.assertIn('EXTRA', config) +- self.assertEquals(PositiveOptionValue(), config['EXTRA']) ++ self.assertEqual(PositiveOptionValue(), config['EXTRA']) + + with self.assertRaises(InvalidOptionError): + self.get_config(['--extra']) +@@ -231,7 +231,7 @@ + def test_template(self): + config = self.get_config(env={'CC': 'gcc'}) + self.assertIn('CFLAGS', config) +- self.assertEquals(config['CFLAGS'], ['-Werror=foobar']) ++ self.assertEqual(config['CFLAGS'], ['-Werror=foobar']) + + config = self.get_config(env={'CC': 'clang'}) + self.assertNotIn('CFLAGS', config) +@@ -288,7 +288,7 @@ + sandbox + ) + +- import __builtin__ ++ import builtins + self.assertIs(sandbox['foo'](), __builtin__) + + exec_(textwrap.dedent(''' +@@ -300,7 +300,7 @@ + ) + + f = sandbox['foo']() +- self.assertEquals(f.name, os.devnull) ++ self.assertEqual(f.name, os.devnull) + f.close() + + # This unlocks the sandbox +@@ -336,8 +336,8 @@ + self.assertIs(sandbox['foo'](), sandbox) + + # Nothing leaked from the function being executed +- self.assertEquals(sandbox.keys(), ['__builtins__', 'foo']) +- self.assertEquals(sandbox['__builtins__'], ConfigureSandbox.BUILTINS) ++ self.assertEqual(list(sandbox.keys()), ['__builtins__', 'foo']) ++ self.assertEqual(sandbox['__builtins__'], ConfigureSandbox.BUILTINS) + + exec_(textwrap.dedent(''' + @template +@@ -354,7 +354,7 @@ + with self.assertRaises(NameError) as e: + sandbox._depends[sandbox['bar']].result + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "global name 'sys' is not defined") + + def test_apply_imports(self): +@@ -380,28 +380,28 @@ + sandbox + ) + +- self.assertEquals(len(imports), 1) ++ self.assertEqual(len(imports), 1) + + def test_os_path(self): + config = self.get_config(['--with-imports=%s' % __file__]) + self.assertIn('HAS_ABSPATH', config) +- self.assertEquals(config['HAS_ABSPATH'], True) ++ self.assertEqual(config['HAS_ABSPATH'], True) + self.assertIn('HAS_GETATIME', config) +- self.assertEquals(config['HAS_GETATIME'], True) ++ self.assertEqual(config['HAS_GETATIME'], True) + self.assertIn('HAS_GETATIME2', config) +- self.assertEquals(config['HAS_GETATIME2'], False) ++ self.assertEqual(config['HAS_GETATIME2'], False) + + def test_template_call(self): + config = self.get_config(env={'CC': 'gcc'}) + self.assertIn('TEMPLATE_VALUE', config) +- self.assertEquals(config['TEMPLATE_VALUE'], 42) ++ self.assertEqual(config['TEMPLATE_VALUE'], 42) + self.assertIn('TEMPLATE_VALUE_2', config) +- self.assertEquals(config['TEMPLATE_VALUE_2'], 21) ++ self.assertEqual(config['TEMPLATE_VALUE_2'], 21) + + def test_template_imports(self): + config = self.get_config(['--enable-imports-in-template']) + self.assertIn('PLATFORM', config) +- self.assertEquals(config['PLATFORM'], sys.platform) ++ self.assertEqual(config['PLATFORM'], sys.platform) + + def test_decorators(self): + config = {} +@@ -419,27 +419,27 @@ + return self.get_config(*args, configure='set_config.configure') + + help, config = get_config(['--help']) +- self.assertEquals(config, {}) ++ self.assertEqual(config, {}) + + config = get_config(['--set-foo']) + self.assertIn('FOO', config) +- self.assertEquals(config['FOO'], True) ++ self.assertEqual(config['FOO'], True) + + config = get_config(['--set-bar']) + self.assertNotIn('FOO', config) + self.assertIn('BAR', config) +- self.assertEquals(config['BAR'], True) ++ self.assertEqual(config['BAR'], True) + + config = get_config(['--set-value=qux']) + self.assertIn('VALUE', config) +- self.assertEquals(config['VALUE'], 'qux') ++ self.assertEqual(config['VALUE'], 'qux') + + config = get_config(['--set-name=hoge']) + self.assertIn('hoge', config) +- self.assertEquals(config['hoge'], True) ++ self.assertEqual(config['hoge'], True) + + config = get_config([]) +- self.assertEquals(config, {'BAR': False}) ++ self.assertEqual(config, {'BAR': False}) + + with self.assertRaises(ConfigureError): + # Both --set-foo and --set-name=FOO are going to try to +@@ -454,11 +454,11 @@ + set_config('QUX', 'qux', when='--with-qux') + '''): + config = self.get_config() +- self.assertEquals(config, { ++ self.assertEqual(config, { + 'FOO': 'foo', + }) + config = self.get_config(['--with-qux']) +- self.assertEquals(config, { ++ self.assertEqual(config, { + 'FOO': 'foo', + 'QUX': 'qux', + }) +@@ -468,27 +468,27 @@ + return self.get_config(*args, configure='set_define.configure') + + help, config = get_config(['--help']) +- self.assertEquals(config, {'DEFINES': {}}) ++ self.assertEqual(config, {'DEFINES': {}}) + + config = get_config(['--set-foo']) + self.assertIn('FOO', config['DEFINES']) +- self.assertEquals(config['DEFINES']['FOO'], True) ++ self.assertEqual(config['DEFINES']['FOO'], True) + + config = get_config(['--set-bar']) + self.assertNotIn('FOO', config['DEFINES']) + self.assertIn('BAR', config['DEFINES']) +- self.assertEquals(config['DEFINES']['BAR'], True) ++ self.assertEqual(config['DEFINES']['BAR'], True) + + config = get_config(['--set-value=qux']) + self.assertIn('VALUE', config['DEFINES']) +- self.assertEquals(config['DEFINES']['VALUE'], 'qux') ++ self.assertEqual(config['DEFINES']['VALUE'], 'qux') + + config = get_config(['--set-name=hoge']) + self.assertIn('hoge', config['DEFINES']) +- self.assertEquals(config['DEFINES']['hoge'], True) ++ self.assertEqual(config['DEFINES']['hoge'], True) + + config = get_config([]) +- self.assertEquals(config['DEFINES'], {'BAR': False}) ++ self.assertEqual(config['DEFINES'], {'BAR': False}) + + with self.assertRaises(ConfigureError): + # Both --set-foo and --set-name=FOO are going to try to +@@ -503,11 +503,11 @@ + set_define('QUX', 'qux', when='--with-qux') + '''): + config = self.get_config() +- self.assertEquals(config['DEFINES'], { ++ self.assertEqual(config['DEFINES'], { + 'FOO': 'foo', + }) + config = self.get_config(['--with-qux']) +- self.assertEquals(config['DEFINES'], { ++ self.assertEqual(config['DEFINES'], { + 'FOO': 'foo', + 'QUX': 'qux', + }) +@@ -518,19 +518,19 @@ + *args, configure='imply_option/simple.configure') + + help, config = get_config(['--help']) +- self.assertEquals(config, {}) ++ self.assertEqual(config, {}) + + config = get_config([]) +- self.assertEquals(config, {}) ++ self.assertEqual(config, {}) + + config = get_config(['--enable-foo']) + self.assertIn('BAR', config) +- self.assertEquals(config['BAR'], PositiveOptionValue()) ++ self.assertEqual(config['BAR'], PositiveOptionValue()) + + with self.assertRaises(InvalidOptionError) as e: + get_config(['--enable-foo', '--disable-bar']) + +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + "'--enable-bar' implied by '--enable-foo' conflicts with " + "'--disable-bar' from the command-line") +@@ -541,31 +541,31 @@ + *args, configure='imply_option/negative.configure') + + help, config = get_config(['--help']) +- self.assertEquals(config, {}) ++ self.assertEqual(config, {}) + + config = get_config([]) +- self.assertEquals(config, {}) ++ self.assertEqual(config, {}) + + config = get_config(['--enable-foo']) + self.assertIn('BAR', config) +- self.assertEquals(config['BAR'], NegativeOptionValue()) ++ self.assertEqual(config['BAR'], NegativeOptionValue()) + + with self.assertRaises(InvalidOptionError) as e: + get_config(['--enable-foo', '--enable-bar']) + +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + "'--disable-bar' implied by '--enable-foo' conflicts with " + "'--enable-bar' from the command-line") + + config = get_config(['--disable-hoge']) + self.assertIn('BAR', config) +- self.assertEquals(config['BAR'], NegativeOptionValue()) ++ self.assertEqual(config['BAR'], NegativeOptionValue()) + + with self.assertRaises(InvalidOptionError) as e: + get_config(['--disable-hoge', '--enable-bar']) + +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + "'--disable-bar' implied by '--disable-hoge' conflicts with " + "'--enable-bar' from the command-line") +@@ -576,23 +576,23 @@ + *args, configure='imply_option/values.configure') + + help, config = get_config(['--help']) +- self.assertEquals(config, {}) ++ self.assertEqual(config, {}) + + config = get_config([]) +- self.assertEquals(config, {}) ++ self.assertEqual(config, {}) + + config = get_config(['--enable-foo=a']) + self.assertIn('BAR', config) +- self.assertEquals(config['BAR'], PositiveOptionValue(('a',))) ++ self.assertEqual(config['BAR'], PositiveOptionValue(('a',))) + + config = get_config(['--enable-foo=a,b']) + self.assertIn('BAR', config) +- self.assertEquals(config['BAR'], PositiveOptionValue(('a','b'))) ++ self.assertEqual(config['BAR'], PositiveOptionValue(('a','b'))) + + with self.assertRaises(InvalidOptionError) as e: + get_config(['--enable-foo=a,b', '--disable-bar']) + +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + "'--enable-bar=a,b' implied by '--enable-foo' conflicts with " + "'--disable-bar' from the command-line") +@@ -603,15 +603,15 @@ + *args, configure='imply_option/infer.configure') + + help, config = get_config(['--help']) +- self.assertEquals(config, {}) ++ self.assertEqual(config, {}) + + config = get_config([]) +- self.assertEquals(config, {}) ++ self.assertEqual(config, {}) + + with self.assertRaises(InvalidOptionError) as e: + get_config(['--enable-foo', '--disable-bar']) + +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + "'--enable-bar' implied by '--enable-foo' conflicts with " + "'--disable-bar' from the command-line") +@@ -619,7 +619,7 @@ + with self.assertRaises(ConfigureError) as e: + self.get_config([], configure='imply_option/infer_ko.configure') + +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + "Cannot infer what implies '--enable-bar'. Please add a `reason` " + "to the `imply_option` call.") +@@ -630,25 +630,25 @@ + *args, configure='imply_option/imm.configure') + + help, config = get_config(['--help']) +- self.assertEquals(config, {}) ++ self.assertEqual(config, {}) + + config = get_config([]) +- self.assertEquals(config, {}) ++ self.assertEqual(config, {}) + + config_path = mozpath.abspath( + mozpath.join(test_data_path, 'imply_option', 'imm.configure')) + +- with self.assertRaisesRegexp(InvalidOptionError, ++ with self.assertRaisesRegex(InvalidOptionError, + "--enable-foo' implied by 'imply_option at %s:7' conflicts with " + "'--disable-foo' from the command-line" % config_path): + get_config(['--disable-foo']) + +- with self.assertRaisesRegexp(InvalidOptionError, ++ with self.assertRaisesRegex(InvalidOptionError, + "--enable-bar=foo,bar' implied by 'imply_option at %s:16' conflicts" + " with '--enable-bar=a,b,c' from the command-line" % config_path): + get_config(['--enable-bar=a,b,c']) + +- with self.assertRaisesRegexp(InvalidOptionError, ++ with self.assertRaisesRegex(InvalidOptionError, + "--enable-baz=BAZ' implied by 'imply_option at %s:25' conflicts" + " with '--enable-baz=QUUX' from the command-line" % config_path): + get_config(['--enable-baz=QUUX']) +@@ -660,7 +660,7 @@ + '''): + self.get_config() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "`--with-foo`, emitted from `%s` line 2, is unknown." + % mozpath.join(test_data_path, 'moz.configure')) + +@@ -675,7 +675,7 @@ + '''): + self.get_config() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "Unexpected type: 'int'") + + def test_imply_option_when(self): +@@ -686,12 +686,12 @@ + set_config('QUX', depends('--with-qux')(lambda x: x)) + '''): + config = self.get_config() +- self.assertEquals(config, { ++ self.assertEqual(config, { + 'QUX': NegativeOptionValue(), + }) + + config = self.get_config(['--with-foo']) +- self.assertEquals(config, { ++ self.assertEqual(config, { + 'QUX': PositiveOptionValue(), + }) + +@@ -700,7 +700,7 @@ + with self.moz_configure('option("--with-foo", help="foo")'): + self.get_config() + +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + 'Option `--with-foo` is not handled ; reference it with a @depends' + ) +@@ -712,7 +712,7 @@ + '''): + self.get_config() + +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + 'Option `--with-foo` already defined' + ) +@@ -724,7 +724,7 @@ + '''): + self.get_config() + +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + 'Option `MOZ_FOO` already defined' + ) +@@ -736,7 +736,7 @@ + '''): + self.get_config() + +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + 'Option `MOZ_FOO` already defined' + ) +@@ -748,7 +748,7 @@ + '''): + self.get_config() + +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + 'Option `MOZ_FOO` already defined' + ) +@@ -760,7 +760,7 @@ + '''): + self.get_config() + +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + 'Option `--with-foo` already defined' + ) +@@ -776,18 +776,18 @@ + set_config('QUX', depends('--with-qux', when='--with-foo')(lambda x: x)) + '''): + config = self.get_config() +- self.assertEquals(config, { ++ self.assertEqual(config, { + 'FOO': NegativeOptionValue(), + }) + + config = self.get_config(['--with-foo']) +- self.assertEquals(config, { ++ self.assertEqual(config, { + 'FOO': PositiveOptionValue(), + 'QUX': NegativeOptionValue(), + }) + + config = self.get_config(['--with-foo', '--with-qux']) +- self.assertEquals(config, { ++ self.assertEqual(config, { + 'FOO': PositiveOptionValue(), + 'QUX': PositiveOptionValue(), + }) +@@ -795,7 +795,7 @@ + with self.assertRaises(InvalidOptionError) as e: + self.get_config(['--with-bar']) + +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + '--with-bar is not available in this configuration' + ) +@@ -803,7 +803,7 @@ + with self.assertRaises(InvalidOptionError) as e: + self.get_config(['--with-qux']) + +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + '--with-qux is not available in this configuration' + ) +@@ -811,18 +811,18 @@ + with self.assertRaises(InvalidOptionError) as e: + self.get_config(['QUX=1']) + +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + 'QUX is not available in this configuration' + ) + + config = self.get_config(env={'QUX': '1'}) +- self.assertEquals(config, { ++ self.assertEqual(config, { + 'FOO': NegativeOptionValue(), + }) + + help, config = self.get_config(['--help']) +- self.assertEquals(help, textwrap.dedent('''\ ++ self.assertEqual(help, textwrap.dedent('''\ + Usage: configure [options] + + Options: [defaults in brackets after descriptions] +@@ -833,7 +833,7 @@ + ''')) + + help, config = self.get_config(['--help', '--with-foo']) +- self.assertEquals(help, textwrap.dedent('''\ ++ self.assertEqual(help, textwrap.dedent('''\ + Usage: configure [options] + + Options: [defaults in brackets after descriptions] +@@ -851,7 +851,7 @@ + with self.assertRaises(ConfigureError) as e: + self.get_config() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '@depends function needs the same `when` as ' + 'options it depends on') + +@@ -868,7 +868,7 @@ + with self.assertRaises(ConfigureError) as e: + self.get_config() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '@depends function needs the same `when` as ' + 'options it depends on') + +@@ -877,7 +877,7 @@ + with self.moz_configure('include("../foo.configure")'): + self.get_config() + +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + 'Cannot include `%s` because it is not in a subdirectory of `%s`' + % (mozpath.normpath(mozpath.join(test_data_path, '..', +@@ -892,7 +892,7 @@ + '''): + self.get_config() + +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + 'Cannot include `%s` because it was included already.' + % mozpath.normpath(mozpath.join(test_data_path, +@@ -905,7 +905,7 @@ + '''): + self.get_config() + +- self.assertEquals(e.exception.message, "Unexpected type: 'int'") ++ self.assertEqual(e.exception.message, "Unexpected type: 'int'") + + def test_include_when(self): + with MockedOpen({ +@@ -948,26 +948,26 @@ + '''), + }): + config = self.get_config() +- self.assertEquals(config, {}) ++ self.assertEqual(config, {}) + + config = self.get_config(['--with-foo']) +- self.assertEquals(config, {}) ++ self.assertEqual(config, {}) + + config = self.get_config(['--with-bar']) +- self.assertEquals(config, { ++ self.assertEqual(config, { + 'BAR': 'bar', + }) + + with self.assertRaises(InvalidOptionError) as e: + self.get_config(['--with-qux']) + +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + '--with-qux is not available in this configuration' + ) + + config = self.get_config(['--with-foo', '--with-foo-really']) +- self.assertEquals(config, { ++ self.assertEqual(config, { + 'FOO': 'foo', + 'FOO2': True, + }) +@@ -979,7 +979,7 @@ + '''): + self.get_config() + +- self.assertEquals(e.exception.message, 'Cannot reassign builtins') ++ self.assertEqual(e.exception.message, 'Cannot reassign builtins') + + with self.assertRaises(KeyError) as e: + with self.moz_configure(''' +@@ -987,7 +987,7 @@ + '''): + self.get_config() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + 'Cannot assign `foo` because it is neither a ' + '@depends nor a @template') + +@@ -1000,7 +1000,7 @@ + '''): + self.get_config() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "@depends needs at least one argument") + + with self.assertRaises(ConfigureError) as e: +@@ -1011,7 +1011,7 @@ + '''): + self.get_config() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "'--with-foo' is not a known option. Maybe it's " + "declared too late?") + +@@ -1023,7 +1023,7 @@ + '''): + self.get_config() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "Option must not contain an '='") + + with self.assertRaises(TypeError) as e: +@@ -1034,7 +1034,7 @@ + '''): + self.get_config() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "Cannot use object of type 'int' as argument " + "to @depends") + +@@ -1046,7 +1046,7 @@ + '''): + self.get_config() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "Cannot decorate generator functions with @depends") + + with self.assertRaises(TypeError) as e: +@@ -1055,7 +1055,7 @@ + '''): + self.get_config() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "Unexpected type: 'int'") + + with self.assertRaises(ConfigureError) as e: +@@ -1069,7 +1069,7 @@ + '''): + self.get_config() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "The `foo` function may not be called") + + with self.assertRaises(TypeError) as e: +@@ -1080,7 +1080,7 @@ + '''): + self.get_config() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "depends_impl() got an unexpected keyword argument 'foo'") + + def test_depends_when(self): +@@ -1105,12 +1105,12 @@ + set_config('QUX', qux) + '''): + config = self.get_config() +- self.assertEquals(config, { ++ self.assertEqual(config, { + 'FOO': 'foo', + }) + + config = self.get_config(['--with-qux']) +- self.assertEquals(config, { ++ self.assertEqual(config, { + 'FOO': 'foo', + 'QUX': 'qux', + }) +@@ -1125,7 +1125,7 @@ + '''): + self.get_config() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '@imports must appear after @template') + + with self.assertRaises(ConfigureError) as e: +@@ -1138,7 +1138,7 @@ + '''): + self.get_config() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '@imports must appear after @depends') + + for import_ in ( +@@ -1155,7 +1155,7 @@ + ''' % import_): + self.get_config() + +- self.assertEquals(e.exception.message, "Unexpected type: 'int'") ++ self.assertEqual(e.exception.message, "Unexpected type: 'int'") + + with self.assertRaises(TypeError) as e: + with self.moz_configure(''' +@@ -1166,7 +1166,7 @@ + '''): + self.get_config() + +- self.assertEquals(e.exception.message, "Unexpected type: 'int'") ++ self.assertEqual(e.exception.message, "Unexpected type: 'int'") + + with self.assertRaises(ValueError) as e: + with self.moz_configure(''' +@@ -1176,7 +1176,7 @@ + '''): + self.get_config() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "Invalid argument to @imports: 'os*'") + + def test_only_when(self): +@@ -1231,7 +1231,7 @@ + with self.assertRaises(InvalidOptionError) as e: + self.get_config(['--foo']) + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '--foo is not available in this configuration') + + # Cannot depend on an option defined in a only_when block, because we +@@ -1242,7 +1242,7 @@ + with self.assertRaises(ConfigureError) as e: + self.get_config() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '@depends function needs the same `when` as ' + 'options it depends on') + +@@ -1259,7 +1259,7 @@ + with self.assertRaises(InvalidOptionError) as e: + self.get_config() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '--foo is not available in this configuration') + + # And similarly doesn't fail when the condition is true. +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_lint.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_lint.py (refactored) +@@ -2,9 +2,9 @@ + # 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, print_function, unicode_literals + +-from StringIO import StringIO ++ ++from io import StringIO + import os + import textwrap + import unittest +@@ -62,7 +62,7 @@ + '''): + self.lint_test() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "`bar` depends on '--help' and `foo`. " + "`foo` must depend on '--help'") + +@@ -85,7 +85,7 @@ + '''): + self.lint_test() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "`bar` depends on '--help' and `foo`. " + "`foo` must depend on '--help'") + +@@ -111,7 +111,7 @@ + '''): + self.lint_test() + +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "Missing @depends for `foo`: '--help'") + + # There is a default restricted `os` module when there is no explicit +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_moz_configure.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_moz_configure.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + from mozunit import main + from mozpack import path as mozpath +@@ -23,10 +23,10 @@ + shell = mozpath.abspath('/bin/sh') + return result.replace('CONFIG_SHELL=%s ' % shell, '') + +- self.assertEquals('--enable-application=browser', ++ self.assertEqual('--enable-application=browser', + get_value_for(['--enable-application=browser'])) + +- self.assertEquals('--enable-application=browser ' ++ self.assertEqual('--enable-application=browser ' + 'MOZ_PROFILING=1', + get_value_for(['--enable-application=browser', + 'MOZ_PROFILING=1'])) +@@ -35,25 +35,25 @@ + environ={'MOZ_PROFILING': '1'}, + mozconfig='ac_add_options --enable-project=js') + +- self.assertEquals('--enable-project=js MOZ_PROFILING=1', ++ self.assertEqual('--enable-project=js MOZ_PROFILING=1', + value) + + # --disable-js-shell is the default, so it's filtered out. +- self.assertEquals('--enable-application=browser', ++ self.assertEqual('--enable-application=browser', + get_value_for(['--enable-application=browser', + '--disable-js-shell'])) + + # Normally, --without-foo would be filtered out because that's the + # default, but since it is a (fake) old-configure option, it always + # appears. +- self.assertEquals('--enable-application=browser --without-foo', ++ self.assertEqual('--enable-application=browser --without-foo', + get_value_for(['--enable-application=browser', + '--without-foo'])) +- self.assertEquals('--enable-application=browser --with-foo', ++ self.assertEqual('--enable-application=browser --with-foo', + get_value_for(['--enable-application=browser', + '--with-foo'])) + +- self.assertEquals("--enable-application=browser '--with-foo=foo bar'", ++ self.assertEqual("--enable-application=browser '--with-foo=foo bar'", + get_value_for(['--enable-application=browser', + '--with-foo=foo bar'])) + +@@ -65,7 +65,7 @@ + self.version = version + + def __call__(self, stdin, args): +- this.assertEquals(args, ('-version',)) ++ this.assertEqual(args, ('-version',)) + return 0, self.version, '' + + def check_nsis_version(version): +@@ -80,13 +80,13 @@ + with self.assertRaises(SystemExit) as e: + check_nsis_version('v3.0a2') + +- self.assertEquals(check_nsis_version('v3.0b1'), '3.0b1') +- self.assertEquals(check_nsis_version('v3.0b2'), '3.0b2') +- self.assertEquals(check_nsis_version('v3.0rc1'), '3.0rc1') +- self.assertEquals(check_nsis_version('v3.0'), '3.0') +- self.assertEquals(check_nsis_version('v3.0-2'), '3.0') +- self.assertEquals(check_nsis_version('v3.0.1'), '3.0') +- self.assertEquals(check_nsis_version('v3.1'), '3.1') ++ self.assertEqual(check_nsis_version('v3.0b1'), '3.0b1') ++ self.assertEqual(check_nsis_version('v3.0b2'), '3.0b2') ++ self.assertEqual(check_nsis_version('v3.0rc1'), '3.0rc1') ++ self.assertEqual(check_nsis_version('v3.0'), '3.0') ++ self.assertEqual(check_nsis_version('v3.0-2'), '3.0') ++ self.assertEqual(check_nsis_version('v3.0.1'), '3.0') ++ self.assertEqual(check_nsis_version('v3.1'), '3.1') + + + if __name__ == '__main__': +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_options.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_options.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + import unittest + +@@ -27,139 +27,139 @@ + class TestOption(unittest.TestCase): + def test_option(self): + option = Option('--option') +- self.assertEquals(option.prefix, '') +- self.assertEquals(option.name, 'option') +- self.assertEquals(option.env, None) ++ self.assertEqual(option.prefix, '') ++ self.assertEqual(option.name, 'option') ++ self.assertEqual(option.env, None) + self.assertFalse(option.default) + + option = Option('--enable-option') +- self.assertEquals(option.prefix, 'enable') +- self.assertEquals(option.name, 'option') +- self.assertEquals(option.env, None) ++ self.assertEqual(option.prefix, 'enable') ++ self.assertEqual(option.name, 'option') ++ self.assertEqual(option.env, None) + self.assertFalse(option.default) + + option = Option('--disable-option') +- self.assertEquals(option.prefix, 'disable') +- self.assertEquals(option.name, 'option') +- self.assertEquals(option.env, None) ++ self.assertEqual(option.prefix, 'disable') ++ self.assertEqual(option.name, 'option') ++ self.assertEqual(option.env, None) + self.assertTrue(option.default) + + option = Option('--with-option') +- self.assertEquals(option.prefix, 'with') +- self.assertEquals(option.name, 'option') +- self.assertEquals(option.env, None) ++ self.assertEqual(option.prefix, 'with') ++ self.assertEqual(option.name, 'option') ++ self.assertEqual(option.env, None) + self.assertFalse(option.default) + + option = Option('--without-option') +- self.assertEquals(option.prefix, 'without') +- self.assertEquals(option.name, 'option') +- self.assertEquals(option.env, None) ++ self.assertEqual(option.prefix, 'without') ++ self.assertEqual(option.name, 'option') ++ self.assertEqual(option.env, None) + self.assertTrue(option.default) + + option = Option('--without-option-foo', env='MOZ_OPTION') +- self.assertEquals(option.env, 'MOZ_OPTION') ++ self.assertEqual(option.env, 'MOZ_OPTION') + + option = Option(env='MOZ_OPTION') +- self.assertEquals(option.prefix, '') +- self.assertEquals(option.name, None) +- self.assertEquals(option.env, 'MOZ_OPTION') ++ self.assertEqual(option.prefix, '') ++ self.assertEqual(option.name, None) ++ self.assertEqual(option.env, 'MOZ_OPTION') + self.assertFalse(option.default) + + with self.assertRaises(InvalidOptionError) as e: + Option('--option', nargs=0, default=('a',)) +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "The given `default` doesn't satisfy `nargs`") + + with self.assertRaises(InvalidOptionError) as e: + Option('--option', nargs=1, default=()) +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + 'default must be a bool, a string or a tuple of strings') + + with self.assertRaises(InvalidOptionError) as e: + Option('--option', nargs=1, default=True) +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "The given `default` doesn't satisfy `nargs`") + + with self.assertRaises(InvalidOptionError) as e: + Option('--option', nargs=1, default=('a', 'b')) +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "The given `default` doesn't satisfy `nargs`") + + with self.assertRaises(InvalidOptionError) as e: + Option('--option', nargs=2, default=()) +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + 'default must be a bool, a string or a tuple of strings') + + with self.assertRaises(InvalidOptionError) as e: + Option('--option', nargs=2, default=True) +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "The given `default` doesn't satisfy `nargs`") + + with self.assertRaises(InvalidOptionError) as e: + Option('--option', nargs=2, default=('a',)) +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "The given `default` doesn't satisfy `nargs`") + + with self.assertRaises(InvalidOptionError) as e: + Option('--option', nargs='?', default=('a', 'b')) +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "The given `default` doesn't satisfy `nargs`") + + with self.assertRaises(InvalidOptionError) as e: + Option('--option', nargs='+', default=()) +- self.assertEquals( ++ self.assertEqual( + e.exception.message, + 'default must be a bool, a string or a tuple of strings') + + with self.assertRaises(InvalidOptionError) as e: + Option('--option', nargs='+', default=True) +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "The given `default` doesn't satisfy `nargs`") + + # --disable options with a nargs value that requires at least one + # argument need to be given a default. + with self.assertRaises(InvalidOptionError) as e: + Option('--disable-option', nargs=1) +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "The given `default` doesn't satisfy `nargs`") + + with self.assertRaises(InvalidOptionError) as e: + Option('--disable-option', nargs='+') +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "The given `default` doesn't satisfy `nargs`") + + # Test nargs inference from default value + option = Option('--with-foo', default=True) +- self.assertEquals(option.nargs, 0) ++ self.assertEqual(option.nargs, 0) + + option = Option('--with-foo', default=False) +- self.assertEquals(option.nargs, 0) ++ self.assertEqual(option.nargs, 0) + + option = Option('--with-foo', default='a') +- self.assertEquals(option.nargs, '?') ++ self.assertEqual(option.nargs, '?') + + option = Option('--with-foo', default=('a',)) +- self.assertEquals(option.nargs, '?') ++ self.assertEqual(option.nargs, '?') + + option = Option('--with-foo', default=('a', 'b')) +- self.assertEquals(option.nargs, '*') ++ self.assertEqual(option.nargs, '*') + + option = Option(env='FOO', default=True) +- self.assertEquals(option.nargs, 0) ++ self.assertEqual(option.nargs, 0) + + option = Option(env='FOO', default=False) +- self.assertEquals(option.nargs, 0) ++ self.assertEqual(option.nargs, 0) + + option = Option(env='FOO', default='a') +- self.assertEquals(option.nargs, '?') ++ self.assertEqual(option.nargs, '?') + + option = Option(env='FOO', default=('a',)) +- self.assertEquals(option.nargs, '?') ++ self.assertEqual(option.nargs, '?') + + option = Option(env='FOO', default=('a', 'b')) +- self.assertEquals(option.nargs, '*') ++ self.assertEqual(option.nargs, '*') + + def test_option_option(self): + for option in ( +@@ -169,70 +169,70 @@ + '--with-option', + '--without-option', + ): +- self.assertEquals(Option(option).option, option) +- self.assertEquals(Option(option, env='FOO').option, option) ++ self.assertEqual(Option(option).option, option) ++ self.assertEqual(Option(option, env='FOO').option, option) + + opt = Option(option, default=False) +- self.assertEquals(opt.option, ++ self.assertEqual(opt.option, + option.replace('-disable-', '-enable-') + .replace('-without-', '-with-')) + + opt = Option(option, default=True) +- self.assertEquals(opt.option, ++ self.assertEqual(opt.option, + option.replace('-enable-', '-disable-') + .replace('-with-', '-without-')) + +- self.assertEquals(Option(env='FOO').option, 'FOO') ++ self.assertEqual(Option(env='FOO').option, 'FOO') + + def test_option_choices(self): + with self.assertRaises(InvalidOptionError) as e: + Option('--option', nargs=3, choices=('a', 'b')) +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + 'Not enough `choices` for `nargs`') + + with self.assertRaises(InvalidOptionError) as e: + Option('--without-option', nargs=1, choices=('a', 'b')) +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + 'A `default` must be given along with `choices`') + + with self.assertRaises(InvalidOptionError) as e: + Option('--without-option', nargs='+', choices=('a', 'b')) +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + 'A `default` must be given along with `choices`') + + with self.assertRaises(InvalidOptionError) as e: + Option('--without-option', default='c', choices=('a', 'b')) +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "The `default` value must be one of 'a', 'b'") + + with self.assertRaises(InvalidOptionError) as e: + Option('--without-option', default=('a', 'c',), choices=('a', 'b')) +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "The `default` value must be one of 'a', 'b'") + + with self.assertRaises(InvalidOptionError) as e: + Option('--without-option', default=('c',), choices=('a', 'b')) +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "The `default` value must be one of 'a', 'b'") + + option = Option('--with-option', nargs='+', choices=('a', 'b')) + with self.assertRaises(InvalidOptionError) as e: + option.get_value('--with-option=c') +- self.assertEquals(e.exception.message, "'c' is not one of 'a', 'b'") ++ self.assertEqual(e.exception.message, "'c' is not one of 'a', 'b'") + + value = option.get_value('--with-option=b,a') + self.assertTrue(value) +- self.assertEquals(PositiveOptionValue(('b', 'a')), value) ++ self.assertEqual(PositiveOptionValue(('b', 'a')), value) + + option = Option('--without-option', nargs='*', default='a', + choices=('a', 'b')) + with self.assertRaises(InvalidOptionError) as e: + option.get_value('--with-option=c') +- self.assertEquals(e.exception.message, "'c' is not one of 'a', 'b'") ++ self.assertEqual(e.exception.message, "'c' is not one of 'a', 'b'") + + value = option.get_value('--with-option=b,a') + self.assertTrue(value) +- self.assertEquals(PositiveOptionValue(('b', 'a')), value) ++ self.assertEqual(PositiveOptionValue(('b', 'a')), value) + + # Test nargs inference from choices + option = Option('--with-option', choices=('a', 'b')) +@@ -243,71 +243,71 @@ + choices=('a', 'b', 'c', 'd')) + + value = option.get_value('--with-option=+d') +- self.assertEquals(PositiveOptionValue(('b', 'c', 'd')), value) ++ self.assertEqual(PositiveOptionValue(('b', 'c', 'd')), value) + + value = option.get_value('--with-option=-b') +- self.assertEquals(PositiveOptionValue(('c',)), value) ++ self.assertEqual(PositiveOptionValue(('c',)), value) + + value = option.get_value('--with-option=-b,+d') +- self.assertEquals(PositiveOptionValue(('c','d')), value) ++ self.assertEqual(PositiveOptionValue(('c','d')), value) + + # Adding something that is in the default is fine + value = option.get_value('--with-option=+b') +- self.assertEquals(PositiveOptionValue(('b', 'c')), value) ++ self.assertEqual(PositiveOptionValue(('b', 'c')), value) + + # Removing something that is not in the default is fine, as long as it + # is one of the choices + value = option.get_value('--with-option=-a') +- self.assertEquals(PositiveOptionValue(('b', 'c')), value) ++ self.assertEqual(PositiveOptionValue(('b', 'c')), value) + + with self.assertRaises(InvalidOptionError) as e: + option.get_value('--with-option=-e') +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "'e' is not one of 'a', 'b', 'c', 'd'") + + # Other "not a choice" errors. + with self.assertRaises(InvalidOptionError) as e: + option.get_value('--with-option=+e') +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "'e' is not one of 'a', 'b', 'c', 'd'") + + with self.assertRaises(InvalidOptionError) as e: + option.get_value('--with-option=e') +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "'e' is not one of 'a', 'b', 'c', 'd'") + + def test_option_value_format(self): + val = PositiveOptionValue() +- self.assertEquals('--with-value', val.format('--with-value')) +- self.assertEquals('--with-value', val.format('--without-value')) +- self.assertEquals('--enable-value', val.format('--enable-value')) +- self.assertEquals('--enable-value', val.format('--disable-value')) +- self.assertEquals('--value', val.format('--value')) +- self.assertEquals('VALUE=1', val.format('VALUE')) ++ self.assertEqual('--with-value', val.format('--with-value')) ++ self.assertEqual('--with-value', val.format('--without-value')) ++ self.assertEqual('--enable-value', val.format('--enable-value')) ++ self.assertEqual('--enable-value', val.format('--disable-value')) ++ self.assertEqual('--value', val.format('--value')) ++ self.assertEqual('VALUE=1', val.format('VALUE')) + + val = PositiveOptionValue(('a',)) +- self.assertEquals('--with-value=a', val.format('--with-value')) +- self.assertEquals('--with-value=a', val.format('--without-value')) +- self.assertEquals('--enable-value=a', val.format('--enable-value')) +- self.assertEquals('--enable-value=a', val.format('--disable-value')) +- self.assertEquals('--value=a', val.format('--value')) +- self.assertEquals('VALUE=a', val.format('VALUE')) ++ self.assertEqual('--with-value=a', val.format('--with-value')) ++ self.assertEqual('--with-value=a', val.format('--without-value')) ++ self.assertEqual('--enable-value=a', val.format('--enable-value')) ++ self.assertEqual('--enable-value=a', val.format('--disable-value')) ++ self.assertEqual('--value=a', val.format('--value')) ++ self.assertEqual('VALUE=a', val.format('VALUE')) + + val = PositiveOptionValue(('a', 'b')) +- self.assertEquals('--with-value=a,b', val.format('--with-value')) +- self.assertEquals('--with-value=a,b', val.format('--without-value')) +- self.assertEquals('--enable-value=a,b', val.format('--enable-value')) +- self.assertEquals('--enable-value=a,b', val.format('--disable-value')) +- self.assertEquals('--value=a,b', val.format('--value')) +- self.assertEquals('VALUE=a,b', val.format('VALUE')) ++ self.assertEqual('--with-value=a,b', val.format('--with-value')) ++ self.assertEqual('--with-value=a,b', val.format('--without-value')) ++ self.assertEqual('--enable-value=a,b', val.format('--enable-value')) ++ self.assertEqual('--enable-value=a,b', val.format('--disable-value')) ++ self.assertEqual('--value=a,b', val.format('--value')) ++ self.assertEqual('VALUE=a,b', val.format('VALUE')) + + val = NegativeOptionValue() +- self.assertEquals('--without-value', val.format('--with-value')) +- self.assertEquals('--without-value', val.format('--without-value')) +- self.assertEquals('--disable-value', val.format('--enable-value')) +- self.assertEquals('--disable-value', val.format('--disable-value')) +- self.assertEquals('', val.format('--value')) +- self.assertEquals('VALUE=', val.format('VALUE')) ++ self.assertEqual('--without-value', val.format('--with-value')) ++ self.assertEqual('--without-value', val.format('--without-value')) ++ self.assertEqual('--disable-value', val.format('--enable-value')) ++ self.assertEqual('--disable-value', val.format('--disable-value')) ++ self.assertEqual('', val.format('--value')) ++ self.assertEqual('VALUE=', val.format('VALUE')) + + def test_option_value(self, name='option', nargs=0, default=None): + disabled = name.startswith(('disable-', 'without-')) +@@ -324,28 +324,28 @@ + + if nargs in (0, '?', '*') or disabled: + value = option.get_value('--%s' % name, 'option') +- self.assertEquals(value, posOptionValue()) +- self.assertEquals(value.origin, 'option') ++ self.assertEqual(value, posOptionValue()) ++ self.assertEqual(value.origin, 'option') + else: + with self.assertRaises(InvalidOptionError) as e: + option.get_value('--%s' % name) + if nargs == 1: +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '--%s takes 1 value' % name) + elif nargs == '+': +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '--%s takes 1 or more values' % name) + else: +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '--%s takes 2 values' % name) + + value = option.get_value('') +- self.assertEquals(value, defaultValue) +- self.assertEquals(value.origin, 'default') ++ self.assertEqual(value, defaultValue) ++ self.assertEqual(value.origin, 'default') + + value = option.get_value(None) +- self.assertEquals(value, defaultValue) +- self.assertEquals(value.origin, 'default') ++ self.assertEqual(value, defaultValue) ++ self.assertEqual(value.origin, 'default') + + with self.assertRaises(AssertionError): + value = option.get_value('MOZ_OPTION=', 'environment') +@@ -358,47 +358,47 @@ + + if nargs in (1, '?', '*', '+') and not disabled: + value = option.get_value('--%s=' % name, 'option') +- self.assertEquals(value, PositiveOptionValue(('',))) +- self.assertEquals(value.origin, 'option') ++ self.assertEqual(value, PositiveOptionValue(('',))) ++ self.assertEqual(value.origin, 'option') + else: + with self.assertRaises(InvalidOptionError) as e: + option.get_value('--%s=' % name) + if disabled: +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + 'Cannot pass a value to --%s' % name) + else: +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '--%s takes %d values' % (name, nargs)) + + if nargs in (1, '?', '*', '+') and not disabled: + value = option.get_value('--%s=foo' % name, 'option') +- self.assertEquals(value, PositiveOptionValue(('foo',))) +- self.assertEquals(value.origin, 'option') ++ self.assertEqual(value, PositiveOptionValue(('foo',))) ++ self.assertEqual(value.origin, 'option') + else: + with self.assertRaises(InvalidOptionError) as e: + option.get_value('--%s=foo' % name) + if disabled: +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + 'Cannot pass a value to --%s' % name) + else: +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '--%s takes %d values' % (name, nargs)) + + if nargs in (2, '*', '+') and not disabled: + value = option.get_value('--%s=foo,bar' % name, 'option') +- self.assertEquals(value, PositiveOptionValue(('foo', 'bar'))) +- self.assertEquals(value.origin, 'option') ++ self.assertEqual(value, PositiveOptionValue(('foo', 'bar'))) ++ self.assertEqual(value.origin, 'option') + else: + with self.assertRaises(InvalidOptionError) as e: + option.get_value('--%s=foo,bar' % name, 'option') + if disabled: +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + 'Cannot pass a value to --%s' % name) + elif nargs == '?': +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '--%s takes 0 or 1 values' % name) + else: +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '--%s takes %d value%s' + % (name, nargs, 's' if nargs != 1 else '')) + +@@ -406,59 +406,59 @@ + default=default) + if nargs in (0, '?', '*') or disabled: + value = option.get_value('--%s' % name, 'option') +- self.assertEquals(value, posOptionValue()) +- self.assertEquals(value.origin, 'option') ++ self.assertEqual(value, posOptionValue()) ++ self.assertEqual(value.origin, 'option') + else: + with self.assertRaises(InvalidOptionError) as e: + option.get_value('--%s' % name) + if disabled: +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + 'Cannot pass a value to --%s' % name) + elif nargs == '+': +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '--%s takes 1 or more values' % name) + else: +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '--%s takes %d value%s' + % (name, nargs, 's' if nargs != 1 else '')) + + value = option.get_value('') +- self.assertEquals(value, defaultValue) +- self.assertEquals(value.origin, 'default') ++ self.assertEqual(value, defaultValue) ++ self.assertEqual(value.origin, 'default') + + value = option.get_value(None) +- self.assertEquals(value, defaultValue) +- self.assertEquals(value.origin, 'default') ++ self.assertEqual(value, defaultValue) ++ self.assertEqual(value.origin, 'default') + + value = option.get_value('MOZ_OPTION=', 'environment') +- self.assertEquals(value, NegativeOptionValue()) +- self.assertEquals(value.origin, 'environment') ++ self.assertEqual(value, NegativeOptionValue()) ++ self.assertEqual(value.origin, 'environment') + + if nargs in (0, '?', '*'): + value = option.get_value('MOZ_OPTION=1', 'environment') +- self.assertEquals(value, PositiveOptionValue()) +- self.assertEquals(value.origin, 'environment') ++ self.assertEqual(value, PositiveOptionValue()) ++ self.assertEqual(value.origin, 'environment') + elif nargs in (1, '+'): + value = option.get_value('MOZ_OPTION=1', 'environment') +- self.assertEquals(value, PositiveOptionValue(('1',))) +- self.assertEquals(value.origin, 'environment') ++ self.assertEqual(value, PositiveOptionValue(('1',))) ++ self.assertEqual(value.origin, 'environment') + else: + with self.assertRaises(InvalidOptionError) as e: + option.get_value('MOZ_OPTION=1', 'environment') +- self.assertEquals(e.exception.message, 'MOZ_OPTION takes 2 values') ++ self.assertEqual(e.exception.message, 'MOZ_OPTION takes 2 values') + + if nargs in (1, '?', '*', '+') and not disabled: + value = option.get_value('--%s=' % name, 'option') +- self.assertEquals(value, PositiveOptionValue(('',))) +- self.assertEquals(value.origin, 'option') ++ self.assertEqual(value, PositiveOptionValue(('',))) ++ self.assertEqual(value.origin, 'option') + else: + with self.assertRaises(InvalidOptionError) as e: + option.get_value('--%s=' % name, 'option') + if disabled: +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + 'Cannot pass a value to --%s' % name) + else: +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '--%s takes %d values' % (name, nargs)) + + with self.assertRaises(AssertionError): +@@ -466,26 +466,26 @@ + + if nargs in (1, '?', '*', '+'): + value = option.get_value('MOZ_OPTION=foo', 'environment') +- self.assertEquals(value, PositiveOptionValue(('foo',))) +- self.assertEquals(value.origin, 'environment') ++ self.assertEqual(value, PositiveOptionValue(('foo',))) ++ self.assertEqual(value.origin, 'environment') + else: + with self.assertRaises(InvalidOptionError) as e: + option.get_value('MOZ_OPTION=foo', 'environment') +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + 'MOZ_OPTION takes %d values' % nargs) + + if nargs in (2, '*', '+'): + value = option.get_value('MOZ_OPTION=foo,bar', 'environment') +- self.assertEquals(value, PositiveOptionValue(('foo', 'bar'))) +- self.assertEquals(value.origin, 'environment') ++ self.assertEqual(value, PositiveOptionValue(('foo', 'bar'))) ++ self.assertEqual(value.origin, 'environment') + else: + with self.assertRaises(InvalidOptionError) as e: + option.get_value('MOZ_OPTION=foo,bar', 'environment') + if nargs == '?': +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + 'MOZ_OPTION takes 0 or 1 values') + else: +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + 'MOZ_OPTION takes %d value%s' + % (nargs, 's' if nargs != 1 else '')) + +@@ -497,26 +497,26 @@ + env_option.get_value('--%s' % name) + + value = env_option.get_value('') +- self.assertEquals(value, defaultValue) +- self.assertEquals(value.origin, 'default') ++ self.assertEqual(value, defaultValue) ++ self.assertEqual(value.origin, 'default') + + value = env_option.get_value('MOZ_OPTION=', 'environment') +- self.assertEquals(value, negOptionValue()) +- self.assertEquals(value.origin, 'environment') ++ self.assertEqual(value, negOptionValue()) ++ self.assertEqual(value.origin, 'environment') + + if nargs in (0, '?', '*'): + value = env_option.get_value('MOZ_OPTION=1', 'environment') +- self.assertEquals(value, posOptionValue()) ++ self.assertEqual(value, posOptionValue()) + self.assertTrue(value) +- self.assertEquals(value.origin, 'environment') ++ self.assertEqual(value.origin, 'environment') + elif nargs in (1, '+'): + value = env_option.get_value('MOZ_OPTION=1', 'environment') +- self.assertEquals(value, PositiveOptionValue(('1',))) +- self.assertEquals(value.origin, 'environment') ++ self.assertEqual(value, PositiveOptionValue(('1',))) ++ self.assertEqual(value.origin, 'environment') + else: + with self.assertRaises(InvalidOptionError) as e: + env_option.get_value('MOZ_OPTION=1', 'environment') +- self.assertEquals(e.exception.message, 'MOZ_OPTION takes 2 values') ++ self.assertEqual(e.exception.message, 'MOZ_OPTION takes 2 values') + + with self.assertRaises(AssertionError) as e: + env_option.get_value('--%s' % name) +@@ -526,26 +526,26 @@ + + if nargs in (1, '?', '*', '+'): + value = env_option.get_value('MOZ_OPTION=foo', 'environment') +- self.assertEquals(value, PositiveOptionValue(('foo',))) +- self.assertEquals(value.origin, 'environment') ++ self.assertEqual(value, PositiveOptionValue(('foo',))) ++ self.assertEqual(value.origin, 'environment') + else: + with self.assertRaises(InvalidOptionError) as e: + env_option.get_value('MOZ_OPTION=foo', 'environment') +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + 'MOZ_OPTION takes %d values' % nargs) + + if nargs in (2, '*', '+'): + value = env_option.get_value('MOZ_OPTION=foo,bar', 'environment') +- self.assertEquals(value, PositiveOptionValue(('foo', 'bar'))) +- self.assertEquals(value.origin, 'environment') ++ self.assertEqual(value, PositiveOptionValue(('foo', 'bar'))) ++ self.assertEqual(value.origin, 'environment') + else: + with self.assertRaises(InvalidOptionError) as e: + env_option.get_value('MOZ_OPTION=foo,bar', 'environment') + if nargs == '?': +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + 'MOZ_OPTION takes 0 or 1 values') + else: +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + 'MOZ_OPTION takes %d value%s' + % (nargs, 's' if nargs != 1 else '')) + +@@ -557,28 +557,28 @@ + default=default) + + value = option.get_value('--%s-option' % disable, 'option') +- self.assertEquals(value, NegativeOptionValue()) +- self.assertEquals(value.origin, 'option') ++ self.assertEqual(value, NegativeOptionValue()) ++ self.assertEqual(value.origin, 'option') + + option = self.test_option_value('%s-option' % disable, nargs=nargs, + default=default) + + if nargs in (0, '?', '*'): + value = option.get_value('--%s-option' % enable, 'option') +- self.assertEquals(value, PositiveOptionValue()) +- self.assertEquals(value.origin, 'option') ++ self.assertEqual(value, PositiveOptionValue()) ++ self.assertEqual(value.origin, 'option') + else: + with self.assertRaises(InvalidOptionError) as e: + option.get_value('--%s-option' % enable, 'option') + if nargs == 1: +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '--%s-option takes 1 value' % enable) + elif nargs == '+': +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '--%s-option takes 1 or more values' + % enable) + else: +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + '--%s-option takes 2 values' % enable) + + def test_option_value_with(self): +@@ -587,12 +587,12 @@ + def test_option_value_invalid_nargs(self): + with self.assertRaises(InvalidOptionError) as e: + Option('--option', nargs='foo') +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "nargs must be a positive integer, '?', '*' or '+'") + + with self.assertRaises(InvalidOptionError) as e: + Option('--option', nargs=-2) +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "nargs must be a positive integer, '?', '*' or '+'") + + def test_option_value_nargs_1(self): +@@ -603,7 +603,7 @@ + # A default is required + with self.assertRaises(InvalidOptionError) as e: + Option('--disable-option', nargs=1) +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "The given `default` doesn't satisfy `nargs`") + + def test_option_value_nargs_2(self): +@@ -614,7 +614,7 @@ + # A default is required + with self.assertRaises(InvalidOptionError) as e: + Option('--disable-option', nargs=2) +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "The given `default` doesn't satisfy `nargs`") + + def test_option_value_nargs_0_or_1(self): +@@ -641,7 +641,7 @@ + # A default is required + with self.assertRaises(InvalidOptionError) as e: + Option('--disable-option', nargs='+') +- self.assertEquals(e.exception.message, ++ self.assertEqual(e.exception.message, + "The given `default` doesn't satisfy `nargs`") + + +@@ -649,109 +649,109 @@ + def test_basic(self): + helper = CommandLineHelper({}, ['cmd', '--foo', '--bar']) + +- self.assertEquals(['--foo', '--bar'], list(helper)) ++ self.assertEqual(['--foo', '--bar'], list(helper)) + + helper.add('--enable-qux') + +- self.assertEquals(['--foo', '--bar', '--enable-qux'], list(helper)) ++ self.assertEqual(['--foo', '--bar', '--enable-qux'], list(helper)) + + value, option = helper.handle(Option('--bar')) +- self.assertEquals(['--foo', '--enable-qux'], list(helper)) +- self.assertEquals(PositiveOptionValue(), value) +- self.assertEquals('--bar', option) ++ self.assertEqual(['--foo', '--enable-qux'], list(helper)) ++ self.assertEqual(PositiveOptionValue(), value) ++ self.assertEqual('--bar', option) + + value, option = helper.handle(Option('--baz')) +- self.assertEquals(['--foo', '--enable-qux'], list(helper)) +- self.assertEquals(NegativeOptionValue(), value) +- self.assertEquals(None, option) ++ self.assertEqual(['--foo', '--enable-qux'], list(helper)) ++ self.assertEqual(NegativeOptionValue(), value) ++ self.assertEqual(None, option) + + def test_precedence(self): + foo = Option('--with-foo', nargs='*') + helper = CommandLineHelper({}, ['cmd', '--with-foo=a,b']) + value, option = helper.handle(foo) +- self.assertEquals(PositiveOptionValue(('a', 'b')), value) +- self.assertEquals('command-line', value.origin) +- self.assertEquals('--with-foo=a,b', option) ++ self.assertEqual(PositiveOptionValue(('a', 'b')), value) ++ self.assertEqual('command-line', value.origin) ++ self.assertEqual('--with-foo=a,b', option) + + helper = CommandLineHelper({}, ['cmd', '--with-foo=a,b', + '--without-foo']) + value, option = helper.handle(foo) +- self.assertEquals(NegativeOptionValue(), value) +- self.assertEquals('command-line', value.origin) +- self.assertEquals('--without-foo', option) ++ self.assertEqual(NegativeOptionValue(), value) ++ self.assertEqual('command-line', value.origin) ++ self.assertEqual('--without-foo', option) + + helper = CommandLineHelper({}, ['cmd', '--without-foo', + '--with-foo=a,b']) + value, option = helper.handle(foo) +- self.assertEquals(PositiveOptionValue(('a', 'b')), value) +- self.assertEquals('command-line', value.origin) +- self.assertEquals('--with-foo=a,b', option) ++ self.assertEqual(PositiveOptionValue(('a', 'b')), value) ++ self.assertEqual('command-line', value.origin) ++ self.assertEqual('--with-foo=a,b', option) + + foo = Option('--with-foo', env='FOO', nargs='*') + helper = CommandLineHelper({'FOO': ''}, ['cmd', '--with-foo=a,b']) + value, option = helper.handle(foo) +- self.assertEquals(PositiveOptionValue(('a', 'b')), value) +- self.assertEquals('command-line', value.origin) +- self.assertEquals('--with-foo=a,b', option) ++ self.assertEqual(PositiveOptionValue(('a', 'b')), value) ++ self.assertEqual('command-line', value.origin) ++ self.assertEqual('--with-foo=a,b', option) + + helper = CommandLineHelper({'FOO': 'a,b'}, ['cmd', '--without-foo']) + value, option = helper.handle(foo) +- self.assertEquals(NegativeOptionValue(), value) +- self.assertEquals('command-line', value.origin) +- self.assertEquals('--without-foo', option) ++ self.assertEqual(NegativeOptionValue(), value) ++ self.assertEqual('command-line', value.origin) ++ self.assertEqual('--without-foo', option) + + helper = CommandLineHelper({'FOO': ''}, ['cmd', '--with-bar=a,b']) + value, option = helper.handle(foo) +- self.assertEquals(NegativeOptionValue(), value) +- self.assertEquals('environment', value.origin) +- self.assertEquals('FOO=', option) ++ self.assertEqual(NegativeOptionValue(), value) ++ self.assertEqual('environment', value.origin) ++ self.assertEqual('FOO=', option) + + helper = CommandLineHelper({'FOO': 'a,b'}, ['cmd', '--without-bar']) + value, option = helper.handle(foo) +- self.assertEquals(PositiveOptionValue(('a', 'b')), value) +- self.assertEquals('environment', value.origin) +- self.assertEquals('FOO=a,b', option) ++ self.assertEqual(PositiveOptionValue(('a', 'b')), value) ++ self.assertEqual('environment', value.origin) ++ self.assertEqual('FOO=a,b', option) + + helper = CommandLineHelper({}, ['cmd', '--with-foo=a,b', 'FOO=']) + value, option = helper.handle(foo) +- self.assertEquals(NegativeOptionValue(), value) +- self.assertEquals('command-line', value.origin) +- self.assertEquals('FOO=', option) ++ self.assertEqual(NegativeOptionValue(), value) ++ self.assertEqual('command-line', value.origin) ++ self.assertEqual('FOO=', option) + + helper = CommandLineHelper({}, ['cmd', '--without-foo', 'FOO=a,b']) + value, option = helper.handle(foo) +- self.assertEquals(PositiveOptionValue(('a', 'b')), value) +- self.assertEquals('command-line', value.origin) +- self.assertEquals('FOO=a,b', option) ++ self.assertEqual(PositiveOptionValue(('a', 'b')), value) ++ self.assertEqual('command-line', value.origin) ++ self.assertEqual('FOO=a,b', option) + + helper = CommandLineHelper({}, ['cmd', 'FOO=', '--with-foo=a,b']) + value, option = helper.handle(foo) +- self.assertEquals(PositiveOptionValue(('a', 'b')), value) +- self.assertEquals('command-line', value.origin) +- self.assertEquals('--with-foo=a,b', option) ++ self.assertEqual(PositiveOptionValue(('a', 'b')), value) ++ self.assertEqual('command-line', value.origin) ++ self.assertEqual('--with-foo=a,b', option) + + helper = CommandLineHelper({}, ['cmd', 'FOO=a,b', '--without-foo']) + value, option = helper.handle(foo) +- self.assertEquals(NegativeOptionValue(), value) +- self.assertEquals('command-line', value.origin) +- self.assertEquals('--without-foo', option) ++ self.assertEqual(NegativeOptionValue(), value) ++ self.assertEqual('command-line', value.origin) ++ self.assertEqual('--without-foo', option) + + def test_extra_args(self): + foo = Option('--with-foo', env='FOO', nargs='*') + helper = CommandLineHelper({}, ['cmd']) + helper.add('FOO=a,b,c', 'other-origin') + value, option = helper.handle(foo) +- self.assertEquals(PositiveOptionValue(('a', 'b', 'c')), value) +- self.assertEquals('other-origin', value.origin) +- self.assertEquals('FOO=a,b,c', option) ++ self.assertEqual(PositiveOptionValue(('a', 'b', 'c')), value) ++ self.assertEqual('other-origin', value.origin) ++ self.assertEqual('FOO=a,b,c', option) + + helper = CommandLineHelper({}, ['cmd']) + helper.add('FOO=a,b,c', 'other-origin') + helper.add('--with-foo=a,b,c', 'other-origin') + value, option = helper.handle(foo) +- self.assertEquals(PositiveOptionValue(('a', 'b', 'c')), value) +- self.assertEquals('other-origin', value.origin) +- self.assertEquals('--with-foo=a,b,c', option) ++ self.assertEqual(PositiveOptionValue(('a', 'b', 'c')), value) ++ self.assertEqual('other-origin', value.origin) ++ self.assertEqual('--with-foo=a,b,c', option) + + # Adding conflicting options is not allowed. + helper = CommandLineHelper({}, ['cmd']) +@@ -771,9 +771,9 @@ + # But adding the same is allowed. + helper.add('FOO=a,b,c', 'other-origin') + value, option = helper.handle(foo) +- self.assertEquals(PositiveOptionValue(('a', 'b', 'c')), value) +- self.assertEquals('other-origin', value.origin) +- self.assertEquals('FOO=a,b,c', option) ++ self.assertEqual(PositiveOptionValue(('a', 'b', 'c')), value) ++ self.assertEqual('other-origin', value.origin) ++ self.assertEqual('FOO=a,b,c', option) + + # The same rule as above applies when using the option form vs. the + # variable form. But we can't detect it when .add is called. +@@ -799,9 +799,9 @@ + helper.add('FOO=a,b,c', 'other-origin') + helper.add('--with-foo=a,b,c', 'other-origin') + value, option = helper.handle(foo) +- self.assertEquals(PositiveOptionValue(('a', 'b', 'c')), value) +- self.assertEquals('other-origin', value.origin) +- self.assertEquals('--with-foo=a,b,c', option) ++ self.assertEqual(PositiveOptionValue(('a', 'b', 'c')), value) ++ self.assertEqual('other-origin', value.origin) ++ self.assertEqual('--with-foo=a,b,c', option) + + # Conflicts are also not allowed against what is in the + # environment/on the command line. +@@ -831,19 +831,19 @@ + foo = Option('--foo', + possible_origins=('command-line',)) + value, option = helper.handle(foo) +- self.assertEquals(PositiveOptionValue(), value) +- self.assertEquals('command-line', value.origin) +- self.assertEquals('--foo', option) ++ self.assertEqual(PositiveOptionValue(), value) ++ self.assertEqual('command-line', value.origin) ++ self.assertEqual('--foo', option) + + bar = Option('--bar', + possible_origins=('mozconfig',)) +- with self.assertRaisesRegexp(InvalidOptionError, ++ with self.assertRaisesRegex(InvalidOptionError, + "--bar can not be set by command-line. Values are accepted from: mozconfig"): + helper.handle(bar) + + baz = Option(env='BAZ', + possible_origins=('implied',)) +- with self.assertRaisesRegexp(InvalidOptionError, ++ with self.assertRaisesRegex(InvalidOptionError, + "BAZ=1 can not be set by environment. Values are accepted from: implied"): + helper.handle(baz) + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py (refactored) +@@ -2,12 +2,12 @@ + # 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, print_function, unicode_literals ++ + + import logging + import os + +-from StringIO import StringIO ++from io import StringIO + + from mozunit import main + +@@ -291,9 +291,9 @@ + compiler = sandbox._value_for(sandbox[var]) + # Add var on both ends to make it clear which of the + # variables is failing the test when that happens. +- self.assertEquals((var, compiler), (var, result)) ++ self.assertEqual((var, compiler), (var, result)) + except SystemExit: +- self.assertEquals((var, result), ++ self.assertEqual((var, result), + (var, self.out.getvalue().strip())) + return + +@@ -471,7 +471,7 @@ + # We'll try gcc and clang, but since there is no gcc (gcc-x.y doesn't + # count), find clang. + paths = { +- k: v for k, v in self.PATHS.iteritems() ++ k: v for k, v in self.PATHS.items() + if os.path.basename(k) not in ('gcc', 'g++') + } + self.do_toolchain_test(paths, { +@@ -506,7 +506,7 @@ + # Even if there are gcc-x.y or clang-x.y compilers available, we + # don't try them. This could be considered something to improve. + paths = { +- k: v for k, v in self.PATHS.iteritems() ++ k: v for k, v in self.PATHS.items() + if os.path.basename(k) not in ('gcc', 'g++', 'clang', 'clang++') + } + self.do_toolchain_test(paths, { +@@ -687,7 +687,7 @@ + def test_not_gcc(self): + # We won't pick GCC if it's the only thing available. + paths = { +- k: v for k, v in self.PATHS.iteritems() ++ k: v for k, v in self.PATHS.items() + if os.path.basename(k) not in ('clang', 'clang++') + } + self.do_toolchain_test(paths, { +@@ -851,7 +851,7 @@ + def test_clang_cl(self): + # We'll pick clang-cl if msvc can't be found. + paths = { +- k: v for k, v in self.PATHS.iteritems() ++ k: v for k, v in self.PATHS.items() + if os.path.basename(k) != 'cl' + } + self.do_toolchain_test(paths, { +@@ -862,7 +862,7 @@ + def test_gcc(self): + # We'll pick GCC if msvc and clang-cl can't be found. + paths = { +- k: v for k, v in self.PATHS.iteritems() ++ k: v for k, v in self.PATHS.items() + if os.path.basename(k) not in ('cl', 'clang-cl') + } + self.do_toolchain_test(paths, { +@@ -881,7 +881,7 @@ + def test_clang(self): + # We'll pick clang if nothing else is found. + paths = { +- k: v for k, v in self.PATHS.iteritems() ++ k: v for k, v in self.PATHS.items() + if os.path.basename(k) not in ('cl', 'clang-cl', 'gcc') + } + self.do_toolchain_test(paths, { +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_toolchain_helpers.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_toolchain_helpers.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + import copy + import re +@@ -10,7 +10,7 @@ + import unittest + + from fnmatch import fnmatch +-from StringIO import StringIO ++from io import StringIO + from textwrap import dedent + + from mozunit import ( +@@ -43,7 +43,7 @@ + # Hack around it enough that the configure tests work properly. + context = self.context + def normalize_numbers(value): +- if isinstance(value, types.StringTypes): ++ if isinstance(value, (str,)): + if value[-1:] == 'L' and value[:-1].isdigit(): + value = int(value[:-1]) + return value +@@ -53,7 +53,7 @@ + return self.HAS_FEATURE.sub(r'\1\2', expr) + self.context = self.Context( + (normalize_has_feature(k), normalize_numbers(v)) +- for k, v in context.iteritems() ++ for k, v in context.items() + ) + try: + return Preprocessor.do_if(self, normalize_has_feature(expression), +@@ -95,7 +95,7 @@ + input.name = 'foo' + pp.do_include(input) + +- self.assertEquals(pp.out.getvalue(), '1 . 2 . c "D"') ++ self.assertEqual(pp.out.getvalue(), '1 . 2 . c "D"') + + def test_condition(self): + pp = CompilerPreprocessor({ +@@ -125,7 +125,7 @@ + input.name = 'foo' + pp.do_include(input) + +- self.assertEquals('IFDEF_A\nIF_A\nIF_B\nIF_NOT_C\n', pp.out.getvalue()) ++ self.assertEqual('IFDEF_A\nIF_A\nIF_B\nIF_NOT_C\n', pp.out.getvalue()) + + + class FakeCompiler(dict): +@@ -164,9 +164,9 @@ + ''' + def __init__(self, *definitions): + for definition in definitions: +- if all(not isinstance(d, dict) for d in definition.itervalues()): ++ if all(not isinstance(d, dict) for d in definition.values()): + definition = {None: definition} +- for key, value in definition.iteritems(): ++ for key, value in definition.items(): + self.setdefault(key, {}).update(value) + + def __call__(self, stdin, args): +@@ -178,14 +178,14 @@ + pp = CompilerPreprocessor(self[None]) + + def apply_defn(defn): +- for k, v in defn.iteritems(): ++ for k, v in defn.items(): + if v is False: + if k in pp.context: + del pp.context[k] + else: + pp.context[k] = v + +- for glob, defn in self.iteritems(): ++ for glob, defn in self.items(): + if glob and not glob.startswith('-') and fnmatch(file, glob): + apply_defn(defn) + +@@ -216,7 +216,7 @@ + 'A': '1', + 'B': '2', + }) +- self.assertEquals(compiler(None, ['-E', 'file']), ++ self.assertEqual(compiler(None, ['-E', 'file']), + (0, '1 2 C', '')) + + compiler = FakeCompiler({ +@@ -238,25 +238,25 @@ + 'B': '42', + }, + }) +- self.assertEquals(compiler(None, ['-E', 'file']), ++ self.assertEqual(compiler(None, ['-E', 'file']), + (0, '1 2 C', '')) +- self.assertEquals(compiler(None, ['-E', '-foo', 'file']), ++ self.assertEqual(compiler(None, ['-E', '-foo', 'file']), + (0, '1 2 foo', '')) +- self.assertEquals(compiler(None, ['-E', '-bar', 'file']), ++ self.assertEqual(compiler(None, ['-E', '-bar', 'file']), + (0, '1 bar bar', '')) +- self.assertEquals(compiler(None, ['-E', '-qux', 'file']), ++ self.assertEqual(compiler(None, ['-E', '-qux', 'file']), + (0, '1 B C', '')) +- self.assertEquals(compiler(None, ['-E', '-foo', '-bar', 'file']), ++ self.assertEqual(compiler(None, ['-E', '-foo', '-bar', 'file']), + (0, '1 bar bar', '')) +- self.assertEquals(compiler(None, ['-E', '-bar', '-foo', 'file']), ++ self.assertEqual(compiler(None, ['-E', '-bar', '-foo', 'file']), + (0, '1 bar foo', '')) +- self.assertEquals(compiler(None, ['-E', '-bar', '-qux', 'file']), ++ self.assertEqual(compiler(None, ['-E', '-bar', '-qux', 'file']), + (0, '1 B bar', '')) +- self.assertEquals(compiler(None, ['-E', '-qux', '-bar', 'file']), ++ self.assertEqual(compiler(None, ['-E', '-qux', '-bar', 'file']), + (0, '1 bar bar', '')) +- self.assertEquals(compiler(None, ['-E', 'file.c']), ++ self.assertEqual(compiler(None, ['-E', 'file.c']), + (0, '1 42 C', '')) +- self.assertEquals(compiler(None, ['-E', '-bar', 'file.c']), ++ self.assertEqual(compiler(None, ['-E', '-bar', 'file.c']), + (0, '1 bar bar', '')) + + def test_multiple_definitions(self): +@@ -267,7 +267,7 @@ + 'C': 3, + }) + +- self.assertEquals(compiler, { ++ self.assertEqual(compiler, { + None: { + 'A': 1, + 'B': 2, +@@ -282,7 +282,7 @@ + 'C': 3, + }) + +- self.assertEquals(compiler, { ++ self.assertEqual(compiler, { + None: { + 'A': 1, + 'B': 4, +@@ -302,7 +302,7 @@ + }, + }) + +- self.assertEquals(compiler, { ++ self.assertEqual(compiler, { + None: { + 'A': 1, + 'B': 4, +@@ -330,7 +330,7 @@ + }, + }) + +- self.assertEquals(compiler, { ++ self.assertEqual(compiler, { + None: { + 'A': 1, + 'B': 2, +@@ -370,7 +370,7 @@ + def __add__(self, other): + assert isinstance(other, dict) + result = copy.deepcopy(self.__dict__) +- for k, v in other.iteritems(): ++ for k, v in other.items(): + if k == 'flags': + result.setdefault(k, []).extend(v) + else: +@@ -381,7 +381,7 @@ + class TestCompilerResult(unittest.TestCase): + def test_compiler_result(self): + result = CompilerResult() +- self.assertEquals(result.__dict__, { ++ self.assertEqual(result.__dict__, { + 'wrapper': [], + 'compiler': mozpath.abspath(''), + 'version': '', +@@ -397,7 +397,7 @@ + language='C', + flags=['-std=gnu99'], + ) +- self.assertEquals(result.__dict__, { ++ self.assertEqual(result.__dict__, { + 'wrapper': [], + 'compiler': mozpath.abspath('/usr/bin/gcc'), + 'version': '4.2.1', +@@ -407,7 +407,7 @@ + }) + + result2 = result + {'flags': ['-m32']} +- self.assertEquals(result2.__dict__, { ++ self.assertEqual(result2.__dict__, { + 'wrapper': [], + 'compiler': mozpath.abspath('/usr/bin/gcc'), + 'version': '4.2.1', +@@ -416,14 +416,14 @@ + 'flags': ['-std=gnu99', '-m32'], + }) + # Original flags are untouched. +- self.assertEquals(result.flags, ['-std=gnu99']) ++ self.assertEqual(result.flags, ['-std=gnu99']) + + result3 = result + { + 'compiler': '/usr/bin/gcc-4.7', + 'version': '4.7.3', + 'flags': ['-m32'], + } +- self.assertEquals(result3.__dict__, { ++ self.assertEqual(result3.__dict__, { + 'wrapper': [], + 'compiler': mozpath.abspath('/usr/bin/gcc-4.7'), + 'version': '4.7.3', +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_toolkit_moz_configure.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_toolkit_moz_configure.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + import os + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_util.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/configure/test_util.py (refactored) +@@ -2,7 +2,7 @@ + # 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, print_function, unicode_literals ++ + + import logging + import os +@@ -11,7 +11,7 @@ + import unittest + import sys + +-from StringIO import StringIO ++from io import StringIO + + from mozunit import main + from mozpack import path as mozpath +@@ -434,11 +434,11 @@ + except SystemExit as e: + status = e.code + +- self.assertEquals(status, 0) ++ self.assertEqual(status, 0) + quote_char = "'" + if getpreferredencoding().lower() == 'utf-8': + quote_char = '\u00B4'.encode('utf-8') +- self.assertEquals(out.getvalue().strip(), quote_char) ++ self.assertEqual(out.getvalue().strip(), quote_char) + + + class TestVersion(unittest.TestCase): +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/controller/test_ccachestats.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/controller/test_ccachestats.py (refactored) +@@ -2,7 +2,7 @@ + # 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 unicode_literals ++ + + import unittest + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/controller/test_clobber.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/controller/test_clobber.py (refactored) +@@ -2,14 +2,14 @@ + # 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 unicode_literals ++ + + import os + import shutil + import tempfile + import unittest + +-from StringIO import StringIO ++from io import StringIO + + from mozunit import main + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/frontend/test_context.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/frontend/test_context.py (refactored) +@@ -36,7 +36,7 @@ + 'baz': (dict, dict, ''), + }) + +- self.assertEqual(test.keys(), []) ++ self.assertEqual(list(test.keys()), []) + + self.assertEqual(test['foo'], 0) + +@@ -84,12 +84,12 @@ + 'baz': (dict, list, ''), + }) + +- self.assertEqual(test.keys(), []) ++ self.assertEqual(list(test.keys()), []) + + with self.assertRaises(ValueError): + test.update(bar=True, foo={}) + +- self.assertEqual(test.keys(), []) ++ self.assertEqual(list(test.keys()), []) + + test.update(bar=True, foo=1) + +@@ -258,19 +258,19 @@ + self.assertEqual(lines[-1].strip(), '') + + def test_documentation_formatting(self): +- for typ, inp, doc in VARIABLES.values(): ++ for typ, inp, doc in list(VARIABLES.values()): + self._verify_doc(doc) + +- for attr, args, doc in FUNCTIONS.values(): ++ for attr, args, doc in list(FUNCTIONS.values()): + self._verify_doc(doc) + +- for func, typ, doc in SPECIAL_VARIABLES.values(): ++ for func, typ, doc in list(SPECIAL_VARIABLES.values()): + self._verify_doc(doc) + +- for name, cls in SUBCONTEXTS.items(): ++ for name, cls in list(SUBCONTEXTS.items()): + self._verify_doc(cls.__doc__) + +- for name, v in cls.VARIABLES.items(): ++ for name, v in list(cls.VARIABLES.items()): + self._verify_doc(v[2]) + + +@@ -631,7 +631,7 @@ + class TestTypedRecord(unittest.TestCase): + + def test_fields(self): +- T = ContextDerivedTypedRecord(('field1', unicode), ++ T = ContextDerivedTypedRecord(('field1', str), + ('field2', list)) + inst = T(None) + self.assertEqual(inst.field1, '') +@@ -647,7 +647,7 @@ + inst.field3 = [] + + def test_coercion(self): +- T = ContextDerivedTypedRecord(('field1', unicode), ++ T = ContextDerivedTypedRecord(('field1', str), + ('field2', list)) + inst = T(None) + inst.field1 = 3 +@@ -673,45 +673,45 @@ + def test_single_bug_component(self): + c = Context({}) + f = Files(c, pattern='**') +- f['BUG_COMPONENT'] = (u'Product1', u'Component1') ++ f['BUG_COMPONENT'] = ('Product1', 'Component1') + + files = {'moz.build': f} + self.assertEqual(Files.aggregate(files), { +- 'bug_component_counts': [((u'Product1', u'Component1'), 1)], +- 'recommended_bug_component': (u'Product1', u'Component1'), ++ 'bug_component_counts': [(('Product1', 'Component1'), 1)], ++ 'recommended_bug_component': ('Product1', 'Component1'), + }) + + def test_multiple_bug_components(self): + c = Context({}) + f1 = Files(c, pattern='**') +- f1['BUG_COMPONENT'] = (u'Product1', u'Component1') ++ f1['BUG_COMPONENT'] = ('Product1', 'Component1') + + f2 = Files(c, pattern='**') +- f2['BUG_COMPONENT'] = (u'Product2', u'Component2') ++ f2['BUG_COMPONENT'] = ('Product2', 'Component2') + + files = {'a': f1, 'b': f2, 'c': f1} + self.assertEqual(Files.aggregate(files), { + 'bug_component_counts': [ +- ((u'Product1', u'Component1'), 2), +- ((u'Product2', u'Component2'), 1), ++ (('Product1', 'Component1'), 2), ++ (('Product2', 'Component2'), 1), + ], +- 'recommended_bug_component': (u'Product1', u'Component1'), ++ 'recommended_bug_component': ('Product1', 'Component1'), + }) + + def test_no_recommended_bug_component(self): + """If there is no clear count winner, we don't recommend a bug component.""" + c = Context({}) + f1 = Files(c, pattern='**') +- f1['BUG_COMPONENT'] = (u'Product1', u'Component1') ++ f1['BUG_COMPONENT'] = ('Product1', 'Component1') + + f2 = Files(c, pattern='**') +- f2['BUG_COMPONENT'] = (u'Product2', u'Component2') ++ f2['BUG_COMPONENT'] = ('Product2', 'Component2') + + files = {'a': f1, 'b': f2} + self.assertEqual(Files.aggregate(files), { + 'bug_component_counts': [ +- ((u'Product1', u'Component1'), 1), +- ((u'Product2', u'Component2'), 1), ++ (('Product1', 'Component1'), 1), ++ (('Product2', 'Component2'), 1), + ], + 'recommended_bug_component': None, + }) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/frontend/test_emitter.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/frontend/test_emitter.py (refactored) +@@ -2,7 +2,7 @@ + # 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 unicode_literals ++ + + import os + import unittest +@@ -204,7 +204,7 @@ + def test_use_yasm(self): + # When yasm is not available, this should raise. + reader = self.reader('use-yasm') +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'yasm is not available'): + self.read_topsrcdir(reader) + +@@ -267,25 +267,25 @@ + o = objs[0] + self.assertIsInstance(o, GeneratedFile) + self.assertEqual(o.outputs, ('bar.c',)) +- self.assertRegexpMatches(o.script, 'script.py$') ++ self.assertRegex(o.script, 'script.py$') + self.assertEqual(o.method, 'make_bar') + self.assertEqual(o.inputs, []) + + def test_generated_files_no_script(self): + reader = self.reader('generated-files-no-script') +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'Script for generating bar.c does not exist'): + self.read_topsrcdir(reader) + + def test_generated_files_no_inputs(self): + reader = self.reader('generated-files-no-inputs') +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'Input for generating foo.c does not exist'): + self.read_topsrcdir(reader) + + def test_generated_files_no_python_script(self): + reader = self.reader('generated-files-no-python-script') +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'Script for generating bar.c does not end in .py'): + self.read_topsrcdir(reader) + +@@ -314,7 +314,7 @@ + Missing files in EXPORTS is an error. + ''' + reader = self.reader('exports-missing') +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'File listed in EXPORTS does not exist:'): + self.read_topsrcdir(reader) + +@@ -323,7 +323,7 @@ + An objdir file in EXPORTS that is not in GENERATED_FILES is an error. + ''' + reader = self.reader('exports-missing-generated') +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'Objdir file listed in EXPORTS not in GENERATED_FILES:'): + self.read_topsrcdir(reader) + +@@ -360,7 +360,7 @@ + + def test_test_harness_files_root(self): + reader = self.reader('test-harness-files-root') +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'Cannot install files to the root of TEST_HARNESS_FILES'): + self.read_topsrcdir(reader) + +@@ -413,14 +413,14 @@ + """A missing manifest file should result in an error.""" + reader = self.reader('test-manifest-missing-manifest') + +- with self.assertRaisesRegexp(BuildReaderError, 'IOError: Missing files'): ++ with self.assertRaisesRegex(BuildReaderError, 'IOError: Missing files'): + self.read_topsrcdir(reader) + + def test_empty_test_manifest_rejected(self): + """A test manifest without any entries is rejected.""" + reader = self.reader('test-manifest-empty') + +- with self.assertRaisesRegexp(SandboxValidationError, 'Empty test manifest'): ++ with self.assertRaisesRegex(SandboxValidationError, 'Empty test manifest'): + self.read_topsrcdir(reader) + + +@@ -428,7 +428,7 @@ + """A test manifest with no tests but support-files is not supported.""" + reader = self.reader('test-manifest-just-support') + +- with self.assertRaisesRegexp(SandboxValidationError, 'Empty test manifest'): ++ with self.assertRaisesRegex(SandboxValidationError, 'Empty test manifest'): + self.read_topsrcdir(reader) + + def test_test_manifest_dupe_support_files(self): +@@ -437,7 +437,7 @@ + """ + reader = self.reader('test-manifest-dupes') + +- with self.assertRaisesRegexp(SandboxValidationError, 'bar.js appears multiple times ' ++ with self.assertRaisesRegex(SandboxValidationError, 'bar.js appears multiple times ' + 'in a test manifest under a support-files field, please omit the duplicate entry.'): + self.read_topsrcdir(reader) + +@@ -454,7 +454,7 @@ + mozpath.join(o.install_prefix, "absolute-support.ini"), + mozpath.join(o.install_prefix, "test_file.js"), + ] +- paths = sorted([v[0] for v in o.installs.values()]) ++ paths = sorted([v[0] for v in list(o.installs.values())]) + self.assertEqual(paths, expected) + + @unittest.skip('Bug 1304316 - Items in the second set but not the first') +@@ -481,7 +481,7 @@ + """A non-existent shared support file reference produces an error.""" + reader = self.reader('test-manifest-shared-missing') + +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'entry in support-files not present in the srcdir'): + self.read_topsrcdir(reader) + +@@ -500,7 +500,7 @@ + mozpath.normpath(mozpath.join(o.install_prefix, "subdir/support.txt")), + mozpath.normpath(mozpath.join(o.install_prefix, "subdir/test_foo.html")), + ] +- paths = sorted([v[0] for v in o.installs.values()]) ++ paths = sorted([v[0] for v in list(o.installs.values())]) + self.assertEqual(paths, expected) + + def test_test_manifest_install_includes(self): +@@ -518,7 +518,7 @@ + mozpath.normpath(mozpath.join(o.install_prefix, "subdir/mochitest.ini")), + mozpath.normpath(mozpath.join(o.install_prefix, "subdir/test_foo.html")), + ] +- paths = sorted([v[0] for v in o.installs.values()]) ++ paths = sorted([v[0] for v in list(o.installs.values())]) + self.assertEqual(paths, expected) + + def test_test_manifest_includes(self): +@@ -541,7 +541,7 @@ + def test_python_unit_test_missing(self): + """Missing files in PYTHON_UNIT_TESTS should raise.""" + reader = self.reader('test-python-unit-test-missing') +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'Path specified in PYTHON_UNIT_TESTS does not exist:'): + self.read_topsrcdir(reader) + +@@ -635,7 +635,7 @@ + self.assertEqual(external_normalized, m.get('external', set())) + + self.assertEqual(len(o.installs), len(m['installs'])) +- for path in o.installs.keys(): ++ for path in list(o.installs.keys()): + self.assertTrue(path.startswith(o.directory)) + relpath = path[len(o.directory)+1:] + +@@ -648,7 +648,7 @@ + def test_test_manifest_unmatched_generated(self): + reader = self.reader('test-manifest-unmatched-generated') + +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'entry in generated-files not present elsewhere'): + self.read_topsrcdir(reader), + +@@ -672,7 +672,7 @@ + """Missing test files should result in error.""" + reader = self.reader('test-manifest-missing-test-file') + +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'lists test that does not exist: test_missing.html'): + self.read_topsrcdir(reader) + +@@ -680,7 +680,7 @@ + """Missing test files should result in error, even when the test list is not filtered.""" + reader = self.reader('test-manifest-missing-test-file-unfiltered') + +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'lists test that does not exist: missing.js'): + self.read_topsrcdir(reader) + +@@ -794,20 +794,20 @@ + self.assertIsInstance(obj.path, Path) + + def test_jar_manifests_multiple_files(self): +- with self.assertRaisesRegexp(SandboxValidationError, 'limited to one value'): ++ with self.assertRaisesRegex(SandboxValidationError, 'limited to one value'): + reader = self.reader('jar-manifests-multiple-files') + self.read_topsrcdir(reader) + + def test_xpidl_module_no_sources(self): + """XPIDL_MODULE without XPIDL_SOURCES should be rejected.""" +- with self.assertRaisesRegexp(SandboxValidationError, 'XPIDL_MODULE ' ++ with self.assertRaisesRegex(SandboxValidationError, 'XPIDL_MODULE ' + 'cannot be defined'): + reader = self.reader('xpidl-module-no-sources') + self.read_topsrcdir(reader) + + def test_missing_local_includes(self): + """LOCAL_INCLUDES containing non-existent directories should be rejected.""" +- with self.assertRaisesRegexp(SandboxValidationError, 'Path specified in ' ++ with self.assertRaisesRegex(SandboxValidationError, 'Path specified in ' + 'LOCAL_INCLUDES does not exist'): + reader = self.reader('missing-local-includes') + self.read_topsrcdir(reader) +@@ -852,7 +852,7 @@ + '.S': ['g.S'], + '.s': ['h.s', 'i.asm'], + } +- for suffix, files in expected.items(): ++ for suffix, files in list(expected.items()): + sources = suffix_map[suffix] + self.assertEqual( + sources.files, +@@ -905,7 +905,7 @@ + '.S': ['g.S'], + '.s': ['h.s', 'i.asm'], + } +- for suffix, files in expected.items(): ++ for suffix, files in list(expected.items()): + sources = suffix_map[suffix] + self.assertEqual( + sources.files, +@@ -931,7 +931,7 @@ + '.c': ['d.c'], + '.mm': ['e.mm', 'f.mm'], + } +- for suffix, files in expected.items(): ++ for suffix, files in list(expected.items()): + sources = suffix_map[suffix] + self.assertEqual( + sources.files, +@@ -956,7 +956,7 @@ + '.mm': ['objc1.mm', 'objc2.mm'], + '.c': ['c1.c', 'c2.c'], + } +- for suffix, files in expected.items(): ++ for suffix, files in list(expected.items()): + sources = suffix_map[suffix] + self.assertEqual( + sources.files, +@@ -982,7 +982,7 @@ + '.mm': ['objc1.mm', 'objc2.mm'], + '.c': ['c1.c', 'c2.c'], + } +- for suffix, files in expected.items(): ++ for suffix, files in list(expected.items()): + sources = suffix_map[suffix] + self.assertEqual( + sources.files, +@@ -1005,11 +1005,11 @@ + + expected = {'install.rdf', 'main.js'} + for f in files: +- self.assertTrue(unicode(f) in expected) ++ self.assertTrue(str(f) in expected) + + def test_missing_final_target_pp_files(self): + """Test that FINAL_TARGET_PP_FILES with missing files throws errors.""" +- with self.assertRaisesRegexp(SandboxValidationError, 'File listed in ' ++ with self.assertRaisesRegex(SandboxValidationError, 'File listed in ' + 'FINAL_TARGET_PP_FILES does not exist'): + reader = self.reader('dist-files-missing') + self.read_topsrcdir(reader) +@@ -1017,49 +1017,49 @@ + def test_final_target_pp_files_non_srcdir(self): + '''Test that non-srcdir paths in FINAL_TARGET_PP_FILES throws errors.''' + reader = self.reader('final-target-pp-files-non-srcdir') +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'Only source directory paths allowed in FINAL_TARGET_PP_FILES:'): + self.read_topsrcdir(reader) + + def test_rust_library_no_cargo_toml(self): + '''Test that defining a RustLibrary without a Cargo.toml fails.''' + reader = self.reader('rust-library-no-cargo-toml') +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'No Cargo.toml file found'): + self.read_topsrcdir(reader) + + def test_rust_library_name_mismatch(self): + '''Test that defining a RustLibrary that doesn't match Cargo.toml fails.''' + reader = self.reader('rust-library-name-mismatch') +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'library.*does not match Cargo.toml-defined package'): + self.read_topsrcdir(reader) + + def test_rust_library_no_lib_section(self): + '''Test that a RustLibrary Cargo.toml with no [lib] section fails.''' + reader = self.reader('rust-library-no-lib-section') +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'Cargo.toml for.* has no \\[lib\\] section'): + self.read_topsrcdir(reader) + + def test_rust_library_no_profile_section(self): + '''Test that a RustLibrary Cargo.toml with no [profile] section fails.''' + reader = self.reader('rust-library-no-profile-section') +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'Cargo.toml for.* has no \\[profile\\.dev\\] section'): + self.read_topsrcdir(reader) + + def test_rust_library_invalid_crate_type(self): + '''Test that a RustLibrary Cargo.toml has a permitted crate-type.''' + reader = self.reader('rust-library-invalid-crate-type') +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'crate-type.* is not permitted'): + self.read_topsrcdir(reader) + + def test_rust_library_non_abort_panic(self): + '''Test that a RustLibrary Cargo.toml has `panic = "abort" set''' + reader = self.reader('rust-library-non-abort-panic') +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'does not specify `panic = "abort"`'): + self.read_topsrcdir(reader) + +@@ -1072,15 +1072,15 @@ + self.assertEqual(len(objs), 1) + lib = objs[0] + self.assertIsInstance(lib, RustLibrary) +- self.assertRegexpMatches(lib.lib_name, "random_crate") +- self.assertRegexpMatches(lib.import_name, "random_crate") +- self.assertRegexpMatches(lib.basename, "random-crate") ++ self.assertRegex(lib.lib_name, "random_crate") ++ self.assertRegex(lib.import_name, "random_crate") ++ self.assertRegex(lib.basename, "random-crate") + + def test_multiple_rust_libraries(self): + '''Test that linking multiple Rust libraries throws an error''' + reader = self.reader('multiple-rust-libraries', + extra_substs=dict(RUST_TARGET='i686-pc-windows-msvc')) +- with self.assertRaisesRegexp(LinkageMultipleRustLibrariesError, ++ with self.assertRaisesRegex(LinkageMultipleRustLibrariesError, + 'Cannot link multiple Rust libraries'): + self.read_topsrcdir(reader) + +@@ -1107,7 +1107,7 @@ + mozpath.join(reader.config.topobjdir, 'dir2'), + '/dir3', + ] +- self.assertEquals([p.full_path for p in objs[0].paths], expected) ++ self.assertEqual([p.full_path for p in objs[0].paths], expected) + + def test_binary_components(self): + """Test that IS_COMPONENT/NO_COMPONENTS_MANIFEST work properly.""" +@@ -1163,7 +1163,7 @@ + from GENERATED_FILES is an error. + """ + reader = self.reader('test-symbols-file-objdir-missing-generated') +- with self.assertRaisesRegexp(SandboxValidationError, ++ with self.assertRaisesRegex(SandboxValidationError, + 'Objdir file specified in SYMBOLS_FILE not in GENERATED_FILES:'): + self.read_topsrcdir(reader) + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/frontend/test_namespaces.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/frontend/test_namespaces.py (refactored) +@@ -2,7 +2,7 @@ + # 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 unicode_literals ++ + + import unittest + +@@ -29,7 +29,7 @@ + + class Piyo(ContextDerivedValue): + def __init__(self, context, value): +- if not isinstance(value, unicode): ++ if not isinstance(value, str): + raise ValueError + self.context = context + self.value = value +@@ -48,9 +48,9 @@ + + + VARIABLES = { +- 'HOGE': (unicode, unicode, None), +- 'FUGA': (Fuga, unicode, None), +- 'PIYO': (Piyo, unicode, None), ++ 'HOGE': (str, str, None), ++ 'FUGA': (Fuga, str, None), ++ 'PIYO': (Piyo, str, None), + 'HOGERA': (ContextDerivedTypedList(Piyo, StrictOrderingOnAppendList), + list, None), + 'HOGEHOGE': (ContextDerivedTypedListWithItems( +@@ -104,7 +104,7 @@ + self.assertEqual(e[1], 'set_type') + self.assertEqual(e[2], 'HOGE') + self.assertEqual(e[3], True) +- self.assertEqual(e[4], unicode) ++ self.assertEqual(e[4], str) + + def test_key_checking(self): + # Checking for existence of a key should not populate the key if it +@@ -127,7 +127,7 @@ + self.assertEqual(e[1], 'set_type') + self.assertEqual(e[2], 'FUGA') + self.assertEqual(e[3], False) +- self.assertEqual(e[4], unicode) ++ self.assertEqual(e[4], str) + + ns['FUGA'] = 'fuga' + self.assertIsInstance(ns['FUGA'], Fuga) +@@ -150,7 +150,7 @@ + self.assertEqual(e[1], 'set_type') + self.assertEqual(e[2], 'PIYO') + self.assertEqual(e[3], False) +- self.assertEqual(e[4], unicode) ++ self.assertEqual(e[4], str) + + ns['PIYO'] = 'piyo' + self.assertIsInstance(ns['PIYO'], Piyo) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/frontend/test_reader.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/frontend/test_reader.py (refactored) +@@ -2,7 +2,7 @@ + # 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 unicode_literals ++ + + import os + import sys +@@ -423,7 +423,7 @@ + 'simple/base.cpp', + ]) + +- for path, pattern_set in expected.items(): ++ for path, pattern_set in list(expected.items()): + self.assertEqual(v[path].test_files, + expected[path]) + +@@ -438,7 +438,7 @@ + 'default/tests/reftests/**']), + } + +- for path, pattern_set in expected.items(): ++ for path, pattern_set in list(expected.items()): + self.assertEqual(v[path].test_files, + expected[path]) + +@@ -454,7 +454,7 @@ + 'tagged/src/bar.jsm': set(['tagged/**.js']), + } + +- for path, pattern_set in expected_patterns.items(): ++ for path, pattern_set in list(expected_patterns.items()): + self.assertEqual(v[path].test_files, + expected_patterns[path]) + +@@ -462,7 +462,7 @@ + 'tagged/src/submodule/foo.js': set(['submodule']), + 'tagged/src/bar.jsm': set([]), + } +- for path, pattern_set in expected_tags.items(): ++ for path, pattern_set in list(expected_tags.items()): + self.assertEqual(v[path].test_tags, + expected_tags[path]) + +@@ -470,7 +470,7 @@ + 'tagged/src/bar.jsm': set(['browser-chrome']), + 'tagged/src/submodule/foo.js': set([]), + } +- for path, pattern_set in expected_flavors.items(): ++ for path, pattern_set in list(expected_flavors.items()): + self.assertEqual(v[path].test_flavors, + expected_flavors[path]) + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/frontend/test_sandbox.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/test/frontend/test_sandbox.py (refactored) +@@ -2,7 +2,7 @@ + # 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 unicode_literals ++ + + import os + import shutil +@@ -345,7 +345,7 @@ + sandbox = MozbuildSandbox(Context(VARIABLES, config)) + + self.assertEqual(sandbox['CONFIG']['BAD_UTF8'], +- u'\ufffd\ufffd\ufffd\ufffd:') ++ '\ufffd\ufffd\ufffd\ufffd:') + + def test_invalid_exports_set_base(self): + sandbox = self.sandbox() +@@ -525,7 +525,7 @@ + source = 'a = foo(1, 2)' + sandbox.exec_source(source, 'foo.mozbuild') + +- self.assertEquals(sandbox['a'], (Foo, int)) ++ self.assertEqual(sandbox['a'], (Foo, int)) + finally: + del FUNCTIONS['foo'] + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/archive.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/archive.py (refactored) +@@ -2,7 +2,7 @@ + # 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 +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/copier.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/copier.py (refactored) +@@ -2,7 +2,7 @@ + # 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 os + import stat +@@ -109,7 +109,7 @@ + ''' + Return all paths stored in the container, in the order they were added. + ''' +- return self._files.keys() ++ return list(self._files.keys()) + + def __len__(self): + ''' +@@ -142,7 +142,7 @@ + for path, file in registry: + (...) + ''' +- return self._files.iteritems() ++ return iter(self._files.items()) + + def required_directories(self): + ''' +@@ -151,7 +151,7 @@ + unspecified (virtual) root directory (and do not include said root + directory). + ''' +- return set(k for k, v in self._required_directories.items() if v > 0) ++ return set(k for k, v in list(self._required_directories.items()) if v > 0) + + + class FileRegistrySubtree(object): +@@ -263,7 +263,7 @@ + + Returns a FileCopyResult that details what changed. + ''' +- assert isinstance(destination, basestring) ++ assert isinstance(destination, str) + assert not os.path.exists(destination) or os.path.isdir(destination) + + result = FileCopyResult() +@@ -531,7 +531,7 @@ + def exists(self): + return self.deflater is not None + +- if isinstance(dest, basestring): ++ if isinstance(dest, str): + dest = Dest(dest) + assert isinstance(dest, Dest) + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/errors.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/errors.py (refactored) +@@ -2,7 +2,7 @@ + # 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 sys + from contextlib import contextmanager +@@ -97,7 +97,7 @@ + if self._count is None: + raise ErrorMessage(msg) + self._count += 1 +- print >>self.out, msg ++ print(msg, file=self.out) + + def fatal(self, msg): + self._handle(self.FATAL, msg) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/executables.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/executables.py (refactored) +@@ -2,7 +2,7 @@ + # 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 os + import struct +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/files.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/files.py (refactored) +@@ -2,7 +2,7 @@ + # 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 errno + import os +@@ -57,7 +57,7 @@ + + def _copyfile(src, dest): + # False indicates `dest` should be overwritten if it exists already. +- if isinstance(src, unicode) and isinstance(dest, unicode): ++ if isinstance(src, str) and isinstance(dest, str): + _CopyFileW(src, dest, False) + elif isinstance(src, str) and isinstance(dest, str): + _CopyFileA(src, dest, False) +@@ -145,13 +145,13 @@ + # - 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 ++ if mode & 0o400: ++ ret |= 0o444 ++ if mode & 0o100: ++ ret |= 0o111 + # - keep user write permissions +- if mode & 0200: +- ret |= 0200 ++ if mode & 0o200: ++ ret |= 0o200 + # - leave away sticky bit, setuid, setgid + return ret + +@@ -164,7 +164,7 @@ + disabled when skip_if_older is False. + Returns whether a copy was actually performed (True) or not (False). + ''' +- if isinstance(dest, basestring): ++ if isinstance(dest, str): + dest = Dest(dest) + else: + assert isinstance(dest, Dest) +@@ -258,11 +258,11 @@ + ''' + def copy(self, dest, skip_if_older=True): + real_dest = dest +- if not isinstance(dest, basestring): ++ if not isinstance(dest, str): + fd, dest = mkstemp() + os.close(fd) + os.remove(dest) +- assert isinstance(dest, basestring) ++ assert isinstance(dest, str) + # If File.copy didn't actually copy because dest is newer, check the + # file sizes. If dest is smaller, it means it is already stripped and + # elfhacked, so we can skip. +@@ -299,7 +299,7 @@ + File.__init__(self, path) + + def copy(self, dest, skip_if_older=True): +- assert isinstance(dest, basestring) ++ assert isinstance(dest, str) + + # The logic in this function is complicated by the fact that symlinks + # aren't universally supported. So, where symlinks aren't supported, we +@@ -400,7 +400,7 @@ + self.required = required + + def copy(self, dest, skip_if_older=True): +- if isinstance(dest, basestring): ++ if isinstance(dest, str): + dest = Dest(dest) + else: + assert isinstance(dest, Dest) +@@ -432,7 +432,7 @@ + ''' + Invokes the preprocessor to create the destination file. + ''' +- if isinstance(dest, basestring): ++ if isinstance(dest, str): + dest = Dest(dest) + else: + assert isinstance(dest, Dest) +@@ -563,7 +563,7 @@ + the individual XPTs to link. + skip_if_older is ignored. + ''' +- if isinstance(dest, basestring): ++ if isinstance(dest, str): + dest = Dest(dest) + assert isinstance(dest, Dest) + +@@ -1014,7 +1014,7 @@ + from mozpack.copier import FileRegistry + self.files = FileRegistry() + +- for base, finder in sorted(finders.iteritems()): ++ for base, finder in sorted(finders.items()): + if self.files.contains(base): + self.files.remove(base) + for p, f in finder.find(''): +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/hg.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/hg.py (refactored) +@@ -27,7 +27,7 @@ + # do not wish to do so, delete this exception statement from your + # version. + +-from __future__ import absolute_import ++ + + import mercurial.error as error + import mercurial.hg as hg +@@ -56,7 +56,7 @@ + + Accepts a Mercurial localrepo and changectx instance. + """ +- if isinstance(repo, (str, unicode)): ++ if isinstance(repo, str): + path = repo + repo = hg.repository(hgui.ui(), repo) + else: +@@ -85,7 +85,7 @@ + return self._get(path) + + def _get(self, path): +- if isinstance(path, unicode): ++ if isinstance(path, str): + path = path.encode('utf-8', 'replace') + + try: +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/manifests.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/manifests.py (refactored) +@@ -2,7 +2,7 @@ + # 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, unicode_literals ++ + + from contextlib import contextmanager + import json +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/mozjar.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/mozjar.py (refactored) +@@ -2,7 +2,7 @@ + # 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 ++ + + from io import BytesIO + import struct +@@ -13,8 +13,9 @@ + ZIP_DEFLATED, + ) + from collections import OrderedDict +-from urlparse import urlparse, ParseResult ++from urllib.parse import urlparse, ParseResult + import mozpack.path as mozpath ++from functools import reduce + + JAR_STORED = ZIP_STORED + JAR_DEFLATED = ZIP_DEFLATED +@@ -68,7 +69,7 @@ + an instance with empty fields. + ''' + assert self.MAGIC and isinstance(self.STRUCT, OrderedDict) +- self.size_fields = set(t for t in self.STRUCT.itervalues() ++ self.size_fields = set(t for t in self.STRUCT.values() + if not t in JarStruct.TYPE_MAPPING) + self._values = {} + if data: +@@ -90,7 +91,7 @@ + # For all fields used as other fields sizes, keep track of their value + # separately. + sizes = dict((t, 0) for t in self.size_fields) +- for name, t in self.STRUCT.iteritems(): ++ for name, t in self.STRUCT.items(): + if t in JarStruct.TYPE_MAPPING: + value, size = JarStruct.get_data(t, data[offset:]) + else: +@@ -109,7 +110,7 @@ + Initialize an instance with empty fields. + ''' + self.signature = self.MAGIC +- for name, t in self.STRUCT.iteritems(): ++ for name, t in self.STRUCT.items(): + if name in self.size_fields: + continue + self._values[name] = 0 if t in JarStruct.TYPE_MAPPING else '' +@@ -134,9 +135,9 @@ + from self.STRUCT. + ''' + serialized = struct.pack('<I', self.signature) +- sizes = dict((t, name) for name, t in self.STRUCT.iteritems() ++ sizes = dict((t, name) for name, t in self.STRUCT.items() + if not t in JarStruct.TYPE_MAPPING) +- for name, t in self.STRUCT.iteritems(): ++ for name, t in self.STRUCT.items(): + if t in JarStruct.TYPE_MAPPING: + format, size = JarStruct.TYPE_MAPPING[t] + if name in sizes: +@@ -155,7 +156,7 @@ + variable length fields. + ''' + size = JarStruct.TYPE_MAPPING['uint32'][1] +- for name, type in self.STRUCT.iteritems(): ++ for name, type in self.STRUCT.items(): + if type in JarStruct.TYPE_MAPPING: + size += JarStruct.TYPE_MAPPING[type][1] + else: +@@ -176,7 +177,7 @@ + return key in self._values + + def __iter__(self): +- return self._values.iteritems() ++ return iter(self._values.items()) + + def __repr__(self): + return "<%s %s>" % (self.__class__.__name__, +@@ -374,7 +375,7 @@ + preload = JarStruct.get_data('uint32', self._data)[0] + entries = OrderedDict() + offset = self._cdir_end['cdir_offset'] +- for e in xrange(self._cdir_end['cdir_entries']): ++ for e in range(self._cdir_end['cdir_entries']): + entry = JarCdirEntry(self._data[offset:]) + offset += entry.size + # Creator host system. 0 is MSDOS, 3 is Unix +@@ -385,7 +386,7 @@ + xattr = entry['external_attr'] + # Skip directories + if (host == 0 and xattr & 0x10) or (host == 3 and +- xattr & (040000 << 16)): ++ xattr & (0o40000 << 16)): + continue + entries[entry['filename']] = entry + if entry['offset'] < preload: +@@ -436,7 +437,7 @@ + for file in jarReader: + ... + ''' +- for entry in self.entries.itervalues(): ++ for entry in self.entries.values(): + yield self._getreader(entry) + + def __getitem__(self, name): +@@ -529,7 +530,7 @@ + headers = {} + preload_size = 0 + # Prepare central directory entries +- for entry, content in self._contents.itervalues(): ++ for entry, content in self._contents.values(): + header = JarLocalFileHeader() + for name in entry.STRUCT: + if name in header: +@@ -544,7 +545,7 @@ + end['disk_entries'] = len(self._contents) + end['cdir_entries'] = end['disk_entries'] + end['cdir_size'] = reduce(lambda x, y: x + y[0].size, +- self._contents.values(), 0) ++ list(self._contents.values()), 0) + # On optimized archives, store the preloaded size and the central + # directory entries, followed by the first end of central directory. + if self._optimize: +@@ -553,18 +554,18 @@ + if preload_size: + preload_size += offset + self._data.write(struct.pack('<I', preload_size)) +- for entry, _ in self._contents.itervalues(): ++ for entry, _ in self._contents.values(): + entry['offset'] += offset + self._data.write(entry.serialize()) + self._data.write(end.serialize()) + # Store local file entries followed by compressed data +- for entry, content in self._contents.itervalues(): ++ for entry, content in self._contents.values(): + self._data.write(headers[entry].serialize()) + self._data.write(content) + # On non optimized archives, store the central directory entries. + if not self._optimize: + end['cdir_offset'] = offset +- for entry, _ in self._contents.itervalues(): ++ for entry, _ in self._contents.values(): + self._data.write(entry.serialize()) + # Store the end of central directory. + self._data.write(end.serialize()) +@@ -599,7 +600,7 @@ + deflater = data + else: + deflater = Deflater(compress, compress_level=self._compress_level) +- if isinstance(data, basestring): ++ if isinstance(data, str): + deflater.write(data) + elif hasattr(data, 'read'): + if hasattr(data, 'seek'): +@@ -615,7 +616,7 @@ + # 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 +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/path.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/path.py (refactored) +@@ -2,7 +2,7 @@ + # 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 posixpath + import os +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/unify.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/unify.py (refactored) +@@ -2,7 +2,7 @@ + # 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 ++ + + from mozpack.files import ( + BaseFinder, +@@ -73,7 +73,7 @@ + creating the instance. + skip_if_older is ignored. + ''' +- assert isinstance(dest, basestring) ++ assert isinstance(dest, str) + tmpfiles = [] + try: + for e in self._executables: +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/chrome/flags.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/chrome/flags.py (refactored) +@@ -2,7 +2,7 @@ + # 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 re + from distutils.version import LooseVersion +@@ -250,7 +250,7 @@ + flags.match(application='foo', appversion='3.5') returns True + flags.match(application='foo', appversion='3.0') returns False + ''' +- for name, value in filter.iteritems(): ++ for name, value in filter.items(): + if not name in self: + continue + if not self[name].matches(value): +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/chrome/manifest.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/chrome/manifest.py (refactored) +@@ -2,11 +2,11 @@ + # 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 re + import os +-from urlparse import urlparse ++from urllib.parse import urlparse + import mozpack.path as mozpath + from mozpack.chrome.flags import Flags + from mozpack.errors import errors +@@ -321,7 +321,7 @@ + return self.serialize(self.contractID, self.cid) + + # All manifest classes by their type name. +-MANIFESTS_TYPES = dict([(c.type, c) for c in globals().values() ++MANIFESTS_TYPES = dict([(c.type, c) for c in list(globals().values()) + if type(c) == type and issubclass(c, ManifestEntry) + and hasattr(c, 'type') and c.type]) + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/packager/__init__.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/packager/__init__.py (refactored) +@@ -2,7 +2,7 @@ + # 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 ++ + + from mozbuild.preprocessor import Preprocessor + import re +@@ -50,7 +50,7 @@ + ''' + Split [1, 2, 3, 4, 5, 6, 7] into [(1, 2, 3), (4, 5, 6)]. + ''' +- return zip(*[iter(lst)] * 3) ++ return list(zip(*[iter(lst)] * 3)) + + KEY_VALUE_RE = re.compile(r''' + \s* # optional whitespace. +@@ -118,7 +118,7 @@ + destdir = options.pop('destdir', '') + if options: + errors.fatal('Malformed manifest: options %s not recognized' +- % options.keys()) ++ % list(options.keys())) + return Component(name, destdir=destdir) + + +@@ -328,7 +328,7 @@ + + bases = self.get_bases() + broken_bases = sorted( +- m for m, includer in self._included_manifests.iteritems() ++ m for m, includer in self._included_manifests.items() + if mozpath.basedir(m, bases) != mozpath.basedir(includer, bases)) + for m in broken_bases: + errors.fatal('"%s" is included from "%s", which is outside "%s"' % +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/packager/formats.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/packager/formats.py (refactored) +@@ -2,7 +2,7 @@ + # 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 ++ + + from mozpack.chrome.manifest import ( + Manifest, +@@ -11,7 +11,7 @@ + ManifestBinaryComponent, + ManifestResource, + ) +-from urlparse import urlparse ++from urllib.parse import urlparse + import mozpack.path as mozpath + from mozpack.files import ( + ManifestFile, +@@ -89,7 +89,7 @@ + Return the deepest base directory containing the given path. + ''' + self._frozen_bases = True +- base = mozpath.basedir(path, self._sub_formatter.keys()) ++ base = mozpath.basedir(path, list(self._sub_formatter.keys())) + relpath = mozpath.relpath(path, base) if base else path + return base, relpath + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/packager/l10n.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/packager/l10n.py (refactored) +@@ -2,7 +2,7 @@ + # 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 ++ + + ''' + Replace localized parts of a packaged directory with data from a langpack +@@ -162,7 +162,7 @@ + if not path: + continue + else: +- base = mozpath.basedir(p, paths.keys()) ++ base = mozpath.basedir(p, list(paths.keys())) + if base: + subpath = mozpath.relpath(p, base) + path = mozpath.normpath(mozpath.join(paths[base], +@@ -206,7 +206,7 @@ + formatter.add(p, f) + + # Transplant jar preloading information. +- for path, log in app_finder.jarlogs.iteritems(): ++ for path, log in app_finder.jarlogs.items(): + assert isinstance(copier[path], Jarrer) + copier[path].preload([l.replace(locale, l10n_locale) for l in log]) + +@@ -237,7 +237,7 @@ + finders = { + '': l10n_finder, + } +- for base, path in extra_l10n.iteritems(): ++ for base, path in extra_l10n.items(): + finders[base] = UnpackFinder(path) + l10n_finder = ComposedFinder(finders) + copier = FileCopier() +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/packager/unpack.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/packager/unpack.py (refactored) +@@ -2,7 +2,7 @@ + # 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 mozpack.path as mozpath + from mozpack.files import ( +@@ -27,7 +27,7 @@ + FlatFormatter, + STARTUP_CACHE_PATHS, + ) +-from urlparse import urlparse ++from urllib.parse import urlparse + + + class UnpackFinder(BaseFinder): +@@ -149,7 +149,7 @@ + if not any(f.compressed for f in jar): + self.compressed = False + if jar.last_preloaded: +- jarlog = jar.entries.keys() ++ jarlog = list(jar.entries.keys()) + self.jarlogs[path] = jarlog[:jarlog.index(jar.last_preloaded) + 1] + return jar + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_archive.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_archive.py (refactored) +@@ -2,7 +2,7 @@ + # 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 hashlib + import os +@@ -69,7 +69,7 @@ + try: + tp = os.path.join(d, 'test.tar') + with open(tp, 'wb') as fh: +- with self.assertRaisesRegexp(ValueError, 'not a regular'): ++ with self.assertRaisesRegex(ValueError, 'not a regular'): + create_tar_from_files(fh, {'test': d}) + finally: + shutil.rmtree(d) +@@ -89,9 +89,9 @@ + + tp = os.path.join(d, 'test.tar') + with open(tp, 'wb') as fh: +- with self.assertRaisesRegexp(ValueError, 'cannot add file with setuid'): ++ with self.assertRaisesRegex(ValueError, 'cannot add file with setuid'): + create_tar_from_files(fh, {'test': uid}) +- with self.assertRaisesRegexp(ValueError, 'cannot add file with setuid'): ++ with self.assertRaisesRegex(ValueError, 'cannot add file with setuid'): + create_tar_from_files(fh, {'test': gid}) + finally: + shutil.rmtree(d) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_chrome_manifest.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_chrome_manifest.py (refactored) +@@ -24,7 +24,7 @@ + parse_manifest_line, + ) + from mozpack.errors import errors, AccumulatedErrors +-from test_errors import TestErrors ++from .test_errors import TestErrors + + + class TestManifest(unittest.TestCase): +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_copier.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_copier.py (refactored) +@@ -127,7 +127,7 @@ + 'bar': [], + } + reg = FileRegistry() +- for path, parts in cases.iteritems(): ++ for path, parts in cases.items(): + self.assertEqual(reg._partial_paths(path), parts) + + def test_file_registry(self): +@@ -414,7 +414,7 @@ + self.assertTrue(stat.S_ISDIR(st.st_mode)) + + # What's worse, we have no record that dest was created. +- self.assertEquals(len(result.updated_files), 0) ++ self.assertEqual(len(result.updated_files), 0) + + # But we do have an erroneous record of an optional file + # existing when it does not. +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_errors.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_errors.py (refactored) +@@ -10,7 +10,7 @@ + import unittest + import mozunit + import sys +-from cStringIO import StringIO ++from io import StringIO + + + class TestErrors(object): +@@ -30,14 +30,14 @@ + errors.warn('foo') + self.assertRaises(ErrorMessage, errors.error, 'foo') + self.assertRaises(ErrorMessage, errors.fatal, 'foo') +- self.assertEquals(self.get_output(), ['Warning: foo']) ++ self.assertEqual(self.get_output(), ['Warning: foo']) + + def test_ignore_errors(self): + errors.ignore_errors() + errors.warn('foo') + errors.error('bar') + self.assertRaises(ErrorMessage, errors.fatal, 'foo') +- self.assertEquals(self.get_output(), ['Warning: foo', 'Warning: bar']) ++ self.assertEqual(self.get_output(), ['Warning: foo', 'Warning: bar']) + + def test_no_error(self): + with errors.accumulate(): +@@ -47,14 +47,14 @@ + with self.assertRaises(AccumulatedErrors): + with errors.accumulate(): + errors.error('1') +- self.assertEquals(self.get_output(), ['Error: 1']) ++ self.assertEqual(self.get_output(), ['Error: 1']) + + def test_error_loop(self): + with self.assertRaises(AccumulatedErrors): + with errors.accumulate(): + for i in range(3): + errors.error('%d' % i) +- self.assertEquals(self.get_output(), ++ self.assertEqual(self.get_output(), + ['Error: 0', 'Error: 1', 'Error: 2']) + + def test_multiple_errors(self): +@@ -67,7 +67,7 @@ + else: + errors.error('%d' % i) + errors.error('bar') +- self.assertEquals(self.get_output(), ++ self.assertEqual(self.get_output(), + ['Error: foo', 'Error: 0', 'Error: 1', + 'Warning: 2', 'Error: bar']) + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_files.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_files.py (refactored) +@@ -61,7 +61,7 @@ + import mozpack.path as mozpath + from tempfile import mkdtemp + from io import BytesIO +-from StringIO import StringIO ++from io import StringIO + from xpt import Typelib + + +@@ -146,7 +146,7 @@ + dest.write('qux') + self.assertEqual(dest.read(), 'qux') + +-rand = ''.join(random.choice(string.letters) for i in xrange(131597)) ++rand = ''.join(random.choice(string.letters) for i in range(131597)) + samples = [ + '', + 'test', +@@ -268,7 +268,7 @@ + def test_absolute_relative(self): + AbsoluteSymlinkFile('/foo') + +- with self.assertRaisesRegexp(ValueError, 'Symlink target not absolute'): ++ with self.assertRaisesRegex(ValueError, 'Symlink target not absolute'): + AbsoluteSymlinkFile('./foo') + + def test_symlink_file(self): +@@ -477,7 +477,7 @@ + + class TestExistingFile(TestWithTmpDir): + def test_required_missing_dest(self): +- with self.assertRaisesRegexp(ErrorMessage, 'Required existing file'): ++ with self.assertRaisesRegex(ErrorMessage, 'Required existing file'): + f = ExistingFile(required=True) + f.copy(self.tmppath('dest')) + +@@ -566,7 +566,7 @@ + with JarWriter(src) as jar: + for content in samples: + name = ''.join(random.choice(string.letters) +- for i in xrange(8)) ++ for i in range(8)) + jar.add(name, content, compress=True) + contents[name] = content + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_manifests.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_manifests.py (refactored) +@@ -2,7 +2,7 @@ + # 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 unicode_literals ++ + + import os + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_mozjar.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_mozjar.py (refactored) +@@ -16,8 +16,8 @@ + from mozpack.test.test_files import MockDest + import unittest + import mozunit +-from cStringIO import StringIO +-from urllib import pathname2url ++from io import StringIO ++from urllib.request import pathname2url + import mozpack.path as mozpath + import os + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_packager_formats.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_packager_formats.py (refactored) +@@ -128,7 +128,7 @@ + 'foo': read_interfaces(foo2_xpt.open())['foo'], + 'bar': read_interfaces(bar_xpt.open())['bar'], + }, +- }.iteritems() ++ }.items() + }) + + RESULT_JAR = { +@@ -174,7 +174,7 @@ + }, + 'addon1.xpi': { + mozpath.relpath(p, 'addon1'): f +- for p, f in RESULT_FLAT.iteritems() ++ for p, f in RESULT_FLAT.items() + if p.startswith('addon1/') + }, + }) +@@ -234,7 +234,7 @@ + CONTENTS_WITH_BASE = { + 'bases': { + mozpath.join('base/root', b) if b else 'base/root': a +- for b, a in CONTENTS['bases'].iteritems() ++ for b, a in CONTENTS['bases'].items() + }, + 'manifests': [ + m.move(mozpath.join('base/root', m.base)) +@@ -242,7 +242,7 @@ + ], + 'files': { + mozpath.join('base/root', p): f +- for p, f in CONTENTS['files'].iteritems() ++ for p, f in CONTENTS['files'].items() + }, + } + +@@ -255,7 +255,7 @@ + def result_with_base(results): + result = { + mozpath.join('base/root', p): v +- for p, v in results.iteritems() ++ for p, v in results.items() + } + result.update(EXTRA_CONTENTS) + return result +@@ -271,13 +271,13 @@ + + + def fill_formatter(formatter, contents): +- for base, is_addon in contents['bases'].items(): ++ for base, is_addon in list(contents['bases'].items()): + formatter.add_base(base, is_addon) + + for manifest in contents['manifests']: + formatter.add_manifest(manifest) + +- for k, v in contents['files'].iteritems(): ++ for k, v in contents['files'].items(): + if k.endswith('.xpt'): + formatter.add_interfaces(k, v) + else: +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_packager_l10n.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_packager_l10n.py (refactored) +@@ -4,7 +4,7 @@ + + import unittest + import mozunit +-from test_packager import MockFinder ++from .test_packager import MockFinder + from mozpack.packager import l10n + from mozpack.files import ( + GeneratedFile, +@@ -118,7 +118,7 @@ + + self.assertEqual( + dict((p, f.open().read()) for p, f in copier), +- dict((p, f.open().read()) for p, f in repacked.iteritems()) ++ dict((p, f.open().read()) for p, f in repacked.items()) + ) + + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_unify.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/test_unify.py (refactored) +@@ -13,7 +13,7 @@ + from mozpack.files import FileFinder + from mozpack.mozjar import JarWriter + from mozpack.test.test_files import MockDest +-from cStringIO import StringIO ++from io import StringIO + import os + import sys + from mozpack.errors import ( +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/support/minify_js_verify.py (original) ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/test/support/minify_js_verify.py (refactored) +@@ -2,7 +2,7 @@ + # 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 print_function ++ + import sys + + +--- thunderbird-52.9.0/mozilla/build/moz.configure/keyfiles.configure.old 2017-04-11 02:13:08.000000000 +0000 ++++ thunderbird-52.9.0/mozilla/build/moz.configure/keyfiles.configure 2018-07-10 07:57:16.030000000 +0000 +@@ -16,8 +16,8 @@ + + @depends('--with-%s-keyfile' % name) + @checking('for the %s key' % desc, lambda x: x and x is not no_key) +- @imports(_from='__builtin__', _import='open') +- @imports(_from='__builtin__', _import='IOError') ++ @imports(_from='builtins', _import='open') ++ @imports(_from='builtins', _import='IOError') + def keyfile(value): + if value: + try: +--- thunderbird-52.9.0/mozilla/build/moz.configure/windows.configure.old 2017-04-11 02:13:08.000000000 +0000 ++++ thunderbird-52.9.0/mozilla/build/moz.configure/windows.configure 2018-07-10 07:57:25.210000000 +0000 +@@ -19,7 +19,7 @@ + + + @depends_win('--with-windows-version') +-@imports(_from='__builtin__', _import='ValueError') ++@imports(_from='builtins', _import='ValueError') + def valid_windows_version(value): + if not value: + die('Cannot build with --without-windows-version') +@@ -56,8 +56,8 @@ + # 8.1. + @imports('os') + @imports('re') +-@imports(_from='__builtin__', _import='sorted') +-@imports(_from='__builtin__', _import='WindowsError') ++@imports(_from='builtins', _import='sorted') ++@imports(_from='builtins', _import='WindowsError') + def get_sdk_dirs(sdk, subdir): + def get_dirs_containing(sdk, stem, subdir): + base = os.path.join(sdk, stem) +@@ -102,7 +102,7 @@ + @depends_win(c_compiler, windows_sdk_dir, valid_windows_version, + 'WINDOWSSDKDIR') + @checking('for Windows SDK', valid_windows_sdk_dir_result) +-@imports(_from='__builtin__', _import='sorted') ++@imports(_from='builtins', _import='sorted') + @imports(_from='textwrap', _import='dedent') + def valid_windows_sdk_dir(compiler, windows_sdk_dir, target_version, + windows_sdk_dir_env): +@@ -179,7 +179,7 @@ + @depends_win(windows_sdk_dir, 'WINDOWSSDKDIR') + @checking('for Universal CRT SDK', valid_ucrt_sdk_dir_result) + @imports('os') +-@imports(_from='__builtin__', _import='sorted') ++@imports(_from='builtins', _import='sorted') + @imports(_import='mozpack.path', _as='mozpath') + def valid_ucrt_sdk_dir(windows_sdk_dir, windows_sdk_dir_env): + if windows_sdk_dir_env: +--- thunderbird-52.9.0/mozilla/build/moz.configure/toolchain.configure.old 2017-04-11 02:13:08.000000000 +0000 ++++ thunderbird-52.9.0/mozilla/build/moz.configure/toolchain.configure 2018-07-10 07:57:28.830000000 +0000 +@@ -395,7 +395,7 @@ + + + @imports(_from='collections', _import='defaultdict') +-@imports(_from='__builtin__', _import='sorted') ++@imports(_from='builtins', _import='sorted') + def get_vc_paths(base): + vc = defaultdict(lambda: defaultdict(dict)) + subkey = r'Microsoft\VisualStudio\VC\*\*\*\Compiler' +--- thunderbird-52.9.0/mozilla/build/moz.configure/util.configure.old 2017-04-11 02:13:08.000000000 +0000 ++++ thunderbird-52.9.0/mozilla/build/moz.configure/util.configure 2018-07-10 07:57:31.540000000 +0000 +@@ -234,7 +234,7 @@ + # ('19.0', 'x64', r'C:\...\amd64\cl.exe') + # ('19.0', 'x86', r'C:\...\amd64_x86\cl.exe') + @imports(_import='_winreg', _as='winreg') +-@imports(_from='__builtin__', _import='WindowsError') ++@imports(_from='builtins', _import='WindowsError') + @imports(_from='fnmatch', _import='fnmatch') + def get_registry_values(pattern): + def enum_helper(func, key): +--- thunderbird-52.9.0/mozilla/build/moz.configure/checks.configure.old 2017-04-11 02:13:08.000000000 +0000 ++++ thunderbird-52.9.0/mozilla/build/moz.configure/checks.configure 2018-07-10 07:57:35.630000000 +0000 +@@ -12,7 +12,7 @@ + # _declare_exceptions template, and add it to the return statement. Then + # destructure in the assignment below the function declaration. + @template +-@imports(_from='__builtin__', _import='Exception') ++@imports(_from='builtins', _import='Exception') + def _declare_exceptions(): + class FatalCheckError(Exception): + '''An exception to throw from a function decorated with @checking. +--- thunderbird-52.9.0/mozilla/build/moz.configure/old.configure.old 2017-04-11 02:13:08.000000000 +0000 ++++ thunderbird-52.9.0/mozilla/build/moz.configure/old.configure 2018-07-10 07:57:38.970000000 +0000 +@@ -61,8 +61,8 @@ + + @depends('OLD_CONFIGURE', mozconfig, autoconf, check_build_environment, shell, + old_configure_assignments, build_project) +-@imports(_from='__builtin__', _import='open') +-@imports(_from='__builtin__', _import='print') ++@imports(_from='builtins', _import='open') ++@imports(_from='builtins', _import='print') + @imports('glob') + @imports('itertools') + @imports('subprocess') +@@ -302,8 +302,8 @@ + '--enable-calendar', + '--enable-incomplete-external-linkage', + ) +-@imports(_from='__builtin__', _import='compile') +-@imports(_from='__builtin__', _import='open') ++@imports(_from='builtins', _import='compile') ++@imports(_from='builtins', _import='open') + @imports('logging') + @imports('os') + @imports('subprocess') +--- thunderbird-52.9.0/mozilla/build/moz.configure/android-ndk.configure.old 2017-04-11 02:13:08.000000000 +0000 ++++ thunderbird-52.9.0/mozilla/build/moz.configure/android-ndk.configure 2018-07-10 07:57:41.120000000 +0000 +@@ -22,7 +22,7 @@ + default=min_android_version) + + @depends('--with-android-version', min_android_version) +-@imports(_from='__builtin__', _import='ValueError') ++@imports(_from='builtins', _import='ValueError') + def android_version(value, min_version): + if not value: + # Someone has passed --without-android-version. +--- thunderbird-52.9.0/mozilla/build/moz.configure/init.configure.old 2017-04-11 02:13:08.000000000 +0000 ++++ thunderbird-52.9.0/mozilla/build/moz.configure/init.configure 2018-07-10 07:57:44.330000000 +0000 +@@ -636,7 +636,7 @@ + # - otherwise, if we have "a" in GRE_MILESTONE, we're building Nightly or Aurora + # - otherwise, we're building Release/Beta (define RELEASE_OR_BETA) + @depends(check_build_environment, '--help') +-@imports(_from='__builtin__', _import='open') ++@imports(_from='builtins', _import='open') + def milestone(build_env, _): + milestone_path = os.path.join(build_env.topsrcdir, + 'config', +diff -aur thunderbird-52.9.0/mozilla/config/mozunit.py mozjs-fixed/config/mozunit.py +--- thunderbird-52.9.0/mozilla/config/mozunit.py 2017-04-11 02:13:09.000000000 +0000 ++++ mozjs-fixed/config/mozunit.py 2018-07-10 08:19:37.770000000 +0000 +@@ -5,7 +5,7 @@ + from unittest import TextTestRunner as _TestRunner, TestResult as _TestResult + import unittest + import inspect +-from StringIO import StringIO ++from io import StringIO + import os + import sys + +@@ -74,7 +74,7 @@ + + def printFail(self, test, err): + exctype, value, tb = err +- message = value.message.splitlines()[0] if value.message else 'NO MESSAGE' ++ message = str(value).splitlines()[0] if str(value) else 'NO MESSAGE' + # Skip test runner traceback levels + while tb and self._is_relevant_tb_level(tb): + tb = tb.tb_next +diff -aur thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/configenvironment.py mozjs-fixed/python/mozbuild/mozbuild/backend/configenvironment.py +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/configenvironment.py 2018-07-10 08:24:43.150000000 +0000 ++++ mozjs-fixed/python/mozbuild/mozbuild/backend/configenvironment.py 2018-07-10 08:15:12.650000000 +0000 +@@ -8,7 +8,8 @@ + import sys + + from collections import Iterable +-from types import StringTypes, ModuleType ++from types import ModuleType ++StringTypes = (str,) + + import mozpack.path as mozpath + +diff -aur thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/makeutil.py mozjs-fixed/python/mozbuild/mozbuild/makeutil.py +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/makeutil.py 2018-07-10 08:24:43.150000000 +0000 ++++ mozjs-fixed/python/mozbuild/mozbuild/makeutil.py 2018-07-10 08:20:05.230000000 +0000 +@@ -6,7 +6,6 @@ + + import os + import re +-from types import StringTypes + from collections import Iterable + + +@@ -103,19 +102,19 @@ + + def add_targets(self, targets): + '''Add additional targets to the rule.''' +- assert isinstance(targets, Iterable) and not isinstance(targets, StringTypes) ++ assert isinstance(targets, Iterable) and not isinstance(targets, str) + self._targets.update(targets) + return self + + def add_dependencies(self, deps): + '''Add dependencies to the rule.''' +- assert isinstance(deps, Iterable) and not isinstance(deps, StringTypes) ++ assert isinstance(deps, Iterable) and not isinstance(deps, str) + self._dependencies.update(deps) + return self + + def add_commands(self, commands): + '''Add commands to the rule.''' +- assert isinstance(commands, Iterable) and not isinstance(commands, StringTypes) ++ assert isinstance(commands, Iterable) and not isinstance(commands, str) + self._commands.extend(commands) + return self + +diff -aur thunderbird-52.9.0/mozilla/python/which/which.py mozjs-fixed/python/which/which.py +--- thunderbird-52.9.0/mozilla/python/which/which.py 2017-04-11 02:13:24.000000000 +0000 ++++ mozjs-fixed/python/which/which.py 2018-07-10 08:11:01.570000000 +0000 +@@ -280,17 +280,17 @@ + try: + optlist, args = getopt.getopt(argv[1:], 'haVvqp:e:', + ['help', 'all', 'version', 'verbose', 'quiet', 'path=', 'exts=']) +- except getopt.GetoptError, msg: ++ except getopt.GetoptError as msg: + sys.stderr.write("which: error: %s. Your invocation was: %s\n"\ + % (msg, argv)) + sys.stderr.write("Try 'which --help'.\n") + return 1 + for opt, optarg in optlist: + if opt in ('-h', '--help'): +- print _cmdlnUsage ++ print(_cmdlnUsage) + return 0 + elif opt in ('-V', '--version'): +- print "which %s" % __version__ ++ print("which %s" % __version__) + return 0 + elif opt in ('-a', '--all'): + all = 1 +@@ -318,9 +318,9 @@ + nmatches = 0 + for match in whichgen(arg, path=altpath, verbose=verbose, exts=exts): + if verbose: +- print "%s (%s)" % match ++ print("%s (%s)" % match) + else: +- print match ++ print(match) + nmatches += 1 + if not all: + break +diff -aur thunderbird-52.9.0/mozilla/testing/mozbase/mozprocess/mozprocess/processhandler.py mozjs-fixed/testing/mozbase/mozprocess/mozprocess/processhandler.py +--- thunderbird-52.9.0/mozilla/testing/mozbase/mozprocess/mozprocess/processhandler.py 2017-04-11 02:13:06.000000000 +0000 ++++ mozjs-fixed/testing/mozbase/mozprocess/mozprocess/processhandler.py 2018-07-10 08:13:15.440000000 +0000 +@@ -11,7 +11,7 @@ + import threading + import time + import traceback +-from Queue import Queue, Empty ++from queue import Queue, Empty + from datetime import datetime + + __all__ = ['ProcessHandlerMixin', 'ProcessHandler', 'LogOutput', +@@ -121,14 +121,14 @@ + thread = threading.current_thread().name + print("DBG::MOZPROC PID:{} ({}) | {}".format(self.pid, thread, msg)) + +- def __del__(self, _maxint=sys.maxint): ++ def __del__(self, _maxint=sys.maxsize): + if isWin: + handle = getattr(self, '_handle', None) + if handle: + if hasattr(self, '_internal_poll'): + self._internal_poll(_deadstate=_maxint) + else: +- self.poll(_deadstate=sys.maxint) ++ self.poll(_deadstate=sys.maxsize) + if handle or self._job or self._io_port: + self._cleanup() + else: +@@ -267,7 +267,7 @@ + if not (can_create_job or can_nest_jobs): + # Since we've warned, we just log info here to inform you + # of the consequence of setting ignore_children = True +- print "ProcessManager NOT managing child processes" ++ print("ProcessManager NOT managing child processes") + + # create the process + hp, ht, pid, tid = winprocess.CreateProcess( +@@ -534,11 +534,11 @@ + + if rc == winprocess.WAIT_TIMEOUT: + # The process isn't dead, so kill it +- print "Timed out waiting for process to close, attempting TerminateProcess" ++ print("Timed out waiting for process to close, attempting TerminateProcess") + self.kill() + elif rc == winprocess.WAIT_OBJECT_0: + # We caught WAIT_OBJECT_0, which indicates all is well +- print "Single process terminated successfully" ++ print("Single process terminated successfully") + self.returncode = winprocess.GetExitCodeProcess(self._handle) + else: + # An error occured we should probably throw +diff -aur thunderbird-52.9.0/mozilla/build/moz.configure/checks.configure mozjs-fixed/build/moz.configure/checks.configure +--- thunderbird-52.9.0/mozilla/build/moz.configure/checks.configure 2018-07-10 10:29:50.380000000 +0000 ++++ mozjs-fixed/build/moz.configure/checks.configure 2018-07-10 10:27:45.350000000 +0000 +@@ -52,7 +52,7 @@ + try: + ret = func(*args, **kwargs) + except FatalCheckError as e: +- error = e.message ++ error = str(e) + display_ret = callback(ret) if callback else ret + if display_ret is True: + log.info('yes') +diff -aur thunderbird-52.9.0/mozilla/build/moz.configure/init.configure mozjs-fixed/build/moz.configure/init.configure +--- thunderbird-52.9.0/mozilla/build/moz.configure/init.configure 2018-07-10 10:29:50.380000000 +0000 ++++ mozjs-fixed/build/moz.configure/init.configure 2018-07-10 10:23:19.960000000 +0000 +@@ -213,7 +213,7 @@ + def early_options(): + return set( + option.env +- for option in __sandbox__._options.itervalues() ++ for option in list(__sandbox__._options.values()) + if option.env + ) + return early_options +@@ -297,7 +297,7 @@ + # There is also a quartet form: + # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM + # But we can consider the "KERNEL-OPERATING_SYSTEM" as one. +- cpu, manufacturer, os = triplet.split('-', 2) ++ cpu, manufacturer, os = triplet.decode('utf-8').split('-', 2) + + # Autoconf uses config.sub to validate and canonicalize those triplets, + # but the granularity of its results has never been satisfying to our +@@ -727,7 +727,7 @@ + def all_configure_options(_): + result = [] + previous = None +- for option in __sandbox__._options.itervalues(): ++ for option in list(__sandbox__._options.values()): + # __sandbox__._options contains items for both option.name and + # option.env. But it's also an OrderedDict, meaning both are + # consecutive. +diff -aur thunderbird-52.9.0/mozilla/build/moz.configure/old.configure mozjs-fixed/build/moz.configure/old.configure +--- thunderbird-52.9.0/mozilla/build/moz.configure/old.configure 2018-07-10 10:29:50.380000000 +0000 ++++ mozjs-fixed/build/moz.configure/old.configure 2018-07-10 10:19:19.880000000 +0000 +@@ -360,7 +360,7 @@ + # Every variation of the exec() function I tried led to: + # SyntaxError: unqualified exec is not allowed in function 'main' it + # contains a nested function with free variables +- exec code in raw_config ++ exec(code, raw_config) + + # Ensure all the flags known to old-configure appear in the + # @old_configure_options above. +diff -aur thunderbird-52.9.0/mozilla/build/moz.configure/toolchain.configure mozjs-fixed/build/moz.configure/toolchain.configure +--- thunderbird-52.9.0/mozilla/build/moz.configure/toolchain.configure 2018-07-10 10:29:50.380000000 +0000 ++++ mozjs-fixed/build/moz.configure/toolchain.configure 2018-07-10 10:28:13.020000000 +0000 +@@ -244,7 +244,7 @@ + ('CPU', CPU_preprocessor_checks), + ('KERNEL', kernel_preprocessor_checks), + ): +- for n, (value, condition) in enumerate(preprocessor_checks.iteritems()): ++ for n, (value, condition) in enumerate(preprocessor_checks.items()): + check += dedent('''\ + #%(if)s %(condition)s + %%%(name)s "%(value)s" +@@ -278,9 +278,9 @@ + data = {} + for line in result.splitlines(): + if line.startswith(b'%'): +- k, _, v = line.partition(' ') +- k = k.lstrip('%') +- data[k] = v.replace(' ', '').lstrip('"').rstrip('"') ++ k, _, v = line.partition(b' ') ++ k = k.lstrip(b'%').decode('utf-8') ++ data[k] = v.replace(b' ', b'').lstrip(b'"').rstrip(b'"').decode('utf-8') + log.debug('%s = %s', k, data[k]) + + try: +diff -aur thunderbird-52.9.0/mozilla/build/moz.configure/util.configure mozjs-fixed/build/moz.configure/util.configure +--- thunderbird-52.9.0/mozilla/build/moz.configure/util.configure 2018-07-10 10:29:50.380000000 +0000 ++++ mozjs-fixed/build/moz.configure/util.configure 2018-07-10 10:23:54.980000000 +0000 +@@ -299,6 +299,8 @@ + @imports(_from='mozbuild.configure.util', _import='Version', _as='_Version') + def Version(v): + 'A version number that can be compared usefully.' ++ if isinstance(v, bytes): ++ v = v.decode('utf-8') + return _Version(v) + + # Denotes a deprecated option. Combines option() and @depends: +diff -aur thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/__init__.py mozjs-fixed/python/mozbuild/mozbuild/configure/__init__.py +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/__init__.py 2018-07-10 10:29:50.350000000 +0000 ++++ mozjs-fixed/python/mozbuild/mozbuild/configure/__init__.py 2018-07-10 10:24:33.200000000 +0000 +@@ -97,6 +97,9 @@ + ', '.join(repr(d) for d in self.dependencies), + ) + ++ def __hash__(self): ++ return hash((str(self.func), tuple(self.dependencies), self.when)) ++ + + class CombinedDependsFunction(DependsFunction): + def __init__(self, sandbox, func, dependencies): +@@ -142,6 +145,9 @@ + def __ne__(self, other): + return not self == other + ++ def __hash__(self): ++ return hash((str(self.func), tuple(self.dependencies))) ++ + class SandboxedGlobal(dict): + '''Identifiable dict type for use as function global''' + +@@ -192,7 +198,8 @@ + b: __builtins__[b] + for b in ('None', 'False', 'True', 'int', 'bool', 'any', 'all', 'len', + 'list', 'tuple', 'set', 'dict', 'isinstance', 'getattr', +- 'hasattr', 'enumerate', 'range', 'zip') ++ 'hasattr', 'enumerate', 'range', 'zip', '__build_class__', ++ 'bytes', 'exec') + }, __import__=forbidden_import, str=str) + + # Expose a limited set of functions from os.path +@@ -267,7 +274,7 @@ + return method + def wrapped(*args, **kwargs): + out_args = [ +- arg.decode(encoding) if isinstance(arg, str) else arg ++ arg.decode(encoding) if isinstance(arg, bytes) else arg + for arg in args + ] + return method(*out_args, **kwargs) +diff -aur thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/options.py mozjs-fixed/python/mozbuild/mozbuild/configure/options.py +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/options.py 2018-07-10 10:29:50.350000000 +0000 ++++ mozjs-fixed/python/mozbuild/mozbuild/configure/options.py 2018-07-10 10:15:41.760000000 +0000 +@@ -65,6 +65,9 @@ + return '%s%s' % (self.__class__.__name__, + super(OptionValue, self).__repr__()) + ++ def __hash__(self): ++ return hash(str(self)) ++ + + class PositiveOptionValue(OptionValue): + '''Represents the value for a positive option (--enable/--with/--foo) +diff -aur thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/util.py mozjs-fixed/python/mozbuild/mozbuild/configure/util.py +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/configure/util.py 2018-07-10 10:29:50.350000000 +0000 ++++ mozjs-fixed/python/mozbuild/mozbuild/configure/util.py 2018-07-10 09:04:28.150000000 +0000 +@@ -200,7 +200,7 @@ + self._encoding = getpreferredencoding() + + def write(self, buf): +- if self._encoding and isinstance(buf, str): ++ if self._encoding and isinstance(buf, bytes): + buf = buf.decode(self._encoding) + lines = buf.splitlines() + if not lines: +diff -aur thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/virtualenv.py mozjs-fixed/python/mozbuild/mozbuild/virtualenv.py +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/virtualenv.py 2018-07-10 10:29:50.350000000 +0000 ++++ mozjs-fixed/python/mozbuild/mozbuild/virtualenv.py 2018-07-10 10:11:47.710000000 +0000 +@@ -108,7 +108,7 @@ + """ + ver = subprocess.check_output([python, '-c', 'import sys; print(sys.hexversion)']).rstrip() + with open(self.exe_info_path, 'w') as fh: +- fh.write("%s\n" % ver) ++ fh.write("%s\n" % ver.decode('utf-8')) + fh.write("%s\n" % os.path.getsize(python)) + + def up_to_date(self, python=sys.executable): +@@ -207,7 +207,7 @@ + return self.virtualenv_root + + def packages(self): +- with file(self.manifest_path, 'rU') as fh: ++ with open(self.manifest_path, 'rU') as fh: + packages = [line.rstrip().split(':') + for line in fh] + return packages +@@ -530,9 +530,9 @@ + + our = LooseVersion('%d.%d.%d' % (major, minor, micro)) + +- if major != MINIMUM_PYTHON_MAJOR or our < MINIMUM_PYTHON_VERSION: +- log_handle.write('Python %s or greater (but not Python 3) is ' +- 'required to build. ' % MINIMUM_PYTHON_VERSION) ++ if our < MINIMUM_PYTHON_VERSION: ++ log_handle.write('Python %s or greater is required to build. ' ++ % MINIMUM_PYTHON_VERSION) + log_handle.write('You are running Python %s.\n' % our) + + if os.name in ('nt', 'ce'): +diff -aur thunderbird-52.9.0/mozilla/python/which/which.py mozjs-fixed/python/which/which.py +--- thunderbird-52.9.0/mozilla/python/which/which.py 2018-07-10 10:29:50.380000000 +0000 ++++ mozjs-fixed/python/which/which.py 2018-07-10 10:20:16.770000000 +0000 +@@ -243,7 +243,7 @@ + If no match is found for the command, a WhichError is raised. + """ + try: +- match = whichgen(command, path, verbose, exts).next() ++ match = next(whichgen(command, path, verbose, exts)) + except StopIteration: + raise WhichError("Could not find '%s' on the path." % command) + return match +--- thunderbird-52.9.0/mozilla/build/moz.configure/old.configure.old 2018-07-10 10:32:48.550000000 +0000 ++++ thunderbird-52.9.0/mozilla/build/moz.configure/old.configure 2018-07-10 10:35:32.440000000 +0000 +@@ -107,7 +107,7 @@ + + # Make old-configure append to config.log, where we put our own log. + # This could be done with a m4 macro, but it's way easier this way +- script = script.replace('>./config.log', '>>./config.log') ++ script = script.replace(b'>./config.log', b'>>./config.log') + + with open(old_configure, 'wb') as fh: + fh.write(script) +--- thunderbird-52.9.0/mozilla/build/subconfigure.py.old 2017-04-11 02:13:09.000000000 +0000 ++++ thunderbird-52.9.0/mozilla/build/subconfigure.py 2018-07-10 10:38:08.910000000 +0000 +@@ -27,7 +27,7 @@ + return super(Pool, cls).__new__(cls) + + def imap_unordered(self, fn, iterable): +- return itertools.imap(fn, iterable) ++ return map(fn, iterable) + + def close(self): + pass +@@ -131,11 +131,11 @@ + is_set = cache.get('ac_cv_env_%s_set' % precious) == 'set' + value = cache.get('ac_cv_env_%s_value' % precious) if is_set else None + if value != env.get(precious): +- print 'Removing %s because of %s value change from:' \ +- % (data['cache-file'], precious) +- print ' %s' % (value if value is not None else 'undefined') +- print 'to:' +- print ' %s' % env.get(precious, 'undefined') ++ print('Removing %s because of %s value change from:' \ ++ % (data['cache-file'], precious)) ++ print(' %s' % (value if value is not None else 'undefined')) ++ print('to:') ++ print(' %s' % env.get(precious, 'undefined')) + os.remove(data['cache-file']) + return True + return False +@@ -333,8 +333,8 @@ + # We're going to run it ourselves. + command += ['--no-create'] + +- print prefix_lines('configuring', relobjdir) +- print prefix_lines('running %s' % ' '.join(command[:-1]), relobjdir) ++ print(prefix_lines('configuring', relobjdir)) ++ print(prefix_lines('running %s' % ' '.join(command[:-1]), relobjdir)) + sys.stdout.flush() + try: + output += subprocess.check_output(command, +@@ -368,7 +368,7 @@ + + if not skip_config_status: + if skip_configure: +- print prefix_lines('running config.status', relobjdir) ++ print(prefix_lines('running config.status', relobjdir)) + sys.stdout.flush() + try: + output += subprocess.check_output([data['shell'], '-c', +@@ -410,7 +410,7 @@ + pool = Pool(len(subconfigures)) + for relobjdir, returncode, output in \ + pool.imap_unordered(run, subconfigures): +- print prefix_lines(output, relobjdir) ++ print(prefix_lines(output, relobjdir)) + sys.stdout.flush() + ret = max(returncode, ret) + if ret: +--- thunderbird-52.9.0/mozilla/build/moz.configure/old.configure.old 2018-07-10 10:38:53.530000000 +0000 ++++ thunderbird-52.9.0/mozilla/build/moz.configure/old.configure 2018-07-10 10:41:32.560000000 +0000 +@@ -394,7 +394,7 @@ + def post_old_configure(raw_config): + for k, v in raw_config['substs']: + set_old_configure_config( +- k[1:-1], v[1:-1] if isinstance(v, types.StringTypes) else v) ++ k[1:-1], v[1:-1] if isinstance(v, str) else v) + +- for k, v in dict(raw_config['defines']).iteritems(): ++ for k, v in dict(raw_config['defines']).items(): + set_old_configure_define(k[1:-1], v[1:-1]) +--- thunderbird-52.9.0/mozilla/configure.py (original) ++++ thunderbird-52.9.0/mozilla/configure.py (refactored) +@@ -2,7 +2,7 @@ + # 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 print_function, unicode_literals ++ + + import codecs + import os +@@ -45,11 +45,11 @@ + + sanitized_config = {} + sanitized_config['substs'] = { +- k: sanitized_bools(v) for k, v in config.iteritems() ++ k: sanitized_bools(v) for k, v in config.items() + if k not in ('DEFINES', 'non_global_defines', 'TOPSRCDIR', 'TOPOBJDIR') + } + sanitized_config['defines'] = { +- k: sanitized_bools(v) for k, v in config['DEFINES'].iteritems() ++ k: sanitized_bools(v) for k, v in config['DEFINES'].items() + } + sanitized_config['non_global_defines'] = config['non_global_defines'] + sanitized_config['topsrcdir'] = config['TOPSRCDIR'] +@@ -71,7 +71,7 @@ + ''') % {'python': config['PYTHON'], 'encoding': encoding}) + # A lot of the build backend code is currently expecting byte + # strings and breaks in subtle ways with unicode strings. (bug 1296508) +- for k, v in sanitized_config.iteritems(): ++ for k, v in sanitized_config.items(): + fh.write('%s = encode(%s, encoding)\n' % (k, indented_repr(v))) + fh.write("__all__ = ['topobjdir', 'topsrcdir', 'defines', " + "'non_global_defines', 'substs', 'mozconfig']") +@@ -88,7 +88,7 @@ + # executable permissions. + os.chmod('config.status', 0o755) + if config.get('MOZ_BUILD_APP') != 'js' or config.get('JS_STANDALONE'): +- os.environ[b'WRITE_MOZINFO'] = b'1' ++ os.environ['WRITE_MOZINFO'] = '1' + from mozbuild.config_status import config_status + + # Some values in sanitized_config also have more complex types, such as +--- thunderbird-52.9.0/mozilla/python/blessings/blessings/__init__.py.old 2017-04-11 02:13:23.000000000 +0000 ++++ thunderbird-52.9.0/mozilla/python/blessings/blessings/__init__.py 2018-07-10 10:56:52.820000000 +0000 +@@ -333,7 +333,7 @@ + 'shadow', 'standout', 'subscript', 'superscript'])) + + +-class ParametrizingString(unicode): ++class ParametrizingString(str): + """A Unicode string which can be called to parametrize it as a terminal capability""" + def __new__(cls, formatting, normal=None): + """Instantiate. +@@ -343,7 +343,7 @@ + "normal" capability. + + """ +- new = unicode.__new__(cls, formatting) ++ new = str.__new__(cls, formatting) + new._normal = normal + return new + +@@ -375,10 +375,10 @@ + raise + + +-class FormattingString(unicode): ++class FormattingString(str): + """A Unicode string which can be called upon a piece of text to wrap it in formatting""" + def __new__(cls, formatting, normal): +- new = unicode.__new__(cls, formatting) ++ new = str.__new__(cls, formatting) + new._normal = normal + return new + +@@ -393,7 +393,7 @@ + return self + text + self._normal + + +-class NullCallableString(unicode): ++class NullCallableString(str): + """A dummy class to stand in for ``FormattingString`` and ``ParametrizingString`` + + A callable bytestring that returns an empty Unicode when called with an int +@@ -402,7 +402,7 @@ + + """ + def __new__(cls): +- new = unicode.__new__(cls, u'') ++ new = str.__new__(cls, u'') + return new + + def __call__(self, arg): +--- thunderbird-52.9.0/mozilla/testing/mozbase/mozfile/mozfile/mozfile.py (original) ++++ thunderbird-52.9.0/mozilla/testing/mozbase/mozfile/mozfile/mozfile.py (refactored) +@@ -6,7 +6,7 @@ + + # We don't import all modules at the top for performance reasons. See Bug 1008943 + +-from __future__ import absolute_import ++ + + from contextlib import contextmanager + import errno +@@ -55,7 +55,7 @@ + try: + bundle = zipfile.ZipFile(src) + except Exception: +- print "src: %s" % src ++ print("src: %s" % src) + raise + + namelist = bundle.namelist() +@@ -161,8 +161,8 @@ + + retry_count += 1 + +- print '%s() failed for "%s". Reason: %s (%s). Retrying...' % \ +- (func.__name__, args, e.strerror, e.errno) ++ print('%s() failed for "%s". Reason: %s (%s). Retrying...' % \ ++ (func.__name__, args, e.strerror, e.errno)) + time.sleep(retry_count * retry_delay) + else: + # If no exception has been thrown it should be done +@@ -420,9 +420,9 @@ + Return True if thing looks like a URL. + """ + +- import urlparse +- +- parsed = urlparse.urlparse(thing) ++ import urllib.parse ++ ++ parsed = urllib.parse.urlparse(thing) + if 'scheme' in parsed: + return len(parsed.scheme) >= 2 + else: +@@ -436,7 +436,7 @@ + result of urllib2.urlopen() + """ + +- import urllib2 ++ import urllib.request, urllib.error, urllib.parse + + # handle file URLs separately due to python stdlib limitations + if resource.startswith('file://'): +@@ -446,4 +446,4 @@ + # if no scheme is given, it is a file path +- return file(resource) ++ return open(resource) + +- return urllib2.urlopen(resource) ++ return urllib.request.urlopen(resource) +--- thunderbird-52.9.0/mozilla/testing/mozbase/mozinfo/mozinfo/mozinfo.py (original) ++++ thunderbird-52.9.0/mozilla/testing/mozbase/mozinfo/mozinfo/mozinfo.py (refactored) +@@ -8,7 +8,7 @@ + # linux) to the information; I certainly wouldn't want anyone parsing this + # information and having behaviour depend on it + +-from __future__ import absolute_import ++ + + import os + import platform +@@ -24,7 +24,7 @@ + class unknown(object): + """marker class for unknown information""" + +- def __nonzero__(self): ++ def __bool__(self): + return False + + def __str__(self): +@@ -184,7 +184,7 @@ + to a json file containing the new info. + """ + +- if isinstance(new_info, basestring): ++ if isinstance(new_info, str): + # lazy import + import mozfile + import json +@@ -246,7 +246,7 @@ + update({}) + + # exports +-__all__ = info.keys() ++__all__ = list(info.keys()) + __all__ += ['is' + os_name.title() for os_name in choices['os']] + __all__ += [ + 'info', +@@ -284,17 +284,17 @@ + + # print out choices if requested + flag = False +- for key, value in options.__dict__.items(): ++ for key, value in list(options.__dict__.items()): + if value is True: +- print '%s choices: %s' % (key, ' '.join([str(choice) +- for choice in choices[key]])) ++ print('%s choices: %s' % (key, ' '.join([str(choice) ++ for choice in choices[key]]))) + flag = True + if flag: + return + + # otherwise, print out all info +- for key, value in info.items(): +- print '%s: %s' % (key, value) ++ for key, value in list(info.items()): ++ print('%s: %s' % (key, value)) + + if __name__ == '__main__': + main() +--- thunderbird-52.9.0/mozilla/testing/mozbase/mozinfo/mozinfo/string_version.py.old 2017-04-11 02:13:06.000000000 +0000 ++++ thunderbird-52.9.0/mozilla/testing/mozbase/mozinfo/mozinfo/string_version.py 2018-07-10 11:10:56.140000000 +0000 +@@ -10,8 +10,10 @@ + A string version that can be compared with comparison operators. + """ + ++ def __new__(cls, value): ++ return str.__new__(cls, value) ++ + def __init__(self, vstring): +- str.__init__(self, vstring) + self.version = LooseVersion(vstring) + + def __repr__(self): +--- thunderbird-52.9.0/mozilla/testing/mozbase/manifestparser/manifestparser/manifestparser.py (original) ++++ thunderbird-52.9.0/mozilla/testing/mozbase/manifestparser/manifestparser/manifestparser.py (refactored) +@@ -2,7 +2,7 @@ + # 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 StringIO import StringIO ++from io import StringIO + import json + import fnmatch + import os +@@ -21,7 +21,7 @@ + __all__ = ['ManifestParser', 'TestManifest', 'convert'] + + relpath = os.path.relpath +-string = (basestring,) ++string = (str,) + + + # path normalization +@@ -178,7 +178,7 @@ + + # otherwise an item + # apply ancestor defaults, while maintaining current file priority +- data = dict(self._ancestor_defaults.items() + data.items()) ++ data = dict(list(self._ancestor_defaults.items()) + list(data.items())) + + test = data + test['name'] = section +@@ -306,19 +306,19 @@ + # make some check functions + if inverse: + def has_tags(test): +- return not tags.intersection(test.keys()) ++ return not tags.intersection(list(test.keys())) + + def dict_query(test): +- for key, value in kwargs.items(): ++ for key, value in list(kwargs.items()): + if test.get(key) == value: + return False + return True + else: + def has_tags(test): +- return tags.issubset(test.keys()) ++ return tags.issubset(list(test.keys())) + + def dict_query(test): +- for key, value in kwargs.items(): ++ for key, value in list(kwargs.items()): + if test.get(key) != value: + return False + return True +@@ -340,7 +340,7 @@ + """ + if tests is None: + # Make sure to return all the manifests, even ones without tests. +- return self.manifest_defaults.keys() ++ return list(self.manifest_defaults.keys()) + + manifests = [] + for test in tests: +@@ -373,8 +373,8 @@ + raise IOError("Strict mode enabled, test paths must exist. " + "The following test(s) are missing: %s" % + json.dumps(missing_paths, indent=2)) +- print >> sys.stderr, "Warning: The following test(s) are missing: %s" % \ +- json.dumps(missing_paths, indent=2) ++ print("Warning: The following test(s) are missing: %s" % \ ++ json.dumps(missing_paths, indent=2), file=sys.stderr) + return missing + + def verifyDirectory(self, directories, pattern=None, extensions=None): +@@ -385,7 +385,7 @@ + """ + + files = set([]) +- if isinstance(directories, basestring): ++ if isinstance(directories, str): + directories = [directories] + + # get files in directories +@@ -449,12 +449,12 @@ + + # print the .ini manifest + if global_tags or global_kwargs: +- print >> fp, '[DEFAULT]' ++ print('[DEFAULT]', file=fp) + for tag in global_tags: +- print >> fp, '%s =' % tag +- for key, value in global_kwargs.items(): +- print >> fp, '%s = %s' % (key, value) +- print >> fp ++ print('%s =' % tag, file=fp) ++ for key, value in list(global_kwargs.items()): ++ print('%s = %s' % (key, value), file=fp) ++ print(file=fp) + + for test in tests: + test = test.copy() # don't overwrite +@@ -465,7 +465,7 @@ + if self.rootdir: + path = relpath(test['path'], self.rootdir) + path = denormalize_path(path) +- print >> fp, '[%s]' % path ++ print('[%s]' % path, file=fp) + + # reserved keywords: + reserved = ['path', 'name', 'here', 'manifest', 'relpath', 'ancestor-manifest'] +@@ -476,8 +476,8 @@ + continue + if key in global_tags and not test[key]: + continue +- print >> fp, '%s = %s' % (key, test[key]) +- print >> fp ++ print('%s = %s' % (key, test[key]), file=fp) ++ print(file=fp) + + if close: + # close the created file +@@ -565,7 +565,7 @@ + message = "Missing test: '%s' does not exist!" + if self.strict: + raise IOError(message) +- print >> sys.stderr, message + " Skipping." ++ print(message + " Skipping.", file=sys.stderr) + continue + destination = os.path.join(rootdir, _relpath) + shutil.copy(source, destination) +@@ -578,7 +578,7 @@ + internal function to import directories + """ + +- if isinstance(pattern, basestring): ++ if isinstance(pattern, str): + patterns = [pattern] + else: + patterns = pattern +@@ -670,9 +670,9 @@ + if (dirnames or filenames) and not (os.path.exists(manifest_path) and overwrite): + with file(manifest_path, 'w') as manifest: + for dirname in dirnames: +- print >> manifest, '[include:%s]' % os.path.join(dirname, filename) ++ print('[include:%s]' % os.path.join(dirname, filename), file=manifest) + for _filename in filenames: +- print >> manifest, '[%s]' % _filename ++ print('[%s]' % _filename, file=manifest) + + # add to list of manifests + manifest_dict.setdefault(directory, manifest_path) +@@ -722,8 +722,8 @@ + for filename in filenames] + + # write to manifest +- print >> write, '\n'.join(['[%s]' % denormalize_path(filename) +- for filename in filenames]) ++ print('\n'.join(['[%s]' % denormalize_path(filename) ++ for filename in filenames]), file=write) + + cls._walk_directories(directories, callback, pattern=pattern, ignore=ignore) + +--- thunderbird-52.9.0/mozilla/testing/mozbase/manifestparser/manifestparser/cli.py (original) ++++ thunderbird-52.9.0/mozilla/testing/mozbase/manifestparser/manifestparser/cli.py (refactored) +@@ -81,7 +81,7 @@ + # parse the arguments + try: + kwargs, tags, args = parse_args(args) +- except ParserError, e: ++ except ParserError as e: + self._parser.error(e.message) + + # make sure we have some manifests, otherwise it will +@@ -132,7 +132,7 @@ + manifest = convert(args, pattern=options.pattern, ignore=options.ignore, + write=options.in_place) + if manifest: +- print manifest ++ print(manifest) + + + class WriteCLI(CLICommand): +@@ -146,7 +146,7 @@ + # parse the arguments + try: + kwargs, tags, args = parse_args(args) +- except ParserError, e: ++ except ParserError as e: + self._parser.error(e.message) + + # make sure we have some manifests, otherwise it will +@@ -175,9 +175,9 @@ + commands[args[0]](self._parser).parser().print_help() + else: + self._parser.print_help() +- print '\nCommands:' ++ print('\nCommands:') + for command in sorted(commands): +- print ' %s : %s' % (command, commands[command].__doc__.strip()) ++ print(' %s : %s' % (command, commands[command].__doc__.strip())) + + + class UpdateCLI(CLICommand): +@@ -190,7 +190,7 @@ + # parse the arguments + try: + kwargs, tags, args = parse_args(args) +- except ParserError, e: ++ except ParserError as e: + self._parser.error(e.message) + + # make sure we have some manifests, otherwise it will +--- thunderbird-52.9.0/mozilla/testing/mozbase/manifestparser/manifestparser/expression.py (original) ++++ thunderbird-52.9.0/mozilla/testing/mozbase/manifestparser/manifestparser/expression.py (refactored) +@@ -275,7 +275,7 @@ + """ + if not isinstance(self.token, expected): + raise Exception("Unexpected token!") +- self.token = self.iter.next() ++ self.token = next(self.iter) + + def expression(self, rbp=0): + """ +@@ -283,11 +283,11 @@ + right binding power greater than rbp is encountered. + """ + t = self.token +- self.token = self.iter.next() ++ self.token = next(self.iter) + left = t.nud(self) + while rbp < self.token.lbp: + t = self.token +- self.token = self.iter.next() ++ self.token = next(self.iter) + left = t.led(self, left) + return left + +@@ -299,7 +299,7 @@ + """ + try: + self.iter = self._tokenize() +- self.token = self.iter.next() ++ self.token = next(self.iter) + return self.expression() + except: + extype, ex, tb = sys.exc_info() +@@ -307,7 +307,7 @@ + raise ParseError("could not parse: " + "%s\nexception: %svariables: %s" % (self.text, + formatted, +- self.valuemapping)), None, tb ++ self.valuemapping)).with_traceback(tb) + + __call__ = parse + +--- thunderbird-52.9.0/mozilla/testing/mozbase/manifestparser/manifestparser/filters.py (original) ++++ thunderbird-52.9.0/mozilla/testing/mozbase/manifestparser/manifestparser/filters.py (refactored) +@@ -92,7 +92,7 @@ + def __init__(self, *args, **kwargs): + self.fmt_args = ', '.join(itertools.chain( + [str(a) for a in args], +- ['{}={}'.format(k, v) for k, v in kwargs.iteritems()])) ++ ['{}={}'.format(k, v) for k, v in kwargs.items()])) + + def __eq__(self, other): + if self.unique: +@@ -249,7 +249,7 @@ + # be yielded for reporting purposes. Put them all in chunk 1 for + # simplicity. + if self.this_chunk == 1: +- disabled_dirs = [v for k, v in tests_by_dir.iteritems() ++ disabled_dirs = [v for k, v in tests_by_dir.items() + if k not in ordered_dirs] + for disabled_test in itertools.chain(*disabled_dirs): + yield disabled_test +@@ -326,7 +326,7 @@ + + def __init__(self, tags): + InstanceFilter.__init__(self, tags) +- if isinstance(tags, basestring): ++ if isinstance(tags, str): + tags = [tags] + self.tags = tags + +@@ -349,7 +349,7 @@ + + def __init__(self, paths): + InstanceFilter.__init__(self, paths) +- if isinstance(paths, basestring): ++ if isinstance(paths, str): + paths = [paths] + self.paths = paths + +--- thunderbird-52.9.0/mozilla/testing/mozbase/manifestparser/manifestparser/ini.py (original) ++++ thunderbird-52.9.0/mozilla/testing/mozbase/manifestparser/manifestparser/ini.py (refactored) +@@ -27,7 +27,7 @@ + sections = [] + key = value = None + section_names = set() +- if isinstance(fp, basestring): +- fp = file(fp) ++ if isinstance(fp, str): ++ fp = open(fp) + + # read the lines +@@ -131,7 +131,7 @@ + 'support-files': '%s %s', + } + final_mapping = global_vars.copy() +- for field_name, value in local_vars.items(): ++ for field_name, value in list(local_vars.items()): + if field_name not in field_patterns or field_name not in global_vars: + final_mapping[field_name] = value + continue +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/util.py.old 2018-07-10 11:16:10.690000000 +0000 ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/util.py 2018-07-10 23:36:02.250000000 +0000 +@@ -1254,10 +1254,10 @@ + encode(k, encoding): encode(v, encoding) + for k, v in obj.items() + } +- if isinstance(obj, bytes): +- return obj + if isinstance(obj, str): +- return obj.encode(encoding) ++ return obj ++ if isinstance(obj, bytes): ++ return obj.decode(encoding) + if isinstance(obj, Iterable): + return [encode(i, encoding) for i in obj] + return obj +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/util.py.old 2018-07-10 23:36:33.980000000 +0000 ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/util.py 2018-07-10 23:41:51.900000000 +0000 +@@ -1179,6 +1179,9 @@ + POSSIBLE_VALUES = possible_values + return EnumStringSubclass + ++ def __hash__(self): ++ return hash(str(self)) ++ + + def _escape_char(c): + # str.encode('unicode_espace') doesn't escape quotes, presumably because +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/mozinfo.py.old 2018-07-10 23:42:19.390000000 +0000 ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/mozinfo.py 2018-07-11 01:45:57.930000000 +0000 +@@ -155,6 +155,6 @@ + """ + build_conf = build_dict(config, env) + if isinstance(file, str): +- file = open(file, 'wb') ++ file = open(file, 'w') + + json.dump(build_conf, file, sort_keys=True, indent=4) +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/jar.py.old 2018-07-11 01:46:26.540000000 +0000 ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/jar.py 2018-07-11 02:02:36.010000000 +0000 +@@ -16,7 +16,7 @@ + import re + import logging + from time import localtime +-from MozZipFile import ZipFile ++from zipfile import ZipFile + from io import StringIO + from collections import defaultdict + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/util.py.old 2018-07-11 02:05:38.530000000 +0000 ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/util.py 2018-07-11 02:08:21.020000000 +0000 +@@ -987,8 +987,6 @@ + 'got %s, expected %s' % (fname, + type(value), ftype)) + +- super(TypedTuple, self).__init__(*args, **kwargs) +- + TypedTuple._fields = fields + + return TypedTuple +--- thunderbird-52.9.0/mozilla/build/moz.configure/init.configure.old 2018-07-11 02:08:50.000000000 +0000 ++++ thunderbird-52.9.0/mozilla/build/moz.configure/init.configure 2018-07-11 04:04:26.600000000 +0000 +@@ -297,7 +297,9 @@ + # There is also a quartet form: + # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM + # But we can consider the "KERNEL-OPERATING_SYSTEM" as one. +- cpu, manufacturer, os = triplet.decode('utf-8').split('-', 2) ++ if isinstance(triplet, bytes): ++ triplet = triplet.decode('utf-8') ++ cpu, manufacturer, os = triplet.split('-', 2) + + # Autoconf uses config.sub to validate and canonicalize those triplets, + # but the granularity of its results has never been satisfying to our +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/reader.py.old 2018-07-11 04:25:33.980000000 +0000 ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/reader.py 2018-07-11 04:24:50.630000000 +0000 +@@ -441,6 +441,8 @@ + code = func.__code__ + firstlineno = code.co_firstlineno + lines = sandbox._current_source.splitlines(True) ++ if len(lines) and isinstance(lines[0], bytes): ++ lines = [l.decode('utf-8') for l in lines] + lines = inspect.getblock(lines[firstlineno - 1:]) + + # The code lines we get out of inspect.getsourcelines look like +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/reader.py.old 2018-07-11 04:25:57.090000000 +0000 ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/reader.py 2018-07-11 04:29:46.140000000 +0000 +@@ -460,7 +460,7 @@ + # actually never calls __getitem__ and __setitem__, so we need to + # modify the AST so that accesses to globals are properly directed + # to a dict. +- self._global_name = b'_data' # AST wants str for this, not unicode ++ self._global_name = '_data' # AST wants str for this, not unicode + # In case '_data' is a name used for a variable in the function code, + # prepend more underscores until we find an unused name. + while (self._global_name in code.co_names or +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/context.py.old 2018-07-11 04:30:06.590000000 +0000 ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/frontend/context.py 2018-07-11 04:35:38.670000000 +0000 +@@ -384,8 +384,8 @@ + + def __cmp__(self, other): + if isinstance(other, Path) and self.srcdir != other.srcdir: +- return cmp(self.full_path, other.full_path) +- return cmp(str(self), other) ++ return self.full_path == other.full_path ++ return str(self) == other + + # __cmp__ is not enough because unicode has __eq__, __ne__, etc. defined + # and __cmp__ is only used for those when they don't exist. +--- thunderbird-52.9.0/mozilla/mozglue/build/moz.build.old 2018-07-11 04:40:17.930000000 +0000 ++++ thunderbird-52.9.0/mozilla/mozglue/build/moz.build 2018-07-11 04:42:00.830000000 +0000 +@@ -4,20 +4,15 @@ + # 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/. + +-# Build mozglue as a shared lib on Windows, OSX and Android. ++# Build mozglue as a shared lib on Windows and OSX. + # If this is ever changed, update MOZ_SHARED_MOZGLUE in browser/installer/Makefile.in +-if CONFIG['OS_TARGET'] in ('WINNT', 'Darwin', 'Android'): ++if CONFIG['OS_TARGET'] in ('WINNT', 'Darwin'): + SharedLibrary('mozglue') + else: + Library('mozglue') + + SDK_LIBRARY = True + +-if CONFIG['OS_TARGET'] == 'Android': +- SOURCES += [ +- 'BionicGlue.cpp', +- ] +- + if CONFIG['MOZ_ASAN']: + SOURCES += [ + 'AsanOptions.cpp', +--- thunderbird-52.9.0/mozilla/js/src/moz.build.old 2017-04-11 02:13:16.000000000 +0000 ++++ thunderbird-52.9.0/mozilla/js/src/moz.build 2018-07-11 04:43:59.920000000 +0000 +@@ -707,7 +707,7 @@ + CXXFLAGS += ['-wd4577'] + CXXFLAGS += ['-wd4312'] + +-if CONFIG['OS_ARCH'] not in ('WINNT', 'HP-UX'): ++if CONFIG['OS_ARCH'] != 'WINNT': + OS_LIBS += [ + 'm', + ] +@@ -722,13 +722,13 @@ + 'dl', + ] + +-if CONFIG['OS_ARCH'] == 'SunOS': +- OS_LIBS += [ +- 'posix4', +- 'dl', +- 'nsl', +- 'socket', +- ] ++#if CONFIG['OS_ARCH'] == 'SunOS': ++# OS_LIBS += [ ++# 'posix4', ++# 'dl', ++# 'nsl', ++# 'socket', ++# ] + + OS_LIBS += CONFIG['REALTIME_LIBS'] + +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/util.py.old 2018-07-11 04:44:24.900000000 +0000 ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/util.py 2018-07-11 04:46:47.310000000 +0000 +@@ -267,6 +267,10 @@ + if 'b' in self.mode: + writemode += 'b' + with open(self.name, writemode) as file: ++ if 'b' in self.mode and isinstance(buf, str): ++ buf = buf.encode('utf-8') ++ elif 'b' not in self.mode and isinstance(buf, bytes): ++ buf = buf.decode('utf-8') + file.write(buf) + + if self._capture_diff: +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/recursivemake.py.old 2018-07-11 04:47:15.020000000 +0000 ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/backend/recursivemake.py 2018-07-11 04:53:51.750000000 +0000 +@@ -77,86 +77,86 @@ + from functools import reduce + + MOZBUILD_VARIABLES = [ +- b'ANDROID_APK_NAME', +- b'ANDROID_APK_PACKAGE', +- b'ANDROID_ASSETS_DIRS', +- b'ANDROID_EXTRA_PACKAGES', +- b'ANDROID_EXTRA_RES_DIRS', +- b'ANDROID_GENERATED_RESFILES', +- b'ANDROID_RES_DIRS', +- b'ASFLAGS', +- b'CMSRCS', +- b'CMMSRCS', +- b'CPP_UNIT_TESTS', +- b'DIRS', +- b'DIST_INSTALL', +- b'EXTRA_DSO_LDOPTS', +- b'EXTRA_JS_MODULES', +- b'EXTRA_PP_COMPONENTS', +- b'EXTRA_PP_JS_MODULES', +- b'FORCE_SHARED_LIB', +- b'FORCE_STATIC_LIB', +- b'FINAL_LIBRARY', +- b'HOST_CFLAGS', +- b'HOST_CSRCS', +- b'HOST_CMMSRCS', +- b'HOST_CXXFLAGS', +- b'HOST_EXTRA_LIBS', +- b'HOST_LIBRARY_NAME', +- b'HOST_PROGRAM', +- b'HOST_SIMPLE_PROGRAMS', +- b'IS_COMPONENT', +- b'JAR_MANIFEST', +- b'JAVA_JAR_TARGETS', +- b'LD_VERSION_SCRIPT', +- b'LIBRARY_NAME', +- b'LIBS', +- b'MAKE_FRAMEWORK', +- b'MODULE', +- b'NO_DIST_INSTALL', +- b'NO_EXPAND_LIBS', +- b'NO_INTERFACES_MANIFEST', +- b'NO_JS_MANIFEST', +- b'OS_LIBS', +- b'PARALLEL_DIRS', +- b'PREF_JS_EXPORTS', +- b'PROGRAM', +- b'PYTHON_UNIT_TESTS', +- b'RESOURCE_FILES', +- b'SDK_HEADERS', +- b'SDK_LIBRARY', +- b'SHARED_LIBRARY_LIBS', +- b'SHARED_LIBRARY_NAME', +- b'SIMPLE_PROGRAMS', +- b'SONAME', +- b'STATIC_LIBRARY_NAME', +- b'TEST_DIRS', +- b'TOOL_DIRS', ++ 'ANDROID_APK_NAME', ++ 'ANDROID_APK_PACKAGE', ++ 'ANDROID_ASSETS_DIRS', ++ 'ANDROID_EXTRA_PACKAGES', ++ 'ANDROID_EXTRA_RES_DIRS', ++ 'ANDROID_GENERATED_RESFILES', ++ 'ANDROID_RES_DIRS', ++ 'ASFLAGS', ++ 'CMSRCS', ++ 'CMMSRCS', ++ 'CPP_UNIT_TESTS', ++ 'DIRS', ++ 'DIST_INSTALL', ++ 'EXTRA_DSO_LDOPTS', ++ 'EXTRA_JS_MODULES', ++ 'EXTRA_PP_COMPONENTS', ++ 'EXTRA_PP_JS_MODULES', ++ 'FORCE_SHARED_LIB', ++ 'FORCE_STATIC_LIB', ++ 'FINAL_LIBRARY', ++ 'HOST_CFLAGS', ++ 'HOST_CSRCS', ++ 'HOST_CMMSRCS', ++ 'HOST_CXXFLAGS', ++ 'HOST_EXTRA_LIBS', ++ 'HOST_LIBRARY_NAME', ++ 'HOST_PROGRAM', ++ 'HOST_SIMPLE_PROGRAMS', ++ 'IS_COMPONENT', ++ 'JAR_MANIFEST', ++ 'JAVA_JAR_TARGETS', ++ 'LD_VERSION_SCRIPT', ++ 'LIBRARY_NAME', ++ 'LIBS', ++ 'MAKE_FRAMEWORK', ++ 'MODULE', ++ 'NO_DIST_INSTALL', ++ 'NO_EXPAND_LIBS', ++ 'NO_INTERFACES_MANIFEST', ++ 'NO_JS_MANIFEST', ++ 'OS_LIBS', ++ 'PARALLEL_DIRS', ++ 'PREF_JS_EXPORTS', ++ 'PROGRAM', ++ 'PYTHON_UNIT_TESTS', ++ 'RESOURCE_FILES', ++ 'SDK_HEADERS', ++ 'SDK_LIBRARY', ++ 'SHARED_LIBRARY_LIBS', ++ 'SHARED_LIBRARY_NAME', ++ 'SIMPLE_PROGRAMS', ++ 'SONAME', ++ 'STATIC_LIBRARY_NAME', ++ 'TEST_DIRS', ++ 'TOOL_DIRS', + # XXX config/Makefile.in specifies this in a make invocation + #'USE_EXTENSION_MANIFEST', +- b'XPCSHELL_TESTS', +- b'XPIDL_MODULE', ++ 'XPCSHELL_TESTS', ++ 'XPIDL_MODULE', + ] + + DEPRECATED_VARIABLES = [ +- b'ANDROID_RESFILES', +- b'EXPORT_LIBRARY', +- b'EXTRA_LIBS', +- b'HOST_LIBS', +- b'LIBXUL_LIBRARY', +- b'MOCHITEST_A11Y_FILES', +- b'MOCHITEST_BROWSER_FILES', +- b'MOCHITEST_BROWSER_FILES_PARTS', +- b'MOCHITEST_CHROME_FILES', +- b'MOCHITEST_FILES', +- b'MOCHITEST_FILES_PARTS', +- b'MOCHITEST_METRO_FILES', +- b'MOCHITEST_ROBOCOP_FILES', +- b'MODULE_OPTIMIZE_FLAGS', +- b'MOZ_CHROME_FILE_FORMAT', +- b'SHORT_LIBNAME', +- b'TESTING_JS_MODULES', +- b'TESTING_JS_MODULE_DIR', ++ 'ANDROID_RESFILES', ++ 'EXPORT_LIBRARY', ++ 'EXTRA_LIBS', ++ 'HOST_LIBS', ++ 'LIBXUL_LIBRARY', ++ 'MOCHITEST_A11Y_FILES', ++ 'MOCHITEST_BROWSER_FILES', ++ 'MOCHITEST_BROWSER_FILES_PARTS', ++ 'MOCHITEST_CHROME_FILES', ++ 'MOCHITEST_FILES', ++ 'MOCHITEST_FILES_PARTS', ++ 'MOCHITEST_METRO_FILES', ++ 'MOCHITEST_ROBOCOP_FILES', ++ 'MODULE_OPTIMIZE_FLAGS', ++ 'MOZ_CHROME_FILE_FORMAT', ++ 'SHORT_LIBNAME', ++ 'TESTING_JS_MODULES', ++ 'TESTING_JS_MODULE_DIR', + ] + + MOZBUILD_VARIABLES_MESSAGE = 'It should only be defined in moz.build files.' +@@ -758,7 +758,7 @@ + rule.add_dependencies(['$(CURDIR)/%: %']) + + def _check_blacklisted_variables(self, makefile_in, makefile_content): +- if b'EXTERNALLY_MANAGED_MAKE_FILE' in makefile_content: ++ if 'EXTERNALLY_MANAGED_MAKE_FILE' in makefile_content: + # Bypass the variable restrictions for externally managed makefiles. + return + +@@ -765,7 +765,7 @@ + for l in makefile_content.splitlines(): + l = l.strip() + # Don't check comments +- if l.startswith(b'#'): ++ if l.startswith('#'): + continue + for x in chain(MOZBUILD_VARIABLES, DEPRECATED_VARIABLES): + if x not in l: +@@ -822,11 +822,11 @@ + # Skip every directory but those with a Makefile + # containing a tools target, or XPI_PKGNAME or + # INSTALL_EXTENSION_ID. +- for t in (b'XPI_PKGNAME', b'INSTALL_EXTENSION_ID', +- b'tools'): ++ for t in ('XPI_PKGNAME', 'INSTALL_EXTENSION_ID', ++ 'tools'): + if t not in content: + continue +- if t == b'tools' and not re.search('(?:^|\s)tools.*::', content, re.M): ++ if t == 'tools' and not re.search('(?:^|\s)tools.*::', content, re.M): + continue + if objdir == self.environment.topobjdir: + continue +@@ -1422,20 +1422,20 @@ + pp.context.update(extra) + if not pp.context.get('autoconfmk', ''): + pp.context['autoconfmk'] = 'autoconf.mk' +- pp.handleLine(b'# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT MODIFY BY HAND.\n'); +- pp.handleLine(b'DEPTH := @DEPTH@\n') +- pp.handleLine(b'topobjdir := @topobjdir@\n') +- pp.handleLine(b'topsrcdir := @top_srcdir@\n') +- pp.handleLine(b'srcdir := @srcdir@\n') +- pp.handleLine(b'VPATH := @srcdir@\n') +- pp.handleLine(b'relativesrcdir := @relativesrcdir@\n') +- pp.handleLine(b'include $(DEPTH)/config/@autoconfmk@\n') ++ pp.handleLine('# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT MODIFY BY HAND.\n'); ++ pp.handleLine('DEPTH := @DEPTH@\n') ++ pp.handleLine('topobjdir := @topobjdir@\n') ++ pp.handleLine('topsrcdir := @top_srcdir@\n') ++ pp.handleLine('srcdir := @srcdir@\n') ++ pp.handleLine('VPATH := @srcdir@\n') ++ pp.handleLine('relativesrcdir := @relativesrcdir@\n') ++ pp.handleLine('include $(DEPTH)/config/@autoconfmk@\n') + if not stub: + pp.do_include(obj.input_path) + # Empty line to avoid failures when last line in Makefile.in ends + # with a backslash. +- pp.handleLine(b'\n') +- pp.handleLine(b'include $(topsrcdir)/config/recurse.mk\n') ++ pp.handleLine('\n') ++ pp.handleLine('include $(topsrcdir)/config/recurse.mk\n') + if not stub: + # Adding the Makefile.in here has the desired side-effect + # that if the Makefile.in disappears, this will force +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/manifests.py.old 2018-07-11 04:54:39.260000000 +0000 ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozpack/manifests.py 2018-07-11 04:57:31.710000000 +0000 +@@ -115,7 +115,7 @@ + self._source_files = set() + + if path or fileobj: +- with _auto_fileobj(path, fileobj, 'rb') as fh: ++ with _auto_fileobj(path, fileobj, 'r') as fh: + self._source_files.add(fh.name) + self._load_from_fileobj(fh) + +@@ -174,7 +174,7 @@ + dest, content = fields[1:] + + self.add_content( +- self._decode_field_entry(content).encode('utf-8'), dest) ++ self._decode_field_entry(content), dest) + continue + + # Don't fail for non-actionable items, allowing +@@ -236,7 +236,7 @@ + + It is an error if both are specified. + """ +- with _auto_fileobj(path, fileobj, 'wb') as fh: ++ with _auto_fileobj(path, fileobj, 'w') as fh: + fh.write('%d\n' % self.CURRENT_VERSION) + + for dest in sorted(self._dests): +@@ -244,8 +244,7 @@ + + parts = ['%d' % entry[0], dest] + parts.extend(entry[1:]) +- fh.write('%s\n' % self.FIELD_SEPARATOR.join( +- p.encode('utf-8') for p in parts)) ++ fh.write('%s\n' % self.FIELD_SEPARATOR.join(parts)) + + def add_symlink(self, source, dest): + """Add a symlink to this manifest. +@@ -391,7 +390,7 @@ + if install_type == self.CONTENT: + # GeneratedFile expect the buffer interface, which the unicode + # type doesn't have, so encode to a str. +- content = self._decode_field_entry(entry[1]).encode('utf-8') ++ content = self._decode_field_entry(entry[1]) + registry.add(dest, GeneratedFile(content)) + continue + +--- thunderbird-52.9.0/mozilla/config/MozZipFile.py (original) ++++ thunderbird-52.9.0/mozilla/config/MozZipFile.py (refactored) +@@ -18,7 +18,7 @@ + def __init__(self, file, mode="r", compression=zipfile.ZIP_STORED, + lock = False): + if lock: +- assert isinstance(file, basestring) ++ assert isinstance(file, str) + self.lockfile = lock_file(file + '.lck') + else: + self.lockfile = None +@@ -46,7 +46,7 @@ + date_time=time.localtime(time.time())) + zinfo.compress_type = self.compression + # Add some standard UNIX file access permissions (-rw-r--r--). +- zinfo.external_attr = (0x81a4 & 0xFFFF) << 16L ++ zinfo.external_attr = (0x81a4 & 0xFFFF) << 16 + else: + zinfo = zinfo_or_arcname + +@@ -58,7 +58,7 @@ + # as the old, reuse the existing entry. + + doSeek = False # store if we need to seek to the eof after overwriting +- if self.NameToInfo.has_key(zinfo.filename): ++ if zinfo.filename in self.NameToInfo: + # Find the last ZipInfo with our name. + # Last, because that's catching multiple overwrites + i = len(self.filelist) +@@ -109,14 +109,14 @@ + # adjust file mode if we originally just wrote, now we rewrite + self.fp.close() + self.fp = open(self.filename, 'r+b') +- all = map(lambda zi: (zi, True), self.filelist) + \ +- map(lambda zi: (zi, False), self._remove) ++ all = [(zi, True) for zi in self.filelist] + \ ++ [(zi, False) for zi in self._remove] + all.sort(lambda l, r: cmp(l[0].header_offset, r[0].header_offset)) + # empty _remove for multiple closes + self._remove = [] + + lengths = [all[i+1][0].header_offset - all[i][0].header_offset +- for i in xrange(len(all)-1)] ++ for i in range(len(all)-1)] + lengths.append(self.end - all[-1][0].header_offset) + to_pos = 0 + for (zi, keep), length in zip(all, lengths): +--- thunderbird-52.9.0/mozilla/config/check_spidermonkey_style.py (original) ++++ thunderbird-52.9.0/mozilla/config/check_spidermonkey_style.py (refactored) +@@ -35,7 +35,7 @@ + # isolation, but don't try to do any order checking between such blocks. + #---------------------------------------------------------------------------- + +-from __future__ import print_function ++ + + import difflib + import os +@@ -270,7 +270,7 @@ + edges[inclname] = set() + + # Process all the JS files. +- for filename in js_names.keys(): ++ for filename in list(js_names.keys()): + inclname = js_names[filename] + file_kind = FileKind.get(filename) + if file_kind == FileKind.C or file_kind == FileKind.CPP or \ +--- thunderbird-52.9.0/mozilla/config/expandlibs.py (original) ++++ thunderbird-52.9.0/mozilla/config/expandlibs.py (refactored) +@@ -26,7 +26,7 @@ + descriptor contains. And for each of these LIBS, also apply the same + rules. + ''' +-from __future__ import with_statement ++ + import sys, os, errno + import expandlibs_config as conf + +@@ -36,7 +36,7 @@ + if dir and not os.path.exists(dir): + try: + os.makedirs(dir) +- except OSError, error: ++ except OSError as error: + if error.errno != errno.EEXIST: + raise + +@@ -140,4 +140,4 @@ + return [relativize(arg)] + + if __name__ == '__main__': +- print " ".join(ExpandArgs(sys.argv[1:])) ++ print(" ".join(ExpandArgs(sys.argv[1:]))) +--- thunderbird-52.9.0/mozilla/config/expandlibs_exec.py (original) ++++ thunderbird-52.9.0/mozilla/config/expandlibs_exec.py (refactored) +@@ -20,7 +20,7 @@ + relevant linker options to change the order in which the linker puts the + symbols appear in the resulting binary. Only works for ELF targets. + ''' +-from __future__ import with_statement ++ + import sys + import os + from expandlibs import ( +@@ -304,11 +304,11 @@ + return syms + + def print_command(out, args): +- print >>out, "Executing: " + " ".join(args) ++ print("Executing: " + " ".join(args), file=out) + for tmp in [f for f in args.tmp if os.path.isfile(f)]: +- print >>out, tmp + ":" ++ print(tmp + ":", file=out) + with open(tmp) as file: +- print >>out, "".join([" " + l for l in file.readlines()]) ++ print("".join([" " + l for l in file.readlines()]), file=out) + out.flush() + + def main(args, proc_callback=None): +@@ -338,8 +338,8 @@ + proc = subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.STDOUT) + if proc_callback: + proc_callback(proc) +- except Exception, e: +- print >>sys.stderr, 'error: Launching', args, ':', e ++ except Exception as e: ++ print('error: Launching', args, ':', e, file=sys.stderr) + raise e + (stdout, stderr) = proc.communicate() + if proc.returncode and not options.verbose: +--- thunderbird-52.9.0/mozilla/config/expandlibs_gen.py (original) ++++ thunderbird-52.9.0/mozilla/config/expandlibs_gen.py (refactored) +@@ -5,7 +5,7 @@ + '''Given a list of object files and library names, prints a library + descriptor to standard output''' + +-from __future__ import with_statement ++ + import sys + import os + import expandlibs_config as conf +@@ -38,4 +38,4 @@ + + ensureParentDir(options.output) + with open(options.output, 'w') as outfile: +- print >>outfile, generate(args) ++ print(generate(args), file=outfile) +--- thunderbird-52.9.0/mozilla/config/find_OOM_errors.py (original) ++++ thunderbird-52.9.0/mozilla/config/find_OOM_errors.py (refactored) +@@ -2,7 +2,7 @@ + # 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 print_function ++ + + usage = """%prog: A test for OOM conditions in the shell. + +@@ -95,12 +95,12 @@ + """Keep track of the amount of times individual lines occur, in order to + prioritize the errors which occur most frequently.""" + counts = {} +- for string,count in blacklist.items(): ++ for string,count in list(blacklist.items()): + for line in string.split("\n"): + counts[line] = counts.get(line, 0) + count + + lines = [] +- for k,v in counts.items(): ++ for k,v in list(counts.items()): + lines.append("{0:6}: {1}".format(v, k)) + + lines.sort() +--- thunderbird-52.9.0/mozilla/config/link.py (original) ++++ thunderbird-52.9.0/mozilla/config/link.py (refactored) +@@ -18,7 +18,7 @@ + time.sleep(0.5) + idleTime += 0.5 + if idleTime > 20 * 60: +- print "Still linking, 20 minutes passed..." ++ print("Still linking, 20 minutes passed...") + sys.stdout.flush() + idleTime = 0 + +@@ -42,6 +42,6 @@ + + if __name__ == "__main__": + if len(sys.argv) < 2: +- print >>sys.stderr, "Usage: link.py <commandline>" ++ print("Usage: link.py <commandline>", file=sys.stderr) + sys.exit(1) + sys.exit(wrap_linker(sys.argv[1:])) +--- thunderbird-52.9.0/mozilla/config/mozunit.py (original) ++++ thunderbird-52.9.0/mozilla/config/mozunit.py (refactored) +@@ -140,7 +140,7 @@ + ''' + def __init__(self, files = {}): + self.files = {} +- for name, content in files.iteritems(): ++ for name, content in files.items(): + self.files[normcase(os.path.abspath(name))] = content + + def __call__(self, name, mode = 'r'): +@@ -158,19 +158,19 @@ + return file + + def __enter__(self): +- import __builtin__ +- self.open = __builtin__.open ++ import builtins ++ self.open = builtins.open + self._orig_path_exists = os.path.exists + self._orig_path_isdir = os.path.isdir + self._orig_path_isfile = os.path.isfile +- __builtin__.open = self ++ builtins.open = self + os.path.exists = self._wrapped_exists + os.path.isdir = self._wrapped_isdir + os.path.isfile = self._wrapped_isfile + + def __exit__(self, type, value, traceback): +- import __builtin__ +- __builtin__.open = self.open ++ import builtins ++ builtins.open = self.open + os.path.exists = self._orig_path_exists + os.path.isdir = self._orig_path_isdir + os.path.isfile = self._orig_path_isfile +--- thunderbird-52.9.0/mozilla/config/nsinstall.py (original) ++++ thunderbird-52.9.0/mozilla/config/nsinstall.py (refactored) +@@ -9,7 +9,7 @@ + # a full build environment set up. + # The basic limitation is, it doesn't even try to link and ignores + # all related options. +-from __future__ import print_function ++ + from optparse import OptionParser + import mozfile + import os +@@ -149,7 +149,7 @@ + + # nsinstall as a native command is always UTF-8 + def nsinstall(argv): +- return _nsinstall_internal([unicode(arg, "utf-8") for arg in argv]) ++ return _nsinstall_internal([str(arg, "utf-8") for arg in argv]) + + if __name__ == '__main__': + # sys.argv corrupts characters outside the system code page on Windows +@@ -175,8 +175,8 @@ + else: + # For consistency, do it on Unix as well + if sys.stdin.encoding is not None: +- argv = [unicode(arg, sys.stdin.encoding) for arg in sys.argv] ++ argv = [str(arg, sys.stdin.encoding) for arg in sys.argv] + else: +- argv = [unicode(arg) for arg in sys.argv] ++ argv = [str(arg) for arg in sys.argv] + + sys.exit(_nsinstall_internal(argv[1:])) +--- thunderbird-52.9.0/mozilla/config/printconfigsetting.py (original) ++++ thunderbird-52.9.0/mozilla/config/printconfigsetting.py (refactored) +@@ -5,12 +5,12 @@ + import configobj + import sys + import re +-from StringIO import StringIO ++from io import StringIO + + try: + (file, section, key) = sys.argv[1:] + except ValueError: +- print "Usage: printconfigsetting.py <file> <section> <setting>" ++ print("Usage: printconfigsetting.py <file> <section> <setting>") + sys.exit(1) + + with open(file) as fh: +@@ -21,11 +21,11 @@ + try: + s = c[section] + except KeyError: +- print >>sys.stderr, "Section [%s] not found." % section ++ print("Section [%s] not found." % section, file=sys.stderr) + sys.exit(1) + + try: +- print s[key] ++ print(s[key]) + except KeyError: +- print >>sys.stderr, "Key %s not found." % key ++ print("Key %s not found." % key, file=sys.stderr) + sys.exit(1) +--- thunderbird-52.9.0/mozilla/config/pythonpath.py (original) ++++ thunderbird-52.9.0/mozilla/config/pythonpath.py (refactored) +@@ -9,7 +9,7 @@ + + def main(args): + def usage(): +- print >>sys.stderr, "pythonpath.py -I directory script.py [args...]" ++ print("pythonpath.py -I directory script.py [args...]", file=sys.stderr) + sys.exit(150) + + paths = [] +@@ -45,7 +45,7 @@ + frozenglobals['__name__'] = '__main__' + frozenglobals['__file__'] = script + +- execfile(script, frozenglobals) ++ exec(compile(open(script).read(), script, 'exec'), frozenglobals) + + # Freeze scope here ... why this makes things work I have no idea ... + frozenglobals = globals() +--- thunderbird-52.9.0/mozilla/config/rebuild_check.py (original) ++++ thunderbird-52.9.0/mozilla/config/rebuild_check.py (refactored) +@@ -18,7 +18,7 @@ + deps = args[1:] + t = mtime(target) + if t < 0: +- print target ++ print(target) + return + + newer = [] +@@ -31,13 +31,13 @@ + newer.append(dep) + + if newer and removed: +- print 'Rebuilding %s because %s changed and %s was removed' % (target, ', '.join(newer), ', '.join(removed)) ++ print('Rebuilding %s because %s changed and %s was removed' % (target, ', '.join(newer), ', '.join(removed))) + elif newer: +- print 'Rebuilding %s because %s changed' % (target, ', '.join(newer)) ++ print('Rebuilding %s because %s changed' % (target, ', '.join(newer))) + elif removed: +- print 'Rebuilding %s because %s was removed' % (target, ', '.join(removed)) ++ print('Rebuilding %s because %s was removed' % (target, ', '.join(removed))) + else: +- print 'Rebuilding %s for an unknown reason' % target ++ print('Rebuilding %s for an unknown reason' % target) + + if __name__ == '__main__': + import sys +--- thunderbird-52.9.0/mozilla/config/tests/unit-expandlibs.py (original) ++++ thunderbird-52.9.0/mozilla/config/tests/unit-expandlibs.py (refactored) +@@ -7,7 +7,7 @@ + from shutil import rmtree + import mozunit + +-from UserString import UserString ++from collections import UserString + # Create a controlled configuration for use by expandlibs + config_win = { + 'AR': 'lib', +@@ -120,8 +120,7 @@ + del dict[name] + return type.__new__(cls, clsName, bases, dict) + +-class TestCaseWithTmpDir(unittest.TestCase): +- __metaclass__ = ReplicateTests ++class TestCaseWithTmpDir(unittest.TestCase, metaclass=ReplicateTests): + def init(self): + self.tmpdir = os.path.abspath(mkdtemp(dir=os.curdir)) + +--- thunderbird-52.9.0/mozilla/config/tests/unit-nsinstall.py (original) ++++ thunderbird-52.9.0/mozilla/config/tests/unit-nsinstall.py (refactored) +@@ -28,9 +28,9 @@ + # Unicode strings means non-ASCII children can be deleted properly on + # Windows + if sys.stdin.encoding is None: +- tmpdir = unicode(self.tmpdir) ++ tmpdir = str(self.tmpdir) + else: +- tmpdir = unicode(self.tmpdir, sys.stdin.encoding) ++ tmpdir = str(self.tmpdir, sys.stdin.encoding) + rmtree(tmpdir) + + # utility methods for tests +@@ -50,14 +50,14 @@ + "Test nsinstall -D <dir>" + testdir = os.path.join(self.tmpdir, "test") + self.assertEqual(nsinstall(["-D", testdir]), 0) +- self.assert_(os.path.isdir(testdir)) ++ self.assertTrue(os.path.isdir(testdir)) + + def test_nsinstall_basic(self): + "Test nsinstall <file> <dir>" + testfile = self.touch("testfile") + testdir = self.mkdirs("testdir") + self.assertEqual(nsinstall([testfile, testdir]), 0) +- self.assert_(os.path.isfile(os.path.join(testdir, "testfile"))) ++ self.assertTrue(os.path.isfile(os.path.join(testdir, "testfile"))) + + def test_nsinstall_basic_recursive(self): + "Test nsinstall <dir> <dest dir>" +@@ -76,12 +76,12 @@ + '-X', Xdir]), 0) + + testdir = os.path.join(destdir, "sourcedir") +- self.assert_(os.path.isdir(testdir)) +- self.assert_(os.path.isfile(os.path.join(testdir, "testfile"))) +- self.assert_(not os.path.exists(os.path.join(testdir, "Xfile"))) +- self.assert_(os.path.isdir(os.path.join(testdir, "copieddir"))) +- self.assert_(os.path.isfile(os.path.join(testdir, "copieddir", "testfile2"))) +- self.assert_(not os.path.exists(os.path.join(testdir, "Xdir"))) ++ self.assertTrue(os.path.isdir(testdir)) ++ self.assertTrue(os.path.isfile(os.path.join(testdir, "testfile"))) ++ self.assertTrue(not os.path.exists(os.path.join(testdir, "Xfile"))) ++ self.assertTrue(os.path.isdir(os.path.join(testdir, "copieddir"))) ++ self.assertTrue(os.path.isfile(os.path.join(testdir, "copieddir", "testfile2"))) ++ self.assertTrue(not os.path.exists(os.path.join(testdir, "Xdir"))) + + def test_nsinstall_multiple(self): + "Test nsinstall <three files> <dest dir>" +@@ -91,7 +91,7 @@ + testdir = self.mkdirs("testdir") + self.assertEqual(nsinstall(testfiles + [testdir]), 0) + for f in testfiles: +- self.assert_(os.path.isfile(os.path.join(testdir, ++ self.assertTrue(os.path.isfile(os.path.join(testdir, + os.path.basename(f)))) + + def test_nsinstall_dir_exists(self): +@@ -99,7 +99,7 @@ + srcdir = self.mkdirs("test") + destdir = self.mkdirs("testdir/test") + self.assertEqual(nsinstall([srcdir, os.path.dirname(destdir)]), 0) +- self.assert_(os.path.isdir(destdir)) ++ self.assertTrue(os.path.isdir(destdir)) + + def test_nsinstall_t(self): + "Test that nsinstall -t works (preserve timestamp)" +@@ -110,7 +110,7 @@ + os.utime(testfile, (t, t)) + self.assertEqual(nsinstall(["-t", testfile, testdir]), 0) + destfile = os.path.join(testdir, "testfile") +- self.assert_(os.path.isfile(destfile)) ++ self.assertTrue(os.path.isfile(destfile)) + self.assertEqual(os.stat(testfile).st_mtime, + os.stat(destfile).st_mtime) + +@@ -125,7 +125,7 @@ + self.assertEqual(nsinstall(["-m", "{0:04o}" + .format(mode), testfile, testdir]), 0) + destfile = os.path.join(testdir, "testfile") +- self.assert_(os.path.isfile(destfile)) ++ self.assertTrue(os.path.isfile(destfile)) + self.assertEqual(os.stat(testfile).st_mode, + os.stat(destfile).st_mode) + +@@ -136,25 +136,25 @@ + testdir = self.mkdirs("testdir") + destdir = os.path.join(testdir, "subdir") + self.assertEqual(nsinstall(["-d", testfile, destdir]), 0) +- self.assert_(os.path.isdir(os.path.join(destdir, "testfile"))) ++ self.assertTrue(os.path.isdir(os.path.join(destdir, "testfile"))) + + if RUN_NON_ASCII_TESTS: + def test_nsinstall_non_ascii(self): + "Test that nsinstall handles non-ASCII files" +- filename = u"\u2325\u3452\u2415\u5081" ++ filename = "\u2325\u3452\u2415\u5081" + testfile = self.touch(filename) +- testdir = self.mkdirs(u"\u4241\u1D04\u1414") ++ testdir = self.mkdirs("\u4241\u1D04\u1414") + self.assertEqual(nsinstall([testfile.encode("utf-8"), + testdir.encode("utf-8")]), 0) + + destfile = os.path.join(testdir, filename) +- self.assert_(os.path.isfile(destfile)) ++ self.assertTrue(os.path.isfile(destfile)) + + def test_nsinstall_non_ascii_subprocess(self): + "Test that nsinstall as a subprocess handles non-ASCII files" +- filename = u"\u2325\u3452\u2415\u5081" ++ filename = "\u2325\u3452\u2415\u5081" + testfile = self.touch(filename) +- testdir = self.mkdirs(u"\u4241\u1D04\u1414") ++ testdir = self.mkdirs("\u4241\u1D04\u1414") + # We don't use subprocess because it can't handle Unicode on + # Windows <http://bugs.python.org/issue1759845>. mozprocess calls + # CreateProcessW directly so it's perfect. +@@ -166,7 +166,7 @@ + + self.assertEqual(rv, 0) + destfile = os.path.join(testdir, filename) +- self.assert_(os.path.isfile(destfile)) ++ self.assertTrue(os.path.isfile(destfile)) + + #TODO: implement -R, -l, -L and test them! + +--- thunderbird-52.9.0/mozilla/config/tests/unitMozZipFile.py (original) ++++ thunderbird-52.9.0/mozilla/config/tests/unitMozZipFile.py (refactored) +@@ -11,6 +11,7 @@ + import random + import copy + from string import letters ++from functools import reduce + + ''' + Test case infrastructure for MozZipFile. +@@ -38,7 +39,7 @@ + 'firstdir/oneleaf', + 'seconddir/twoleaf', + 'thirddir/with/sub/threeleaf') +-_lengths = map(lambda n: n * 64, [16, 64, 80]) ++_lengths = [n * 64 for n in [16, 64, 80]] + lengths = 3 + writes = 5 + +@@ -71,7 +72,7 @@ + def getContent(length): + 'Get pseudo random content of given length.' + rv = [None] * length +- for i in xrange(length): ++ for i in range(length): + rv[i] = random.choice(letters) + return ''.join(rv) + +@@ -133,13 +134,13 @@ + def _verifyZip(self): + zf = zipfile.ZipFile(self.f) + badEntry = zf.testzip() +- self.failIf(badEntry, badEntry) ++ self.assertFalse(badEntry, badEntry) + zlist = zf.namelist() + zlist.sort() +- vlist = self.ref.keys() ++ vlist = list(self.ref.keys()) + vlist.sort() + self.assertEqual(zlist, vlist) +- for leaf, content in self.ref.iteritems(): ++ for leaf, content in self.ref.items(): + zcontent = zf.read(leaf) + self.assertEqual(content, zcontent) + +@@ -158,16 +159,16 @@ + open(self.leaf('stage', leaf), 'w').write(content) + + # all leafs in all lengths +-atomics = list(prod(xrange(len(leafs)), xrange(lengths))) ++atomics = list(prod(range(len(leafs)), range(lengths))) + + # populate TestExtensiveStore with testcases +-for w in xrange(writes): ++for w in range(writes): + # Don't iterate over all files for the the first n passes, + # those are redundant as long as w < lengths. + # There are symmetries in the trailing end, too, but I don't know + # how to reduce those out right now. +- nonatomics = [list(prod(range(min(i,len(leafs))), xrange(lengths))) +- for i in xrange(1, w+1)] + [atomics] ++ nonatomics = [list(prod(list(range(min(i,len(leafs)))), range(lengths))) ++ for i in range(1, w+1)] + [atomics] + for descs in prod(*nonatomics): + suffix = getid(descs) + dicts = [dict(leaf=leaf, length=length) for leaf, length in descs] +@@ -181,9 +182,9 @@ + # and then write all atomics again. + # This should catch more or less all artifacts generated + # by the final ordering step when closing the jar. +-files = [list(prod([i], xrange(lengths))) for i in xrange(len(leafs))] ++files = [list(prod([i], range(lengths))) for i in range(len(leafs))] + allfiles = reduce(lambda l,r:l+r, +- [list(prod(*files[:(i+1)])) for i in xrange(len(leafs))]) ++ [list(prod(*files[:(i+1)])) for i in range(len(leafs))]) + + for first in allfiles: + testbasename = 'test{0}_'.format(getid(first)) +--- thunderbird-52.9.0/mozilla/config/expandlibs_exec.py.old 2018-07-11 05:07:18.280000000 +0000 ++++ thunderbird-52.9.0/mozilla/config/expandlibs_exec.py 2018-07-11 05:08:45.670000000 +0000 +@@ -344,7 +344,7 @@ + (stdout, stderr) = proc.communicate() + if proc.returncode and not options.verbose: + print_command(sys.stderr, args) +- sys.stderr.write(stdout) ++ sys.stderr.write(stdout.decode('utf-8')) + sys.stderr.flush() + if proc.returncode: + return proc.returncode +--- thunderbird-52.9.0/mozilla/js/src/jsautokw.py.old 2017-04-11 02:13:16.000000000 +0000 ++++ thunderbird-52.9.0/mozilla/js/src/jsautokw.py 2018-07-11 05:11:27.080000000 +0000 +@@ -80,14 +80,14 @@ + per_column = column_dict.setdefault(keyword[column], []) + per_column.append(item) + +- return sorted(column_dict.items(), key=lambda (char, keyword): ord(char)) ++ return sorted(list(column_dict.items()), key=lambda char_keyword: ord(char_keyword[0])) + + def generate_letter_switch(opt, unprocessed_columns, keyword_list, + columns=None): + assert(len(keyword_list) != 0); + + if not columns: +- columns = range(0, unprocessed_columns) ++ columns = list(range(0, unprocessed_columns)) + + if len(keyword_list) == 1: + index, keyword = keyword_list[0] +@@ -161,7 +161,7 @@ + per_length = length_dict.setdefault(len(keyword), []) + per_length.append(item) + +- return sorted(length_dict.items(), key=lambda (length, keyword): length) ++ return sorted(list(length_dict.items()), key=lambda length_keyword: length_keyword[0]) + + def generate_switch(opt, keyword_list): + assert(len(keyword_list) != 0); +--- thunderbird-52.9.0/mozilla/js/src/builtin/embedjs.py (original) ++++ thunderbird-52.9.0/mozilla/js/src/builtin/embedjs.py (refactored) +@@ -36,7 +36,7 @@ + # + # It uses the C preprocessor to process its inputs. + +-from __future__ import with_statement ++ + import re, sys, os, subprocess + import shlex + import which +@@ -109,7 +109,7 @@ + + with open(tmpIn, 'wb') as input: + input.write(source) +- print(' '.join(cxx + outputArg + args + [tmpIn])) ++ print((' '.join(cxx + outputArg + args + [tmpIn]))) + result = subprocess.Popen(cxx + outputArg + args + [tmpIn]).wait() + if (result != 0): + sys.exit(result); +@@ -132,7 +132,7 @@ + + def get_config_defines(buildconfig): + # Collect defines equivalent to ACDEFINES and add MOZ_DEBUG_DEFINES. +- env = {key: value for key, value in buildconfig.defines.iteritems() ++ env = {key: value for key, value in buildconfig.defines.items() + if key not in buildconfig.non_global_defines} + for define in buildconfig.substs['MOZ_DEBUG_DEFINES']: + env[define] = 1 +--- thunderbird-52.9.0/mozilla/js/src/builtin/embedjs.py.old 2018-07-11 05:13:28.920000000 +0000 ++++ thunderbird-52.9.0/mozilla/js/src/builtin/embedjs.py 2018-07-11 05:15:15.390000000 +0000 +@@ -107,7 +107,7 @@ + tmpOut = 'self-hosting-preprocessed.pp'; + outputArg = shlex.split(preprocessorOption + tmpOut) + +- with open(tmpIn, 'wb') as input: ++ with open(tmpIn, 'w') as input: + input.write(source) + print((' '.join(cxx + outputArg + args + [tmpIn]))) + result = subprocess.Popen(cxx + outputArg + args + [tmpIn]).wait() +--- thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/preprocessor.py.old 2018-07-11 05:15:42.900000000 +0000 ++++ thunderbird-52.9.0/mozilla/python/mozbuild/mozbuild/preprocessor.py 2018-07-11 05:23:10.870000000 +0000 +@@ -451,7 +451,7 @@ + except OSError as error: + if error.errno != errno.EEXIST: + raise +- return open(path, 'wb') ++ return open(path, 'w') + + p = self.getCommandLineParser() + options, args = p.parse_args(args=args) +--- thunderbird-52.9.0/mozilla/js/src/builtin/embedjs.py.old 2018-07-11 05:15:42.950000000 +0000 ++++ thunderbird-52.9.0/mozilla/js/src/builtin/embedjs.py 2018-07-11 05:20:14.280000000 +0000 +@@ -53,7 +53,7 @@ + def ToCArray(lines): + result = [] + for chr in lines: +- result.append(str(ord(chr))) ++ result.append(str(chr)) + return ", ".join(result) + + HEADER_TEMPLATE = """\ +@@ -87,7 +87,7 @@ + + js_out.write(processed) + import zlib +- compressed = zlib.compress(processed) ++ compressed = zlib.compress(processed.encode('utf-8')) + data = ToCArray(compressed) + c_out.write(HEADER_TEMPLATE % { + 'sources_type': 'unsigned char', +--- thunderbird-52.9.0/mozilla/build/mach_bootstrap.py.old 2018-06-29 23:00:39.000000000 +0000 ++++ thunderbird-52.9.0/mozilla/build/mach_bootstrap.py 2018-07-26 00:41:17.740000000 +0000 +@@ -12,7 +12,7 @@ + import subprocess + import sys + import uuid +-import __builtin__ ++import builtins + + from types import ModuleType + +@@ -187,10 +187,10 @@ + # Ensure we are running Python 2.7+. We put this check here so we generate a + # user-friendly error message rather than a cryptic stack trace on module + # import. +- if sys.version_info[0] != 2 or sys.version_info[1] < 7: +- print('Python 2.7 or above (but not Python 3) is required to run mach.') +- print('You are running Python', platform.python_version()) +- sys.exit(1) ++ #if sys.version_info[0] != 2 or sys.version_info[1] < 7: ++ # print('Python 2.7 or above (but not Python 3) is required to run mach.') ++ # print('You are running Python', platform.python_version()) ++ # sys.exit(1) + + # Global build system and mach state is stored in a central directory. By + # default, this is ~/.mozbuild. However, it can be defined via an +@@ -410,4 +410,4 @@ + + + # Install our hook +-__builtin__.__import__ = ImportHook(__builtin__.__import__) ++builtins.__import__ = ImportHook(builtins.__import__) +--- thunderbird-52.9.0/mozilla/python/mach/mach/config.py (original) ++++ thunderbird-52.9.0/mozilla/python/mach/mach/config.py (refactored) +@@ -163,7 +163,7 @@ + return func(*args, **kwargs) + except KeyError: + exc_class, exc, tb = sys.exc_info() +- raise AttributeError().__class__, exc, tb ++ raise AttributeError().__class__(exc).with_traceback(tb) + return _ + + +@@ -357,7 +357,7 @@ + extra -- A dict of additional key/value pairs to add to the + setting metadata. + """ +- if isinstance(type_cls, basestring): ++ if isinstance(type_cls, str_type): + type_cls = TYPE_CLASSES[type_cls] + + meta = { +@@ -397,10 +397,10 @@ + meta = self._format_metadata(provider, section, option, *setting[1:]) + config_settings[section][option] = meta + +- for section_name, settings in config_settings.items(): ++ for section_name, settings in list(config_settings.items()): + section = self._settings.get(section_name, {}) + +- for k, v in settings.items(): ++ for k, v in list(settings.items()): + if k in section: + raise ConfigException('Setting already registered: %s.%s' % + section_name, k) +@@ -432,7 +432,7 @@ + if self._finalized: + return + +- for section, settings in self._settings.items(): ++ for section, settings in list(self._settings.items()): + s = ConfigSettings.ConfigSection(self._config, section, settings) + self._sections[section] = s + +@@ -445,7 +445,7 @@ + def __iter__(self): + self._finalize() + +- return iter(self._sections.keys()) ++ return iter(list(self._sections.keys())) + + def __contains__(self, k): + return k in self._settings +--- thunderbird-52.9.0/mozilla/python/mach/mach/dispatcher.py (original) ++++ thunderbird-52.9.0/mozilla/python/mach/mach/dispatcher.py (refactored) +@@ -243,7 +243,7 @@ + r = self._mach_registrar + disabled_commands = [] + +- cats = [(k, v[2]) for k, v in r.categories.items()] ++ cats = [(k, v[2]) for k, v in list(r.categories.items())] + sorted_cats = sorted(cats, key=itemgetter(1), reverse=True) + for category, priority in sorted_cats: + group = None +@@ -375,7 +375,7 @@ + ' subcommand [subcommand arguments]' + group = parser.add_argument_group('Sub Commands') + +- for subcommand, subhandler in sorted(handler.subcommand_handlers.iteritems()): ++ for subcommand, subhandler in sorted(handler.subcommand_handlers.items()): + group.add_argument(subcommand, help=subhandler.description, + action='store_true') + +@@ -406,7 +406,7 @@ + + def _suggest_command(self, command): + # Make sure we don't suggest any deprecated commands. +- names = [h.name for h in self._mach_registrar.command_handlers.values() ++ names = [h.name for h in list(self._mach_registrar.command_handlers.values()) + if h.cls.__name__ != 'DeprecatedCommands'] + # We first try to look for a valid command that is very similar to the given command. + suggested_commands = difflib.get_close_matches(command, names, cutoff=0.8) +@@ -437,13 +437,13 @@ + if not docstring: + return '' + lines = docstring.expandtabs().splitlines() +- indent = sys.maxint ++ indent = sys.maxsize + for line in lines[1:]: + stripped = line.lstrip() + if stripped: + indent = min(indent, len(line) - len(stripped)) + trimmed = [lines[0].strip()] +- if indent < sys.maxint: ++ if indent < sys.maxsize: + for line in lines[1:]: + trimmed.append(line[indent:].rstrip()) + while trimmed and not trimmed[-1]: +--- thunderbird-52.9.0/mozilla/python/mach/mach/main.py (original) ++++ thunderbird-52.9.0/mozilla/python/mach/mach/main.py (refactored) +@@ -528,7 +528,7 @@ + + machrc, .machrc + """ +- if isinstance(paths, basestring): ++ if isinstance(paths, str): + paths = [paths] + + valid_names = ('machrc', '.machrc') +@@ -541,8 +541,8 @@ + if os.path.isfile(path): + return path + +- files = map(find_in_dir, self.settings_paths) +- files = filter(bool, files) ++ files = list(map(find_in_dir, self.settings_paths)) ++ files = list(filter(bool, files)) + + self.settings.load_files(files) + +--- thunderbird-52.9.0/mozilla/python/mach/mach/registrar.py (original) ++++ thunderbird-52.9.0/mozilla/python/mach/mach/registrar.py (refactored) +@@ -90,7 +90,7 @@ + result = fn(**kwargs) + + result = result or 0 +- assert isinstance(result, (int, long)) ++ assert isinstance(result, int) + + if context: + postrun = getattr(context, 'post_dispatch_handler', None) +--- thunderbird-52.9.0/mozilla/python/mach/mach/terminal.py (original) ++++ thunderbird-52.9.0/mozilla/python/mach/mach/terminal.py (refactored) +@@ -59,7 +59,7 @@ + self.fh = sys.stdout + + def _clear_lines(self, n): +- for i in xrange(n): ++ for i in range(n): + self.fh.write(self.t.move_x(0)) + self.fh.write(self.t.clear_eol()) + self.fh.write(self.t.move_up()) +--- thunderbird-52.9.0/mozilla/python/mach/mach/main.py.old 2018-07-26 00:55:29.330000000 +0000 ++++ thunderbird-52.9.0/mozilla/python/mach/mach/main.py 2018-07-26 00:57:01.260000000 +0000 +@@ -256,9 +256,9 @@ + if module_name is None: + # Ensure parent module is present otherwise we'll (likely) get + # an error due to unknown parent. +- if b'mach.commands' not in sys.modules: +- mod = imp.new_module(b'mach.commands') +- sys.modules[b'mach.commands'] = mod ++ if 'mach.commands' not in sys.modules: ++ mod = imp.new_module('mach.commands') ++ sys.modules['mach.commands'] = mod + + module_name = 'mach.commands.%s' % uuid.uuid1().get_hex() + +@@ -347,7 +347,7 @@ + # is a TTY. This provides a mechanism to allow said processes to + # enable emitting code codes, for example. + if os.isatty(orig_stdout.fileno()): +- os.environ[b'MACH_STDOUT_ISATTY'] = b'1' ++ os.environ['MACH_STDOUT_ISATTY'] = '1' + + return self._run(argv) + except KeyboardInterrupt: |