Bug 1547730 - don't use py2 builtin 'unicode' in mozpack and deps r=#build
☠☠ backed out by ee4b88439111 ☠ ☠
authorJustin Wood <Callek@gmail.com>
Tue, 16 Apr 2019 17:07:08 -0400
changeset 536074 b7b1062d0aad633e369d12613e8919b5e44d4c28
parent 536073 aa2acfd554fccc899c45ab29d5fb4f7062b00167
child 536075 16b1c53aba9d757d50fcd88b91f937266296dd26
push id2082
push userffxbld-merge
push dateMon, 01 Jul 2019 08:34:18 +0000
treeherdermozilla-release@2fb19d0466d2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1547730 - don't use py2 builtin 'unicode' in mozpack and deps r=#build Also adjust 'basestring' usage in some places. Differential Revision: https://phabricator.services.mozilla.com/D28102
--- a/python/mozbuild/mozbuild/backend/configenvironment.py
+++ b/python/mozbuild/mozbuild/backend/configenvironment.py
@@ -17,22 +17,16 @@ import mozpack.path as mozpath
 from mozbuild.util import (
 from mozbuild.shellutil import quote as shell_quote
-if sys.version_info.major == 2:
-    text_type = unicode
-    text_type = str
 class BuildConfig(object):
     """Represents the output of configure."""
     _CODE_CACHE = {}
     def __init__(self):
         self.topsrcdir = None
         self.topobjdir = None
@@ -192,27 +186,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, text_type):
+            if not isinstance(v, six.text_type):
                     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 isinstance(v, Iterable):
                     type(v)(decode(i) for i in v)
-            elif not isinstance(v, text_type):
+            elif not isinstance(v, six.text_type):
                 v = decode(v)
             self.substs_unicode[k] = v
         self.substs_unicode = ReadOnlyDict(self.substs_unicode)
     def is_artifact_build(self):
--- a/python/mozbuild/mozbuild/configure/__init__.py
+++ b/python/mozbuild/mozbuild/configure/__init__.py
@@ -282,17 +282,17 @@ class ConfigureSandbox(dict):
     # The default set of builtins. We expose unicode as str to make sandboxed
     # files more python3-ready.
     BUILTINS = ReadOnlyDict({
         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')
-    }, __import__=forbidden_import, str=unicode)
+    }, __import__=forbidden_import, str=six.text_type)
     # 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')
--- a/python/mozbuild/mozbuild/configure/util.py
+++ b/python/mozbuild/mozbuild/configure/util.py
@@ -4,16 +4,17 @@
 from __future__ import absolute_import, print_function, unicode_literals
 import codecs
 import itertools
 import locale
 import logging
 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
@@ -49,17 +50,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, unicode):
+        if isinstance(other, six.text_type):
             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.
--- a/python/mozbuild/mozbuild/preprocessor.py
+++ b/python/mozbuild/mozbuild/preprocessor.py
@@ -22,16 +22,17 @@ 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
@@ -786,17 +787,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 = type(args) == str or type(args) == unicode
+        isName = isinstance(args, six.string_types)
         oldCheckLineNumbers = self.checkLineNumbers
         self.checkLineNumbers = False
         if isName:
                 args = str(args)
                 if filters:
                     args = self.applyFilters(args)
                 if not os.path.isabs(args):
--- a/python/mozbuild/mozbuild/util.py
+++ b/python/mozbuild/mozbuild/util.py
@@ -28,21 +28,16 @@ from collections import (
 from io import (
-if sys.version_info[0] == 3:
-    str_type = str
-    str_type = basestring
 if sys.platform == 'win32':
     _kernel32 = ctypes.windll.kernel32
 def exec_(object, globals=None, locals=None):
     """Wrapper around the exec statement to avoid bogus errors like:
@@ -73,17 +68,17 @@ def hash_file(path, hasher=None):
             if not len(data):
     return h.hexdigest()
-class EmptyValue(unicode):
+class EmptyValue(six.text_type):
     """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):
@@ -170,17 +165,17 @@ def mkdir(path, not_indexed=False):
     except OSError as e:
         if e.errno != errno.EEXIST:
     if not_indexed:
         if sys.platform == 'win32':
-            if isinstance(path, str_type):
+            if isinstance(path, six.string_types):
                 fn = _kernel32.SetFileAttributesW
                 fn = _kernel32.SetFileAttributesA
         elif sys.platform == 'darwin':
             with open(os.path.join(path, '.metadata_never_index'), 'a'):
@@ -224,17 +219,17 @@ class FileAvoidWrite(BytesIO):
         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, unicode):
+        if isinstance(buf, six.text_type):
             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.
@@ -816,17 +811,17 @@ class HierarchicalStringList(object):
         exports = self._get_exportvariable(name)
         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, str_type):
+            if not isinstance(v, six.string_types):
                 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
@@ -1187,17 +1182,17 @@ class DefinesAction(argparse.Action):
         defines[name] = value
         setattr(namespace, self.dest, defines)
 class EnumStringComparisonError(Exception):
-class EnumString(unicode):
+class EnumString(six.text_type):
     '''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
@@ -1224,17 +1219,17 @@ class EnumString(unicode):
         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 unicode(c.encode('unicode_escape'))
+    return six.text_type(c.encode('unicode_escape'))
 # Mapping table between raw characters below \x80 and their escaped
 # counterpart, when they differ
     c: e
     for c, e in map(lambda x: (x, _escape_char(x)),
                     map(unichr, range(128)))
@@ -1264,17 +1259,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, unicode):
+        elif isinstance(o, six.text_type):
             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]
@@ -1298,17 +1293,17 @@ 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)
     if isinstance(obj, bytes):
         return obj
-    if isinstance(obj, unicode):
+    if isinstance(obj, six.text_type):
         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
@@ -1392,17 +1387,17 @@ def patch_main():
             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, basestring):
+    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/files.py
+++ b/python/mozbuild/mozpack/files.py
@@ -63,17 +63,17 @@ if platform.system() != 'Windows':
     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, unicode) and isinstance(dest, unicode):
+        if isinstance(src, six.text_type) and isinstance(dest, six.text_type):
             _CopyFileW(src, dest, False)
         elif isinstance(src, str) and isinstance(dest, str):
             _CopyFileA(src, dest, False)
             raise TypeError('mismatched path types!')
 class Dest(object):
--- a/python/mozbuild/mozpack/hg.py
+++ b/python/mozbuild/mozpack/hg.py
@@ -27,16 +27,17 @@
 # do not wish to do so, delete this exception statement from your
 # version.
 from __future__ import absolute_import, print_function, unicode_literals
 import mercurial.error as error
 import mercurial.hg as hg
 import mercurial.ui as hgui
+import six
 from .files import (
 import mozpack.path as mozpath
@@ -51,17 +52,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, (str, unicode)):
+        if isinstance(repo, six.string_types):
             path = repo
             repo = hg.repository(hgui.ui(), repo)
             path = repo.root
         super(MercurialNativeRevisionFinder, self).__init__(base=repo.root)
         self._repo = repo
@@ -80,16 +81,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, unicode):
+        if isinstance(path, six.text_type):
             path = path.encode('utf-8', 'replace')
             fctx = self._repo.filectx(path, self._rev)
             return MercurialNativeFile(fctx.data())
         except error.LookupError:
             return None