Bug 1547730 - Do dict.iteritems() via six to support py3. r=#build
☠☠ backed out by ee4b88439111 ☠ ☠
authorJustin Wood <Callek@gmail.com>
Mon, 15 Apr 2019 11:48:03 -0400
changeset 532999 afa5801534e48eda70abc9080cf67217210a1d25
parent 532998 b4e024474194a21d9ade565abfd8340e93aed07c
child 533000 81bc9014907e9394a12551147fbe564c12cb0766
push id11276
push userrgurzau@mozilla.com
push dateMon, 20 May 2019 13:11:24 +0000
treeherdermozilla-beta@847755a7c325 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1547730
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1547730 - Do dict.iteritems() via six to support py3. r=#build shellutil.py needed special handling since it is invoked earlier than the vendor directory adding we do, so it does not have six available. Differential Revision: https://phabricator.services.mozilla.com/D28096
python/mozbuild/mozbuild/configure/__init__.py
python/mozbuild/mozbuild/configure/options.py
python/mozbuild/mozbuild/preprocessor.py
python/mozbuild/mozbuild/shellutil.py
python/mozbuild/mozbuild/util.py
python/mozbuild/mozpack/chrome/flags.py
python/mozbuild/mozpack/copier.py
python/mozbuild/mozpack/files.py
python/mozbuild/mozpack/mozjar.py
python/mozbuild/mozpack/packager/__init__.py
python/mozbuild/mozpack/packager/l10n.py
python/mozbuild/mozpack/test/test_copier.py
python/mozbuild/mozpack/test/test_packager_formats.py
python/mozbuild/mozpack/test/test_packager_l10n.py
--- a/python/mozbuild/mozbuild/configure/__init__.py
+++ b/python/mozbuild/mozbuild/configure/__init__.py
@@ -4,16 +4,17 @@
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import __builtin__
 import inspect
 import logging
 import os
 import re
