Convert libchrome scripts to python 3 am: 22b8126fb5 am: 2f8caa9aa8 am: ac5ab8de4e am: 182e9f2b7a

Original change: https://android-review.googlesource.com/c/platform/external/libchrome/+/2210336

Change-Id: I36966bc09ee84d43346f82284b6e2420f4a76cc3
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index 7d03560..a97429f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1169,19 +1169,6 @@
     ],
 }
 
-// Python in Chrome repository requires still Python 2.
-python_defaults {
-    name: "libmojo_scripts",
-    version: {
-        py2: {
-            enabled: true,
-        },
-        py3: {
-            enabled: false,
-        },
-    },
-}
-
 python_binary_host {
     name: "jni_generator",
     main: "base/android/jni_generator/jni_generator.py",
@@ -1189,7 +1176,6 @@
         "base/android/jni_generator/jni_generator.py",
         "build/**/*.py",
     ],
-    defaults: ["libmojo_scripts"],
 }
 
 python_binary_host {
@@ -1200,7 +1186,6 @@
         "base/android/jni_generator/jni_registration_generator.py",
         "build/**/*.py",
     ],
-    defaults: ["libmojo_scripts"],
 }
 
 python_binary_host {
@@ -1218,7 +1203,6 @@
         "mojo/public/tools/bindings/generators/java_templates/*.tmpl",
         "mojo/public/tools/bindings/generators/js_templates/*.tmpl",
     ],
-    defaults: ["libmojo_scripts"],
 }
 
 genrule {
@@ -1250,7 +1234,6 @@
         "mojo/public/tools/bindings/pylib/mojom/generate/module.py",
         "mojo/public/tools/bindings/pylib/mojom/generate/pack.py",
     ],
-    defaults: ["libmojo_scripts"],
 }
 
 genrule {
@@ -1290,7 +1273,6 @@
     srcs: [
         "mojo/public/tools/bindings/mojom_types_downgrader.py",
     ],
-    defaults: ["libmojo_scripts"],
 }
 
 generate_mojom_downgraded_files {
diff --git a/base/android/jni_generator/jni_generator.py b/base/android/jni_generator/jni_generator.py
index ef676e2..b5bbe1b 100755
--- a/base/android/jni_generator/jni_generator.py
+++ b/base/android/jni_generator/jni_generator.py
@@ -17,14 +17,7 @@
 import textwrap
 import zipfile
 
-CHROMIUM_SRC = os.path.join(
-    os.path.dirname(__file__), os.pardir, os.pardir, os.pardir)
-BUILD_ANDROID_GYP = os.path.join(
-    CHROMIUM_SRC, 'build', 'android', 'gyp')
-
-sys.path.append(BUILD_ANDROID_GYP)
-
-from util import build_utils
+from build.android.gyp.util import build_utils
 
 
 # Match single line comments, multiline comments, character literals, and
@@ -53,7 +46,7 @@
                          replace_whitespace=False,
                          subsequent_indent=' ' * (indent + 4),
                          break_long_words=False)
-    for indent in xrange(50)]  # 50 chosen experimentally.
+    for indent in range(50)]  # 50 chosen experimentally.
 
 
 class ParseError(Exception):
@@ -799,7 +792,7 @@
 
   @staticmethod
   def CreateFromFile(java_file_name, options):
-    contents = file(java_file_name).read()
+    contents = open(java_file_name).read()
     fully_qualified_class = ExtractFullyQualifiedJavaClassName(java_file_name,
                                                                contents)
     return JNIFromJavaSource(contents, fully_qualified_class, options)
@@ -856,7 +849,7 @@
 "${JNI_CLASS_PATH}";
 """)
 
-    for full_clazz in classes.itervalues():
+    for full_clazz in classes.values():
       values = {
           'JAVA_CLASS': GetBinaryClassName(full_clazz),
           'JNI_CLASS_PATH': full_clazz,
@@ -882,7 +875,7 @@
 JNI_REGISTRATION_EXPORT base::subtle::AtomicWord g_${JAVA_CLASS}_clazz = 0;
 """ + class_getter)
 
-    for full_clazz in classes.itervalues():
+    for full_clazz in classes.values():
       values = {
           'JAVA_CLASS': GetBinaryClassName(full_clazz),
       }
@@ -1311,13 +1304,13 @@
       jni_from_java_source = JNIFromJavaSource.CreateFromFile(
           input_file, options)
       content = jni_from_java_source.GetContent()
-  except ParseError, e:
-    print e
+  except ParseError as e:
+    print(e)
     sys.exit(1)
   if output_file:
     WriteOutput(output_file, content)
   else:
-    print content
+    print(content)
 
 
 def WriteOutput(output_file, content):
@@ -1393,7 +1386,7 @@
     input_file = options.input_file
   else:
     option_parser.print_help()
-    print '\nError: Must specify --jar_file or --input_file.'
+    print('\nError: Must specify --jar_file or --input_file.')
     return 1
   output_file = None
   if options.output_dir:
diff --git a/base/android/jni_generator/jni_generator_tests.py b/base/android/jni_generator/jni_generator_tests.py
index 12812a5..4e856be 100755
--- a/base/android/jni_generator/jni_generator_tests.py
+++ b/base/android/jni_generator/jni_generator_tests.py
@@ -53,7 +53,7 @@
     dict_first = first.__dict__
     dict_second = second.__dict__
     self.assertEquals(dict_first.keys(), dict_second.keys())
