Add option to format python using YAPF

README.google:

Name: Formatter for Python code.
URL: https://github.com/google/yapf/
Version: c1d7a213f83ac09e6ddedf9d07277b08d9a26880
Revision: N/A
Date: October 13th 2023
License: See LICENSE
Change-Id: I1a6aeb33f8c6e77899187dd9337da0ecb9bc0e4d
diff --git a/.gitignore b/.gitignore
index 5b8ffd2..2fcc852 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,3 @@
-
 !third_party/chrome/*.sha1
 !third_party/gmail/*.sha1
 !third_party/gmscore/*.sha1
@@ -116,6 +115,8 @@
 third_party/gmscore/*
 third_party/google/google-java-format/1.14.0
 third_party/google/google-java-format/1.14.0.tar.gz
+third_party/google/yapf/20231013
+third_party/google/yapf/20231013.tar.gz
 third_party/google-java-format
 third_party/google-java-format.tar.gz
 third_party/goyt
diff --git a/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt b/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt
index 0a2f070..794e58e 100644
--- a/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt
+++ b/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt
@@ -444,6 +444,10 @@
     "google-java-format-1.14",
     Paths.get("third_party", "google", "google-java-format", "1.14.0").toFile(),
     Paths.get("third_party", "google", "google-java-format", "1.14.0.tar.gz.sha1").toFile())
+  val googleYapf_20231013 = ThirdPartyDependency(
+    "google-yapf-20231013",
+    Paths.get("third_party", "google", "yapf", "20231013").toFile(),
+    Paths.get("third_party", "google", "yapf", "20231013.tar.gz.sha1").toFile())
   val gson = ThirdPartyDependency(
     "gson",
     Paths.get("third_party", "gson", "gson-2.10.1").toFile(),
diff --git a/third_party/google/yapf/20231013.tar.gz.sha1 b/third_party/google/yapf/20231013.tar.gz.sha1
new file mode 100644
index 0000000..dbcbb50
--- /dev/null
+++ b/third_party/google/yapf/20231013.tar.gz.sha1
@@ -0,0 +1 @@
+5469c71a8b6a49fed240977d0a8053c31d599ae7
\ No newline at end of file
diff --git a/tools/fmt-diff.py b/tools/fmt-diff.py
index cda33f9..0e4ada7 100755
--- a/tools/fmt-diff.py
+++ b/tools/fmt-diff.py
@@ -3,6 +3,7 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
+import argparse
 import os
 import subprocess
 import sys
@@ -11,23 +12,60 @@
 
 from subprocess import Popen, PIPE
 
-GOOGLE_JAVA_FORMAT_DIFF = os.path.join(
-    utils.THIRD_PARTY,
-    'google',
-    'google-java-format',
-    '1.14.0',
-    'google-java-format-1.14.0',
-    'scripts',
-    'google-java-format-diff.py')
+GOOGLE_JAVA_FORMAT_DIFF = os.path.join(utils.THIRD_PARTY, 'google',
+                                       'google-java-format', '1.14.0',
+                                       'google-java-format-1.14.0', 'scripts',
+                                       'google-java-format-diff.py')
+
+GOOGLE_YAPF = os.path.join(utils.THIRD_PARTY, 'google/yapf/20231013')
+
+
+def ParseOptions():
+    result = argparse.ArgumentParser()
+    result.add_argument('--no-java',
+                        help='Run google-java-format.',
+                        action='store_true',
+                        default=False)
+    result.add_argument('--python',
+                        help='Run YAPF.',
+                        action='store_true',
+                        default=False)
+    return result.parse_known_args()
+
+
+def FormatJava(upstream):
+    git_diff_process = Popen(['git', 'diff', '-U0', upstream], stdout=PIPE)
+    fmt_process = Popen([sys.executable, GOOGLE_JAVA_FORMAT_DIFF, '-p1', '-i'],
+                        stdin=git_diff_process.stdout)
+    git_diff_process.stdout.close()
+    fmt_process.communicate()
+
+
+def FormatPython(upstream):
+    changed_files_cmd = ['git', 'diff', '--name-only', upstream, '*.py']
+    changed_files = subprocess.check_output(changed_files_cmd).decode(
+        'utf-8').splitlines()
+    if not changed_files:
+        return
+    format_cmd = [
+        sys.executable,
+        os.path.join(GOOGLE_YAPF, 'yapf'), '--in-place', '--style', 'google'
+    ]
+    format_cmd.extend(changed_files)
+    yapf_python_path = [GOOGLE_YAPF, os.path.join(GOOGLE_YAPF, 'third_party')]
+    subprocess.check_call(format_cmd,
+                          env={'PYTHONPATH': ':'.join(yapf_python_path)})
+
 
 def main():
-  upstream = subprocess.check_output(['git', 'cl', 'upstream']).strip()
-  git_diff_process = Popen(['git', 'diff', '-U0', upstream], stdout=PIPE)
-  fmt_process = Popen(
-      [sys.executable, GOOGLE_JAVA_FORMAT_DIFF, '-p1', '-i'],
-      stdin=git_diff_process.stdout)
-  git_diff_process.stdout.close()
-  fmt_process.communicate()
+    (options, args) = ParseOptions()
+    upstream = subprocess.check_output(['git', 'cl',
+                                        'upstream']).decode('utf-8').strip()
+    if not options.no_java:
+        FormatJava(upstream)
+    if options.python:
+        FormatPython(upstream)
+
 
 if __name__ == '__main__':
-  sys.exit(main())
+    sys.exit(main())