Backed out 27 changesets (bug 1542963, bug 1547730) on request from Callek for DWE fails. CLOSED TREE
authorCsoregi Natalia <ncsoregi@mozilla.com>
Thu, 16 May 2019 20:17:46 +0300
changeset 474088 ee4b88439111cf03944808dc170dbefa74fbdab0
parent 474087 dd5c42327e22e7de29060c6a37a550401a8bf9fb
child 474089 181465d74bc486fee79406d4270b2372d5aea1e5
push id113128
push userncsoregi@mozilla.com
push dateThu, 16 May 2019 17:18:18 +0000
treeherdermozilla-inbound@ee4b88439111 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1542963, 1547730
milestone68.0a1
backs out9e9c2e06d0fbf2688be81b6f210a18c3da01cb3a
d282ddabcb3d214f603704468f8e172d09bc7c2d
3df19a96f8ac74b2c4100d40dc91b18efcb59749
27ff9602d80a13414d81422eaa02d01d60475a4e
48f2c4980ad0f2cccf92d9a45c0885db3f1f7b45
cef492de6a7f54986925e2e2f56cbdcdad04a916
59a1393697e0ac36ee62be71adf58a51904e02b6
61b8fcc639e087ced07e6dacf77fb66c1bb5f178
2d6ba80390c8d4f09a53b89936836982baebd31f
75879e53727cca39ce05eb638b60a8516c5eb029
03bdcaab1623f0b867ba989663b31477f74b6d60
6c9f98dacbde5f8bd5a810e17ca3013812e814f2
3037f5bf1019d1eb730e31857e1a8d4d4216eadb
3df74540bde34a0514c2b98bab05152d2b1cffed
1891cfbb55d1570132882c3adda6ad8d80e08cc4
16b1c53aba9d757d50fcd88b91f937266296dd26
b7b1062d0aad633e369d12613e8919b5e44d4c28
aa2acfd554fccc899c45ab29d5fb4f7062b00167
fa39fb43fd1284eb017291717bb4ae85fdb4b09b
35e2dc6ad3474355bdeb4d1639fba65d61c24cf6
1b766ee6bf2385df6cd79ad01edd47dcfa56b657
c846bf431b5c79ea08053f1fa9952ea6543d41d7
042cdcc4e1031f6ca1270a85fc383cc40f8cb79c
81bc9014907e9394a12551147fbe564c12cb0766
afa5801534e48eda70abc9080cf67217210a1d25
b4e024474194a21d9ade565abfd8340e93aed07c
5f3c10562df335827c80fd866a1eba8f256540d2
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
Backed out 27 changesets (bug 1542963, bug 1547730) on request from Callek for DWE fails. CLOSED TREE Backed out changeset 9e9c2e06d0fb (bug 1547730) Backed out changeset d282ddabcb3d (bug 1547730) Backed out changeset 3df19a96f8ac (bug 1547730) Backed out changeset 27ff9602d80a (bug 1547730) Backed out changeset 48f2c4980ad0 (bug 1547730) Backed out changeset cef492de6a7f (bug 1547730) Backed out changeset 59a1393697e0 (bug 1547730) Backed out changeset 61b8fcc639e0 (bug 1547730) Backed out changeset 2d6ba80390c8 (bug 1547730) Backed out changeset 75879e53727c (bug 1547730) Backed out changeset 03bdcaab1623 (bug 1547730) Backed out changeset 6c9f98dacbde (bug 1547730) Backed out changeset 3037f5bf1019 (bug 1547730) Backed out changeset 3df74540bde3 (bug 1547730) Backed out changeset 1891cfbb55d1 (bug 1547730) Backed out changeset 16b1c53aba9d (bug 1547730) Backed out changeset b7b1062d0aad (bug 1547730) Backed out changeset aa2acfd554fc (bug 1547730) Backed out changeset fa39fb43fd12 (bug 1547730) Backed out changeset 35e2dc6ad347 (bug 1547730) Backed out changeset 1b766ee6bf23 (bug 1547730) Backed out changeset c846bf431b5c (bug 1547730) Backed out changeset 042cdcc4e103 (bug 1547730) Backed out changeset 81bc9014907e (bug 1547730) Backed out changeset afa5801534e4 (bug 1547730) Backed out changeset b4e024474194 (bug 1547730) Backed out changeset 5f3c10562df3 (bug 1542963)
build/moz.configure/init.configure
configure.py
python/moz.build
python/mozbuild/mozbuild/backend/configenvironment.py
python/mozbuild/mozbuild/base.py
python/mozbuild/mozbuild/configure/__init__.py
python/mozbuild/mozbuild/configure/lint.py
python/mozbuild/mozbuild/configure/options.py
python/mozbuild/mozbuild/configure/util.py
python/mozbuild/mozbuild/jar.py
python/mozbuild/mozbuild/makeutil.py
python/mozbuild/mozbuild/preprocessor.py
python/mozbuild/mozbuild/repackaging/mar.py
python/mozbuild/mozbuild/shellutil.py
python/mozbuild/mozbuild/test/python.ini
python/mozbuild/mozbuild/test/python2.ini
python/mozbuild/mozbuild/util.py
python/mozbuild/mozpack/archive.py
python/mozbuild/mozpack/chrome/flags.py
python/mozbuild/mozpack/chrome/manifest.py
python/mozbuild/mozpack/copier.py
python/mozbuild/mozpack/dmg.py
python/mozbuild/mozpack/errors.py
python/mozbuild/mozpack/executables.py
python/mozbuild/mozpack/files.py
python/mozbuild/mozpack/hg.py
python/mozbuild/mozpack/mozjar.py
python/mozbuild/mozpack/packager/__init__.py
python/mozbuild/mozpack/packager/formats.py
python/mozbuild/mozpack/packager/l10n.py
python/mozbuild/mozpack/packager/unpack.py
python/mozbuild/mozpack/path.py
python/mozbuild/mozpack/test/python.ini
python/mozbuild/mozpack/test/python2.ini
python/mozbuild/mozpack/test/support/minify_js_verify.py
python/mozbuild/mozpack/test/test_archive.py
python/mozbuild/mozpack/test/test_chrome_flags.py
python/mozbuild/mozpack/test/test_chrome_manifest.py
python/mozbuild/mozpack/test/test_copier.py
python/mozbuild/mozpack/test/test_errors.py
python/mozbuild/mozpack/test/test_files.py
python/mozbuild/mozpack/test/test_mozjar.py
python/mozbuild/mozpack/test/test_packager.py
python/mozbuild/mozpack/test/test_packager_formats.py
python/mozbuild/mozpack/test/test_packager_l10n.py
python/mozbuild/mozpack/test/test_packager_unpack.py
python/mozbuild/mozpack/test/test_path.py
--- a/build/moz.configure/init.configure
+++ b/build/moz.configure/init.configure
@@ -301,17 +301,16 @@ def early_options():
 
 early_options = early_options()
 
 
 @depends(mozconfig, 'MOZ_AUTOMATION', '--help')
 # This gives access to the sandbox. Don't copy this blindly.
 @imports('__sandbox__')
 @imports('os')