-    for key, value in dict_first.iteritems():
+    for key, value in dict_first.items():
       if (type(value) is list and len(value) and
           isinstance(type(value[0]), object)):
         self.assertListEquals(value, second.__getattribute__(key))
@@ -64,7 +64,7 @@
 
   def assertListEquals(self, first, second):
     self.assertEquals(len(first), len(second))
-    for i in xrange(len(first)):
+    for i in range(len(first)):
       if isinstance(first[i], object):
         self.assertObjEquals(first[i], second[i])
       else:
diff --git a/base/android/jni_generator/jni_registration_generator.py b/base/android/jni_generator/jni_registration_generator.py
index 8c545f6..f9c3fcd 100755
--- a/base/android/jni_generator/jni_registration_generator.py
+++ b/base/android/jni_generator/jni_registration_generator.py
@@ -10,11 +10,12 @@
 to register all native methods that exist within an application."""
 
 import argparse
-import jni_generator
 import multiprocessing
 import string
 import sys
-from util import build_utils
+
+import jni_generator
+from build.android.gyp.util import build_utils
 
 
 # All but FULL_CLASS_NAME, which is used only for sorting.
@@ -58,7 +59,7 @@
   if output_file:
     jni_generator.WriteOutput(output_file, header_content)
   else:
-    print header_content
+    print(header_content)
 
 
 def _DictForPath(path):
@@ -244,7 +245,7 @@
     ret = []
     all_classes = self.helper.GetUniqueClasses(self.natives)
     all_classes[self.class_name] = self.fully_qualified_class
-    for clazz, full_clazz in all_classes.iteritems():
+    for clazz, full_clazz in all_classes.items():
       kmethods = self._GetKMethodsString(clazz)
       namespace_str = ''
       if self.namespace:
@@ -321,7 +322,7 @@
   args.sources_files = build_utils.ParseGnList(args.sources_files)
 
   if not args.sources_files:
-    print '\nError: Must specify --sources_files.'
+    print('\nError: Must specify --sources_files.')
     return 1
 
   java_file_paths = []
diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py
index 426de03..f41a43a 100644
--- a/build/android/gyp/util/build_utils.py
+++ b/build/android/gyp/util/build_utils.py
@@ -23,19 +23,8 @@
 #     //build/config/android/internal_rules.gni
 
 # Some clients do not add //build/android/gyp to PYTHONPATH.
-import md5_check  # pylint: disable=relative-import
-
-# pylib conflicts with mojo/public/tools/bindings/pylib. Prioritize
-# build/android/pylib.
-# PYTHONPATH wouldn't help in this case, because soong put source files under
-# temp directory for each build, so the abspath is unknown until the
-# execution.
-#sys.path.append(os.path.join(os.path.dirname(__file__),
-#                             os.pardir, os.pardir, os.pardir))
-sys.path.insert(0, os.path.join(os.path.dirname(__file__),
-                                os.pardir, os.pardir))
-
-import gn_helpers
+import build.android.gyp.util.md5_check as md5_check # pylint: disable=relative-import
+import build.gn_helpers as gn_helpers
 
 # Definition copied from pylib/constants/__init__.py to avoid adding
 # a dependency on pylib.
@@ -44,7 +33,7 @@
                                  os.pardir, os.pardir, os.pardir, os.pardir)))
 
 HERMETIC_TIMESTAMP = (2001, 1, 1, 0, 0, 0)
-_HERMETIC_FILE_ATTR = (0644 << 16L)
+_HERMETIC_FILE_ATTR = (0o644 << 16)
 
 
 @contextlib.contextmanager
@@ -246,7 +235,7 @@
 
   # The two high-order bytes of ZipInfo.external_attr represent
   # UNIX permissions and file type bits.
-  return stat.S_ISLNK(zi.external_attr >> 16L)
+  return stat.S_ISLNK(zi.external_attr >> 16)
 
 
 def ExtractAll(zip_path, path=None, no_clobber=True, pattern=None,
@@ -309,12 +298,12 @@
 
   if src_path and os.path.islink(src_path):
     zipinfo.filename = zip_path
-    zipinfo.external_attr |= stat.S_IFLNK << 16L # mark as a symlink
+    zipinfo.external_attr |= stat.S_IFLNK << 16 # mark as a symlink
     zip_file.writestr(zipinfo, os.readlink(src_path))
     return
 
   if src_path:
-    with file(src_path) as f:
+    with open(src_path) as f:
       data = f.read()
 
   # zipfile will deflate even when it makes the file bigger. To avoid
@@ -342,7 +331,7 @@
   """
   input_tuples = []
   for tup in inputs:
-    if isinstance(tup, basestring):
+    if isinstance(tup, str):
       tup = (os.path.relpath(tup, base_dir), tup)
     input_tuples.append(tup)
 
@@ -382,7 +371,7 @@
   path_transform = path_transform or (lambda p: p)
   added_names = set()
 
-  output_is_already_open = not isinstance(output, basestring)
+  output_is_already_open = not isinstance(output, str)
   if output_is_already_open:
     assert isinstance(output, zipfile.ZipFile)
     out_zip = output