+import six
 import sys
 import types
 from collections import OrderedDict
 from contextlib import contextmanager
 from functools import wraps
 from mozbuild.configure.options import (
     CommandLineHelper,
     ConflictingOptionError,
@@ -659,17 +660,17 @@ class ConfigureSandbox(dict):
         resolved arguments (uses the result of functions when functions are
         passed). In most cases, the result of this function is not expected to
         be used.
         Command line argument/environment variable parsing for this Option is
         handled here.
         '''
         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 six.iteritems(kwargs)
                   if k != 'when'}
         option = Option(*args, **kwargs)
         if when:
             self._conditions[option] = when
         if option.name in self._options:
             raise ConfigureError('Option `%s` already defined' % option.option)
         if option.env in self._options:
             raise ConfigureError('Option `%s` already defined' % option.env)
@@ -757,17 +758,17 @@ class ConfigureSandbox(dict):
         Templates allow to simplify repetitive constructs, or to implement
         helper decorators and somesuch.
         '''
         def update_globals(glob):
             glob.update(
                 (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 six.iteritems(self) if k not in glob)
 
         template = self._prepare_function(func, update_globals)
 
         # 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
         # likely a decorator), that function must be prepared to be sandboxed as
         # well.
         def wrap_template(template):
@@ -782,17 +783,17 @@ class ConfigureSandbox(dict):
             # so it mustn't depend on anything from the global scope in this
             # file. It can however depend on variables from the closure, thus
             # maybe_prepare_function and isfunction are declared above to be
             # available there.
             @self.wraps(template)
             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
                     # details of implementing decorators, so do some of the
                     # work for them. If the function takes exactly one function
                     # as argument and returns a function, it must be a
                     # decorator, so mark the returned function as wrapping the
                     # function passed in.
@@ -1050,17 +1051,18 @@ class ConfigureSandbox(dict):
         for @depends, and @template.
         '''
         if not inspect.isfunction(func):
             raise TypeError("Unexpected type: '%s'" % type(func).__name__)
         if func in self._prepared_functions:
             return func
 
         glob = SandboxedGlobal(
-            (k, v) for k, v in func.func_globals.iteritems()
+            (k, v)
+            for k, v in six.iteritems(func.func_globals)
             if (inspect.isfunction(v) and v not in self._templates) or (
                 inspect.isclass(v) and issubclass(v, Exception))
         )
         glob.update(
             __builtins__=self.BUILTINS,
             __file__=self._paths[-1] if self._paths else '',
             __name__=self._paths[-1] if self._paths else '',
             os=self.OS,
--- a/python/mozbuild/mozbuild/configure/options.py
+++ b/python/mozbuild/mozbuild/configure/options.py
@@ -1,15 +1,16 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import os
+import six
 import sys
 import types
 from collections import OrderedDict
 
 
 def istupleofstrings(obj):
     return isinstance(obj, tuple) and len(obj) and all(
         isinstance(o, types.StringTypes) for o in obj)
@@ -127,17 +128,17 @@ class InvalidOptionError(Exception):
     pass
 
 
 class ConflictingOptionError(InvalidOptionError):
     def __init__(self, message, **format_data):
         if format_data:
             message = message.format(**format_data)
         super(ConflictingOptionError, self).__init__(message)
-        for k, v in format_data.iteritems():
+        for k, v in six.iteritems(format_data):
             setattr(self, k, v)
 
 
 class Option(object):
     '''Represents a configure option
 
     A configure option can be a command line flag or an environment variable
     or both.
--- a/python/mozbuild/mozbuild/preprocessor.py
+++ b/python/mozbuild/mozbuild/preprocessor.py
@@ -291,20 +291,21 @@ class Preprocessor:
         def __init__(self, cpp, MSG, context):
             self.file = cpp.context['FILE']
             self.line = cpp.context['LINE']
             self.key = MSG
             RuntimeError.__init__(self, (self.file, self.line, self.key, context))
 
     def __init__(self, defines=None, marker='#'):
         self.context = Context()
-        for k, v in {'FILE': '',
-                     'LINE': 0,
-                     'DIRECTORY': os.path.abspath('.')}.iteritems():
-            self.context[k] = v
+        self.context.update({
+            'FILE': '',
+            'LINE': 0,
+            'DIRECTORY': os.path.abspath('.')
+            })
         try:
             # Can import globally because of bootstrapping issues.
             from buildconfig import topsrcdir, topobjdir
         except ImportError:
             # Allow this script to still work independently of a configured objdir.
             topsrcdir = topobjdir = None
         self.topsrcdir = topsrcdir
         self.topobjdir = topobjdir
@@ -314,33 +315,35 @@ class Preprocessor:
         # ifStates can be
         #  0: hadTrue
         #  1: wantsTrue
         #  2: #else found
         self.ifStates = []
         self.checkLineNumbers = False
         self.filters = []
         self.cmds = {}
-        for cmd, level in {'define': 0,
-                           'undef': 0,
-                           'if': sys.maxint,
-                           'ifdef': sys.maxint,
-                           'ifndef': sys.maxint,
-                           'else': 1,
-                           'elif': 1,
-                           'elifdef': 1,
-                           'elifndef': 1,
-                           'endif': sys.maxint,
-                           'expand': 0,
-                           'literal': 0,
-                           'filter': 0,
-                           'unfilter': 0,
-                           'include': 0,
-                           'includesubst': 0,
-                           'error': 0}.iteritems():
+        for cmd, level in (
+            ('define', 0),
+            ('undef', 0),
+            ('if', sys.maxint),
+            ('ifdef', sys.maxint),
+            ('ifndef', sys.maxint),
+            ('else', 1),
+            ('elif', 1),
+            ('elifdef', 1),
+            ('elifndef', 1),
+            ('endif', sys.maxint),
+            ('expand', 0),
+            ('literal', 0),
+            ('filter', 0),
+            ('unfilter', 0),
+            ('include', 0),
+            ('includesubst', 0),
+            ('error', 0),
+        ):
             self.cmds[cmd] = (level, getattr(self, 'do_' + cmd))
         self.out = sys.stdout
         self.setMarker(marker)
         self.varsubst = re.compile('@(?P<VAR>\w+)@', re.U)
         self.includes = set()
         self.silenceMissingDirectiveWarnings = False
         if defines:
             self.context.update(defines)
--- a/python/mozbuild/mozbuild/shellutil.py
+++ b/python/mozbuild/mozbuild/shellutil.py
@@ -12,17 +12,17 @@ def _tokens2re(**tokens):
     #   (?<!\\)(?:a|b|c...)
     # This is meant to match patterns a, b, or c, or ... if they are not
     # preceded by a backslash.
     # where a, b, c... are in the form
     #   (?P<name>pattern)
     # 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
     # backslash, captured in the "escape" match group.
     return re.compile('(?:%s|%s)' % (nonescaped, r'(?P<escape>\\\\)'))
 
 
 UNQUOTED_TOKENS_RE = _tokens2re(
--- a/python/mozbuild/mozbuild/util.py
+++ b/python/mozbuild/mozbuild/util.py
@@ -12,16 +12,17 @@ import collections
 import ctypes
 import difflib
 import errno
 import functools
 import hashlib
 import itertools
 import os
 import re
+import six
 import stat
 import sys
 import time
 import types
 
 from collections import (
     Iterable,
     OrderedDict,
@@ -88,17 +89,17 @@ class EmptyValue(unicode):
     def __init__(self):
         super(EmptyValue, self).__init__()
 
 
 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 six.iteritems(kwargs):
             super(ReadOnlyNamespace, self).__setattr__(k, v)
 
     def __delattr__(self, key):
         raise Exception('Object does not support deletion.')
 
     def __setattr__(self, key, value):
         raise Exception('Object does not support assignment.')
 
@@ -577,17 +578,17 @@ def FlagsFactory(flags):
     assert isinstance(flags, dict)
     assert all(isinstance(v, type) for v in flags.values())
 
     class Flags(object):
         __slots__ = flags.keys()
         _flags = flags
 
         def update(self, **kwargs):
-            for k, v in kwargs.iteritems():
+            for k, v in six.iteritems(kwargs):
                 setattr(self, k, v)
 
         def __getattr__(self, name):
             if name not in self.__slots__:
                 raise AttributeError("'%s' object has no attribute '%s'" %
                                      (self.__class__.__name__, name))
             try:
                 return object.__getattr__(self, name)
@@ -1293,17 +1294,17 @@ def indented_repr(o, indent=4):
     return ''.join(recurse_indented_repr(o, 0))
 
 
 def encode(obj, encoding='utf-8'):
     '''Recursively encode unicode strings with the given encoding.'''
     if isinstance(obj, dict):
         return {
             encode(k, encoding): encode(v, encoding)
-            for k, v in obj.iteritems()
+            for k, v in six.iteritems(obj)
         }
     if isinstance(obj, bytes):
         return obj
     if isinstance(obj, unicode):
         return obj.encode(encoding)
     if isinstance(obj, Iterable):
         return [encode(i, encoding) for i in obj]
     return obj
--- a/python/mozbuild/mozpack/chrome/flags.py
+++ b/python/mozbuild/mozpack/chrome/flags.py
@@ -1,15 +1,16 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import re
+import six
 from distutils.version import LooseVersion
 from mozpack.errors import errors
 from collections import OrderedDict
 
 
 class Flag(object):
     '''
     Class for flags in manifest entries in the form:
@@ -257,14 +258,14 @@ class Flags(OrderedDict):
         '''
         Return whether the set of flags match the set of given filters.
             flags = Flags('contentaccessible=yes', 'appversion>=3.5',
                           'application=foo')
             flags.match(application='foo') returns True
             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 six.iteritems(filter):
             if name not in self:
                 continue
             if not self[name].matches(value):
                 return False
         return True
--- a/python/mozbuild/mozpack/copier.py
+++ b/python/mozbuild/mozpack/copier.py
@@ -1,15 +1,16 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import os
+import six
 import stat
 import sys
 
 from mozpack.errors import errors
 from mozpack.files import (
     BaseFile,
     DeflatedFile,
     Dest,
@@ -140,17 +141,17 @@ class FileRegistry(object):
         return self._files[path]
 
     def __iter__(self):
         '''
         Iterate over all (path, BaseFile instance) pairs from the container.
             for path, file in registry:
                 (...)
         '''
-        return self._files.iteritems()
+        return six.iteritems(self._files)
 
     def required_directories(self):
         '''
         Return the set of directories required by the paths in the container,
         in no particular order.  The returned directories are relative to an
         unspecified (virtual) root directory (and do not include said root
         directory).
         '''
--- a/python/mozbuild/mozpack/files.py
+++ b/python/mozbuild/mozpack/files.py
@@ -4,16 +4,17 @@
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import errno
 import inspect
 import os
 import platform
 import shutil
+import six
 import stat
 import subprocess
 import uuid
 import mozbuild.makeutil as makeutil
 from itertools import chain
 from mozbuild.preprocessor import Preprocessor
 from mozbuild.util import (
     FileAvoidWrite,
@@ -1088,17 +1089,17 @@ class ComposedFinder(BaseFinder):
     '''
 
     def __init__(self, finders):
         # Can't import globally, because of the dependency of mozpack.copier
         # on this module.
         from mozpack.copier import FileRegistry
         self.files = FileRegistry()
 
-        for base, finder in sorted(finders.iteritems()):
+        for base, finder in sorted(six.iteritems(finders)):
             if self.files.contains(base):
                 self.files.remove(base)
             for p, f in finder.find(''):
                 self.files.add(mozpath.join(base, p), f)
 
     def find(self, pattern):
         for p in self.files.match(pattern):
             yield p, self.files[p]
--- a/python/mozbuild/mozpack/mozjar.py
+++ b/python/mozbuild/mozpack/mozjar.py
@@ -4,16 +4,17 @@
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 from io import BytesIO
 import struct
 import subprocess
 import zlib
 import os
+import six
 from zipfile import (
     ZIP_STORED,
     ZIP_DEFLATED,
 )
 from collections import OrderedDict
 import mozpack.path as mozpath
 from mozbuild.util import (
     memoize,
@@ -91,17 +92,17 @@ class JarStruct(object):
         assert data is not None
         self.signature, size = JarStruct.get_data('uint32', data)
         if self.signature != self.MAGIC:
             raise JarReaderError('Bad magic')
         offset = size
         # 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 six.iteritems(self.STRUCT):
             if t in JarStruct.TYPE_MAPPING:
                 value, size = JarStruct.get_data(t, data[offset:])
             else:
                 size = sizes[t]
                 value = data[offset:offset + size]
                 if isinstance(value, memoryview):
                     value = value.tobytes()
             if name not in sizes:
@@ -110,17 +111,17 @@ class JarStruct(object):
                 sizes[name] = value
             offset += size
 
     def _init_empty(self):
         '''
         Initialize an instance with empty fields.
         '''
         self.signature = self.MAGIC
-        for name, t in self.STRUCT.iteritems():
+        for name, t in six.iteritems(self.STRUCT):
             if name in self.size_fields:
                 continue
             self._values[name] = 0 if t in JarStruct.TYPE_MAPPING else ''
 
     @staticmethod
     def get_data(type, data):
         '''
         Deserialize a single field of given type (must be one of
@@ -135,19 +136,20 @@ class JarStruct(object):
         return struct.unpack(b'<' + format, data)[0], size
 
     def serialize(self):
         '''
         Serialize the data structure according to the data structure definition
         from self.STRUCT.
         '''
         serialized = struct.pack(b'<I', self.signature)
-        sizes = dict((t, name) for name, t in self.STRUCT.iteritems()
+        sizes = dict((t, name)
+                     for name, t in six.iteritems(self.STRUCT)
                      if t not in JarStruct.TYPE_MAPPING)
-        for name, t in self.STRUCT.iteritems():
+        for name, t in six.iteritems(self.STRUCT):
             if t in JarStruct.TYPE_MAPPING:
                 format, size = JarStruct.TYPE_MAPPING[t]
                 if name in sizes:
                     value = len(self[sizes[name]])
                 else:
                     value = self[name]
                 serialized += struct.pack(b'<' + format, value)
             else:
@@ -156,17 +158,17 @@ class JarStruct(object):
 
     @property
     def size(self):
         '''
         Return the size of the data structure, given the current values of all
         variable length fields.
         '''
         size = JarStruct.TYPE_MAPPING['uint32'][1]
-        for name, type in self.STRUCT.iteritems():
+        for name, type in six.iteritems(self.STRUCT):
             if type in JarStruct.TYPE_MAPPING:
                 size += JarStruct.TYPE_MAPPING[type][1]
             else:
                 size += len(self[name])
         return size
 
     def __getitem__(self, key):
         return self._values[key]
@@ -177,17 +179,17 @@ class JarStruct(object):
         if key in self.size_fields:
             raise AttributeError("can't set attribute")
         self._values[key] = value
 
     def __contains__(self, key):
         return key in self._values
 
     def __iter__(self):
-        return self._values.iteritems()
+        return six.iteritems(self._values)
 
     def __repr__(self):
         return "<%s %s>" % (self.__class__.__name__,
                             ' '.join('%s=%s' % (n, v) for n, v in self))
 
 
 class JarCdirEnd(JarStruct):
     '''
--- a/python/mozbuild/mozpack/packager/__init__.py
+++ b/python/mozbuild/mozpack/packager/__init__.py
@@ -2,16 +2,17 @@
 # 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.preprocessor import Preprocessor
 import re
 import os
+import six
 from mozpack.errors import errors
 from mozpack.chrome.manifest import (
     Manifest,
     ManifestBinaryComponent,
     ManifestChrome,
     ManifestInterfaces,
     is_manifest,
     parse_manifest,
@@ -361,17 +362,18 @@ class SimplePackager(object):
     def close(self):
         '''
         Push all instructions to the formatter.
         '''
         self._closed = True
 
         bases = self.get_bases()
         broken_bases = sorted(
-            m for m, includer in self._included_manifests.iteritems()
+            m
+            for m, includer in six.iteritems(self._included_manifests)
             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"' %
                          (m, self._included_manifests[m],
                           mozpath.basedir(m, bases)))
         for base in sorted(bases):
             self.formatter.add_base(base, self._addons.get(base, False))
         self._chrome_queue.execute()
--- a/python/mozbuild/mozpack/packager/l10n.py
+++ b/python/mozbuild/mozpack/packager/l10n.py
@@ -6,16 +6,17 @@ from __future__ import absolute_import, 
 
 '''
 Replace localized parts of a packaged directory with data from a langpack
 directory.
 '''
 
 import json
 import os
+import six
 import mozpack.path as mozpath
 from mozpack.packager.formats import (
     FlatFormatter,
     JarFormatter,
     OmniJarFormatter,
 )
 from mozpack.packager import (
     Component,
@@ -253,17 +254,17 @@ def _repack(app_finder, l10n_finder, cop
     # Resources in `localization` directories are packaged from the source and then
     # if localized versions are present in the l10n dir, we package them as well
     # keeping the source dir resources as a runtime fallback.
     for p, f in l10n_finder.find('**/localization'):
         if not formatter.contains(p):
             formatter.add(p, f)
 
     # Transplant jar preloading information.
-    for path, log in app_finder.jarlogs.iteritems():
+    for path, log in six.iteritems(app_finder.jarlogs):
         assert isinstance(copier[path], Jarrer)
         copier[path].preload([l.replace(locale, l10n_locale) for l in log])
 
 
 def repack(source, l10n, extra_l10n={}, non_resources=[], non_chrome=set()):
     '''
     Replace localized data from the `source` directory with localized data
     from `l10n` and `extra_l10n`.
@@ -284,17 +285,17 @@ def repack(source, l10n, extra_l10n={}, 
     localized files that are not listed in a chrome.manifest.
     '''
     app_finder = UnpackFinder(source)
     l10n_finder = UnpackFinder(l10n)
     if extra_l10n:
         finders = {
             '': l10n_finder,
         }
-        for base, path in extra_l10n.iteritems():
+        for base, path in six.iteritems(extra_l10n):
             finders[base] = UnpackFinder(path)
         l10n_finder = ComposedFinder(finders)
     copier = FileCopier()
     compress = min(app_finder.compressed, JAR_DEFLATED)
     if app_finder.kind == 'flat':
         formatter = FlatFormatter(copier)
     elif app_finder.kind == 'jar':
         formatter = JarFormatter(copier,
--- a/python/mozbuild/mozpack/test/test_copier.py
+++ b/python/mozbuild/mozpack/test/test_copier.py
@@ -14,16 +14,17 @@ from mozpack.files import (
     GeneratedFile,
     ExistingFile,
 )
 from mozpack.mozjar import JarReader
 import mozpack.path as mozpath
 import unittest
 import mozunit
 import os
+import six
 import stat
 from mozpack.errors import ErrorMessage
 from mozpack.test.test_files import (
     MockDest,
     MatchTestTemplate,
     TestWithTmpDir,
 )
 
@@ -125,17 +126,17 @@ class BaseTestFileRegistry(MatchTestTemp
 class TestFileRegistry(BaseTestFileRegistry, unittest.TestCase):
     def test_partial_paths(self):
         cases = {
             'foo/bar/baz/zot': ['foo/bar/baz', 'foo/bar', 'foo'],
             'foo/bar': ['foo'],
             'bar': [],
         }
         reg = FileRegistry()
-        for path, parts in cases.iteritems():
+        for path, parts in six.iteritems(cases):
             self.assertEqual(reg._partial_paths(path), parts)
 
     def test_file_registry(self):
         self.do_test_file_registry(FileRegistry())
 
     def test_registry_paths(self):
         self.do_test_registry_paths(FileRegistry())
 
--- a/python/mozbuild/mozpack/test/test_packager_formats.py
+++ b/python/mozbuild/mozpack/test/test_packager_formats.py
@@ -28,16 +28,17 @@ from mozpack.errors import (
     ErrorMessage,
 )
 from mozpack.test.test_files import (
     foo_xpt,
     foo2_xpt,
     bar_xpt,
 )
 import mozpack.path as mozpath
+import six
 from itertools import chain
 from test_errors import TestErrors
 
 
 CONTENTS = {
     'bases': {
         # base_path: is_addon?
         '': False,
@@ -118,32 +119,32 @@ RESULT_FLAT = {
         'component {foo-id} foo.js',
     ],
     'app/components/foo.js': FILES['app/components/foo.js'],
 }
 
 for addon in ('addon0', 'addon1', 'app/chrome/addons/addon2'):
     RESULT_FLAT.update({
         mozpath.join(addon, p): f
-        for p, f in {
+        for p, f in six.iteritems({
             'chrome.manifest': [
                 'manifest chrome/chrome.manifest',
                 'manifest components/components.manifest',
             ],
             'chrome/chrome.manifest': [
                 'content %s foo/bar/' % mozpath.basename(addon),
             ],
             'chrome/foo/bar/baz': FILES[mozpath.join(addon, 'chrome/foo/bar/baz')],
             'components/components.manifest': [
                 'interfaces bar.xpt',
                 'interfaces foo.xpt',
             ],
             'components/bar.xpt': bar_xpt,
             'components/foo.xpt': foo2_xpt,
-        }.iteritems()
+        })
     })
 
 RESULT_JAR = {
     p: RESULT_FLAT[p]
     for p in (
         'chrome.manifest',
         'chrome/chrome.manifest',
         'components/components.manifest',
@@ -181,22 +182,22 @@ RESULT_JAR.update({
     'addon0/chrome/chrome.manifest': [
         'content addon0 jar:foo.jar!/bar/',
     ],
     'addon0/chrome/foo.jar': {
         'bar/baz': FILES['addon0/chrome/foo/bar/baz'],
     },
     'addon1.xpi': {
         mozpath.relpath(p, 'addon1'): f
-        for p, f in RESULT_FLAT.iteritems()
+        for p, f in six.iteritems(RESULT_FLAT)
         if p.startswith('addon1/')
     },
     'app/chrome/addons/addon2.xpi': {
         mozpath.relpath(p, 'app/chrome/addons/addon2'): f
-        for p, f in RESULT_FLAT.iteritems()
+        for p, f in six.iteritems(RESULT_FLAT)
         if p.startswith('app/chrome/addons/addon2/')
     },
 })
 
 RESULT_OMNIJAR = {
     p: RESULT_FLAT[p]
     for p in (
         'components/foo.so',
@@ -257,39 +258,39 @@ RESULT_OMNIJAR['omni.foo'].update({
 RESULT_OMNIJAR_WITH_SUBPATH = {
     k.replace('omni.foo', 'bar/omni.foo'): v
     for k, v in RESULT_OMNIJAR.items()
 }
 
 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 six.iteritems(CONTENTS['bases'])
     },
     'manifests': [
         m.move(mozpath.join('base/root', m.base))
         for m in CONTENTS['manifests']
     ],
     'files': {
         mozpath.join('base/root', p): f
-        for p, f in CONTENTS['files'].iteritems()
+        for p, f in six.iteritems(CONTENTS['files'])
     },
 }
 
 EXTRA_CONTENTS = {
     'extra/file': GeneratedFile(b'extra file'),
 }
 
 CONTENTS_WITH_BASE['files'].update(EXTRA_CONTENTS)
 
 
 def result_with_base(results):
     result = {
         mozpath.join('base/root', p): v
-        for p, v in results.iteritems()
+        for p, v in six.iteritems(results)
     }
     result.update(EXTRA_CONTENTS)
     return result
 
 
 RESULT_FLAT_WITH_BASE = result_with_base(RESULT_FLAT)
 RESULT_JAR_WITH_BASE = result_with_base(RESULT_JAR)
 RESULT_OMNIJAR_WITH_BASE = result_with_base(RESULT_OMNIJAR)
@@ -297,17 +298,17 @@ RESULT_OMNIJAR_WITH_BASE = result_with_b
 
 def fill_formatter(formatter, contents):
     for base, is_addon in sorted(contents['bases'].items()):
         formatter.add_base(base, is_addon)
 
     for manifest in contents['manifests']:
         formatter.add_manifest(manifest)
 
-    for k, v in sorted(contents['files'].iteritems()):
+    for k, v in sorted(six.iteritems(contents['files'])):
         if k.endswith('.xpt'):
             formatter.add_interfaces(k, v)
         else:
             formatter.add(k, v)
 
 
 def get_contents(registry, read_all=False):
     result = {}
--- a/python/mozbuild/mozpack/test/test_packager_l10n.py
+++ b/python/mozbuild/mozpack/test/test_packager_l10n.py
@@ -1,15 +1,16 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import unittest
+import six
 import mozunit
 from test_packager import MockFinder
 from mozpack.packager import l10n
 from mozpack.files import (
     GeneratedFile,
     ManifestFile,
 )
 from mozpack.chrome.manifest import (
@@ -115,14 +116,14 @@ class TestL10NRepack(unittest.TestCase):
             'app/dict/aa': dict_aa,
             'app/chrome/bar-l10n/search/foo.xml': foo_l10n,
             'app/chrome/bar-l10n/search/qux.xml': qux_l10n,
             'app/chrome/bar-l10n/search/lst.txt': lst_l10n,
         }
 
         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 six.iteritems(repacked)),
         )
 
 
 if __name__ == '__main__':
     mozunit.main()