-@imports('six')
 def mozconfig_options(mozconfig, automation, help):
     if mozconfig['path']:
         if 'MOZ_AUTOMATION_MOZCONFIG' in mozconfig['env']['added']:
             if not automation:
                 log.error('%s directly or indirectly includes an in-tree '
                           'mozconfig.', mozconfig['path'])
                 log.error('In-tree mozconfigs make strong assumptions about '
                           'and are only meant to be used by Mozilla '
@@ -327,25 +326,25 @@ def mozconfig_options(mozconfig, automat
             helper.add(arg, origin='mozconfig', args=helper._args)
 
         def add(key, value):
             if key.isupper():
                 arg = '%s=%s' % (key, value)
                 log.info('  %s' % arg)
                 helper.add(arg, origin='mozconfig', args=helper._args)
 
-        for key, value in six.iteritems(mozconfig['env']['added']):
+        for key, value in mozconfig['env']['added'].iteritems():
             add(key, value)
             os.environ[key] = value
-        for key, (_, value) in six.iteritems(mozconfig['env']['modified']):
+        for key, (_, value) in mozconfig['env']['modified'].iteritems():
             add(key, value)
             os.environ[key] = value
-        for key, value in six.iteritems(mozconfig['vars']['added']):
+        for key, value in mozconfig['vars']['added'].iteritems():
             add(key, value)
-        for key, (_, value) in six.iteritems(mozconfig['vars']['modified']):
+        for key, (_, value) in mozconfig['vars']['modified'].iteritems():
             add(key, value)
 
 
 # Mozilla-Build
 # ==============================================================
 option(env='MOZILLABUILD', nargs=1,
        help='Path to Mozilla Build (Windows-only)')
 
--- a/configure.py
+++ b/configure.py
@@ -9,17 +9,16 @@ import itertools
 import logging
 import os
 import sys
 import textwrap
 
 
 base_dir = os.path.abspath(os.path.dirname(__file__))
 sys.path.insert(0, os.path.join(base_dir, 'python', 'mozbuild'))
-sys.path.insert(0, os.path.join(base_dir, 'third_party', 'python', 'six'))
 from mozbuild.configure import (
     ConfigureSandbox,
     TRACE,
 )
 from mozbuild.pythonutil import iter_modules_in_path
 from mozbuild.backend.configenvironment import PartialConfigEnvironment
 from mozbuild.util import (
     indented_repr,
--- a/python/moz.build
+++ b/python/moz.build
@@ -61,12 +61,10 @@ PYTHON_UNITTEST_MANIFESTS += [
     'mozrelease/test/python.ini',
     'mozterm/test/python.ini',
     'mozversioncontrol/test/python.ini',
 ]
 
 if CONFIG['MOZ_BUILD_APP']:
     PYTHON_UNITTEST_MANIFESTS += [
         'mozbuild/mozbuild/test/python.ini',
-        'mozbuild/mozbuild/test/python2.ini',
         'mozbuild/mozpack/test/python.ini',
-        'mozbuild/mozpack/test/python2.ini',
     ]
--- a/python/mozbuild/mozbuild/backend/configenvironment.py
+++ b/python/mozbuild/mozbuild/backend/configenvironment.py
@@ -1,32 +1,37 @@
 # 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
 
 import os
-import six
 import sys
 import json
 
 from collections import Iterable, OrderedDict
-from types import ModuleType
+from types import StringTypes, ModuleType
 
 import mozpack.path as mozpath
 
 from mozbuild.util import (
     FileAvoidWrite,
     memoized_property,
     ReadOnlyDict,
 )
 from mozbuild.shellutil import quote as shell_quote
 
 
+if sys.version_info.major == 2:
+    text_type = unicode
+else:
+    text_type = str
+
+
 class BuildConfig(object):
     """Represents the output of configure."""
 
     _CODE_CACHE = {}
 
     def __init__(self):
         self.topsrcdir = None
         self.topobjdir = None
@@ -147,17 +152,17 @@ class ConfigEnvironment(object):
         self.substs["ACDEFINES"] = ' '.join(
             [
                 '-D%s=%s' % (name, shell_quote(self.defines[name]).replace('$', '$$'))
                 for name in sorted(global_defines)
             ]
         )
 
         def serialize(name, obj):
-            if isinstance(obj, six.string_types):
+            if isinstance(obj, StringTypes):
                 return obj
             if isinstance(obj, Iterable):
                 return ' '.join(obj)
             raise Exception('Unhandled type %s for %s', type(obj), str(name))
         self.substs['ALLSUBSTS'] = '\n'.join(
             sorted([
                 '%s = %s' % (
                     name,
@@ -186,27 +191,27 @@ class ConfigEnvironment(object):
         # Populate a Unicode version of substs. This is an optimization to make
         # moz.build reading faster, since each sandbox needs a Unicode version
         # of these variables and doing it over a thousand times is a hotspot
         # during sandbox execution!
         # Bug 844509 tracks moving everything to Unicode.
         self.substs_unicode = {}
 
         def decode(v):
-            if not isinstance(v, six.text_type):
+            if not isinstance(v, text_type):
                 try:
                     return v.decode('utf-8')
                 except UnicodeDecodeError:
                     return v.decode('utf-8', 'replace')
 
         for k, v in self.substs.items():
-            if not isinstance(v, six.string_types):
+            if not isinstance(v, StringTypes):
                 if isinstance(v, Iterable):
                     type(v)(decode(i) for i in v)
-            elif not isinstance(v, six.text_type):
+            elif not isinstance(v, text_type):
                 v = decode(v)
 
             self.substs_unicode[k] = v
 
         self.substs_unicode = ReadOnlyDict(self.substs_unicode)
 
     @property
     def is_artifact_build(self):
--- a/python/mozbuild/mozbuild/base.py
+++ b/python/mozbuild/mozbuild/base.py
@@ -4,26 +4,27 @@
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import json
 import logging
 import mozpack.path as mozpath
 import multiprocessing
 import os
-import six
 import subprocess
 import sys
+import types
 import errno
 try:
     from shutil import which
 except ImportError:
     # shutil.which is not available in Python 2.7
     import which
 
+from StringIO import StringIO
 from mach.mixin.process import ProcessExecutionMixin
 from mozversioncontrol import (
     get_repository_from_build_config,
     get_repository_object,
     InvalidRepoPath,
 )
 
 from .backend.configenvironment import ConfigEnvironment
@@ -267,33 +268,33 @@ class MozbuildObject(ProcessExecutionMix
 
     @staticmethod
     @memoize
     def get_mozconfig_and_target(topsrcdir, path, env_mozconfig):
         # env_mozconfig is only useful for unittests, which change the value of
         # the environment variable, which has an impact on autodetection (when
         # path is MozconfigLoader.AUTODETECT), and memoization wouldn't account
         # for it without the explicit (unused) argument.
-        out = six.StringIO()
+        out = StringIO()
         env = os.environ
         if path and path != MozconfigLoader.AUTODETECT:
             env = dict(env)
             env['MOZCONFIG'] = path
 
         # We use python configure to get mozconfig content and the value for
         # --target (from mozconfig if necessary, guessed otherwise).
 
         # Modified configure sandbox that replaces '--help' dependencies with
         # `always`, such that depends functions with a '--help' dependency are
         # not automatically executed when including files. We don't want all of
         # those from init.configure to execute, only a subset.
         class ReducedConfigureSandbox(ConfigureSandbox):
             def depends_impl(self, *args, **kwargs):
                 args = tuple(
-                    a if not isinstance(a, six.string_types) or a != '--help'
+                    a if not isinstance(a, types.StringTypes) or a != '--help'
                     else self._always.sandboxed
                     for a in args
                 )
                 return super(ReducedConfigureSandbox, self).depends_impl(*args, **kwargs)
 
         sandbox = ReducedConfigureSandbox({}, environ=env, argv=['mach', '--help'],
                                           stdout=out, stderr=out)
         base_dir = os.path.join(topsrcdir, 'build', 'moz.configure')
--- a/python/mozbuild/mozbuild/configure/__init__.py
+++ b/python/mozbuild/mozbuild/configure/__init__.py
@@ -1,20 +1,19 @@
 # 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 __builtin__
 import inspect
 import logging
 import os
 import re
-import six
-from six.moves import builtins as __builtin__
 import sys
 import types
 from collections import OrderedDict
 from contextlib import contextmanager
 from functools import wraps
 from mozbuild.configure.options import (
     CommandLineHelper,
     ConflictingOptionError,
@@ -73,19 +72,16 @@ class SandboxDependsFunction(object):
         return self._and(other).sandboxed
 
     def __cmp__(self, other):
         raise ConfigureError('Cannot compare @depends functions.')
 
     def __eq__(self, other):
         raise ConfigureError('Cannot compare @depends functions.')
 
-    def __hash__(self):
-        return object.__hash__(self)
-
     def __ne__(self, other):
         raise ConfigureError('Cannot compare @depends functions.')
 
     def __lt__(self, other):
         raise ConfigureError('Cannot compare @depends functions.')
 
     def __le__(self, other):
         raise ConfigureError('Cannot compare @depends functions.')
@@ -230,19 +226,16 @@ class CombinedDependsFunction(DependsFun
                          for d in self.dependencies)
         return self._func(resolved_args)
 
     def __eq__(self, other):
         return (isinstance(other, self.__class__) and
                 self._func is other._func and
                 set(self.dependencies) == set(other.dependencies))
 
-    def __hash__(self):
-        return object.__hash__(self)
-
     def __ne__(self, other):
         return not self == other
 
 
 class SandboxedGlobal(dict):
     '''Identifiable dict type for use as function global'''
 
 
@@ -284,23 +277,21 @@ class ConfigureSandbox(dict):
         sandbox = ConfigureSandbox(config)
         sandbox.run(path)
         do_stuff(config)
     """
 
     # The default set of builtins. We expose unicode as str to make sandboxed
     # files more python3-ready.
     BUILTINS = ReadOnlyDict({
-        b: getattr(__builtin__, b, None)
+        b: getattr(__builtin__, b)
         for b in ('None', 'False', 'True', 'int', 'bool', 'any', 'all', 'len',
                   'list', 'tuple', 'set', 'dict', 'isinstance', 'getattr',
-                  'hasattr', 'enumerate', 'range', 'zip', 'AssertionError',
-                  '__build_class__',  # will be None on py2
-                  )
-    }, __import__=forbidden_import, str=six.text_type)
+                  'hasattr', 'enumerate', 'range', 'zip', 'AssertionError')
+    }, __import__=forbidden_import, str=unicode)
 
     # Expose a limited set of functions from os.path
     OS = ReadOnlyNamespace(path=ReadOnlyNamespace(**{
         k: getattr(mozpath, k, getattr(os.path, k))
         for k in ('abspath', 'basename', 'dirname', 'isabs', 'join',
                   'normcase', 'normpath', 'realpath', 'relpath')
     }))
 
@@ -371,17 +362,17 @@ class ConfigureSandbox(dict):
 
         def wrapped_log_method(logger, key):
             method = getattr(logger, key)
             if not encoding:
                 return method
 
             def wrapped(*args, **kwargs):
                 out_args = [
-                    arg.decode(encoding) if isinstance(arg, six.binary_type) else arg
+                    arg.decode(encoding) if isinstance(arg, str) else arg
                     for arg in args
                 ]
                 return method(*out_args, **kwargs)
             return wrapped
 
         log_namespace = {
             k: wrapped_log_method(logger, k)
             for k in ('debug', 'info', 'warning', 'error')
@@ -438,17 +429,17 @@ class ConfigureSandbox(dict):
 
     def run(self, path=None):
         '''Executes the given file within the sandbox, as well as everything
         pending from any other included file, and ensure the overall
         consistency of the executed script(s).'''
         if path:
             self.include_file(path)
 
-        for option in six.itervalues(self._options):
+        for option in self._options.itervalues():
             # All options must be referenced by some @depends function
             if option not in self._seen:
                 raise ConfigureError(
                     'Option `%s` is not handled ; reference it with a @depends'
                     % option.option
                 )
 
             self._value_for(option)
@@ -604,17 +595,17 @@ class ConfigureSandbox(dict):
                     % option_string.split('=', 1)[0])
             self._logger.log(TRACE, '%r = None', option)
             return None
 
         self._logger.log(TRACE, '%r = %r', option, value)
         return value
 
     def _dependency(self, arg, callee_name, arg_name=None):
-        if isinstance(arg, six.string_types):
+        if isinstance(arg, types.StringTypes):
             prefix, name, values = Option.split_option(arg)
             if values != ():
                 raise ConfigureError("Option must not contain an '='")
             if name not in self._options:
                 raise ConfigureError("'%s' is not a known option. "
                                      "Maybe it's declared too late?"
                                      % arg)
             arg = self._options[name]
@@ -668,17 +659,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 six.iteritems(kwargs)
+        kwargs = {k: self._resolve(v) for k, v in kwargs.iteritems()
                   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)
@@ -748,17 +739,17 @@ class ConfigureSandbox(dict):
         Allows to include external files for execution in the sandbox.
         It is possible to use a @depends function as argument, in which case
         the result of the function is the file name to include. This latter
         feature is only really meant for --enable-application/--enable-project.
         '''
         with self.only_when_impl(when):
             what = self._resolve(what)
             if what:
-                if not isinstance(what, six.string_types):
+                if not isinstance(what, types.StringTypes):
                     raise TypeError("Unexpected type: '%s'" % type(what).__name__)
                 self.include_file(what)
 
     def template_impl(self, func):
         '''Implementation of @template.
         This function is a decorator. Template functions are called
         immediately. They are altered so that their global namespace exposes
         a limited set of functions from os.path, as well as `depends` and
@@ -766,17 +757,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 six.iteritems(self) if k not in glob)
+            glob.update((k, v) for k, v in self.iteritems() 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):
@@ -791,17 +782,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.items()}
+                          for k, v in kwargs.iteritems()}
                 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.
@@ -826,17 +817,17 @@ class ConfigureSandbox(dict):
         optionally under a different _as name.
         The options correspond to the various forms for the import builtin.
             @imports('sys')
             @imports(_from='mozpack', _import='path', _as='mozpath')
         '''
         for value, required in (
                 (_import, True), (_from, False), (_as, False)):
 
-            if not isinstance(value, six.string_types) and (
+            if not isinstance(value, types.StringTypes) 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):
                 raise ValueError("Invalid argument to @imports: '%s'" % value)
         if _as and '.' in _as:
             raise ValueError("Invalid argument to @imports: '%s'" % _as)
 
         def decorator(func):
@@ -910,34 +901,32 @@ class ConfigureSandbox(dict):
         if what in ('subprocess.call', 'subprocess.check_call',
                     'subprocess.check_output', 'subprocess.Popen'):
             return getattr(self._wrapped_subprocess, what[len('subprocess.'):])
         # Until this proves to be a performance problem, just construct an
         # import statement and execute it.
         import_line = ''
         if '.' in what:
             _from, what = what.rsplit('.', 1)
-            if _from == '__builtin__' or _from.startswith('__builtin__.'):
-                _from = _from.replace('__builtin__', 'six.moves.builtins')
             import_line += 'from %s ' % _from
         import_line += 'import %s as imported' % what
         glob = {}
         exec_(import_line, {}, glob)
         return glob['imported']
 
     def _resolve_and_set(self, data, name, value, when=None):
         # Don't set anything when --help was on the command line
         if self._help:
             return
         if when and not self._value_for(when):
             return
         name = self._resolve(name)
         if name is None:
             return
-        if not isinstance(name, six.string_types):
+        if not isinstance(name, types.StringTypes):
             raise TypeError("Unexpected type: '%s'" % type(name).__name__)
         if name in data:
             raise ConfigureError(
                 "Cannot add '%s' to configuration: Key already "
                 "exists" % name)
         value = self._resolve(value)
         if value is not None:
             if self._logger.isEnabledFor(TRACE):
@@ -1025,17 +1014,17 @@ class ConfigureSandbox(dict):
             return
         if not reason and isinstance(value, SandboxDependsFunction):
             deps = self._depends[value].dependencies
             possible_reasons = [d for d in deps if d != self._help_option]
             if len(possible_reasons) == 1:
                 if isinstance(possible_reasons[0], Option):
                     reason = possible_reasons[0]
         if not reason and (isinstance(value, (bool, tuple)) or
-                           isinstance(value, six.string_types)):
+                           isinstance(value, types.StringTypes)):
             # A reason can be provided automatically when imply_option
             # is called with an immediate value.
             _, filename, line, _, _, _ = inspect.stack()[1]
             reason = "imply_option at %s:%s" % (filename, line)
 
         if not reason:
             raise ConfigureError(
                 "Cannot infer what implies '%s'. Please add a `reason` to "
@@ -1061,18 +1050,17 @@ 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 six.iteritems(func.__globals__)
+            (k, v) for k, v in func.func_globals.iteritems()
             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,
@@ -1085,30 +1073,30 @@ class ConfigureSandbox(dict):
         # order will always be the same for a given function, and if it uses
         # variables from a closure that are changed after the function is
         # declared, depending when the function is executed, the value of the
         # variable can differ. For consistency, we force the function to use
         # the value from the earliest it can be run, which is at declaration.
         # 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.__closure__:
+        if func.func_closure:
             def makecell(content):
                 def f():
                     content
-                return f.__closure__[0]
+                return f.func_closure[0]
 
             closure = tuple(makecell(cell.cell_contents)
-                            for cell in func.__closure__)
+                            for cell in func.func_closure)
 
         new_func = self.wraps(func)(types.FunctionType(
-            func.__code__,
+            func.func_code,
             glob,
             func.__name__,
-            func.__defaults__,
+            func.func_defaults,
             closure
         ))
         @self.wraps(new_func)
         def wrapped(*args, **kwargs):
             if func in self._imports:
                 self._apply_imports(func, glob)
             return new_func(*args, **kwargs)
 
--- a/python/mozbuild/mozbuild/configure/lint.py
+++ b/python/mozbuild/mozbuild/configure/lint.py
@@ -82,37 +82,37 @@ class LintSandbox(ConfigureSandbox):
         # argument, and the `raise` line is on the line given as argument.
 
         offset = line - firstline
         # co_lnotab is a string where each pair of consecutive character is
         # (chr(byte_increment), chr(line_increment)), mapping bytes in co_code
         # to line numbers relative to co_firstlineno.
         # If the offset we need to encode is larger than 255, we need to split it.
         co_lnotab = (chr(0) + chr(255)) * (offset / 255) + chr(0) + chr(offset % 255)
-        code = thrower.__code__
+        code = thrower.func_code
         code = types.CodeType(
             code.co_argcount,
             code.co_nlocals,
             code.co_stacksize,
             code.co_flags,
             code.co_code,
             code.co_consts,
             code.co_names,
             code.co_varnames,
             filename,
             funcname,
             firstline,
             co_lnotab
         )
         thrower = types.FunctionType(
             code,
-            thrower.__globals__,
+            thrower.func_globals,
             funcname,
-            thrower.__defaults__,
-            thrower.__closure__
+            thrower.func_defaults,
+            thrower.func_closure
         )
         thrower(exception)
 
     def _check_dependencies(self, obj):
         if isinstance(obj, CombinedDependsFunction) or obj in (self._always,
                                                                self._never):
             return
         func, glob = self.unwrap(obj._func)
@@ -149,17 +149,17 @@ class LintSandbox(ConfigureSandbox):
         if isinstance(obj, DependsFunction):
             if obj in (self._always, self._never):
                 return False
             func, glob = self.unwrap(obj._func)
             # We allow missing --help dependencies for functions that:
             # - don't use @imports
             # - don't have a closure
             # - don't use global variables
-            if func in self._has_imports or func.__closure__:
+            if func in self._has_imports or func.func_closure:
                 return True
             for op, arg, _ in disassemble_as_iter(func):
                 if op in ('LOAD_GLOBAL', 'STORE_GLOBAL'):
                     # There is a fake os module when one is not imported,
                     # and it's allowed for functions without a --help
                     # dependency.
                     if arg == 'os' and glob.get('os') is self.OS:
                         continue
@@ -264,20 +264,20 @@ class LintSandbox(ConfigureSandbox):
         while frame and frame.f_code.co_name != self.option_impl.__name__:
             frame = frame.f_back
         e = ConfigureError(
             '`help` should contain "{}" because of non-constant default'
             .format(rule))
         self._raise_from(e, frame.f_back if frame else None)
 
     def unwrap(self, func):
-        glob = func.__globals__
+        glob = func.func_globals
         while func in self._wrapped:
-            if isinstance(func.__globals__, SandboxedGlobal):
-                glob = func.__globals__
+            if isinstance(func.func_globals, SandboxedGlobal):
+                glob = func.func_globals
             func = self._wrapped[func]
         return func, glob
 
     def wraps(self, func):
         def do_wraps(wrapper):
             self._wrapped[wrapper] = func
             return wraps(func)(wrapper)
         return do_wraps
@@ -296,17 +296,17 @@ class LintSandbox(ConfigureSandbox):
         imports = set()
         for _from, _import, _as in self._imports.get(func, ()):
             if _as:
                 imports.add(_as)
             else:
                 what = _import.split('.')[0]
                 imports.add(what)
         for op, arg, line in disassemble_as_iter(func):
-            code = func.__code__
+            code = func.func_code
             if op == 'LOAD_GLOBAL' and \
                     arg not in glob and \
                     arg not in imports and \
                     arg not in glob['__builtins__'] and \
                     arg not in code.co_varnames[:code.co_argcount]:
                 # Raise the same kind of error as what would happen during
                 # execution.
                 e = NameError("global name '{}' is not defined".format(arg))
--- a/python/mozbuild/mozbuild/configure/options.py
+++ b/python/mozbuild/mozbuild/configure/options.py
@@ -1,23 +1,23 @@
 # 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, six.string_types) for o in obj)
+        isinstance(o, types.StringTypes) for o in obj)
 
 
 class OptionValue(tuple):
     '''Represents the value of a configure option.
 
     This class is not meant to be used directly. Use its subclasses instead.
 
     The `origin` attribute holds where the option comes from (e.g. environment,
@@ -87,17 +87,17 @@ class OptionValue(tuple):
     @staticmethod
     def from_(value):
         if isinstance(value, OptionValue):
             return value
         elif value is True:
             return PositiveOptionValue()
         elif value is False or value == ():
             return NegativeOptionValue()
-        elif isinstance(value, six.string_types):
+        elif isinstance(value, types.StringTypes):
             return PositiveOptionValue((value,))
         elif isinstance(value, tuple):
             return PositiveOptionValue(value)
         else:
             raise TypeError("Unexpected type: '%s'"
                             % type(value).__name__)
 
 
@@ -127,17 +127,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 six.iteritems(format_data):
+        for k, v in format_data.iteritems():
             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.
@@ -163,37 +163,37 @@ class Option(object):
 
     def __init__(self, name=None, env=None, nargs=None, default=None,
                  possible_origins=None, choices=None, help=None):
         if not name and not env:
             raise InvalidOptionError(
                 'At least an option name or an environment variable name must '
                 'be given')
         if name:
-            if not isinstance(name, six.string_types):
+            if not isinstance(name, types.StringTypes):
                 raise InvalidOptionError('Option must be a string')
             if not name.startswith('--'):
                 raise InvalidOptionError('Option must start with `--`')
             if '=' in name:
                 raise InvalidOptionError('Option must not contain an `=`')
             if not name.islower():
                 raise InvalidOptionError('Option must be all lowercase')
         if env:
-            if not isinstance(env, six.string_types):
+            if not isinstance(env, types.StringTypes):
                 raise InvalidOptionError(
                     'Environment variable name must be a string')
             if not env.isupper():
                 raise InvalidOptionError(
                     'Environment variable name must be all uppercase')
         if nargs not in (None, '?', '*', '+') and not (
                 isinstance(nargs, int) and nargs >= 0):
             raise InvalidOptionError(
                 "nargs must be a positive integer, '?', '*' or '+'")
-        if (not isinstance(default, six.string_types) and
-                not isinstance(default, (bool, type(None))) and
+        if (not isinstance(default, types.StringTypes) and
+                not isinstance(default, (bool, types.NoneType)) and
                 not istupleofstrings(default)):
             raise InvalidOptionError(
                 'default must be a bool, a string or a tuple of strings')
         if choices and not istupleofstrings(choices):
             raise InvalidOptionError(
                 'choices must be a tuple of strings')
         if not help:
             raise InvalidOptionError('A help string must be provided')
@@ -269,17 +269,17 @@ class Option(object):
     def split_option(option):
         '''Split a flag or variable into a prefix, a name and values
 
         Variables come in the form NAME=values (no prefix).
         Flags come in the form --name=values or --prefix-name=values
         where prefix is one of 'with', 'without', 'enable' or 'disable'.
         The '=values' part is optional. Values are separated with commas.
         '''
-        if not isinstance(option, six.string_types):
+        if not isinstance(option, types.StringTypes):
             raise InvalidOptionError('Option must be a string')
 
         elements = option.split('=', 1)
         name = elements[0]
         values = tuple(elements[1].split(',')) if len(elements) == 2 else ()
         if name.startswith('--'):
             name = name[2:]
             if not name.islower():
@@ -513,10 +513,10 @@ class CommandLineHelper(object):
                 "Cannot add '{arg}' to the {origin} set because it conflicts "
                 "with {old_arg} from the {old_origin} set", arg=extra_arg,
                 origin=extra_ret.origin, old_arg=arg, old_origin=ret.origin)
 
         return extra_ret, extra_arg
 
     def __iter__(self):
         for d in (self._args, self._extra_args):
-            for arg, pos in six.itervalues(d):
+            for arg, pos in d.itervalues():
                 yield arg
--- a/python/mozbuild/mozbuild/configure/util.py
+++ b/python/mozbuild/mozbuild/configure/util.py
@@ -3,19 +3,17 @@
 # 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
 import locale
 import logging
-import io
 import os
-import six
 import sys
 from collections import deque
 from contextlib import contextmanager
 from distutils.version import LooseVersion
 
 
 def getpreferredencoding():
     # locale._parse_localename makes locale.getpreferredencoding
@@ -51,17 +49,17 @@ class Version(LooseVersion):
         # Take the first three integer components, stopping at the first
         # non-integer and padding the rest with zeroes.
         (self.major, self.minor, self.patch) = list(itertools.chain(
             itertools.takewhile(lambda x: isinstance(x, int), self.version),
             (0, 0, 0)))[:3]
 
     def __cmp__(self, other):
         # LooseVersion checks isinstance(StringType), so work around it.
-        if isinstance(other, six.text_type):
+        if isinstance(other, unicode):
             other = other.encode('ascii')
         return LooseVersion.__cmp__(self, other)
 
 
 class ConfigureOutputHandler(logging.Handler):
     '''A logging handler class that sends info messages to stdout and other
     messages to stderr.
 
@@ -95,17 +93,17 @@ class ConfigureOutputHandler(logging.Han
             return fh
 
         self._stdout = fix_encoding(stdout)
         self._stderr = fix_encoding(stderr) if stdout != stderr else self._stdout
         try:
             fd1 = self._stdout.fileno()
             fd2 = self._stderr.fileno()
             self._same_output = self._is_same_output(fd1, fd2)
-        except (AttributeError, io.UnsupportedOperation):
+        except AttributeError:
             self._same_output = self._stdout == self._stderr
         self._stdout_waiting = None
         self._debug = deque(maxlen=maxlen + 1)
         self._keep_if_debug = self.THROW
         self._queue_is_active = False
 
     @staticmethod
     def _is_same_output(fd1, fd2):
--- a/python/mozbuild/mozbuild/jar.py
+++ b/python/mozbuild/mozbuild/jar.py
@@ -9,25 +9,23 @@ See the documentation for jar.mn on MDC 
 '''
 
 from __future__ import absolute_import, print_function
 
 import sys
 import os
 import errno
 import re
-import six
 import logging
 from time import localtime
 from MozZipFile import ZipFile
 from cStringIO import StringIO
 
 from mozbuild.preprocessor import Preprocessor
 from mozbuild.action.buildlist import addEntriesToListFile
-from mozbuild.util import ensure_bytes
 from mozpack.files import FileFinder
 import mozpack.path as mozpath
 if sys.platform == 'win32':
     from ctypes import windll, WinError
     CreateHardLink = windll.kernel32.CreateHardLinkA
 
 __all__ = ['JarMaker']
 
@@ -302,17 +300,17 @@ class JarMaker(object):
                                      self.rootManifestAppId)])
 
     def updateManifest(self, manifestPath, chromebasepath, register):
         '''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, six.iterkeys(myregister))
+        addEntriesToListFile(manifestPath, myregister.iterkeys())
 
     def makeJar(self, infile, jardir):
         '''makeJar is the main entry point to JarMaker.
 
         It takes the input file, the output directory, the source dirs and the
         top source dir as argument, and optionally the l10n dirs.
         '''
 
@@ -557,17 +555,17 @@ class JarMaker(object):
                 os.remove(out)
             except OSError as e:
                 if e.errno != errno.ENOENT:
                     raise
             if sys.platform != 'win32':
                 os.symlink(src, out)
             else:
                 # On Win32, use ctypes to create a hardlink
-                rv = CreateHardLink(ensure_bytes(out), ensure_bytes(src), None)
+                rv = CreateHardLink(out, src, None)
                 if rv == 0:
                     raise WinError()
 
 
 def main(args=None):
     args = args or sys.argv
     jm = JarMaker()
     p = jm.getCommandLineParser()
--- a/python/mozbuild/mozbuild/makeutil.py
+++ b/python/mozbuild/mozbuild/makeutil.py
@@ -1,17 +1,17 @@
 # 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
 
 import os
 import re
-import six
+from types import StringTypes
 from collections import Iterable
 
 
 class Makefile(object):
     '''Provides an interface for writing simple makefiles
 
     Instances of this class are created, populated with rules, then
     written.
@@ -100,29 +100,29 @@ class Rule(object):
     def __init__(self, targets=[]):
         self._targets = _SimpleOrderedSet()
         self._dependencies = _SimpleOrderedSet()
         self._commands = []
         self.add_targets(targets)
 
     def add_targets(self, targets):
         '''Add additional targets to the rule.'''
-        assert isinstance(targets, Iterable) and not isinstance(targets, six.string_types)
+        assert isinstance(targets, Iterable) and not isinstance(targets, StringTypes)
         self._targets.update(targets)
         return self
 
     def add_dependencies(self, deps):
         '''Add dependencies to the rule.'''
-        assert isinstance(deps, Iterable) and not isinstance(deps, six.string_types)
+        assert isinstance(deps, Iterable) and not isinstance(deps, StringTypes)
         self._dependencies.update(deps)
         return self
 
     def add_commands(self, commands):
         '''Add commands to the rule.'''
-        assert isinstance(commands, Iterable) and not isinstance(commands, six.string_types)
+        assert isinstance(commands, Iterable) and not isinstance(commands, StringTypes)
         self._commands.extend(commands)
         return self
 
     def targets(self):
         '''Return an iterator on the rule targets.'''
         # Ensure the returned iterator is actually just that, an iterator.
         # Avoids caller fiddling with the set itself.
         return iter(self._targets)
--- a/python/mozbuild/mozbuild/preprocessor.py
+++ b/python/mozbuild/mozbuild/preprocessor.py
@@ -22,17 +22,16 @@ value :
   | \w+  # string identifier or value;
 """
 
 from __future__ import absolute_import, print_function
 
 import sys
 import os
 import re
-import six
 from optparse import OptionParser
 import errno
 from mozbuild.makeutil import Makefile
 
 # hack around win32 mangling our line endings
 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65443
 if sys.platform == "win32":
     import msvcrt
@@ -242,17 +241,17 @@ class Expression:
             self.type = type
 
         def __str__(self):
             return self.value.__str__()
 
         def __repr__(self):
             return self.value.__repr__()
 
-    class ParseError(Exception):
+    class ParseError(StandardError):
         """
         Error raised when parsing fails.
         It has two members, offset and content, which give the offset of the
         error and the offending content.
         """
 
         def __init__(self, expression):
             self.offset = expression.offset
@@ -292,21 +291,20 @@ 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()
-        self.context.update({
-            'FILE': '',
-            'LINE': 0,
-            'DIRECTORY': os.path.abspath('.')
-            })
+        for k, v in {'FILE': '',
+                     'LINE': 0,
+                     'DIRECTORY': os.path.abspath('.')}.iteritems():
+            self.context[k] = v
         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
@@ -316,35 +314,33 @@ 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),
-        ):
+        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():
             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)
@@ -713,17 +709,17 @@ class Preprocessor:
 
         def vsubst(v):
             if v in self.context:
                 return str(self.context[v])
             return ''
         for i in range(1, len(lst), 2):
             lst[i] = vsubst(lst[i])
         lst.append('\n')  # add back the newline
-        self.write(six.moves.reduce(lambda x, y: x+y, lst, ''))
+        self.write(reduce(lambda x, y: x+y, lst, ''))
 
     def do_literal(self, args):
         self.write(args + '\n')
 
     def do_filter(self, args):
         filters = [f for f in args.split(' ') if hasattr(self, 'filter_' + f)]
         if len(filters) == 0:
             return
@@ -787,17 +783,17 @@ class Preprocessor:
     # File ops
 
     def do_include(self, args, filters=True):
         """
         Preprocess a given file.
         args can either be a file name, or a file-like object.
         Files should be opened, and will be closed after processing.
         """
-        isName = isinstance(args, six.string_types)
+        isName = type(args) == str or type(args) == unicode
         oldCheckLineNumbers = self.checkLineNumbers
         self.checkLineNumbers = False
         if isName:
             try:
                 args = str(args)
                 if filters:
                     args = self.applyFilters(args)
                 if not os.path.isabs(args):
--- a/python/mozbuild/mozbuild/repackaging/mar.py
+++ b/python/mozbuild/mozbuild/repackaging/mar.py
@@ -8,20 +8,17 @@ import os
 import sys
 import tempfile
 import shutil
 import zipfile
 import tarfile
 import subprocess
 import mozpack.path as mozpath
 from mozbuild.repackaging.application_ini import get_application_ini_value
-from mozbuild.util import (
-    ensureParentDir,
-    ensure_bytes,
-)
+from mozbuild.util import ensureParentDir
 
 
 _BCJ_OPTIONS = {
     'x86': ['--x86'],
     'x86_64': ['--x86'],
     'aarch64': [],
 }
 
@@ -73,14 +70,12 @@ def repackage_mar(topsrcdir, package, ma
         if os.path.exists(xz_path):
             env['XZ'] = mozpath.normpath(xz_path)
 
         cmd = [make_full_update, output, ffxdir]
         if sys.platform == 'win32':
             # make_full_update.sh is a bash script, and Windows needs to
             # explicitly call out the shell to execute the script from Python.
             cmd.insert(0, env['MOZILLABUILD'] + '/msys/bin/bash.exe')
-        # in py2 env needs str not unicode.
-        env = {ensure_bytes(k): ensure_bytes(v) for k, v in env.iteritems()}
         subprocess.check_call(cmd, env=env)
 
     finally:
         shutil.rmtree(tmpdir)
--- 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.items())
+                          for name, value in tokens.iteritems())
     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/test/python.ini
+++ b/python/mozbuild/mozbuild/test/python.ini
@@ -1,5 +1,52 @@
 [DEFAULT]
+skip-if = python == 3
 
+[action/test_buildlist.py]
+[action/test_langpack_manifest.py]
+[action/test_node.py]
+[action/test_process_install_manifest.py]
+[action/test_package_fennec_apk.py]
+[analyze/test_graph.py]
+skip-if = (os == "win")
+[backend/test_build.py]
+[backend/test_configenvironment.py]
+[backend/test_fastermake.py]
+[backend/test_gn_processor.py]
+[backend/test_partialconfigenvironment.py]
+[backend/test_recursivemake.py]
+[backend/test_test_manifest.py]
+[backend/test_visualstudio.py]
+[codecoverage/test_lcov_rewrite.py]
+[compilation/test_warnings.py]
+[configure/lint.py]
+[configure/test_checks_configure.py]
+[configure/test_compile_checks.py]
+[configure/test_configure.py]
+[configure/test_lint.py]
+[configure/test_moz_configure.py]
+[configure/test_options.py]
+[configure/test_toolchain_configure.py]
+[configure/test_toolchain_helpers.py]
+[configure/test_toolkit_moz_configure.py]
+[configure/test_util.py]
+[controller/test_ccachestats.py]
+[controller/test_clobber.py]
+[frontend/test_context.py]
+[frontend/test_emitter.py]
+[frontend/test_namespaces.py]
+[frontend/test_reader.py]
+[frontend/test_sandbox.py]
+[test_artifact_cache.py]
+[test_base.py]
+[test_containers.py]
+[test_dotproperties.py]
 [test_expression.py]
+[test_jarmaker.py]
 [test_licenses.py]
+[test_line_endings.py]
+[test_makeutil.py]
+[test_mozconfig.py]
+[test_mozinfo.py]
+[test_preprocessor.py]
 [test_pythonutil.py]
+[test_util.py]
deleted file mode 100644
--- a/python/mozbuild/mozbuild/test/python2.ini
+++ /dev/null
@@ -1,49 +0,0 @@
-[DEFAULT]
-skip-if = python == 3
-
-[action/test_buildlist.py]
-[action/test_langpack_manifest.py]
-[action/test_node.py]
-[action/test_process_install_manifest.py]
-[action/test_package_fennec_apk.py]
-[analyze/test_graph.py]
-skip-if = (os == "win")
-[backend/test_build.py]
-[backend/test_configenvironment.py]
-[backend/test_fastermake.py]
-[backend/test_gn_processor.py]
-[backend/test_partialconfigenvironment.py]
-[backend/test_recursivemake.py]
-[backend/test_test_manifest.py]
-[backend/test_visualstudio.py]
-[codecoverage/test_lcov_rewrite.py]
-[compilation/test_warnings.py]
-[configure/lint.py]
-[configure/test_checks_configure.py]
-[configure/test_compile_checks.py]
-[configure/test_configure.py]
-[configure/test_lint.py]
-[configure/test_moz_configure.py]
-[configure/test_options.py]
-[configure/test_toolchain_configure.py]
-[configure/test_toolchain_helpers.py]
-[configure/test_toolkit_moz_configure.py]
-[configure/test_util.py]
-[controller/test_ccachestats.py]
-[controller/test_clobber.py]
-[frontend/test_context.py]
-[frontend/test_emitter.py]
-[frontend/test_namespaces.py]
-[frontend/test_reader.py]
-[frontend/test_sandbox.py]
-[test_artifact_cache.py]
-[test_base.py]
-[test_containers.py]
-[test_dotproperties.py]
-[test_jarmaker.py]
-[test_line_endings.py]
-[test_makeutil.py]
-[test_mozconfig.py]
-[test_mozinfo.py]
-[test_preprocessor.py]
-[test_util.py]
--- a/python/mozbuild/mozbuild/util.py
+++ b/python/mozbuild/mozbuild/util.py
@@ -12,31 +12,36 @@ 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,
 )
 from io import (
     StringIO,
     BytesIO,
 )
 
 
+if sys.version_info[0] == 3:
+    str_type = str
+else:
+    str_type = basestring
+
 if sys.platform == 'win32':
     _kernel32 = ctypes.windll.kernel32
     _FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x2000
 
 
 def exec_(object, globals=None, locals=None):
     """Wrapper around the exec statement to avoid bogus errors like:
 
@@ -67,33 +72,33 @@ def hash_file(path, hasher=None):
             if not len(data):
                 break
 
             h.update(data)
 
     return h.hexdigest()
 
 
-class EmptyValue(six.text_type):
+class EmptyValue(unicode):
     """A dummy type that behaves like an empty string and sequence.
 
     This type exists in order to support
     :py:class:`mozbuild.frontend.reader.EmptyConfig`. It should likely not be
     used elsewhere.
     """
 
     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 six.iteritems(kwargs):
+        for k, v in kwargs.iteritems():
             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.')
 
@@ -164,17 +169,17 @@ def mkdir(path, not_indexed=False):
     try:
         os.makedirs(path)
     except OSError as e:
         if e.errno != errno.EEXIST:
             raise
 
     if not_indexed:
         if sys.platform == 'win32':
-            if isinstance(path, six.string_types):
+            if isinstance(path, str_type):
                 fn = _kernel32.SetFileAttributesW
             else:
                 fn = _kernel32.SetFileAttributesA
 
             fn(path, _FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
         elif sys.platform == 'darwin':
             with open(os.path.join(path, '.metadata_never_index'), 'a'):
                 pass
@@ -218,17 +223,17 @@ class FileAvoidWrite(BytesIO):
         BytesIO.__init__(self)
         self.name = filename
         self._capture_diff = capture_diff
         self._write_to_file = not dry_run
         self.diff = None
         self.mode = mode
 
     def write(self, buf):
-        if isinstance(buf, six.text_type):
+        if isinstance(buf, unicode):
             buf = buf.encode('utf-8')
         BytesIO.write(self, buf)
 
     def avoid_writing_to_file(self):
         self._write_to_file = False
 
     def close(self):
         """Stop accepting writes, compare file contents, and rewrite if needed.
@@ -379,26 +384,26 @@ class ListMixin(object):
         if not isinstance(sequence, list):
             raise ValueError('List can only be sliced with other list instances.')
 
         return super(ListMixin, self).__setslice__(i, j, sequence)
 
     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, (type(None), EmptyValue)) else other
+        other = [] if isinstance(other, (types.NoneType, EmptyValue)) else other
         if not isinstance(other, list):
             raise ValueError('Only lists can be appended to lists.')
 
         new_list = self.__class__(self, **self._kwargs)
         new_list.extend(other)
         return new_list
 
     def __iadd__(self, other):
-        other = [] if isinstance(other, (type(None), EmptyValue)) else other
+        other = [] if isinstance(other, (types.NoneType, EmptyValue)) else other
         if not isinstance(other, list):
             raise ValueError('Only lists can be appended to lists.')
 
         return super(ListMixin, self).__iadd__(other)
 
 
 class List(ListMixin, list):
     """A list specialized for moz.build environments.
@@ -572,17 +577,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 six.iteritems(kwargs):
+            for k, v in kwargs.iteritems():
                 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)
@@ -810,17 +815,17 @@ class HierarchicalStringList(object):
         exports = self._get_exportvariable(name)
         exports._check_list(value)
         exports._strings += value
 
     def _check_list(self, value):
         if not isinstance(value, list):
             raise ValueError('Expected a list of strings, not %s' % type(value))
         for v in value:
-            if not isinstance(v, six.string_types):
+            if not isinstance(v, str_type):
                 raise ValueError(
                     'Expected a list of strings, not an element of %s' % type(v))
 
 
 class LockFile(object):
     """LockFile is used by the lock_file method to hold the lock.
 
     This object should not be used directly, but only through
@@ -1153,17 +1158,17 @@ def expand_variables(s, variables):
     If a variable value is not a string, it is iterated and its items are
     joined with a whitespace.'''
     result = ''
     for s, name in pair(VARIABLES_RE.split(s)):
         result += s
         value = variables.get(name)
         if not value:
             continue
-        if not isinstance(value, six.string_types):
+        if not isinstance(value, types.StringTypes):
             value = ' '.join(value)
         result += value
     return result
 
 
 class DefinesAction(argparse.Action):
     '''An ArgumentParser action to handle -Dvar[=value] type of arguments.'''
 
@@ -1181,17 +1186,17 @@ class DefinesAction(argparse.Action):
         defines[name] = value
         setattr(namespace, self.dest, defines)
 
 
 class EnumStringComparisonError(Exception):
     pass
 
 
-class EnumString(six.text_type):
+class EnumString(unicode):
     '''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.
 
     The class is meant to be subclassed, where the subclass defines
     POSSIBLE_VALUES. The `subclass` method is a helper to create such
     subclasses.
     '''
     POSSIBLE_VALUES = ()
@@ -1218,41 +1223,38 @@ class EnumString(six.text_type):
         return EnumStringSubclass
 
 
 def _escape_char(c):
     # str.encode('unicode_espace') doesn't escape quotes, presumably because
     # quoting could be done with either ' or ".
     if c == "'":
         return "\\'"
-    return six.text_type(c.encode('unicode_escape'))
+    return unicode(c.encode('unicode_escape'))
 
 
-if six.PY2:  # Not supported for py3 yet
-    # 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)))
-        if c != e
-    }
-    # Regexp matching all characters to escape.
-    _INDENTED_REPR_RE = re.compile(
-        '([' + ''.join(_INDENTED_REPR_TABLE.values()) + ']+)')
+# 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)))
+    if c != e
+}
+# Regexp matching all characters to escape.
+_INDENTED_REPR_RE = re.compile(
+    '([' + ''.join(_INDENTED_REPR_TABLE.values()) + ']+)')
 
 
 def indented_repr(o, indent=4):
     '''Similar to repr(), but returns an indented representation of the object
 
     One notable difference with repr is that the returned representation
     assumes `from __future__ import unicode_literals`.
     '''
-    if six.PY3:
-        raise NotImplementedError("indented_repr is not yet supported on py3")
     one_indent = ' ' * indent
 
     def recurse_indented_repr(o, level):
         if isinstance(o, dict):
             yield '{\n'
             for k, v in sorted(o.items()):
                 yield one_indent * (level + 1)
                 for d in recurse_indented_repr(k, level + 1):
@@ -1261,17 +1263,17 @@ def indented_repr(o, indent=4):
                 for d in recurse_indented_repr(v, level + 1):
                     yield d
                 yield ',\n'
             yield one_indent * level
             yield '}'
         elif isinstance(o, bytes):
             yield 'b'
             yield repr(o)
-        elif isinstance(o, six.text_type):
+        elif isinstance(o, unicode):
             yield "'"
             # We want a readable string (non escaped unicode), but some
             # special characters need escaping (e.g. \n, \t, etc.)
             for i, s in enumerate(_INDENTED_REPR_RE.split(o)):
                 if i % 2:
                     for c in s:
                         yield _INDENTED_REPR_TABLE[c]
                 else:
@@ -1291,21 +1293,21 @@ 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 six.iteritems(obj)
+            for k, v in obj.iteritems()
         }
     if isinstance(obj, bytes):
         return obj
-    if isinstance(obj, six.text_type):
+    if isinstance(obj, unicode):
         return obj.encode(encoding)
     if isinstance(obj, Iterable):
         return [encode(i, encoding) for i in obj]
     return obj
 
 
 def patch_main():
     '''This is a hack to work around the fact that Windows multiprocessing needs
@@ -1386,20 +1388,8 @@ def patch_main():
             fork_string = ("main_file_name = '%s'\n" % main_file_name +
                            "main_module_name = '%s'\n" % main_module_name +
                            ''.join(x[12:] for x in fork_code[1:]))
             cmdline = orig_command_line()
             cmdline[2] = fork_string
             return cmdline
         orig_command_line = forking.get_command_line
         forking.get_command_line = my_get_command_line
-
-
-def ensure_bytes(value):
-    if isinstance(value, six.text_type):
-        return value.encode('utf8')
-    return value
-
-
-def ensure_unicode(value):
-    if isinstance(value, type(b'')):
-        return value.decode('utf8')
-    return value
--- a/python/mozbuild/mozpack/archive.py
+++ b/python/mozbuild/mozpack/archive.py
@@ -1,13 +1,13 @@
 # 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
+from __future__ import absolute_import, print_function
 
 import bz2
 import gzip
 import stat
 import tarfile
 
 from .files import (
     BaseFile, File,
--- a/python/mozbuild/mozpack/chrome/flags.py
+++ b/python/mozbuild/mozpack/chrome/flags.py
@@ -1,16 +1,15 @@
 # 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
+from __future__ import absolute_import, print_function
 
 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:
@@ -258,14 +257,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 six.iteritems(filter):
+        for name, value in filter.iteritems():
             if name not in self:
                 continue
             if not self[name].matches(value):
                 return False
         return True
--- a/python/mozbuild/mozpack/chrome/manifest.py
+++ b/python/mozbuild/mozpack/chrome/manifest.py
@@ -1,21 +1,25 @@
 # 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
+from __future__ import absolute_import, print_function
 
 import re
 import os
 
+try:
+    from urlparse import urlparse
+except ImportError:
+    from urllib.parse import urlparse
+
 import mozpack.path as mozpath
 from mozpack.chrome.flags import Flags
 from mozpack.errors import errors
-from six.moves.urllib.parse import urlparse
 
 
 class ManifestEntry(object):
     '''
     Base class for all manifest entry types.
     Subclasses may define the following class or member variables:
         - localized: indicates whether the manifest entry is used for localized
           data.
--- a/python/mozbuild/mozpack/copier.py
+++ b/python/mozbuild/mozpack/copier.py
@@ -1,16 +1,15 @@
 # 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
+from __future__ import absolute_import, print_function
 
 import os
-import six
 import stat
 import sys
 
 from mozpack.errors import errors
 from mozpack.files import (
     BaseFile,
     DeflatedFile,
     Dest,
@@ -141,17 +140,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 six.iteritems(self._files)
+        return self._files.iteritems()
 
     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).
         '''
@@ -291,17 +290,17 @@ class FileCopier(FileRegistry):
         destination directory (at least those that are not required to
         be regular directories): pass
         remove_all_directory_symlinks=False. Exercise caution with
         this flag: you almost certainly do not want to preserve
         directory symlinks.
 
         Returns a FileCopyResult that details what changed.
         '''
-        assert isinstance(destination, six.string_types)
+        assert isinstance(destination, basestring)
         assert not os.path.exists(destination) or os.path.isdir(destination)
 
         result = FileCopyResult()
         have_symlinks = hasattr(os, 'symlink')
         destination = os.path.normpath(destination)
 
         # We create the destination directory specially. We can't do this as
         # part of the loop doing mkdir() below because that loop munges
@@ -560,17 +559,17 @@ class Jarrer(FileRegistry, BaseFile):
                     from mozpack.mozjar import Deflater
                     self.deflater = Deflater(self.compress)
                     self.mode = 'w'
                 self.deflater.write(data)
 
             def exists(self):
                 return self.deflater is not None
 
-        if isinstance(dest, six.string_types):
+        if isinstance(dest, basestring):
             dest = Dest(dest)
         assert isinstance(dest, Dest)
 
         from mozpack.mozjar import JarWriter, JarReader, JAR_BROTLI
         try:
             old_jar = JarReader(fileobj=dest)
         except Exception:
             old_jar = []
--- a/python/mozbuild/mozpack/dmg.py
+++ b/python/mozbuild/mozpack/dmg.py
@@ -1,13 +1,13 @@
 # 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
+from __future__ import absolute_import, print_function
 
 import buildconfig
 import errno
 import mozfile
 import os
 import platform
 import shutil
 import subprocess
--- a/python/mozbuild/mozpack/errors.py
+++ b/python/mozbuild/mozpack/errors.py
@@ -1,13 +1,13 @@
 # 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
+from __future__ import absolute_import, print_function
 
 import sys
 from contextlib import contextmanager
 
 
 class ErrorMessage(Exception):
     '''Exception type raised from errors.error() and errors.fatal()'''
 
--- a/python/mozbuild/mozpack/executables.py
+++ b/python/mozbuild/mozpack/executables.py
@@ -1,13 +1,13 @@
 # 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
+from __future__ import absolute_import, print_function
 
 import os
 import struct
 import subprocess
 from mozpack.errors import errors
 
 MACHO_SIGNATURES = [
     0xfeedface,  # mach-o 32-bits big endian
--- a/python/mozbuild/mozpack/files.py
+++ b/python/mozbuild/mozpack/files.py
@@ -1,31 +1,26 @@
 # 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
+from __future__ import absolute_import, print_function
 
 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,
-    ensure_bytes,
-    ensure_unicode,
-)
+from mozbuild.util import FileAvoidWrite
 from mozpack.executables import (
     is_executable,
     may_strip,
     strip,
     may_elfhack,
     elfhack,
     xz_compress,
 )
@@ -63,17 +58,17 @@ if platform.system() != 'Windows':
 else:
     import ctypes
     _kernel32 = ctypes.windll.kernel32
     _CopyFileA = _kernel32.CopyFileA
     _CopyFileW = _kernel32.CopyFileW
 
     def _copyfile(src, dest):
         # False indicates `dest` should be overwritten if it exists already.
-        if isinstance(src, six.text_type) and isinstance(dest, six.text_type):
+        if isinstance(src, unicode) and isinstance(dest, unicode):
             _CopyFileW(src, dest, False)
         elif isinstance(src, str) and isinstance(dest, str):
             _CopyFileA(src, dest, False)
         else:
             raise TypeError('mismatched path types!')
 
 
 class Dest(object):
@@ -83,17 +78,17 @@ class Dest(object):
       underlying file.
     - a call to read() after a write() will re-open the underlying file and
       read from it.
     - a call to write() after a read() will re-open the underlying file,
       emptying it, and write to it.
     '''
 
     def __init__(self, path):
-        self.path = ensure_unicode(path)
+        self.path = path
         self.mode = None
 
     @property
     def name(self):
         return self.path
 
     def read(self, length=-1):
         if self.mode != 'r':
@@ -172,17 +167,17 @@ class BaseFile(object):
         '''
         Copy the BaseFile content to the destination given as a string or a
         Dest instance. Avoids replacing existing files if the BaseFile content
         matches that of the destination, or in case of plain files, if the
         destination is newer than the original file. This latter behaviour is
         disabled when skip_if_older is False.
         Returns whether a copy was actually performed (True) or not (False).
         '''
-        if isinstance(dest, six.string_types):
+        if isinstance(dest, basestring):
             dest = Dest(dest)
         else:
             assert isinstance(dest, Dest)
 
         can_skip_content_check = False
         if not dest.exists():
             can_skip_content_check = True
         elif getattr(self, 'path', None) and getattr(dest, 'path', None):
@@ -193,22 +188,22 @@ class BaseFile(object):
 
         if can_skip_content_check:
             if getattr(self, 'path', None) and getattr(dest, 'path', None):
                 _copyfile(self.path, dest.path)
                 shutil.copystat(self.path, dest.path)
             else:
                 # Ensure the file is always created
                 if not dest.exists():
-                    dest.write(b'')
+                    dest.write('')
                 shutil.copyfileobj(self.open(), dest)
             return True
 
         src = self.open()
-        copy_content = b''
+        copy_content = ''
         while True:
             dest_content = dest.read(32768)
             src_content = src.read(32768)
             copy_content += src_content
             if len(dest_content) == len(src_content) == 0:
                 break
             # If the read content differs between origin and destination,
             # write what was read up to now, and copy the remainder.
@@ -255,17 +250,17 @@ class BaseFile(object):
 
 
 class File(BaseFile):
     '''
     File class for plain files.
     '''
 
     def __init__(self, path):
-        self.path = ensure_unicode(path)
+        self.path = path
 
     @property
     def mode(self):
         '''
         Return the file's unix mode, as returned by os.stat().st_mode.
         '''
         if platform.system() == 'Windows':
             return None
@@ -292,21 +287,21 @@ class ExecutableFile(File):
     '''
 
     def __init__(self, path, xz_compress=False):
         File.__init__(self, path)
         self.xz_compress = xz_compress
 
     def copy(self, dest, skip_if_older=True):
         real_dest = dest
-        if not isinstance(dest, six.string_types):
+        if not isinstance(dest, basestring):
             fd, dest = mkstemp()
             os.close(fd)
             os.remove(dest)
-        assert isinstance(dest, six.string_types)
+        assert isinstance(dest, basestring)
         # 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 and xz_compressed, so we can skip.
         if not File.copy(self, dest, skip_if_older) and \
                 os.path.getsize(self.path) > os.path.getsize(dest):
             return False
         try:
             if may_strip(dest):
@@ -335,17 +330,17 @@ class AbsoluteSymlinkFile(File):
 
     def __init__(self, path):
         if not os.path.isabs(path):
             raise ValueError('Symlink target not absolute: %s' % path)
 
         File.__init__(self, path)
 
     def copy(self, dest, skip_if_older=True):
-        assert isinstance(dest, six.string_types)
+        assert isinstance(dest, basestring)
 
         # The logic in this function is complicated by the fact that symlinks
         # aren't universally supported. So, where symlinks aren't supported, we
         # fall back to file copying. Keep in mind that symlink support is
         # per-filesystem, not per-OS.
 
         # Handle the simple case where symlinks are definitely not supported by
         # falling back to file copy.
@@ -426,17 +421,17 @@ class HardlinkFile(File):
 
     This is similar to the AbsoluteSymlinkFile, but with hard links. The symlink
     implementation requires paths to be absolute, because they are resolved at
     read time, which makes relative paths messy. Hard links resolve paths at
     link-creation time, so relative paths are fine.
     '''
 
     def copy(self, dest, skip_if_older=True):
-        assert isinstance(dest, six.string_types)
+        assert isinstance(dest, basestring)
 
         if not hasattr(os, 'link'):
             return super(HardlinkFile, self).copy(
                 dest, skip_if_older=skip_if_older
             )
 
         try:
             path_st = os.stat(self.path)
@@ -488,17 +483,17 @@ class ExistingFile(BaseFile):
     existing file is required, it must exist during copy() or an error is
     raised.
     '''
 
     def __init__(self, required):
         self.required = required
 
     def copy(self, dest, skip_if_older=True):
-        if isinstance(dest, six.string_types):
+        if isinstance(dest, basestring):
             dest = Dest(dest)
         else:
             assert isinstance(dest, Dest)
 
         if not self.required:
             return
 
         if not dest.exists():
@@ -512,18 +507,18 @@ class ExistingFile(BaseFile):
 class PreprocessedFile(BaseFile):
     '''
     File class for a file that is preprocessed. PreprocessedFile.copy() runs
     the preprocessor on the file to create the output.
     '''
 
     def __init__(self, path, depfile_path, marker, defines, extra_depends=None,
                  silence_missing_directive_warnings=False):
-        self.path = ensure_unicode(path)
-        self.depfile = ensure_unicode(depfile_path)
+        self.path = path
+        self.depfile = depfile_path
         self.marker = marker
         self.defines = defines
         self.extra_depends = list(extra_depends or [])
         self.silence_missing_directive_warnings = \
             silence_missing_directive_warnings
 
     def inputs(self):
         pp = Preprocessor(defines=self.defines, marker=self.marker)
@@ -535,17 +530,17 @@ class PreprocessedFile(BaseFile):
 
         # This always yields at least self.path.
         return pp.includes
 
     def copy(self, dest, skip_if_older=True):
         '''
         Invokes the preprocessor to create the destination file.
         '''
-        if isinstance(dest, six.string_types):
+        if isinstance(dest, basestring):
             dest = Dest(dest)
         else:
             assert isinstance(dest, Dest)
 
         # We have to account for the case where the destination exists and is a
         # symlink to something. Since we know the preprocessor is certainly not
         # going to create a symlink, we can just remove the existing one. If the
         # destination is not a symlink, we leave it alone, since we're going to
@@ -706,22 +701,19 @@ class ManifestFile(BaseFile):
         else:
             self._entries.remove(entry)
 
     def open(self):
         '''
         Return a file-like object allowing to read() the serialized content of
         the manifest.
         '''
-        return BytesIO(
-            ensure_bytes(
-                ''.join(
-                    '%s\n' % e.rebase(self._base)
-                    for e in chain(self._entries, self._interfaces)
-                )))
+        return BytesIO(''.join('%s\n' % e.rebase(self._base)
+                               for e in chain(self._entries,
+                                              self._interfaces)))
 
     def __iter__(self):
         '''
         Iterate over entries in the manifest file.
         '''
         return chain(self._entries, self._interfaces)
 
     def isempty(self):
@@ -741,18 +733,18 @@ class MinifiedProperties(BaseFile):
         assert isinstance(file, BaseFile)
         self._file = file
 
     def open(self):
         '''
         Return a file-like object allowing to read() the minified content of
         the properties file.
         '''
-        return BytesIO(b''.join(l for l in self._file.open().readlines()
-                                if not l.startswith(b'#')))
+        return BytesIO(''.join(l for l in self._file.open().readlines()
+                               if not l.startswith('#')))
 
 
 class MinifiedJavaScript(BaseFile):
     '''
     File class for minifying JavaScript files.
     '''
 
     def __init__(self, file, verify_command=None):
@@ -1089,17 +1081,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(six.iteritems(finders)):
+        for base, finder in sorted(finders.iteritems()):
             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/hg.py
+++ b/python/mozbuild/mozpack/hg.py
@@ -22,22 +22,21 @@
 # modification of the file, and distribution when not combined with
 # mozbuild.)
 #
 # If you modify this code, you may extend this exception to your
 # version of the code, but you are not obliged to do so. If you
 # do not wish to do so, delete this exception statement from your
 # version.
 
-from __future__ import absolute_import, print_function, unicode_literals
+from __future__ import absolute_import, print_function
 
 import mercurial.error as error
 import mercurial.hg as hg
 import mercurial.ui as hgui
-import six
 
 from .files import (
     BaseFinder,
     MercurialFile,
 )
 import mozpack.path as mozpath
 
 
@@ -52,17 +51,17 @@ class MercurialNativeFile(MercurialFile)
 
 
 class MercurialNativeRevisionFinder(BaseFinder):
     def __init__(self, repo, rev='.', recognize_repo_paths=False):
         """Create a finder attached to a specific changeset.
 
         Accepts a Mercurial localrepo and changectx instance.
         """
-        if isinstance(repo, six.string_types):
+        if isinstance(repo, (str, unicode)):
             path = repo
             repo = hg.repository(hgui.ui(), repo)
         else:
             path = repo.root
 
         super(MercurialNativeRevisionFinder, self).__init__(base=repo.root)
 
         self._repo = repo
@@ -81,16 +80,16 @@ class MercurialNativeRevisionFinder(Base
             if not path.startswith(self._root):
                 raise ValueError('lookups in recognize_repo_paths mode must be '
                                  'prefixed with repo path: %s' % path)
             path = path[len(self._root) + 1:]
 
         return self._get(path)
 
     def _get(self, path):
-        if isinstance(path, six.text_type):
+        if isinstance(path, unicode):
             path = path.encode('utf-8', 'replace')
 
         try:
             fctx = self._repo.filectx(path, self._rev)
             return MercurialNativeFile(fctx.data())
         except error.LookupError:
             return None
--- a/python/mozbuild/mozpack/mozjar.py
+++ b/python/mozbuild/mozpack/mozjar.py
@@ -1,33 +1,26 @@
 # 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
+from __future__ import absolute_import, print_function
 
-from io import (
-    BytesIO,
-    UnsupportedOperation,
-)
+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,
-    ensure_bytes,
-)
+from mozbuild.util import memoize
 
 
 JAR_STORED = ZIP_STORED
 JAR_DEFLATED = ZIP_DEFLATED
 JAR_BROTLI = 0x81
 MAX_WBITS = 15
 
 
@@ -65,25 +58,25 @@ class JarStruct(object):
         obj['version']
         obj['filename']
     filename_size would be obtained with len(obj['filename']).
 
     JarStruct subclasses instances can be either initialized from existing data
     (deserialized), or with empty fields.
     '''
 
-    TYPE_MAPPING = {'uint32': (b'I', 4), 'uint16': (b'H', 2)}
+    TYPE_MAPPING = {'uint32': ('I', 4), 'uint16': ('H', 2)}
 
     def __init__(self, data=None):
         '''
         Create an instance from the given data. Data may be omitted to create
         an instance with empty fields.
         '''
         assert self.MAGIC and isinstance(self.STRUCT, OrderedDict)
-        self.size_fields = set(t for t in six.itervalues(self.STRUCT)
+        self.size_fields = set(t for t in self.STRUCT.itervalues()
                                if t not in JarStruct.TYPE_MAPPING)
         self._values = {}
         if data:
             self._init_data(data)
         else:
             self._init_empty()
 
     def _init_data(self, data):
@@ -95,17 +88,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 six.iteritems(self.STRUCT):
+        for name, t in self.STRUCT.iteritems():
             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:
@@ -114,64 +107,63 @@ 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 six.iteritems(self.STRUCT):
+        for name, t in self.STRUCT.iteritems():
             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
         JarStruct.TYPE_MAPPING) at the given offset in the given data.
         '''
         assert type in JarStruct.TYPE_MAPPING
         assert data is not None
         format, size = JarStruct.TYPE_MAPPING[type]
         data = data[:size]
         if isinstance(data, memoryview):
             data = data.tobytes()
-        return struct.unpack(b'<' + format, data)[0], size
+        return struct.unpack('<' + 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 six.iteritems(self.STRUCT)
+        serialized = struct.pack('<I', self.signature)
+        sizes = dict((t, name) for name, t in self.STRUCT.iteritems()
                      if t not in JarStruct.TYPE_MAPPING)
-        for name, t in six.iteritems(self.STRUCT):
+        for name, t in self.STRUCT.iteritems():
             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)
+                serialized += struct.pack('<' + format, value)
             else:
-                serialized += ensure_bytes(self[name])
+                serialized += self[name]
         return serialized
 
     @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 six.iteritems(self.STRUCT):
+        for name, type in self.STRUCT.iteritems():
             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]
@@ -182,17 +174,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 six.iteritems(self._values)
+        return self._values.iteritems()
 
     def __repr__(self):
         return "<%s %s>" % (self.__class__.__name__,
                             ' '.join('%s=%s' % (n, v) for n, v in self))
 
 
 class JarCdirEnd(JarStruct):
     '''
@@ -379,33 +371,33 @@ class JarReader(object):
         '''
         del self._data
 
     @property
     def compression(self):
         entries = self.entries
         if not entries:
             return JAR_STORED
-        return max(f['compression'] for f in six.itervalues(entries))
+        return max(f['compression'] for f in entries.itervalues())
 
     @property
     def entries(self):
         '''
         Return an ordered dict of central directory entries, indexed by
         filename, in the order they appear in the Jar archive central
         directory. Directory entries are skipped.
         '''
         if hasattr(self, '_entries'):
             return self._entries
         preload = 0
         if self.is_optimized:
             preload = JarStruct.get_data('uint32', self._data)[0]
         entries = OrderedDict()
         offset = self._cdir_end['cdir_offset']
-        for e in six.moves.xrange(self._cdir_end['cdir_entries']):
+        for e in xrange(self._cdir_end['cdir_entries']):
             entry = JarCdirEntry(self._data[offset:])
             offset += entry.size
             # Creator host system. 0 is MSDOS, 3 is Unix
             host = entry['creator_version'] >> 8
             # External attributes values depend on host above. On Unix the
             # higher bits are the stat.st_mode value. On MSDOS, the lower bits
             # are the FAT attributes.
             xattr = entry['external_attr']
@@ -457,17 +449,17 @@ class JarReader(object):
 
     def __iter__(self):
         '''
         Iterate over all files in the Jar archive, in the form of
         JarFileReaders.
             for file in jarReader:
                 ...
         '''
-        for entry in six.itervalues(self.entries):
+        for entry in self.entries.itervalues():
             yield self._getreader(entry)
 
     def __getitem__(self, name):
         '''
         Get a JarFileReader for the given file name.
         '''
         return self._getreader(self.entries[name])
 
@@ -551,51 +543,51 @@ class JarWriter(object):
         The duplication of the End of central directory is to accomodate some
         Zip reading tools that want an end of central directory structure to
         follow the central directory entries.
         '''
         offset = 0
         headers = {}
         preload_size = 0
         # Prepare central directory entries
-        for entry, content in six.itervalues(self._contents):
+        for entry, content in self._contents.itervalues():
             header = JarLocalFileHeader()
             for name in entry.STRUCT:
                 if name in header:
                     header[name] = entry[name]
             entry['offset'] = offset
             offset += len(content) + header.size
             if entry['filename'] == self._last_preloaded:
                 preload_size = offset
             headers[entry] = header
         # Prepare end of central directory
         end = JarCdirEnd()
         end['disk_entries'] = len(self._contents)
         end['cdir_entries'] = end['disk_entries']
-        end['cdir_size'] = six.moves.reduce(lambda x, y: x + y[0].size,
-                                            self._contents.values(), 0)
+        end['cdir_size'] = reduce(lambda x, y: x + y[0].size,
+                                  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 preload_size:
             end['cdir_offset'] = 4
             offset = end['cdir_size'] + end['cdir_offset'] + end.size
             preload_size += offset
             self._data.write(struct.pack('<I', preload_size))
-            for entry, _ in six.itervalues(self._contents):
+            for entry, _ in self._contents.itervalues():
                 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 six.itervalues(self._contents):
+        for entry, content in self._contents.itervalues():
             self._data.write(headers[entry].serialize())
             self._data.write(content)
         # On non optimized archives, store the central directory entries.
         if not preload_size:
             end['cdir_offset'] = offset
-            for entry, _ in six.itervalues(self._contents):
+            for entry, _ in self._contents.itervalues():
                 self._data.write(entry.serialize())
         # Store the end of central directory.
         self._data.write(end.serialize())
         self._data.close()
 
     def add(self, name, data, compress=None, mode=None, skip_duplicates=False):
         '''
         Add a new member to the jar archive, with the given name and the given
@@ -625,23 +617,21 @@ class JarWriter(object):
             compress = JAR_DEFLATED
         if compress is False:
             compress = JAR_STORED
         if (isinstance(data, (JarFileReader, Deflater)) and
                 data.compress == compress):
             deflater = data
         else:
             deflater = Deflater(compress, compress_level=self._compress_level)
-            if isinstance(data, (six.binary_type, six.string_types)):
+            if isinstance(data, basestring):
                 deflater.write(data)
             elif hasattr(data, 'read'):
-                try:
+                if hasattr(data, 'seek'):
                     data.seek(0)
-                except (UnsupportedOperation, AttributeError):
-                    pass
                 deflater.write(data.read())
             else:
                 raise JarWriterError("Don't know how to handle %s" %
                                      type(data))
         # Fill a central directory entry for this new member.
         entry = JarCdirEntry()
         entry['creator_version'] = 20
         if mode is not None:
--- a/python/mozbuild/mozpack/packager/__init__.py
+++ b/python/mozbuild/mozpack/packager/__init__.py
@@ -1,18 +1,17 @@
 # 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
+from __future__ import absolute_import, print_function
 
 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,
@@ -362,18 +361,17 @@ 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 six.iteritems(self._included_manifests)
+            m for m, includer in self._included_manifests.iteritems()
             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/formats.py
+++ b/python/mozbuild/mozpack/packager/formats.py
@@ -1,24 +1,24 @@
 # 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
+from __future__ import absolute_import, print_function
 
 from mozpack.chrome.manifest import (
     Manifest,
     ManifestInterfaces,
     ManifestChrome,
     ManifestBinaryComponent,
     ManifestResource,
     ManifestMultiContent,
 )
 from mozpack.errors import errors
-from six.moves.urllib.parse import urlparse
+from urlparse import urlparse
 import mozpack.path as mozpath
 from mozpack.files import ManifestFile
 from mozpack.copier import (
     FileRegistry,
     FileRegistrySubtree,
     Jarrer,
 )
 
--- a/python/mozbuild/mozpack/packager/l10n.py
+++ b/python/mozbuild/mozpack/packager/l10n.py
@@ -1,22 +1,21 @@
 # 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
+from __future__ import absolute_import, print_function
 
 '''
 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,
@@ -254,17 +253,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 six.iteritems(app_finder.jarlogs):
+    for path, log in app_finder.jarlogs.iteritems():
         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`.
@@ -285,17 +284,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 six.iteritems(extra_l10n):
+        for base, path in extra_l10n.iteritems():
             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/packager/unpack.py
+++ b/python/mozbuild/mozpack/packager/unpack.py
@@ -1,13 +1,13 @@
 # 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
+from __future__ import absolute_import, print_function
 
 import mozpack.path as mozpath
 from mozpack.files import (
     BaseFinder,
     FileFinder,
     DeflatedFile,
     ManifestFile,
 )
@@ -19,17 +19,17 @@ from mozpack.chrome.manifest import (
 )
 from mozpack.mozjar import JarReader
 from mozpack.copier import (
     FileRegistry,
     FileCopier,
 )
 from mozpack.packager import SimplePackager
 from mozpack.packager.formats import FlatFormatter
-from six.moves.urllib.parse import urlparse
+from urlparse import urlparse
 
 
 class UnpackFinder(BaseFinder):
     '''
     Special Finder object that treats the source package directory as if it
     were in the flat chrome format, whatever chrome format it actually is in.
 
     This means that for example, paths like chrome/browser/content/... match
--- a/python/mozbuild/mozpack/path.py
+++ b/python/mozbuild/mozpack/path.py
@@ -3,17 +3,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 '''
 Like :py:mod:`os.path`, with a reduced set of functions, and with normalized path
 separators (always use forward slashes).
 Also contains a few additional utilities not found in :py:mod:`os.path`.
 '''
 
-from __future__ import absolute_import, print_function, unicode_literals
+from __future__ import absolute_import, print_function
 
 import ctypes
 import posixpath
 import os
 import re
 import sys
 
 
--- a/python/mozbuild/mozpack/test/python.ini
+++ b/python/mozbuild/mozpack/test/python.ini
@@ -1,6 +1,15 @@
 [DEFAULT]
+skip-if = python == 3
 
 [test_chrome_flags.py]
 [test_chrome_manifest.py]
+[test_copier.py]
+[test_errors.py]
+[test_files.py]
+[test_manifests.py]
 [test_mozjar.py]
+[test_packager.py]
+[test_packager_formats.py]
+[test_packager_l10n.py]
+[test_packager_unpack.py]
 [test_path.py]
deleted file mode 100644
--- a/python/mozbuild/mozpack/test/python2.ini
+++ /dev/null
@@ -1,11 +0,0 @@
-[DEFAULT]
-skip-if = python == 3
-
-[test_copier.py]
-[test_errors.py]
-[test_files.py]
-[test_manifests.py]
-[test_packager.py]
-[test_packager_formats.py]
-[test_packager_l10n.py]
-[test_packager_unpack.py]
--- a/python/mozbuild/mozpack/test/support/minify_js_verify.py
+++ b/python/mozbuild/mozpack/test/support/minify_js_verify.py
@@ -1,13 +1,13 @@
 # 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
+from __future__ import absolute_import, print_function
 import sys
 
 
 if len(sys.argv) != 4:
     raise Exception('Usage: minify_js_verify <exitcode> <orig> <minified>')
 
 retcode = int(sys.argv[1])
 
--- a/python/mozbuild/mozpack/test/test_archive.py
+++ b/python/mozbuild/mozpack/test/test_archive.py
@@ -1,13 +1,13 @@
 # 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
+from __future__ import absolute_import, print_function
 
 import hashlib
 import os
 import shutil
 import stat
 import tarfile
 import tempfile
 import unittest
--- a/python/mozbuild/mozpack/test/test_chrome_flags.py
+++ b/python/mozbuild/mozpack/test/test_chrome_flags.py
@@ -1,13 +1,13 @@
 # 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
+from __future__ import absolute_import, print_function
 
 import unittest
 import mozunit
 from mozpack.chrome.flags import (
     Flag,
     StringFlag,
     VersionFlag,
     Flags,
--- a/python/mozbuild/mozpack/test/test_chrome_manifest.py
+++ b/python/mozbuild/mozpack/test/test_chrome_manifest.py
@@ -1,13 +1,13 @@
 # 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
+from __future__ import absolute_import, print_function
 
 import unittest
 import mozunit
 import os
 from mozpack.chrome.manifest import (
     ManifestContent,
     ManifestLocale,
     ManifestSkin,
--- a/python/mozbuild/mozpack/test/test_copier.py
+++ b/python/mozbuild/mozpack/test/test_copier.py
@@ -1,30 +1,29 @@
 # 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
+from __future__ import absolute_import, print_function
 
 from mozpack.copier import (
     FileCopier,
     FileRegistry,
     FileRegistrySubtree,
     Jarrer,
 )
 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,
 )
 
@@ -38,31 +37,31 @@ class BaseTestFileRegistry(MatchTestTemp
         if result:
             self.assertTrue(self.registry.contains(pattern))
         else:
             self.assertFalse(self.registry.contains(pattern))
         self.assertEqual(self.registry.match(pattern), result)
 
     def do_test_file_registry(self, registry):
         self.registry = registry
-        self.registry.add('foo', GeneratedFile(b'foo'))
-        bar = GeneratedFile(b'bar')
+        self.registry.add('foo', GeneratedFile('foo'))
+        bar = GeneratedFile('bar')
         self.registry.add('bar', bar)
         self.assertEqual(self.registry.paths(), ['foo', 'bar'])
         self.assertEqual(self.registry['bar'], bar)
 
         self.assertRaises(ErrorMessage, self.registry.add, 'foo',
-                          GeneratedFile(b'foo2'))
+                          GeneratedFile('foo2'))
 
         self.assertRaises(ErrorMessage, self.registry.remove, 'qux')
 
         self.assertRaises(ErrorMessage, self.registry.add, 'foo/bar',
-                          GeneratedFile(b'foobar'))
+                          GeneratedFile('foobar'))
         self.assertRaises(ErrorMessage, self.registry.add, 'foo/bar/baz',
-                          GeneratedFile(b'foobar'))
+                          GeneratedFile('foobar'))
 
         self.assertEqual(self.registry.paths(), ['foo', 'bar'])
 
         self.registry.remove('foo')
         self.assertEqual(self.registry.paths(), ['bar'])
         self.registry.remove('bar')
         self.assertEqual(self.registry.paths(), [])
 
@@ -77,112 +76,112 @@ class BaseTestFileRegistry(MatchTestTemp
             'foo/qux/bar',
             'foo/qux/2/test',
             'foo/qux/2/test2',
         ])
 
         self.registry.remove('foo/qux')
         self.assertEqual(self.registry.paths(), ['bar', 'foo/bar', 'foo/baz'])
 
-        self.registry.add('foo/qux', GeneratedFile(b'fooqux'))
+        self.registry.add('foo/qux', GeneratedFile('fooqux'))
         self.assertEqual(self.registry.paths(), ['bar', 'foo/bar', 'foo/baz',
                                                  'foo/qux'])
         self.registry.remove('foo/b*')
         self.assertEqual(self.registry.paths(), ['bar', 'foo/qux'])
 
         self.assertEqual([f for f, c in self.registry], ['bar', 'foo/qux'])
         self.assertEqual(len(self.registry), 2)
 
         self.add('foo/.foo')
         self.assertTrue(self.registry.contains('foo/.foo'))
 
     def do_test_registry_paths(self, registry):
         self.registry = registry
 
         # Can't add a file if it requires a directory in place of a
         # file we also require.
-        self.registry.add('foo', GeneratedFile(b'foo'))
+        self.registry.add('foo', GeneratedFile('foo'))
         self.assertRaises(ErrorMessage, self.registry.add, 'foo/bar',
-                          GeneratedFile(b'foobar'))
+                          GeneratedFile('foobar'))
 
         # Can't add a file if we already have a directory there.
-        self.registry.add('bar/baz', GeneratedFile(b'barbaz'))
+        self.registry.add('bar/baz', GeneratedFile('barbaz'))
         self.assertRaises(ErrorMessage, self.registry.add, 'bar',
-                          GeneratedFile(b'bar'))
+                          GeneratedFile('bar'))
 
         # Bump the count of things that require bar/ to 2.
-        self.registry.add('bar/zot', GeneratedFile(b'barzot'))
+        self.registry.add('bar/zot', GeneratedFile('barzot'))
         self.assertRaises(ErrorMessage, self.registry.add, 'bar',
-                          GeneratedFile(b'bar'))
+                          GeneratedFile('bar'))
 
         # Drop the count of things that require bar/ to 1.
         self.registry.remove('bar/baz')
         self.assertRaises(ErrorMessage, self.registry.add, 'bar',
-                          GeneratedFile(b'bar'))
+                          GeneratedFile('bar'))
 
         # Drop the count of things that require bar/ to 0.
         self.registry.remove('bar/zot')
-        self.registry.add('bar/zot', GeneratedFile(b'barzot'))
+        self.registry.add('bar/zot', GeneratedFile('barzot'))
 
 
 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 six.iteritems(cases):
+        for path, parts in cases.iteritems():
             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())
 
     def test_required_directories(self):
         self.registry = FileRegistry()
 
-        self.registry.add('foo', GeneratedFile(b'foo'))
+        self.registry.add('foo', GeneratedFile('foo'))
         self.assertEqual(self.registry.required_directories(), set())
 
-        self.registry.add('bar/baz', GeneratedFile(b'barbaz'))
+        self.registry.add('bar/baz', GeneratedFile('barbaz'))
         self.assertEqual(self.registry.required_directories(), {'bar'})
 
-        self.registry.add('bar/zot', GeneratedFile(b'barzot'))
+        self.registry.add('bar/zot', GeneratedFile('barzot'))
         self.assertEqual(self.registry.required_directories(), {'bar'})
 
-        self.registry.add('bar/zap/zot', GeneratedFile(b'barzapzot'))
+        self.registry.add('bar/zap/zot', GeneratedFile('barzapzot'))
         self.assertEqual(self.registry.required_directories(), {'bar', 'bar/zap'})
 
         self.registry.remove('bar/zap/zot')
         self.assertEqual(self.registry.required_directories(), {'bar'})
 
         self.registry.remove('bar/baz')
         self.assertEqual(self.registry.required_directories(), {'bar'})
 
         self.registry.remove('bar/zot')
         self.assertEqual(self.registry.required_directories(), set())
 
-        self.registry.add('x/y/z', GeneratedFile(b'xyz'))
+        self.registry.add('x/y/z', GeneratedFile('xyz'))
         self.assertEqual(self.registry.required_directories(), {'x', 'x/y'})
 
 
 class TestFileRegistrySubtree(BaseTestFileRegistry, unittest.TestCase):
     def test_file_registry_subtree_base(self):
         registry = FileRegistry()
         self.assertEqual(registry, FileRegistrySubtree('', registry))
         self.assertNotEqual(registry, FileRegistrySubtree('base', registry))
 
     def create_registry(self):
         registry = FileRegistry()
-        registry.add('foo/bar', GeneratedFile(b'foo/bar'))
-        registry.add('baz/qux', GeneratedFile(b'baz/qux'))
+        registry.add('foo/bar', GeneratedFile('foo/bar'))
+        registry.add('baz/qux', GeneratedFile('baz/qux'))
         return FileRegistrySubtree('base/root', registry)
 
     def test_file_registry_subtree(self):
         self.do_test_file_registry(self.create_registry())
 
     def test_registry_paths_subtree(self):
         FileRegistry()
         self.do_test_registry_paths(self.create_registry())
@@ -201,53 +200,53 @@ class TestFileCopier(TestWithTmpDir):
         for root, dirs, files in os.walk(base):
             for f in files:
                 all_files.add(
                     mozpath.join(mozpath.relpath(root, base), f))
         return all_files
 
     def test_file_copier(self):
         copier = FileCopier()
-        copier.add('foo/bar', GeneratedFile(b'foobar'))
-        copier.add('foo/qux', GeneratedFile(b'fooqux'))
-        copier.add('foo/deep/nested/directory/file', GeneratedFile(b'fooz'))
-        copier.add('bar', GeneratedFile(b'bar'))
-        copier.add('qux/foo', GeneratedFile(b'quxfoo'))
-        copier.add('qux/bar', GeneratedFile(b''))
+        copier.add('foo/bar', GeneratedFile('foobar'))
+        copier.add('foo/qux', GeneratedFile('fooqux'))
+        copier.add('foo/deep/nested/directory/file', GeneratedFile('fooz'))
+        copier.add('bar', GeneratedFile('bar'))
+        copier.add('qux/foo', GeneratedFile('quxfoo'))
+        copier.add('qux/bar', GeneratedFile(''))
 
         result = copier.copy(self.tmpdir)
         self.assertEqual(self.all_files(self.tmpdir), set(copier.paths()))
         self.assertEqual(self.all_dirs(self.tmpdir),
                          set(['foo/deep/nested/directory', 'qux']))
 
         self.assertEqual(result.updated_files, set(self.tmppath(p) for p in
                                                    self.all_files(self.tmpdir)))
         self.assertEqual(result.existing_files, set())
         self.assertEqual(result.removed_files, set())
         self.assertEqual(result.removed_directories, set())
 
         copier.remove('foo')
-        copier.add('test', GeneratedFile(b'test'))
+        copier.add('test', GeneratedFile('test'))
         result = copier.copy(self.tmpdir)
         self.assertEqual(self.all_files(self.tmpdir), set(copier.paths()))
         self.assertEqual(self.all_dirs(self.tmpdir), set(['qux']))
         self.assertEqual(result.removed_files, set(self.tmppath(p) for p in
                                                    ('foo/bar', 'foo/qux',
                                                     'foo/deep/nested/directory/file')))
 
     def test_symlink_directory_replaced(self):
         """Directory symlinks in destination are replaced if they need to be
         real directories."""
         if not self.symlink_supported:
             return
 
         dest = self.tmppath('dest')
 
         copier = FileCopier()
-        copier.add('foo/bar/baz', GeneratedFile(b'foobarbaz'))
+        copier.add('foo/bar/baz', GeneratedFile('foobarbaz'))
 
         os.makedirs(self.tmppath('dest/foo'))
         dummy = self.tmppath('dummy')
         os.mkdir(dummy)
         link = self.tmppath('dest/foo/bar')
         os.symlink(dummy, link)
 
         result = copier.copy(dest)
@@ -267,17 +266,17 @@ class TestFileCopier(TestWithTmpDir):
         remove_all_directory_symlinks.
         """
         if not self.symlink_supported:
             return
 
         dest = self.tmppath('dest')
 
         copier = FileCopier()
-        copier.add('foo/bar/baz', GeneratedFile(b'foobarbaz'))
+        copier.add('foo/bar/baz', GeneratedFile('foobarbaz'))
 
         os.makedirs(self.tmppath('dest/foo'))
         dummy = self.tmppath('dummy')
         os.mkdir(dummy)
 
         os.mkdir(self.tmppath('dest/zot'))
         link = self.tmppath('dest/zot/zap')
         os.symlink(dummy, link)
@@ -341,24 +340,24 @@ class TestFileCopier(TestWithTmpDir):
 
         # Make file and directory unwritable. Reminder: making a directory
         # unwritable prevents modifications (including deletes) from the list
         # of files in that directory.
         os.chmod(p, 0o400)
         os.chmod(self.tmpdir, 0o400)
 
         copier = FileCopier()
-        copier.add('dummy', GeneratedFile(b'content'))
+        copier.add('dummy', GeneratedFile('content'))
         result = copier.copy(self.tmpdir)
         self.assertEqual(result.removed_files_count, 1)
         self.assertFalse(os.path.exists(p))
 
     def test_no_remove(self):
         copier = FileCopier()
-        copier.add('foo', GeneratedFile(b'foo'))
+        copier.add('foo', GeneratedFile('foo'))
 
         with open(self.tmppath('bar'), 'a'):
             pass
 
         os.mkdir(self.tmppath('emptydir'))
         d = self.tmppath('populateddir')
         os.mkdir(d)
 
@@ -371,17 +370,17 @@ class TestFileCopier(TestWithTmpDir):
                                                            'populateddir/foo']))
         self.assertEqual(self.all_dirs(self.tmpdir), set(['populateddir']))
         self.assertEqual(result.removed_files, set())
         self.assertEqual(result.removed_directories,
                          set([self.tmppath('emptydir')]))
 
     def test_no_remove_empty_directories(self):
         copier = FileCopier()
-        copier.add('foo', GeneratedFile(b'foo'))
+        copier.add('foo', GeneratedFile('foo'))
 
         with open(self.tmppath('bar'), 'a'):
             pass
 
         os.mkdir(self.tmppath('emptydir'))
         d = self.tmppath('populateddir')
         os.mkdir(d)
 
@@ -426,37 +425,37 @@ class TestFileCopier(TestWithTmpDir):
         self.assertIn(self.tmppath('dest/foo/bar'), result.existing_files)
 
     def test_remove_unaccounted_file_registry(self):
         """Test FileCopier.copy(remove_unaccounted=FileRegistry())"""
 
         dest = self.tmppath('dest')
 
         copier = FileCopier()
-        copier.add('foo/bar/baz', GeneratedFile(b'foobarbaz'))
-        copier.add('foo/bar/qux', GeneratedFile(b'foobarqux'))
-        copier.add('foo/hoge/fuga', GeneratedFile(b'foohogefuga'))
-        copier.add('foo/toto/tata', GeneratedFile(b'footototata'))
+        copier.add('foo/bar/baz', GeneratedFile('foobarbaz'))
+        copier.add('foo/bar/qux', GeneratedFile('foobarqux'))
+        copier.add('foo/hoge/fuga', GeneratedFile('foohogefuga'))
+        copier.add('foo/toto/tata', GeneratedFile('footototata'))
 
         os.makedirs(os.path.join(dest, 'bar'))
         with open(os.path.join(dest, 'bar', 'bar'), 'w') as fh:
             fh.write('barbar')
         os.makedirs(os.path.join(dest, 'foo', 'toto'))
         with open(os.path.join(dest, 'foo', 'toto', 'toto'), 'w') as fh:
             fh.write('foototototo')
 
         result = copier.copy(dest, remove_unaccounted=False)
 
         self.assertEqual(self.all_files(dest),
                          set(copier.paths()) | {'foo/toto/toto', 'bar/bar'})
         self.assertEqual(self.all_dirs(dest),
                          {'foo/bar', 'foo/hoge', 'foo/toto', 'bar'})
 
         copier2 = FileCopier()
-        copier2.add('foo/hoge/fuga', GeneratedFile(b'foohogefuga'))
+        copier2.add('foo/hoge/fuga', GeneratedFile('foohogefuga'))
 
         # We expect only files copied from the first copier to be removed,
         # not the extra file that was there beforehand.
         result = copier2.copy(dest, remove_unaccounted=copier)
 
         self.assertEqual(self.all_files(dest),
                          set(copier2.paths()) | {'foo/toto/toto', 'bar/bar'})
         self.assertEqual(self.all_dirs(dest),
@@ -476,34 +475,34 @@ class TestJarrer(unittest.TestCase):
         jar = JarReader(fileobj=dest)
         self.assertEqual([f.filename for f in jar], copier.paths())
         for f in jar:
             self.assertEqual(f.uncompressed_data.read(),
                              copier[f.filename].content)
 
     def test_jarrer(self):
         copier = Jarrer()
-        copier.add('foo/bar', GeneratedFile(b'foobar'))
-        copier.add('foo/qux', GeneratedFile(b'fooqux'))
-        copier.add('foo/deep/nested/directory/file', GeneratedFile(b'fooz'))
-        copier.add('bar', GeneratedFile(b'bar'))
-        copier.add('qux/foo', GeneratedFile(b'quxfoo'))
-        copier.add('qux/bar', GeneratedFile(b''))
+        copier.add('foo/bar', GeneratedFile('foobar'))
+        copier.add('foo/qux', GeneratedFile('fooqux'))
+        copier.add('foo/deep/nested/directory/file', GeneratedFile('fooz'))
+        copier.add('bar', GeneratedFile('bar'))
+        copier.add('qux/foo', GeneratedFile('quxfoo'))
+        copier.add('qux/bar', GeneratedFile(''))
 
         dest = MockDest()
         copier.copy(dest)
         self.check_jar(dest, copier)
 
         copier.remove('foo')
-        copier.add('test', GeneratedFile(b'test'))
+        copier.add('test', GeneratedFile('test'))
         copier.copy(dest)
         self.check_jar(dest, copier)
 
         copier.remove('test')
-        copier.add('test', GeneratedFile(b'replaced-content'))
+        copier.add('test', GeneratedFile('replaced-content'))
         copier.copy(dest)
         self.check_jar(dest, copier)
 
         copier.copy(dest)
         self.check_jar(dest, copier)
 
         preloaded = ['qux/bar', 'bar']
         copier.preload(preloaded)
@@ -512,18 +511,18 @@ class TestJarrer(unittest.TestCase):
         dest.seek(0)
         jar = JarReader(fileobj=dest)
         self.assertEqual([f.filename for f in jar], preloaded +
                          [p for p in copier.paths() if p not in preloaded])
         self.assertEqual(jar.last_preloaded, preloaded[-1])
 
     def test_jarrer_compress(self):
         copier = Jarrer()
-        copier.add('foo/bar', GeneratedFile(b'ffffff'))
-        copier.add('foo/qux', GeneratedFile(b'ffffff'), compress=False)
+        copier.add('foo/bar', GeneratedFile('ffffff'))
+        copier.add('foo/qux', GeneratedFile('ffffff'), compress=False)
 
         dest = MockDest()
         copier.copy(dest)
         self.check_jar(dest, copier)
 
         dest.seek(0)
         jar = JarReader(fileobj=dest)
         self.assertTrue(jar['foo/bar'].compressed)
--- a/python/mozbuild/mozpack/test/test_errors.py
+++ b/python/mozbuild/mozpack/test/test_errors.py
@@ -1,28 +1,28 @@
 # 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
+from __future__ import absolute_import, print_function
 
 from mozpack.errors import (
     errors,
     ErrorMessage,
     AccumulatedErrors,
 )
 import unittest
 import mozunit
-import six
 import sys
+from cStringIO import StringIO
 
 
 class TestErrors(object):
     def setUp(self):
-        errors.out = six.moves.cStringIO()
+        errors.out = StringIO()
         errors.ignore_errors(False)
 
     def tearDown(self):
         errors.out = sys.stderr
 
     def get_output(self):
         return [l.strip() for l in errors.out.getvalue().splitlines()]
 
--- a/python/mozbuild/mozpack/test/test_files.py
+++ b/python/mozbuild/mozpack/test/test_files.py
@@ -1,18 +1,15 @@
 # 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
+from __future__ import absolute_import, print_function
 
-from mozbuild.util import (
-    ensureParentDir,
-    ensure_bytes,
-)
+from mozbuild.util import ensureParentDir
 
 from mozpack.errors import (
     ErrorMessage,
     errors,
 )
 from mozpack.files import (
     AbsoluteSymlinkFile,
     ComposedFinder,
@@ -55,22 +52,23 @@ from mozpack.chrome.manifest import (
     ManifestLocale,
     ManifestOverride,
 )
 import unittest
 import mozfile
 import mozunit
 import os
 import random
-import six
+import string
 import sys
 import tarfile
 import mozpack.path as mozpath
 from tempfile import mkdtemp
 from io import BytesIO
+from StringIO import StringIO
 
 
 class TestWithTmpDir(unittest.TestCase):
     def setUp(self):
         self.tmpdir = mkdtemp()
 
         self.symlink_supported = False
         self.hardlink_supported = False
@@ -158,29 +156,28 @@ class TestDest(TestWithTmpDir):
         dest.close()
         self.assertEqual(dest.read(), 'bar')
         dest.write('foo')
         dest.close()
         dest.write('qux')
         self.assertEqual(dest.read(), 'qux')
 
 
-rand = bytes(random.choice(b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
-             for i in six.moves.xrange(131597))
+rand = ''.join(random.choice(string.letters) for i in xrange(131597))
 samples = [
-    b'',
-    b'test',
-    b'fooo',
-    b'same',
-    b'same',
-    b'Different and longer',
+    '',
+    'test',
+    'fooo',
+    'same',
+    'same',
+    'Different and longer',
     rand,
     rand,
-    rand[:-1] + b'_',
-    b'test',
+    rand[:-1] + '_',
+    'test'
 ]
 
 
 class TestFile(TestWithTmpDir):
     def test_file(self):
         '''
         Check that File.copy yields the proper content in the destination file
         in all situations that trigger different code paths:
@@ -627,148 +624,147 @@ class TestGeneratedFile(TestWithTmpDir):
             f.copy(dest)
             self.assertEqual(content, open(dest, 'rb').read())
 
     def test_generated_file_open(self):
         '''
         Test whether GeneratedFile.open returns an appropriately reset file
         object.
         '''
-        content = b''.join(samples)
+        content = ''.join(samples)
         f = GeneratedFile(content)
         self.assertEqual(content[:42], f.open().read(42))
         self.assertEqual(content, f.open().read())
 
     def test_generated_file_no_write(self):
         '''
         Test various conditions where GeneratedFile.copy is expected not to
         write in the destination file.
         '''
         dest = self.tmppath('dest')
 
         # Initial copy
-        f = GeneratedFile(b'test')
+        f = GeneratedFile('test')
         f.copy(dest)
 
         # Ensure subsequent copies won't trigger writes
         f.copy(DestNoWrite(dest))
-        self.assertEqual(b'test', open(dest, 'rb').read())
+        self.assertEqual('test', open(dest, 'rb').read())
 
         # When using a new instance with the same content, no copy should occur
-        f = GeneratedFile(b'test')
+        f = GeneratedFile('test')
         f.copy(DestNoWrite(dest))
-        self.assertEqual(b'test', open(dest, 'rb').read())
+        self.assertEqual('test', open(dest, 'rb').read())
 
         # Double check that under conditions where a copy occurs, we would get
         # an exception.
-        f = GeneratedFile(b'fooo')
+        f = GeneratedFile('fooo')
         self.assertRaises(RuntimeError, f.copy, DestNoWrite(dest))
 
     def test_generated_file_function(self):
         '''
         Test GeneratedFile behavior with functions.
         '''
         dest = self.tmppath('dest')
         data = {
             'num_calls': 0,
         }
 
         def content():
             data['num_calls'] += 1
-            return b'content'
+            return 'content'
 
         f = GeneratedFile(content)
         self.assertEqual(data['num_calls'], 0)
         f.copy(dest)
         self.assertEqual(data['num_calls'], 1)
-        self.assertEqual(b'content', open(dest, 'rb').read())
-        self.assertEqual(b'content', f.open().read())
-        self.assertEqual(b'content', f.read())
-        self.assertEqual(len(b'content'), f.size())
+        self.assertEqual('content', open(dest, 'rb').read())
+        self.assertEqual('content', f.open().read())
+        self.assertEqual('content', f.read())
+        self.assertEqual(len('content'), f.size())
         self.assertEqual(data['num_calls'], 1)
 
-        f.content = b'modified'
+        f.content = 'modified'
         f.copy(dest)
         self.assertEqual(data['num_calls'], 1)
-        self.assertEqual(b'modified', open(dest, 'rb').read())
-        self.assertEqual(b'modified', f.open().read())
-        self.assertEqual(b'modified', f.read())
-        self.assertEqual(len(b'modified'), f.size())
+        self.assertEqual('modified', open(dest, 'rb').read())
+        self.assertEqual('modified', f.open().read())
+        self.assertEqual('modified', f.read())
+        self.assertEqual(len('modified'), f.size())
 
         f.content = content
         self.assertEqual(data['num_calls'], 1)
-        self.assertEqual(b'content', f.read())
+        self.assertEqual('content', f.read())
         self.assertEqual(data['num_calls'], 2)
 
 
 class TestDeflatedFile(TestWithTmpDir):
     def test_deflated_file(self):
         '''
         Check that DeflatedFile.copy yields the proper content in the
         destination file in all situations that trigger different code paths
         (see TestFile.test_file)
         '''
         src = self.tmppath('src.jar')
         dest = self.tmppath('dest')
 
         contents = {}
         with JarWriter(src) as jar:
             for content in samples:
-                name = b''.join(random.choice(
-                    b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
-                    for i in range(8))
+                name = ''.join(random.choice(string.letters)
+                               for i in xrange(8))
                 jar.add(name, content, compress=True)
                 contents[name] = content
 
         for j in JarReader(src):
             f = DeflatedFile(j)
             f.copy(dest)
             self.assertEqual(contents[j.filename], open(dest, 'rb').read())
 
     def test_deflated_file_open(self):
         '''
         Test whether DeflatedFile.open returns an appropriately reset file
         object.
         '''
         src = self.tmppath('src.jar')
-        content = b''.join(samples)
+        content = ''.join(samples)
         with JarWriter(src) as jar:
             jar.add('content', content)
 
         f = DeflatedFile(JarReader(src)['content'])
         self.assertEqual(content[:42], f.open().read(42))
         self.assertEqual(content, f.open().read())
 
     def test_deflated_file_no_write(self):
         '''
         Test various conditions where DeflatedFile.copy is expected not to
         write in the destination file.
         '''
         src = self.tmppath('src.jar')
         dest = self.tmppath('dest')
 
         with JarWriter(src) as jar:
-            jar.add('test', b'test')
-            jar.add('test2', b'test')
-            jar.add('fooo', b'fooo')
+            jar.add('test', 'test')
+            jar.add('test2', 'test')
+            jar.add('fooo', 'fooo')
 
         jar = JarReader(src)
         # Initial copy
         f = DeflatedFile(jar['test'])
         f.copy(dest)
 
         # Ensure subsequent copies won't trigger writes
         f.copy(DestNoWrite(dest))
-        self.assertEqual(b'test', open(dest, 'rb').read())
+        self.assertEqual('test', open(dest, 'rb').read())
 
         # When using a different file with the same content, no copy should
         # occur
         f = DeflatedFile(jar['test2'])
         f.copy(DestNoWrite(dest))
-        self.assertEqual(b'test', open(dest, 'rb').read())
+        self.assertEqual('test', open(dest, 'rb').read())
 
         # Double check that under conditions where a copy occurs, we would get
         # an exception.
         f = DeflatedFile(jar['fooo'])
         self.assertRaises(RuntimeError, f.copy, DestNoWrite(dest))
 
 
 class TestManifestFile(TestWithTmpDir):
@@ -864,68 +860,68 @@ foo2_xpt = GeneratedFile(
     b'\x66\x6F\x6F\x00\x66\x6F\x6F\x00\x00\x00\x00\x01\x00\x00\x00\x00' +
     b'\x05\x00\x80\x06\x00\x00\x00'
 )
 
 
 class TestMinifiedProperties(TestWithTmpDir):
     def test_minified_properties(self):
         propLines = [
-            b'# Comments are removed',
-            b'foo = bar',
-            b'',
-            b'# Another comment',
+            '# Comments are removed',
+            'foo = bar',
+            '',
+            '# Another comment',
         ]
-        prop = GeneratedFile(b'\n'.join(propLines))
+        prop = GeneratedFile('\n'.join(propLines))
         self.assertEqual(MinifiedProperties(prop).open().readlines(),
                          ['foo = bar\n', '\n'])
         open(self.tmppath('prop'), 'wb').write('\n'.join(propLines))
         MinifiedProperties(File(self.tmppath('prop'))) \
             .copy(self.tmppath('prop2'))
         self.assertEqual(open(self.tmppath('prop2')).readlines(),
                          ['foo = bar\n', '\n'])
 
 
 class TestMinifiedJavaScript(TestWithTmpDir):
     orig_lines = [
-        b'// Comment line',
-        b'let foo = "bar";',
-        b'var bar = true;',
-        b'',
-        b'// Another comment',
+        '// Comment line',
+        'let foo = "bar";',
+        'var bar = true;',
+        '',
+        '// Another comment',
     ]
 
     def test_minified_javascript(self):
-        orig_f = GeneratedFile(b'\n'.join(self.orig_lines))
+        orig_f = GeneratedFile('\n'.join(self.orig_lines))
         min_f = MinifiedJavaScript(orig_f)
 
         mini_lines = min_f.open().readlines()
         self.assertTrue(mini_lines)
         self.assertTrue(len(mini_lines) < len(self.orig_lines))
 
     def _verify_command(self, code):
         our_dir = os.path.abspath(os.path.dirname(__file__))
         return [
             sys.executable,
             os.path.join(our_dir, 'support', 'minify_js_verify.py'),
             code,
         ]
 
     def test_minified_verify_success(self):
-        orig_f = GeneratedFile(b'\n'.join(self.orig_lines))
+        orig_f = GeneratedFile('\n'.join(self.orig_lines))
         min_f = MinifiedJavaScript(orig_f,
                                    verify_command=self._verify_command('0'))
 
         mini_lines = min_f.open().readlines()
         self.assertTrue(mini_lines)
         self.assertTrue(len(mini_lines) < len(self.orig_lines))
 
     def test_minified_verify_failure(self):
-        orig_f = GeneratedFile(b'\n'.join(self.orig_lines))
-        errors.out = six.StringIO()
+        orig_f = GeneratedFile('\n'.join(self.orig_lines))
+        errors.out = StringIO()
         min_f = MinifiedJavaScript(orig_f,
                                    verify_command=self._verify_command('1'))
 
         mini_lines = min_f.open().readlines()
         output = errors.out.getvalue()
         errors.out = sys.stderr
         self.assertEqual(output,
                          'Warning: JS minification verification failed for <unknown>:\n'
@@ -1096,17 +1092,17 @@ class TestFileFinder(MatchTestTemplate, 
         self.finder = FileFinder(self.tmpdir, find_dotfiles=True,
                                  ignore=['foo/.bar/**'])
         self.do_check('foo/**', ['foo/.foo', 'foo/bar', 'foo/baz',
                                  'foo/qux/1', 'foo/qux/bar', 'foo/qux/2/test', 'foo/qux/2/test2'])
 
 
 class TestJarFinder(MatchTestTemplate, TestWithTmpDir):
     def add(self, path):
-        self.jar.add(path, ensure_bytes(path), compress=True)
+        self.jar.add(path, path, compress=True)
 
     def do_check(self, pattern, result):
         do_check(self, self.finder, pattern, result)
 
     def test_jar_finder(self):
         self.jar = JarWriter(file=self.tmppath('test.jar'))
         self.prepare_match_test()
         self.jar.finish()
@@ -1189,21 +1185,20 @@ class TestMercurialRevisionFinder(MatchT
                 client.close()
 
         self._clients[:] = []
 
         super(TestMercurialRevisionFinder, self).tearDown()
 
     def _client(self):
         configs = (
-            # b'' because py2 needs !unicode
-            b'ui.username="Dummy User <dummy@example.com>"',
+            'ui.username="Dummy User <dummy@example.com>"',
         )
-        client = hglib.open(self.tmpdir,
-                            encoding=b'UTF-8',  # b'' because py2 needs !unicode
+
+        client = hglib.open(self.tmpdir, encoding='UTF-8',
                             configs=configs)
         self._clients.append(client)
         return client
 
     def add(self, path):
         with self._client() as c:
             ensureParentDir(self.tmppath(path))
             with open(self.tmppath(path), 'wb') as fh:
--- a/python/mozbuild/mozpack/test/test_mozjar.py
+++ b/python/mozbuild/mozpack/test/test_mozjar.py
@@ -1,29 +1,29 @@
 # 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
+from __future__ import absolute_import, print_function
 
 from mozpack.files import FileFinder
 from mozpack.mozjar import (
     JarReaderError,
     JarWriterError,
     JarStruct,
     JarReader,
     JarWriter,
     Deflater,
     JarLog,
 )
 from collections import OrderedDict
 from mozpack.test.test_files import MockDest
 import unittest
 import mozunit
-import six
+from cStringIO import StringIO
 import mozpack.path as mozpath
 import os
 
 
 test_data_path = mozpath.abspath(mozpath.dirname(__file__))
 test_data_path = mozpath.join(test_data_path, 'data')
 
 
@@ -70,18 +70,18 @@ class TestJarStruct(unittest.TestCase):
         self.assertRaises(JarReaderError, TestJarStruct.Foo, data[2:])
 
         foo = TestJarStruct.Foo(data[1:])
         self.assertEqual(foo['foo'], 0x45444342)
         self.assertEqual(foo['bar'], 0xcdab)
         self.assertEqual(foo['qux'], 0x01ef)
         self.assertFalse('length' in foo)
         self.assertFalse('length2' in foo)
-        self.assertEqual(foo['string'], b'012345')
-        self.assertEqual(foo['string2'], b'67')
+        self.assertEqual(foo['string'], '012345')
+        self.assertEqual(foo['string2'], '67')
 
     def test_read_jar_struct(self):
         data = b'\x00\x04\x03\x02\x01\x42\x43\x44\x45\xab\xcd\xef' + \
                b'\x01\x06\x00\x02\x0001234567890'
         self.do_test_read_jar_struct(data)
 
     def test_read_jar_struct_memoryview(self):
         data = b'\x00\x04\x03\x02\x01\x42\x43\x44\x45\xab\xcd\xef' + \
@@ -90,213 +90,213 @@ class TestJarStruct(unittest.TestCase):
 
 
 class TestDeflater(unittest.TestCase):
     def wrap(self, data):
         return data
 
     def test_deflater_no_compress(self):
         deflater = Deflater(False)
-        deflater.write(self.wrap(b'abc'))
+        deflater.write(self.wrap('abc'))
         self.assertFalse(deflater.compressed)
         self.assertEqual(deflater.uncompressed_size, 3)
         self.assertEqual(deflater.compressed_size, deflater.uncompressed_size)
-        self.assertEqual(deflater.compressed_data, b'abc')
+        self.assertEqual(deflater.compressed_data, 'abc')
         self.assertEqual(deflater.crc32, 0x352441c2)
 
     def test_deflater_compress_no_gain(self):
         deflater = Deflater(True)
-        deflater.write(self.wrap(b'abc'))
+        deflater.write(self.wrap('abc'))
         self.assertFalse(deflater.compressed)
         self.assertEqual(deflater.uncompressed_size, 3)
         self.assertEqual(deflater.compressed_size, deflater.uncompressed_size)
-        self.assertEqual(deflater.compressed_data, b'abc')
+        self.assertEqual(deflater.compressed_data, 'abc')
         self.assertEqual(deflater.crc32, 0x352441c2)
 
     def test_deflater_compress(self):
         deflater = Deflater(True)
-        deflater.write(self.wrap(b'aaaaaaaaaaaaanopqrstuvwxyz'))
+        deflater.write(self.wrap('aaaaaaaaaaaaanopqrstuvwxyz'))
         self.assertTrue(deflater.compressed)
         self.assertEqual(deflater.uncompressed_size, 26)
         self.assertNotEqual(deflater.compressed_size,
                             deflater.uncompressed_size)
         self.assertEqual(deflater.crc32, 0xd46b97ed)
         # The CRC is the same as when not compressed
         deflater = Deflater(False)
         self.assertFalse(deflater.compressed)
-        deflater.write(self.wrap(b'aaaaaaaaaaaaanopqrstuvwxyz'))
+        deflater.write(self.wrap('aaaaaaaaaaaaanopqrstuvwxyz'))
         self.assertEqual(deflater.crc32, 0xd46b97ed)
 
     def test_deflater_empty(self):
         deflater = Deflater(False)
         self.assertFalse(deflater.compressed)
         self.assertEqual(deflater.uncompressed_size, 0)
         self.assertEqual(deflater.compressed_size, deflater.uncompressed_size)
-        self.assertEqual(deflater.compressed_data, b'')
+        self.assertEqual(deflater.compressed_data, '')
         self.assertEqual(deflater.crc32, 0)
 
 
 class TestDeflaterMemoryView(TestDeflater):
     def wrap(self, data):
         return memoryview(data)
 
 
 class TestJar(unittest.TestCase):
     def test_jar(self):
         s = MockDest()
         with JarWriter(fileobj=s) as jar:
-            jar.add('foo', b'foo')
-            self.assertRaises(JarWriterError, jar.add, 'foo', b'bar')
-            jar.add('bar', b'aaaaaaaaaaaaanopqrstuvwxyz')
-            jar.add('baz/qux', b'aaaaaaaaaaaaanopqrstuvwxyz', False)
-            jar.add('baz\\backslash', b'aaaaaaaaaaaaaaa')
+            jar.add('foo', 'foo')
+            self.assertRaises(JarWriterError, jar.add, 'foo', 'bar')
+            jar.add('bar', 'aaaaaaaaaaaaanopqrstuvwxyz')
+            jar.add('baz/qux', 'aaaaaaaaaaaaanopqrstuvwxyz', False)
+            jar.add('baz\\backslash', 'aaaaaaaaaaaaaaa')
 
         files = [j for j in JarReader(fileobj=s)]
 
-        self.assertEqual(files[0].filename, b'foo')
+        self.assertEqual(files[0].filename, 'foo')
         self.assertFalse(files[0].compressed)
-        self.assertEqual(files[0].read(), b'foo')
+        self.assertEqual(files[0].read(), 'foo')
 
-        self.assertEqual(files[1].filename, b'bar')
+        self.assertEqual(files[1].filename, 'bar')
         self.assertTrue(files[1].compressed)
-        self.assertEqual(files[1].read(), b'aaaaaaaaaaaaanopqrstuvwxyz')
+        self.assertEqual(files[1].read(), 'aaaaaaaaaaaaanopqrstuvwxyz')
 
-        self.assertEqual(files[2].filename, b'baz/qux')
+        self.assertEqual(files[2].filename, 'baz/qux')
         self.assertFalse(files[2].compressed)
-        self.assertEqual(files[2].read(), b'aaaaaaaaaaaaanopqrstuvwxyz')
+        self.assertEqual(files[2].read(), 'aaaaaaaaaaaaanopqrstuvwxyz')
 
         if os.sep == '\\':
-            self.assertEqual(files[3].filename, b'baz/backslash',
+            self.assertEqual(files[3].filename, 'baz/backslash',
                              'backslashes in filenames on Windows should get normalized')
         else:
-            self.assertEqual(files[3].filename, b'baz\\backslash',
+            self.assertEqual(files[3].filename, 'baz\\backslash',
                              'backslashes in filenames on POSIX platform are untouched')
 
         s = MockDest()
         with JarWriter(fileobj=s, compress=False) as jar:
-            jar.add('bar', b'aaaaaaaaaaaaanopqrstuvwxyz')
-            jar.add('foo', b'foo')
-            jar.add('baz/qux', b'aaaaaaaaaaaaanopqrstuvwxyz', True)
+            jar.add('bar', 'aaaaaaaaaaaaanopqrstuvwxyz')
+            jar.add('foo', 'foo')
+            jar.add('baz/qux', 'aaaaaaaaaaaaanopqrstuvwxyz', True)
 
         jar = JarReader(fileobj=s)
         files = [j for j in jar]
 
-        self.assertEqual(files[0].filename, b'bar')
+        self.assertEqual(files[0].filename, 'bar')
         self.assertFalse(files[0].compressed)
-        self.assertEqual(files[0].read(), b'aaaaaaaaaaaaanopqrstuvwxyz')
+        self.assertEqual(files[0].read(), 'aaaaaaaaaaaaanopqrstuvwxyz')
 
-        self.assertEqual(files[1].filename, b'foo')
+        self.assertEqual(files[1].filename, 'foo')
         self.assertFalse(files[1].compressed)
-        self.assertEqual(files[1].read(), b'foo')
+        self.assertEqual(files[1].read(), 'foo')
 
-        self.assertEqual(files[2].filename, b'baz/qux')
+        self.assertEqual(files[2].filename, 'baz/qux')
         self.assertTrue(files[2].compressed)
-        self.assertEqual(files[2].read(), b'aaaaaaaaaaaaanopqrstuvwxyz')
+        self.assertEqual(files[2].read(), 'aaaaaaaaaaaaanopqrstuvwxyz')
 
-        self.assertTrue(b'bar' in jar)
-        self.assertTrue(b'foo' in jar)
-        self.assertFalse(b'baz' in jar)
-        self.assertTrue(b'baz/qux' in jar)
-        self.assertTrue(jar[b'bar'], files[1])
-        self.assertTrue(jar[b'foo'], files[0])
-        self.assertTrue(jar[b'baz/qux'], files[2])
+        self.assertTrue('bar' in jar)
+        self.assertTrue('foo' in jar)
+        self.assertFalse('baz' in jar)
+        self.assertTrue('baz/qux' in jar)
+        self.assertTrue(jar['bar'], files[1])
+        self.assertTrue(jar['foo'], files[0])
+        self.assertTrue(jar['baz/qux'], files[2])
 
         s.seek(0)
         jar = JarReader(fileobj=s)
-        self.assertTrue(b'bar' in jar)
-        self.assertTrue(b'foo' in jar)
-        self.assertFalse(b'baz' in jar)
-        self.assertTrue(b'baz/qux' in jar)
+        self.assertTrue('bar' in jar)
+        self.assertTrue('foo' in jar)
+        self.assertFalse('baz' in jar)
+        self.assertTrue('baz/qux' in jar)
 
         files[0].seek(0)
-        self.assertEqual(jar[b'bar'].filename, files[0].filename)
-        self.assertEqual(jar[b'bar'].compressed, files[0].compressed)
-        self.assertEqual(jar[b'bar'].read(), files[0].read())
+        self.assertEqual(jar['bar'].filename, files[0].filename)
+        self.assertEqual(jar['bar'].compressed, files[0].compressed)
+        self.assertEqual(jar['bar'].read(), files[0].read())
 
         files[1].seek(0)
-        self.assertEqual(jar[b'foo'].filename, files[1].filename)
-        self.assertEqual(jar[b'foo'].compressed, files[1].compressed)
-        self.assertEqual(jar[b'foo'].read(), files[1].read())
+        self.assertEqual(jar['foo'].filename, files[1].filename)
+        self.assertEqual(jar['foo'].compressed, files[1].compressed)
+        self.assertEqual(jar['foo'].read(), files[1].read())
 
         files[2].seek(0)
-        self.assertEqual(jar[b'baz/qux'].filename, files[2].filename)
-        self.assertEqual(jar[b'baz/qux'].compressed, files[2].compressed)
-        self.assertEqual(jar[b'baz/qux'].read(), files[2].read())
+        self.assertEqual(jar['baz/qux'].filename, files[2].filename)
+        self.assertEqual(jar['baz/qux'].compressed, files[2].compressed)
+        self.assertEqual(jar['baz/qux'].read(), files[2].read())
 
     def test_rejar(self):
         s = MockDest()
         with JarWriter(fileobj=s) as jar:
-            jar.add('foo', b'foo')
-            jar.add('bar', b'aaaaaaaaaaaaanopqrstuvwxyz')
-            jar.add('baz/qux', b'aaaaaaaaaaaaanopqrstuvwxyz', False)
+            jar.add('foo', 'foo')
+            jar.add('bar', 'aaaaaaaaaaaaanopqrstuvwxyz')
+            jar.add('baz/qux', 'aaaaaaaaaaaaanopqrstuvwxyz', False)
 
         new = MockDest()
         with JarWriter(fileobj=new) as jar:
             for j in JarReader(fileobj=s):
                 jar.add(j.filename, j)
 
         jar = JarReader(fileobj=new)
         files = [j for j in jar]
 
-        self.assertEqual(files[0].filename, b'foo')
+        self.assertEqual(files[0].filename, 'foo')
         self.assertFalse(files[0].compressed)
-        self.assertEqual(files[0].read(), b'foo')
+        self.assertEqual(files[0].read(), 'foo')
 
-        self.assertEqual(files[1].filename, b'bar')
+        self.assertEqual(files[1].filename, 'bar')
         self.assertTrue(files[1].compressed)
-        self.assertEqual(files[1].read(), b'aaaaaaaaaaaaanopqrstuvwxyz')
+        self.assertEqual(files[1].read(), 'aaaaaaaaaaaaanopqrstuvwxyz')
 
-        self.assertEqual(files[2].filename, b'baz/qux')
+        self.assertEqual(files[2].filename, 'baz/qux')
         self.assertTrue(files[2].compressed)
-        self.assertEqual(files[2].read(), b'aaaaaaaaaaaaanopqrstuvwxyz')
+        self.assertEqual(files[2].read(), 'aaaaaaaaaaaaanopqrstuvwxyz')
 
     def test_add_from_finder(self):
         s = MockDest()
         with JarWriter(fileobj=s) as jar:
             finder = FileFinder(test_data_path)
             for p, f in finder.find('test_data'):
                 jar.add('test_data', f)
 
         jar = JarReader(fileobj=s)
         files = [j for j in jar]
 
-        self.assertEqual(files[0].filename, b'test_data')
+        self.assertEqual(files[0].filename, 'test_data')
         self.assertFalse(files[0].compressed)
-        self.assertEqual(files[0].read(), b'test_data')
+        self.assertEqual(files[0].read(), 'test_data')
 
 
 class TestPreload(unittest.TestCase):
     def test_preload(self):
         s = MockDest()
         with JarWriter(fileobj=s) as jar:
-            jar.add('foo', b'foo')
-            jar.add('bar', b'abcdefghijklmnopqrstuvwxyz')
-            jar.add('baz/qux', b'aaaaaaaaaaaaanopqrstuvwxyz')
+            jar.add('foo', 'foo')
+            jar.add('bar', 'abcdefghijklmnopqrstuvwxyz')
+            jar.add('baz/qux', 'aaaaaaaaaaaaanopqrstuvwxyz')
 
         jar = JarReader(fileobj=s)
         self.assertEqual(jar.last_preloaded, None)
 
         with JarWriter(fileobj=s) as jar:
-            jar.add('foo', b'foo')
-            jar.add('bar', b'abcdefghijklmnopqrstuvwxyz')
-            jar.add('baz/qux', b'aaaaaaaaaaaaanopqrstuvwxyz')
+            jar.add('foo', 'foo')
+            jar.add('bar', 'abcdefghijklmnopqrstuvwxyz')
+            jar.add('baz/qux', 'aaaaaaaaaaaaanopqrstuvwxyz')
             jar.preload(['baz/qux', 'bar'])
 
         jar = JarReader(fileobj=s)
-        self.assertEqual(jar.last_preloaded, b'bar')
+        self.assertEqual(jar.last_preloaded, 'bar')
         files = [j for j in jar]
 
-        self.assertEqual(files[0].filename, b'baz/qux')
-        self.assertEqual(files[1].filename, b'bar')
-        self.assertEqual(files[2].filename, b'foo')
+        self.assertEqual(files[0].filename, 'baz/qux')
+        self.assertEqual(files[1].filename, 'bar')
+        self.assertEqual(files[2].filename, 'foo')
 
 
 class TestJarLog(unittest.TestCase):
     def test_jarlog(self):
-        s = six.moves.cStringIO('\n'.join([
+        s = StringIO('\n'.join([
             'bar/baz.jar first',
             'bar/baz.jar second',
             'bar/baz.jar third',
             'bar/baz.jar second',
             'bar/baz.jar second',
             'omni.ja stuff',
             'bar/baz.jar first',
             'omni.ja other/stuff',
--- a/python/mozbuild/mozpack/test/test_packager.py
+++ b/python/mozbuild/mozpack/test/test_packager.py
@@ -1,13 +1,13 @@
 # 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
+from __future__ import absolute_import, print_function
 
 import unittest
 import mozunit
 import os
 from buildconfig import topobjdir
 from mozpack.packager import (
     preprocess_manifest,
     CallDeque,
@@ -142,116 +142,116 @@ class TestSimplePackager(unittest.TestCa
                 GeneratedFile.__init__(self, content)
                 self.path = path
 
         formatter = MockFormatter()
         packager = SimplePackager(formatter)
         curdir = os.path.abspath(os.curdir)
         file = GeneratedFileWithPath(os.path.join(curdir, 'foo',
                                                   'bar.manifest'),
-                                     b'resource bar bar/\ncontent bar bar/')
+                                     'resource bar bar/\ncontent bar bar/')
         with errors.context('manifest', 1):
             packager.add('foo/bar.manifest', file)
 
         file = GeneratedFileWithPath(os.path.join(curdir, 'foo',
                                                   'baz.manifest'),
-                                     b'resource baz baz/')
+                                     'resource baz baz/')
         with errors.context('manifest', 2):
             packager.add('bar/baz.manifest', file)
 
         with errors.context('manifest', 3):
             packager.add('qux/qux.manifest',
-                         GeneratedFile(b''.join([
-                            b'resource qux qux/\n',
-                            b'binary-component qux.so\n',
+                         GeneratedFile(''.join([
+                            'resource qux qux/\n',
+                            'binary-component qux.so\n',
                          ])))
-        bar_xpt = GeneratedFile(b'bar.xpt')
-        qux_xpt = GeneratedFile(b'qux.xpt')
-        foo_html = GeneratedFile(b'foo_html')
-        bar_html = GeneratedFile(b'bar_html')
+        bar_xpt = GeneratedFile('bar.xpt')
+        qux_xpt = GeneratedFile('qux.xpt')
+        foo_html = GeneratedFile('foo_html')
+        bar_html = GeneratedFile('bar_html')
         with errors.context('manifest', 4):
             packager.add('foo/bar.xpt', bar_xpt)
         with errors.context('manifest', 5):
             packager.add('foo/bar/foo.html', foo_html)
             packager.add('foo/bar/bar.html', bar_html)
 
         file = GeneratedFileWithPath(os.path.join(curdir, 'foo.manifest'),
-                                     b''.join([
-                                         b'manifest foo/bar.manifest\n',
-                                         b'manifest bar/baz.manifest\n',
+                                     ''.join([
+                                         'manifest foo/bar.manifest\n',
+                                         'manifest bar/baz.manifest\n',
                                      ]))
         with errors.context('manifest', 6):
             packager.add('foo.manifest', file)
         with errors.context('manifest', 7):
             packager.add('foo/qux.xpt', qux_xpt)
 
         file = GeneratedFileWithPath(os.path.join(curdir, 'addon',
                                                   'chrome.manifest'),
-                                     b'resource hoge hoge/')
+                                     'resource hoge hoge/')
         with errors.context('manifest', 8):
             packager.add('addon/chrome.manifest', file)
 
-        install_rdf = GeneratedFile(b'<RDF></RDF>')
+        install_rdf = GeneratedFile('<RDF></RDF>')
         with errors.context('manifest', 9):
             packager.add('addon/install.rdf', install_rdf)
 
         with errors.context('manifest', 10):
             packager.add('addon2/install.rdf', install_rdf)
             packager.add('addon2/chrome.manifest',
-                         GeneratedFile(b'binary-component addon2.so'))
+                         GeneratedFile('binary-component addon2.so'))
 
         with errors.context('manifest', 11):
             packager.add('addon3/install.rdf', install_rdf)
             packager.add('addon3/chrome.manifest', GeneratedFile(
-                b'manifest components/components.manifest'))
+                'manifest components/components.manifest'))
             packager.add('addon3/components/components.manifest',
-                         GeneratedFile(b'binary-component addon3.so'))
+                         GeneratedFile('binary-component addon3.so'))
 
         with errors.context('manifest', 12):
             install_rdf_addon4 = GeneratedFile(
-                b'<RDF>\n<...>\n<em:unpack>true</em:unpack>\n<...>\n</RDF>')
+                '<RDF>\n<...>\n<em:unpack>true</em:unpack>\n<...>\n</RDF>')
             packager.add('addon4/install.rdf', install_rdf_addon4)
 
         with errors.context('manifest', 13):
             install_rdf_addon5 = GeneratedFile(
-                b'<RDF>\n<...>\n<em:unpack>false</em:unpack>\n<...>\n</RDF>')
+                '<RDF>\n<...>\n<em:unpack>false</em:unpack>\n<...>\n</RDF>')
             packager.add('addon5/install.rdf', install_rdf_addon5)
 
         with errors.context('manifest', 14):
             install_rdf_addon6 = GeneratedFile(
-                b'<RDF>\n<... em:unpack=true>\n<...>\n</RDF>')
+                '<RDF>\n<... em:unpack=true>\n<...>\n</RDF>')
             packager.add('addon6/install.rdf', install_rdf_addon6)
 
         with errors.context('manifest', 15):
             install_rdf_addon7 = GeneratedFile(
-                b'<RDF>\n<... em:unpack=false>\n<...>\n</RDF>')
+                '<RDF>\n<... em:unpack=false>\n<...>\n</RDF>')
             packager.add('addon7/install.rdf', install_rdf_addon7)
 
         with errors.context('manifest', 16):
             install_rdf_addon8 = GeneratedFile(
-                b'<RDF>\n<... em:unpack="true">\n<...>\n</RDF>')
+                '<RDF>\n<... em:unpack="true">\n<...>\n</RDF>')
             packager.add('addon8/install.rdf', install_rdf_addon8)
 
         with errors.context('manifest', 17):
             install_rdf_addon9 = GeneratedFile(
-                b'<RDF>\n<... em:unpack="false">\n<...>\n</RDF>')
+                '<RDF>\n<... em:unpack="false">\n<...>\n</RDF>')
             packager.add('addon9/install.rdf', install_rdf_addon9)
 
         with errors.context('manifest', 18):
             install_rdf_addon10 = GeneratedFile(
-                b'<RDF>\n<... em:unpack=\'true\'>\n<...>\n</RDF>')
+                '<RDF>\n<... em:unpack=\'true\'>\n<...>\n</RDF>')
             packager.add('addon10/install.rdf', install_rdf_addon10)
 
         with errors.context('manifest', 19):
             install_rdf_addon11 = GeneratedFile(
-                b'<RDF>\n<... em:unpack=\'false\'>\n<...>\n</RDF>')
+                '<RDF>\n<... em:unpack=\'false\'>\n<...>\n</RDF>')
             packager.add('addon11/install.rdf', install_rdf_addon11)
 
         we_manifest = GeneratedFile(
-            b'{"manifest_version": 2, "name": "Test WebExtension", "version": "1.0"}')
+            '{"manifest_version": 2, "name": "Test WebExtension", "version": "1.0"}')
         # hybrid and hybrid2 are both bootstrapped extensions with
         # embedded webextensions, they differ in the order in which
         # the manifests are added to the packager.
         with errors.context('manifest', 20):
             packager.add('hybrid/install.rdf', install_rdf)
 
         with errors.context('manifest', 21):
             packager.add('hybrid/webextension/manifest.json', we_manifest)
@@ -260,17 +260,17 @@ class TestSimplePackager(unittest.TestCa
             packager.add('hybrid2/webextension/manifest.json', we_manifest)
 
         with errors.context('manifest', 23):
             packager.add('hybrid2/install.rdf', install_rdf)
 
         with errors.context('manifest', 24):
             packager.add('webextension/manifest.json', we_manifest)
 
-        non_we_manifest = GeneratedFile(b'{"not a webextension": true}')
+        non_we_manifest = GeneratedFile('{"not a webextension": true}')
         with errors.context('manifest', 25):
             packager.add('nonwebextension/manifest.json', non_we_manifest)
 
         self.assertEqual(formatter.log, [])
 
         with errors.context('dummy', 1):
             packager.close()
         self.maxDiff = None
@@ -352,78 +352,78 @@ class TestSimplePackager(unittest.TestCa
         self.assertEqual(packager.get_bases(addons=False), set(['', 'qux']))
 
     def test_simple_packager_manifest_consistency(self):
         formatter = MockFormatter()
         # bar/ is detected as an addon because of install.rdf, but top-level
         # includes a manifest inside bar/.
         packager = SimplePackager(formatter)
         packager.add('base.manifest', GeneratedFile(
-            b'manifest foo/bar.manifest\n'
-            b'manifest bar/baz.manifest\n'
+            'manifest foo/bar.manifest\n'
+            'manifest bar/baz.manifest\n'
         ))
-        packager.add('foo/bar.manifest', GeneratedFile(b'resource bar bar'))
-        packager.add('bar/baz.manifest', GeneratedFile(b'resource baz baz'))
-        packager.add('bar/install.rdf', GeneratedFile(b''))
+        packager.add('foo/bar.manifest', GeneratedFile('resource bar bar'))
+        packager.add('bar/baz.manifest', GeneratedFile('resource baz baz'))
+        packager.add('bar/install.rdf', GeneratedFile(''))
 
         with self.assertRaises(ErrorMessage) as e:
             packager.close()
 
         self.assertEqual(e.exception.message,
                          'Error: "bar/baz.manifest" is included from "base.manifest", '
                          'which is outside "bar"')
 
         # bar/ is detected as a separate base because of chrome.manifest that
         # is included nowhere, but top-level includes another manifest inside
         # bar/.
         packager = SimplePackager(formatter)
         packager.add('base.manifest', GeneratedFile(
-            b'manifest foo/bar.manifest\n'
-            b'manifest bar/baz.manifest\n'
+            'manifest foo/bar.manifest\n'
+            'manifest bar/baz.manifest\n'
         ))
-        packager.add('foo/bar.manifest', GeneratedFile(b'resource bar bar'))
-        packager.add('bar/baz.manifest', GeneratedFile(b'resource baz baz'))
-        packager.add('bar/chrome.manifest', GeneratedFile(b'resource baz baz'))
+        packager.add('foo/bar.manifest', GeneratedFile('resource bar bar'))
+        packager.add('bar/baz.manifest', GeneratedFile('resource baz baz'))
+        packager.add('bar/chrome.manifest', GeneratedFile('resource baz baz'))
 
         with self.assertRaises(ErrorMessage) as e:
             packager.close()
 
         self.assertEqual(e.exception.message,
                          'Error: "bar/baz.manifest" is included from "base.manifest", '
                          'which is outside "bar"')
 
         # bar/ is detected as a separate base because of chrome.manifest that
         # is included nowhere, but chrome.manifest includes baz.manifest from
         # the same directory. This shouldn't error out.
         packager = SimplePackager(formatter)
         packager.add('base.manifest', GeneratedFile(
-            b'manifest foo/bar.manifest\n'
+            'manifest foo/bar.manifest\n'
         ))
-        packager.add('foo/bar.manifest', GeneratedFile(b'resource bar bar'))
-        packager.add('bar/baz.manifest', GeneratedFile(b'resource baz baz'))
+        packager.add('foo/bar.manifest', GeneratedFile('resource bar bar'))
+        packager.add('bar/baz.manifest', GeneratedFile('resource baz baz'))
         packager.add('bar/chrome.manifest',
-                     GeneratedFile(b'manifest baz.manifest'))
+                     GeneratedFile('manifest baz.manifest'))
         packager.close()
 
 
 class TestSimpleManifestSink(unittest.TestCase):
     def test_simple_manifest_parser(self):
         formatter = MockFormatter()
-        foobar = GeneratedFile(b'foobar')
-        foobaz = GeneratedFile(b'foobaz')
-        fooqux = GeneratedFile(b'fooqux')
-        foozot = GeneratedFile(b'foozot')
+        foobar = GeneratedFile('foobar')
+        foobaz = GeneratedFile('foobaz')
+        fooqux = GeneratedFile('fooqux')
+        foozot = GeneratedFile('foozot')
         finder = MockFinder({
             'bin/foo/bar': foobar,
             'bin/foo/baz': foobaz,
             'bin/foo/qux': fooqux,
             'bin/foo/zot': foozot,
-            'bin/foo/chrome.manifest': GeneratedFile(b'resource foo foo/'),
+            'bin/foo/chrome.manifest': GeneratedFile('resource foo foo/'),
             'bin/chrome.manifest':
-            GeneratedFile(b'manifest foo/chrome.manifest'),
+            GeneratedFile('manifest foo/chrome.manifest'),
         })
         parser = SimpleManifestSink(finder, formatter)
         component0 = Component('component0')
         component1 = Component('component1')
         component2 = Component('component2', destdir='destdir')
         parser.add(component0, 'bin/foo/b*')
         parser.add(component1, 'bin/foo/qux')
         parser.add(component1, 'bin/foo/chrome.manifest')
--- a/python/mozbuild/mozpack/test/test_packager_formats.py
+++ b/python/mozbuild/mozpack/test/test_packager_formats.py
@@ -1,13 +1,13 @@
 # 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
+from __future__ import absolute_import, print_function
 
 import mozunit
 import unittest
 from mozpack.packager.formats import (
     FlatFormatter,
     JarFormatter,
     OmniJarFormatter,
 )
@@ -28,17 +28,16 @@ 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,
@@ -54,32 +53,32 @@ CONTENTS = {
         ManifestBinaryComponent('components', 'foo.so'),
         ManifestContent('app/chrome', 'content', 'foo/'),
         ManifestComponent('app/components', '{foo-id}', 'foo.js'),
         ManifestContent('addon0/chrome', 'addon0', 'foo/bar/'),
         ManifestContent('addon1/chrome', 'addon1', 'foo/bar/'),
         ManifestContent('app/chrome/addons/addon2/chrome', 'addon2', 'foo/bar/'),
     ],
     'files': {
-        'chrome/f/oo/bar/baz': GeneratedFile(b'foobarbaz'),
-        'chrome/f/oo/baz': GeneratedFile(b'foobaz'),
-        'chrome/f/oo/qux': GeneratedFile(b'fooqux'),
-        'components/foo.so': GeneratedFile(b'foo.so'),
+        'chrome/f/oo/bar/baz': GeneratedFile('foobarbaz'),
+        'chrome/f/oo/baz': GeneratedFile('foobaz'),
+        'chrome/f/oo/qux': GeneratedFile('fooqux'),
+        'components/foo.so': GeneratedFile('foo.so'),
         'components/foo.xpt': foo_xpt,
         'components/bar.xpt': bar_xpt,
-        'foo': GeneratedFile(b'foo'),
-        'app/chrome/foo/foo': GeneratedFile(b'appfoo'),
-        'app/components/foo.js': GeneratedFile(b'foo.js'),
-        'addon0/chrome/foo/bar/baz': GeneratedFile(b'foobarbaz'),
+        'foo': GeneratedFile('foo'),
+        'app/chrome/foo/foo': GeneratedFile('appfoo'),
+        'app/components/foo.js': GeneratedFile('foo.js'),
+        'addon0/chrome/foo/bar/baz': GeneratedFile('foobarbaz'),
         'addon0/components/foo.xpt': foo2_xpt,
         'addon0/components/bar.xpt': bar_xpt,
-        'addon1/chrome/foo/bar/baz': GeneratedFile(b'foobarbaz'),
+        'addon1/chrome/foo/bar/baz': GeneratedFile('foobarbaz'),
         'addon1/components/foo.xpt': foo2_xpt,
         'addon1/components/bar.xpt': bar_xpt,
-        'app/chrome/addons/addon2/chrome/foo/bar/baz': GeneratedFile(b'foobarbaz'),
+        'app/chrome/addons/addon2/chrome/foo/bar/baz': GeneratedFile('foobarbaz'),
         'app/chrome/addons/addon2/components/foo.xpt': foo2_xpt,
         'app/chrome/addons/addon2/components/bar.xpt': bar_xpt,
     },
 }
 
 FILES = CONTENTS['files']
 
 RESULT_FLAT = {
@@ -119,32 +118,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 six.iteritems({
+        for p, f in {
             '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',
@@ -182,22 +181,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 six.iteritems(RESULT_FLAT)
+        for p, f in RESULT_FLAT.iteritems()
         if p.startswith('addon1/')
     },
     'app/chrome/addons/addon2.xpi': {
         mozpath.relpath(p, 'app/chrome/addons/addon2'): f
-        for p, f in six.iteritems(RESULT_FLAT)
+        for p, f in RESULT_FLAT.iteritems()
         if p.startswith('app/chrome/addons/addon2/')
     },
 })
 
 RESULT_OMNIJAR = {
     p: RESULT_FLAT[p]
     for p in (
         'components/foo.so',
@@ -229,17 +228,17 @@ RESULT_OMNIJAR.update({
         for p in chain((
             'chrome.manifest',
             'chrome/chrome.manifest',
             'chrome/foo/foo',
             'components/components.manifest',
             'components/foo.js',
         ), (
             mozpath.relpath(p, 'app')
-            for p in six.iterkeys(RESULT_FLAT)
+            for p in RESULT_FLAT.iterkeys()
             if p.startswith('app/chrome/addons/addon2/')
         ))
     },
     'app/chrome.manifest': [],
 })
 
 RESULT_OMNIJAR['omni.foo'].update({
     p: RESULT_FLAT[p]
@@ -258,39 +257,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 six.iteritems(CONTENTS['bases'])
+        for b, a in CONTENTS['bases'].iteritems()
     },
     '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 six.iteritems(CONTENTS['files'])
+        for p, f in CONTENTS['files'].iteritems()
     },
 }
 
 EXTRA_CONTENTS = {
-    'extra/file': GeneratedFile(b'extra file'),
+    'extra/file': GeneratedFile('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 six.iteritems(results)
+        for p, v in results.iteritems()
     }
     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)
@@ -298,17 +297,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(six.iteritems(contents['files'])):
+    for k, v in sorted(contents['files'].iteritems()):
         if k.endswith('.xpt'):
             formatter.add_interfaces(k, v)
         else:
             formatter.add(k, v)
 
 
 def get_contents(registry, read_all=False):
     result = {}
@@ -404,17 +403,17 @@ class TestFormatters(TestErrors, unittes
             registry = FileRegistry()
             f = OmniJarFormatter(registry, 'omni.foo', non_resources=[
                 'defaults/messenger/mailViews.dat',
                 'defaults/foo/*',
                 '*/dummy',
             ])
             f.add_base('')
             f.add_base('app')
-            f.add(mozpath.join(base, path), GeneratedFile(b''))
+            f.add(mozpath.join(base, path), GeneratedFile(''))
             if f.copier.contains(mozpath.join(base, path)):
                 return False
             self.assertTrue(f.copier.contains(mozpath.join(base, 'omni.foo')))
             self.assertTrue(f.copier[mozpath.join(base, 'omni.foo')]
                             .contains(path))
             return True
 
         for base in ['', 'app/']:
--- a/python/mozbuild/mozpack/test/test_packager_l10n.py
+++ b/python/mozbuild/mozpack/test/test_packager_l10n.py
@@ -1,16 +1,15 @@
 # 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
+from __future__ import absolute_import, print_function
 
 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 (
@@ -19,26 +18,26 @@ from mozpack.chrome.manifest import (
     ManifestContent,
 )
 from mozpack.copier import FileRegistry
 from mozpack.packager.formats import FlatFormatter
 
 
 class TestL10NRepack(unittest.TestCase):
     def test_l10n_repack(self):
-        foo = GeneratedFile(b'foo')
-        foobar = GeneratedFile(b'foobar')
-        qux = GeneratedFile(b'qux')
-        bar = GeneratedFile(b'bar')
-        baz = GeneratedFile(b'baz')
-        dict_aa = GeneratedFile(b'dict_aa')
-        dict_bb = GeneratedFile(b'dict_bb')
-        dict_cc = GeneratedFile(b'dict_cc')
-        barbaz = GeneratedFile(b'barbaz')
-        lst = GeneratedFile(b'foo\nbar')
+        foo = GeneratedFile('foo')
+        foobar = GeneratedFile('foobar')
+        qux = GeneratedFile('qux')
+        bar = GeneratedFile('bar')
+        baz = GeneratedFile('baz')
+        dict_aa = GeneratedFile('dict_aa')
+        dict_bb = GeneratedFile('dict_bb')
+        dict_cc = GeneratedFile('dict_cc')
+        barbaz = GeneratedFile('barbaz')
+        lst = GeneratedFile('foo\nbar')
         app_finder = MockFinder({
             'bar/foo': foo,
             'chrome/foo/foobar': foobar,
             'chrome/qux/qux.properties': qux,
             'chrome/qux/baz/baz.properties': baz,
             'chrome/chrome.manifest': ManifestFile('chrome', [
                 ManifestContent('chrome', 'foo', 'foo/'),
                 ManifestLocale('chrome', 'qux', 'en-US', 'qux/'),
@@ -55,21 +54,21 @@ class TestL10NRepack(unittest.TestCase):
             'app/dict/bb': dict_bb,
             'app/dict/cc': dict_cc,
             'app/chrome/bar/search/foo.xml': foo,
             'app/chrome/bar/search/bar.xml': bar,
             'app/chrome/bar/search/lst.txt': lst,
         })
         app_finder.jarlogs = {}
         app_finder.base = 'app'
-        foo_l10n = GeneratedFile(b'foo_l10n')
-        qux_l10n = GeneratedFile(b'qux_l10n')
-        baz_l10n = GeneratedFile(b'baz_l10n')
-        barbaz_l10n = GeneratedFile(b'barbaz_l10n')
-        lst_l10n = GeneratedFile(b'foo\nqux')
+        foo_l10n = GeneratedFile('foo_l10n')
+        qux_l10n = GeneratedFile('qux_l10n')
+        baz_l10n = GeneratedFile('baz_l10n')
+        barbaz_l10n = GeneratedFile('barbaz_l10n')
+        lst_l10n = GeneratedFile('foo\nqux')
         l10n_finder = MockFinder({
             'chrome/qux-l10n/qux.properties': qux_l10n,
             'chrome/qux-l10n/baz/baz.properties': baz_l10n,
             'chrome/chrome.manifest': ManifestFile('chrome', [
                 ManifestLocale('chrome', 'qux', 'x-test', 'qux-l10n/'),
             ]),
             'chrome.manifest':
             ManifestFile('', [Manifest('', 'chrome/chrome.manifest')]),
@@ -116,14 +115,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 six.iteritems(repacked)),
+            dict((p, f.open().read()) for p, f in repacked.iteritems())
         )
 
 
 if __name__ == '__main__':
     mozunit.main()
--- a/python/mozbuild/mozpack/test/test_packager_unpack.py
+++ b/python/mozbuild/mozpack/test/test_packager_unpack.py
@@ -1,13 +1,13 @@
 # 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
+from __future__ import absolute_import, print_function
 
 import mozunit
 from mozpack.packager.formats import (
     FlatFormatter,
     JarFormatter,
     OmniJarFormatter,
 )
 from mozpack.packager.unpack import unpack_to_registry
--- a/python/mozbuild/mozpack/test/test_path.py
+++ b/python/mozbuild/mozpack/test/test_path.py
@@ -1,13 +1,13 @@
 # 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
+from __future__ import absolute_import, print_function
 
 from mozpack.path import (
     relpath,
     join,
     normpath,
     dirname,
     commonprefix,
     basename,