@@ -445,7 +434,7 @@
   src/. The paths will be relative to the current directory.
   """
   _ForceLazyModulesToLoad()
-  module_paths = (m.__file__ for m in sys.modules.itervalues()
+  module_paths = (m.__file__ for m in sys.modules.values()
                   if m is not None and hasattr(m, '__file__'))
   abs_module_paths = map(os.path.abspath, module_paths)
 
diff --git a/build/android/gyp/util/jar_info_utils.py b/build/android/gyp/util/jar_info_utils.py
index 987ee9d..546ce5d 100644
--- a/build/android/gyp/util/jar_info_utils.py
+++ b/build/android/gyp/util/jar_info_utils.py
@@ -44,7 +44,7 @@
       temporary location.
   """
   with open(info_path, 'w') as info_file:
-    for fully_qualified_name, path in info_data.iteritems():
+    for fully_qualified_name, path in info_data.items():
       if source_file_map and path in source_file_map:
         path = source_file_map[path]
         assert not path.startswith('/tmp'), (
diff --git a/build/android/gyp/util/md5_check.py b/build/android/gyp/util/md5_check.py
index 7659124..9ead335 100644
--- a/build/android/gyp/util/md5_check.py
+++ b/build/android/gyp/util/md5_check.py
@@ -78,10 +78,10 @@
     return
 
   if PRINT_EXPLANATIONS:
-    print '=' * 80
-    print 'Target is stale: %s' % record_path
-    print changes.DescribeDifference()
-    print '=' * 80
+    print('=' * 80)
+    print('Target is stale: %s' % record_path)
+    print(changes.DescribeDifference())
+    print('=' * 80)
 
   args = (changes,) if pass_changes else ()
   function(*args)
diff --git a/build/android/gyp/util/resource_utils.py b/build/android/gyp/util/resource_utils.py
index 875fd12..9e756ab 100644
--- a/build/android/gyp/util/resource_utils.py
+++ b/build/android/gyp/util/resource_utils.py
@@ -59,7 +59,7 @@
   """
   info_file_path = zip_path + '.info'
   with open(info_file_path, 'w') as info_file:
-    for archive_path, source_path in files_to_zip.iteritems():
+    for archive_path, source_path in files_to_zip.items():
       info_file.write('{},{}\n'.format(archive_path, source_path))
 
 
@@ -260,7 +260,7 @@
       if entry:
         resources_by_type[entry.resource_type].append(entry)
 
-  for package, resources_by_type in resources_by_package.iteritems():
+  for package, resources_by_type in resources_by_package.items():
     _CreateRJavaSourceFile(srcjar_dir, package, resources_by_type,
                            rjava_build_options)
 
@@ -296,7 +296,7 @@
   """Render an R.java source file. See _CreateRJaveSourceFile for args info."""
   final_resources_by_type = collections.defaultdict(list)
   non_final_resources_by_type = collections.defaultdict(list)
-  for res_type, resources in resources_by_type.iteritems():
+  for res_type, resources in resources_by_type.items():
     for entry in resources:
       # Entries in stylable that are not int[] are not actually resource ids
       # but constants.
diff --git a/build/android/pylib/constants/host_paths_unittest.py b/build/android/pylib/constants/host_paths_unittest.py
index 658ed08..a84ac0a 100755
--- a/build/android/pylib/constants/host_paths_unittest.py
+++ b/build/android/pylib/constants/host_paths_unittest.py
@@ -40,7 +40,7 @@
     self.assertEqual(host_paths.GetAaptPath(), _EXPECTED_AAPT_PATH)
 
   def test_ToolPath(self):
-    for cpu_arch, binprefix in _EXPECTED_NDK_TOOL_SUBDIR_MAP.iteritems():
+    for cpu_arch, binprefix in _EXPECTED_NDK_TOOL_SUBDIR_MAP.items():
       expected_binprefix = os.path.join(constants.ANDROID_NDK_ROOT, binprefix)
       expected_path = expected_binprefix + 'foo'
       self.assertEqual(host_paths.ToolPath('foo', cpu_arch), expected_path)
diff --git a/build/android/pylib/content_settings.py b/build/android/pylib/content_settings.py
index 3bf11bc..3ad4c17 100644
--- a/build/android/pylib/content_settings.py
+++ b/build/android/pylib/content_settings.py
@@ -29,7 +29,7 @@
       return 's'
     raise ValueError('Unsupported type %s' % type(value))
 
-  def iteritems(self):
+  def items(self):
     # Example row:
     # 'Row: 0 _id=13, name=logging_id2, value=-1fccbaa546705b05'
     for row in self._device.RunShellCommand(
diff --git a/build/android/pylib/device_settings.py b/build/android/pylib/device_settings.py
index ab4ad1b..a9830af 100644
--- a/build/android/pylib/device_settings.py
+++ b/build/android/pylib/device_settings.py
@@ -33,7 +33,7 @@
     for key, value in key_value:
       settings[key] = value
     logging.info('\n%s %s', table, (80 - len(table)) * '-')
-    for key, value in sorted(settings.iteritems()):
+    for key, value in sorted(settings.items()):
       logging.info('\t%s: %s', key, value)
 
 
diff --git a/build/check_gn_headers.py b/build/check_gn_headers.py
index f6ae8f5..42ea80f 100755
--- a/build/check_gn_headers.py
+++ b/build/check_gn_headers.py
@@ -110,7 +110,7 @@
   """Parse GN output and get the header files"""
   all_headers = set()
 
-  for _target, properties in gn['targets'].iteritems():
+  for _target, properties in gn['targets'].items():
     sources = properties.get('sources', [])
     public = properties.get('public', [])
     # Exclude '"public": "*"'.
@@ -292,7 +292,7 @@
         print '  ', cc
 
     print '\nMissing headers sorted by number of affected object files:'
-    count = {k: len(v) for (k, v) in d.iteritems()}
+    count = {k: len(v) for (k, v) in d.items()}
     for f in sorted(count, key=count.get, reverse=True):
       if f in missing:
         print count[f], f
diff --git a/build/get_syzygy_binaries.py b/build/get_syzygy_binaries.py
index 09b1199..bad18e2 100755
--- a/build/get_syzygy_binaries.py
+++ b/build/get_syzygy_binaries.py
@@ -97,7 +97,7 @@
   if not isinstance(c, dict):
     _LOGGER.debug('State must contain a contents dict.')
     return False
-  for (relpath, md5) in c.iteritems():
+  for (relpath, md5) in c.items():
     if not isinstance(relpath, basestring) or len(relpath) == 0:
       _LOGGER.debug('State contents dict contains an invalid path.')
       return False
@@ -115,7 +115,7 @@
   """
   contents = {}
   state = { 'revision': revision, 'contents': contents }
-  for relpath, md5 in stored['contents'].iteritems():
+  for relpath, md5 in stored['contents'].items():
     abspath = os.path.abspath(os.path.join(output_dir, relpath))
     if os.path.isfile(abspath):
       m = _Md5(abspath)
@@ -133,7 +133,7 @@
     return False
   cont_stored = stored['contents']
   cont_actual = actual['contents']
-  for relpath, md5 in cont_stored.iteritems():
+  for relpath, md5 in cont_stored.items():
     if relpath not in cont_actual:
       _LOGGER.debug('Missing content: %s', relpath)
       return False
diff --git a/mojo/public/tools/bindings/generate_type_mappings.py b/mojo/public/tools/bindings/generate_type_mappings.py
index ee55e99..d6796af 100755
--- a/mojo/public/tools/bindings/generate_type_mappings.py
+++ b/mojo/public/tools/bindings/generate_type_mappings.py
@@ -149,7 +149,7 @@
   for path in params.dependency:
     typemaps.update(ReadTypemap(path))
 
-  WriteFile(json.dumps({'c++': typemaps}, indent=2), params.output)
+  WriteFile(json.dumps({'c++': typemaps}, indent=2).encode(), params.output)
 
 
 if __name__ == '__main__':
diff --git a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
index ceded69..97bc827 100644
--- a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
@@ -266,7 +266,7 @@
                 for typename in
                 self.module.structs + all_enums + self.module.unions)
     headers = set()
-    for typename, typemap in self.typemap.iteritems():
+    for typename, typemap in self.typemap.items():
       if typename in types:
         headers.update(typemap.get("public_headers", []))
     return sorted(headers)
@@ -788,7 +788,7 @@
       if param_counts[-1] != version.num_fields:
         param_counts.append(version.num_fields)
 
-    ordinal_fields = sorted(struct.fields, key=lambda field: field.ordinal)
+    ordinal_fields = sorted(struct.fields, key=lambda field: field.ordinal if field.ordinal != None else -1)
     return (StructConstructor(struct.fields, ordinal_fields[:param_count])
             for param_count in param_counts)
 
diff --git a/mojo/public/tools/bindings/generators/mojom_java_generator.py b/mojo/public/tools/bindings/generators/mojom_java_generator.py
index 0f2b618..4e32c52 100644
--- a/mojo/public/tools/bindings/generators/mojom_java_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_java_generator.py
@@ -153,7 +153,7 @@
   return UpperCamelCase(method.name + 'Response')
 
 def ParseStringAttribute(attribute):
-  assert isinstance(attribute, basestring)
+  assert isinstance(attribute, str)
   return attribute
 
 def GetJavaTrueFalse(value):
@@ -333,7 +333,7 @@
   if kind_spec.startswith('i') or kind_spec.startswith('u'):
     # Add Long suffix to all integer literals.
     number = ast.literal_eval(token.lstrip('+ '))
-    if not isinstance(number, (int, long)):
+    if not isinstance(number, int):
       raise ValueError('got unexpected type %r for int literal %r' % (
           type(number), token))
     # If the literal is too large to fit a signed long, convert it to the
diff --git a/mojo/public/tools/bindings/mojom_bindings_generator.py b/mojo/public/tools/bindings/mojom_bindings_generator.py
index 57a8031..8c8cb43 100755
--- a/mojo/public/tools/bindings/mojom_bindings_generator.py
+++ b/mojo/public/tools/bindings/mojom_bindings_generator.py
@@ -7,7 +7,7 @@
 
 
 import argparse
-import cPickle
+import pickle
 import hashlib
 import importlib
 import json
@@ -62,7 +62,7 @@
   for generator_name in [s.strip() for s in generators_string.split(",")]:
     language = generator_name.lower()
     if language not in _BUILTIN_GENERATORS:
-      print "Unknown generator name %s" % generator_name
+      print("Unknown generator name %s" % generator_name)
       sys.exit(1)
     generator_module = importlib.import_module(
         "generators.%s" % _BUILTIN_GENERATORS[language])
@@ -158,7 +158,7 @@
     for filename in typemaps:
       with open(filename) as f:
         typemaps = json.loads("".join(filter(no_comments, f.readlines())))
-        for language, typemap in typemaps.iteritems():
+        for language, typemap in typemaps.items():
           language_map = self._typemap.get(language, {})
           language_map.update(typemap)
           self._typemap[language] = language_map
@@ -170,12 +170,13 @@
       return self._processed_files[rel_filename.path]
 
     if rel_filename.path in imported_filename_stack:
-      print "%s: Error: Circular dependency" % rel_filename.path + \
-          MakeImportStackMessage(imported_filename_stack + [rel_filename.path])
+      print("%s: Error: Circular dependency" % rel_filename.path +
+          MakeImportStackMessage(imported_filename_stack + [rel_filename.path]))
       sys.exit(1)
 
     tree = _UnpickleAST(_FindPicklePath(rel_filename, args.gen_directories +
                                         [args.output_dir]))
+
     dirname = os.path.dirname(rel_filename.path)
 
     # Process all our imports first and collect the module object for each.
@@ -202,7 +203,7 @@
 
     if self._should_generate(rel_filename.path):
       AddComputedData(module)
-      for language, generator_module in generator_modules.iteritems():
+      for language, generator_module in generator_modules.items():
         generator = generator_module.Generator(
             module, args.output_dir, typemap=self._typemap.get(language, {}),
             variant=args.variant, bytecode_path=args.bytecode_path,
@@ -278,17 +279,17 @@
   fileutil.EnsureDirectoryExists(full_dir)
 
   try:
-    WriteFile(cPickle.dumps(ast), output_file)
-  except (IOError, cPickle.PicklingError) as e:
-    print "%s: Error: %s" % (output_file, str(e))
+    WriteFile(pickle.dumps(ast, protocol=0), output_file)
+  except (IOError, pickle.PicklingError) as e:
+    print("%s: Error: %s" % (output_file, str(e)))
     sys.exit(1)
 
 def _UnpickleAST(input_file):
     try:
       with open(input_file, "rb") as f:
-        return cPickle.load(f)
-    except (IOError, cPickle.UnpicklingError) as e:
-      print "%s: Error: %s" % (input_file, str(e))
+        return pickle.load(f)
+    except (IOError, pickle.UnpicklingError) as e:
+      print("%s: Error: %s" % (input_file, str(e)))
       sys.exit(1)
 
 def _ParseFile(args, rel_filename):
@@ -296,14 +297,14 @@
     with open(rel_filename.path) as f:
       source = f.read()
   except IOError as e:
-    print "%s: Error: %s" % (rel_filename.path, e.strerror)
+    print("%s: Error: %s" % (rel_filename.path, e.strerror))
     sys.exit(1)
 
   try:
     tree = Parse(source, rel_filename.path)
     RemoveDisabledDefinitions(tree, args.enabled_features)
   except Error as e:
-    print "%s: Error: %s" % (rel_filename.path, str(e))
+    print("%s: Error: %s" % (rel_filename.path, str(e)))
     sys.exit(1)
   _PickleAST(tree, _GetPicklePath(rel_filename, args.output_dir))
 
@@ -355,9 +356,9 @@
         deps_sources.add(full_source_path.rstrip('\n'))
 
     if (not deps_sources.issuperset(mojom_imports)):
-      print ">>> [%s] Missing dependencies for the following imports: %s" % ( \
-        args.filename[0], \
-        list(mojom_imports.difference(deps_sources)))
+      print(">>> [%s] Missing dependencies for the following imports: %s" % (
+        args.filename[0],
+        list(mojom_imports.difference(deps_sources))))
       sys.exit(1)
 
     source_filename, _ = os.path.splitext(rel_path.relative_path())
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/generator.py b/mojo/public/tools/bindings/pylib/mojom/generate/generator.py
index acf029f..8202df4 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/generator.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/generator.py
@@ -8,9 +8,9 @@
 import os.path
 import re
 
-import module as mojom
+import mojom.generate.module as mojom
 import mojom.fileutil as fileutil
-import pack
+import mojom.generate.pack as pack
 
 
 def ExpectedArraySize(kind):
@@ -185,10 +185,10 @@
 
   def Write(self, contents, filename):
     if self.output_dir is None:
-      print contents
+      print(contents)
       return
     full_path = os.path.join(self.output_dir, filename)
-    WriteFile(contents, full_path)
+    WriteFile(contents.encode(), full_path)
 
   def GenerateFiles(self, args):
     raise NotImplementedError("Subclasses must override/implement this method")
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/module.py b/mojo/public/tools/bindings/pylib/mojom/generate/module.py
index db45e33..aeeb4fc 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/module.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/module.py
@@ -49,7 +49,7 @@
       return ('{\n%s\n}' % (',\n'.join('    %s: %s' % (
           Repr(key, as_ref).replace('\n', '\n    '),
           Repr(val, as_ref).replace('\n', '\n    '))
-          for key, val in obj.iteritems())))
+          for key, val in obj.items())))
   else:
     return repr(obj)
 
@@ -73,7 +73,7 @@
   return '%s(\n%s\n)' % (
       obj.__class__.__name__,
       ',\n'.join(ReprIndent(name, as_ref)
-                 for (name, as_ref) in names.iteritems()))
+                 for (name, as_ref) in names.items()))
 
 
 class Kind(object):
@@ -156,7 +156,10 @@
          print b.name  # Outputs 'test_struct_2'.
     """
     def Get(self):
-      return self.shared_definition[name]
+      try:
+        return self.shared_definition[name]
+      except KeyError:
+        raise AttributeError()
 
     def Set(self, value):
       self.shared_definition[name] = value
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/module_tests.py b/mojo/public/tools/bindings/pylib/mojom/generate/module_tests.py
index a887686..9c25bda 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/module_tests.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/module_tests.py
@@ -4,7 +4,7 @@
 
 import sys
 
-import test_support
+import mojom.generate.test_support as test_support
 
 EXPECT_EQ = test_support.EXPECT_EQ
 EXPECT_TRUE = test_support.EXPECT_TRUE
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/pack.py b/mojo/public/tools/bindings/pylib/mojom/generate/pack.py
index e4204a0..f8a396e 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/pack.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/pack.py
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import module as mojom
+import mojom.generate.module as mojom
 
 # This module provides a mechanism for determining the packed order and offsets
 # of a mojom.Struct.
@@ -164,7 +164,7 @@
     # Then find first slot that each field will fit.
     for src_field in src_fields[1:]:
       last_field = dst_fields[0]
-      for i in xrange(1, len(dst_fields)):
+      for i in range(1, len(dst_fields)):
         next_field = dst_fields[i]
         offset, bit = GetFieldOffset(src_field, last_field)
         if offset + src_field.size <= next_field.offset:
@@ -189,16 +189,16 @@
 def GetByteLayout(packed_struct):
   total_payload_size = GetPayloadSizeUpToField(
       packed_struct.packed_fields[-1] if packed_struct.packed_fields else None)
-  bytes = [ByteInfo() for i in xrange(total_payload_size)]
+  bytes = [ByteInfo() for i in range(total_payload_size)]
 
   limit_of_previous_field = 0
   for packed_field in packed_struct.packed_fields:
-    for i in xrange(limit_of_previous_field, packed_field.offset):
+    for i in range(limit_of_previous_field, packed_field.offset):
       bytes[i].is_padding = True
     bytes[packed_field.offset].packed_fields.append(packed_field)
     limit_of_previous_field = packed_field.offset + packed_field.size
 
-  for i in xrange(limit_of_previous_field, len(bytes)):
+  for i in range(limit_of_previous_field, len(bytes)):
     bytes[i].is_padding = True
 
   for byte in bytes:
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/pack_tests.py b/mojo/public/tools/bindings/pylib/mojom/generate/pack_tests.py
index 14f699d..b991c42 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/pack_tests.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/pack_tests.py
@@ -4,9 +4,9 @@
 
 import sys
 
-import module as mojom
-import pack
-import test_support
+import mojom.generate.module as mojom
+import mojom.generate.pack as pack
+import mojom.generate.test_support as test_support
 
 
 EXPECT_EQ = test_support.EXPECT_EQ
@@ -59,7 +59,7 @@
   ps = pack.PackedStruct(struct)
   num_fields = len(ps.packed_fields)
   errors += EXPECT_EQ(len(kinds), num_fields)
-  for i in xrange(num_fields):
+  for i in range(num_fields):
     EXPECT_EQ("%d" % fields[i], ps.packed_fields[i].field.name)
     EXPECT_EQ(offsets[i], ps.packed_fields[i].offset)
 
@@ -156,7 +156,7 @@
   errors += EXPECT_EQ(10, len(ps.packed_fields))
 
   # First 8 bits packed together.
-  for i in xrange(8):
+  for i in range(8):
     pf = ps.packed_fields[i]
     errors += EXPECT_EQ(0, pf.offset)
     errors += EXPECT_EQ("bit%d" % i, pf.field.name)
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py b/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py
index 653a2df..948ba3d 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py
@@ -35,7 +35,7 @@
     def GeneratorInternal(*args, **kwargs2):
       parameters = generator(*args, **kwargs2)
       return ApplyTemplate(args[0], path_to_template, parameters, **kwargs)
-    GeneratorInternal.func_name = generator.func_name
+    GeneratorInternal.__name__ = generator.__name__
     return GeneratorInternal
   return RealDecorator
 
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/test_support.py b/mojo/public/tools/bindings/pylib/mojom/generate/test_support.py
index eb39461..fb7c892 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/test_support.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/test_support.py
@@ -5,7 +5,7 @@
 import sys
 import traceback
 
-import module as mojom
+import mojom.generate.module as mojom
 
 # Support for writing mojom test cases.
 # RunTest(fn) will execute fn, catching any exceptions. fn should return
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/translate.py b/mojo/public/tools/bindings/pylib/mojom/generate/translate.py
index 94fe2a6..a30fd1c 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/translate.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/translate.py
@@ -13,7 +13,7 @@
 import os
 import re
 
-import module as mojom
+import mojom.generate.module as mojom
 from mojom.parse import ast
 
 def _DuplicateName(values):
@@ -122,7 +122,7 @@
   to the location where the type is referenced."""
   if spec.startswith('x:'):
     mojom_name = spec[2:]
-    for i in xrange(len(scope), -1, -1):
+    for i in range(len(scope), -1, -1):
       test_spec = 'x:'
       if i > 0:
         test_spec += '.'.join(scope[:i]) + '.'
@@ -141,7 +141,7 @@
   # enum name.
   if isinstance(kind, mojom.Enum) and '.' not in mojom_name:
     mojom_name = '%s.%s' % (kind.spec.split(':', 1)[1], mojom_name)
-  for i in reversed(xrange(len(scope) + 1)):
+  for i in reversed(range(len(scope) + 1)):
     test_spec = '.'.join(scope[:i])
     if test_spec:
       test_spec += '.'
@@ -225,12 +225,12 @@
 def _Import(module, import_module):
   # Copy the struct kinds from our imports into the current module.
   importable_kinds = (mojom.Struct, mojom.Union, mojom.Enum, mojom.Interface)
-  for kind in import_module.kinds.itervalues():
+  for kind in import_module.kinds.values():
     if (isinstance(kind, importable_kinds) and
         kind.module.path == import_module.path):
       module.kinds[kind.spec] = kind
   # Ditto for values.
-  for value in import_module.values.itervalues():
+  for value in import_module.values.values():
     if value.module.path == import_module.path:
       module.values[value.GetSpec()] = value
 
@@ -255,12 +255,14 @@
     struct.constants = []
     struct.fields_data = []
   else:
-    struct.enums = map(
-        lambda enum: _Enum(module, enum, struct),
-        _ElemsOfType(parsed_struct.body, ast.Enum, parsed_struct.mojom_name))
-    struct.constants = map(
-        lambda constant: _Constant(module, constant, struct),
-        _ElemsOfType(parsed_struct.body, ast.Const, parsed_struct.mojom_name))
+    struct.enums = [
+        _Enum(module, enum, struct) for enum in
+        _ElemsOfType(parsed_struct.body, ast.Enum, parsed_struct.mojom_name)
+    ]
+    struct.constants = [
+        _Constant(module, constant, struct) for constant in
+        _ElemsOfType(parsed_struct.body, ast.Const, parsed_struct.mojom_name)
+    ]
     # Stash fields parsed_struct here temporarily.
     struct.fields_data = _ElemsOfType(
         parsed_struct.body, ast.StructField, parsed_struct.mojom_name)
@@ -374,13 +376,15 @@
   method = mojom.Method(
       interface, parsed_method.mojom_name,
       ordinal=parsed_method.ordinal.value if parsed_method.ordinal else None)
-  method.parameters = map(
-      lambda parameter: _Parameter(module, parameter, interface),
-      parsed_method.parameter_list)
+  method.parameters = [
+      _Parameter(module, parameter, interface) for parameter in
+      parsed_method.parameter_list
+  ]
   if parsed_method.response_parameter_list is not None:
-    method.response_parameters = map(
-        lambda parameter: _Parameter(module, parameter, interface),
-                          parsed_method.response_parameter_list)
+    method.response_parameters = [
+        _Parameter(module, parameter, interface) for parameter in
+        parsed_method.response_parameter_list
+    ]
   method.attributes = _AttributeListToDict(parsed_method.attribute_list)
 
   # Enforce that only methods with response can have a [Sync] attribute.
@@ -405,12 +409,14 @@
   interface.mojom_name = parsed_iface.mojom_name
   interface.spec = 'x:' + module.mojom_namespace + '.' + interface.mojom_name
   module.kinds[interface.spec] = interface
-  interface.enums = map(
-      lambda enum: _Enum(module, enum, interface),
-      _ElemsOfType(parsed_iface.body, ast.Enum, parsed_iface.mojom_name))
-  interface.constants = map(
-      lambda constant: _Constant(module, constant, interface),
-      _ElemsOfType(parsed_iface.body, ast.Const, parsed_iface.mojom_name))
+  interface.enums = [
+    _Enum(module, enum, interface) for enum in
+    _ElemsOfType(parsed_iface.body, ast.Enum, parsed_iface.mojom_name)
+  ]
+  interface.constants = [
+      _Constant(module, constant, interface) for constant in
+      _ElemsOfType(parsed_iface.body, ast.Const, parsed_iface.mojom_name)
+  ]
   # Stash methods parsed_iface here temporarily.
   interface.methods_data = _ElemsOfType(
       parsed_iface.body, ast.Method, parsed_iface.mojom_name)
@@ -504,9 +510,10 @@
   enum.parent_kind = parent_kind
   enum.attributes = _AttributeListToDict(parsed_enum.attribute_list)
   if not enum.native_only:
-    enum.fields = map(
-        lambda field: _EnumField(module, enum, field, parent_kind),
-        parsed_enum.enum_value_list)
+    enum.fields = [
+        _EnumField(module, enum, field, parent_kind) for field in
+        parsed_enum.enum_value_list
+    ]
     enum.min_value, enum.max_value = _ResolveNumericEnumValues(enum.fields)
 
   module.kinds[enum.spec] = enum
@@ -576,35 +583,37 @@
 
   filename = os.path.basename(path)
   # First pass collects kinds.
-  module.enums = map(
-      lambda enum: _Enum(module, enum, None),
-      _ElemsOfType(tree.definition_list, ast.Enum, filename))
-  module.structs = map(
-      lambda struct: _Struct(module, struct),
-      _ElemsOfType(tree.definition_list, ast.Struct, filename))
-  module.unions = map(
-      lambda union: _Union(module, union),
-      _ElemsOfType(tree.definition_list, ast.Union, filename))
-  module.interfaces = map(
-      lambda interface: _Interface(module, interface),
-      _ElemsOfType(tree.definition_list, ast.Interface, filename))
-  module.constants = map(
-      lambda constant: _Constant(module, constant, None),
-      _ElemsOfType(tree.definition_list, ast.Const, filename))
+  module.enums = [
+      _Enum(module, enum, None) for enum in
+      _ElemsOfType(tree.definition_list, ast.Enum, filename)
+  ]
+  module.structs = [
+      _Struct(module, struct) for struct in
+      _ElemsOfType(tree.definition_list, ast.Struct, filename)
+  ]
+  module.unions = [
+      _Union(module, union) for union in
+      _ElemsOfType(tree.definition_list, ast.Union, filename)
+  ]
+  module.interfaces = [
+      _Interface(module, interface) for interface in
+      _ElemsOfType(tree.definition_list, ast.Interface, filename)
+  ]
+  module.constants = [
+      _Constant(module, constant, None) for constant in
+      _ElemsOfType(tree.definition_list, ast.Const, filename)
+  ]
 
   # Second pass expands fields and methods. This allows fields and parameters
   # to refer to kinds defined anywhere in the mojom.
   for struct in module.structs:
-    struct.fields = map(lambda field:
-        _StructField(module, field, struct), struct.fields_data)
+    struct.fields = [_StructField(module, field, struct) for field in struct.fields_data]
     del struct.fields_data
   for union in module.unions:
-    union.fields = map(lambda field:
-        _UnionField(module, field, union), union.fields_data)
+    union.fields = [_UnionField(module, field, union) for field in union.fields_data]
     del union.fields_data
   for interface in module.interfaces:
-    interface.methods = map(lambda method:
-        _Method(module, method, interface), interface.methods_data)
+    interface.methods = [_Method(module, method, interface) for method in interface.methods_data]
     del interface.methods_data
 
   return module
diff --git a/mojo/public/tools/bindings/pylib/mojom_tests/generate/pack_unittest.py b/mojo/public/tools/bindings/pylib/mojom_tests/generate/pack_unittest.py
index 75f6d51..5fcc9c0 100644
--- a/mojo/public/tools/bindings/pylib/mojom_tests/generate/pack_unittest.py
+++ b/mojo/public/tools/bindings/pylib/mojom_tests/generate/pack_unittest.py
@@ -47,7 +47,7 @@
     ps = pack.PackedStruct(struct)
     num_fields = len(ps.packed_fields)
     self.assertEquals(len(kinds), num_fields)
-    for i in xrange(num_fields):
+    for i in range(num_fields):
       self.assertEquals('%d' % fields[i], ps.packed_fields[i].field.name)
       self.assertEquals(offsets[i], ps.packed_fields[i].offset)
 
diff --git a/mojo/public/tools/chrome_ipc/generate_mojom.py b/mojo/public/tools/chrome_ipc/generate_mojom.py
index 04e933b..db0c50d 100755
--- a/mojo/public/tools/chrome_ipc/generate_mojom.py
+++ b/mojo/public/tools/chrome_ipc/generate_mojom.py
@@ -95,11 +95,11 @@
     yield 'type_mappings = [\n  %s\n]' % '\n  '.join(new_mappings)
 
   def _format_new_mappings(self, namespace):
-    for native, mojom in self._new_custom_mappings.iteritems():
+    for native, mojom in self._new_custom_mappings.items():
       yield '"%s.%s=::%s",' % (namespace, mojom, native)
 
   def format_new_types(self):
-    for native_type, typename in self._new_custom_mappings.iteritems():
+    for native_type, typename in self._new_custom_mappings.items():
       if native_type in self._enums:
         yield '[Native]\nenum %s;\n' % typename
       else:
@@ -188,7 +188,7 @@
   def _add_includes(self, namespace, name, fullname):
     name_components = name.split('::')
     is_enum = False
-    for i in xrange(len(name_components)):
+    for i in range(len(name_components)):
       subname = '::'.join(name_components[i:])
       extra_names = name_components[:i] + [subname]
       patterns = [r'\(struct\|class\|enum\)[A-Z_ ]* %s {' % s
@@ -353,7 +353,7 @@
     for m in self._get_messages():
       grouped_messages.setdefault(m.group, []).append(m)
     self._typemaps.load_typemaps()
-    for interface, messages in grouped_messages.iteritems():
+    for interface, messages in grouped_messages.items():
       self._interface_definitions.append(self._format_interface(interface,
                                                                 messages))
 
diff --git a/third_party/jinja2/tests.py b/third_party/jinja2/tests.py
index 0adc3d4..a6cb8fe 100644
--- a/third_party/jinja2/tests.py
+++ b/third_party/jinja2/tests.py
@@ -10,7 +10,6 @@
 """
 import operator
 import re
-from collections import Mapping
 from jinja2.runtime import Undefined
 from jinja2._compat import text_type, string_types, integer_types
 import decimal
@@ -79,14 +78,6 @@
     return isinstance(value, string_types)
 
 
-def test_mapping(value):
-    """Return true if the object is a mapping (dict etc.).
-
-    .. versionadded:: 2.6
-    """
-    return isinstance(value, Mapping)
-
-
 def test_number(value):
     """Return true if the variable is a number."""
     return isinstance(value, integer_types + (float, complex, decimal.Decimal))
@@ -149,7 +140,6 @@
     'lower':            test_lower,
     'upper':            test_upper,
     'string':           test_string,
-    'mapping':          test_mapping,
     'number':           test_number,
     'sequence':         test_sequence,
     'iterable':         test_iterable,
diff --git a/third_party/ply/yacc.py b/third_party/ply/yacc.py
index f70439e..9824217 100644
--- a/third_party/ply/yacc.py
+++ b/third_party/ply/yacc.py
@@ -195,8 +195,11 @@
         self.lexer = None
         self.parser= None
     def __getitem__(self,n):
-        if n >= 0: return self.slice[n].value
-        else: return self.stack[n].value
+        if type(n) is slice:
+            return [s.value for s in self.slice[n]]
+        else:
+            if n >= 0: return self.slice[n].value
+            else: return self.stack[n].value
 
     def __setitem__(self,n,v):
         self.slice[n].value = v