Parallelize zap_convert_all.py. (#24181)

It's 4-5x faster for me this way.

Also sets ZAP_SKIP_REAL_VERSION so that once
https://github.com/project-chip/zap/pull/876 merges we stop messing with the ZAP
repo just to run it.
diff --git a/scripts/tools/zap/convert.py b/scripts/tools/zap/convert.py
index 0edc091..c3fab0d 100755
--- a/scripts/tools/zap/convert.py
+++ b/scripts/tools/zap/convert.py
@@ -102,6 +102,8 @@
     if 'ZAP_DEVELOPMENT_PATH' in os.environ:
         convert_cmd = ['node', 'src-script/zap-start.js', 'convert']
         working_directory = os.environ['ZAP_DEVELOPMENT_PATH']
+        # Make sure we don't try to munge the package.json in the ZAP repo.
+        os.environ['ZAP_SKIP_REAL_VERSION'] = '1'
     elif 'ZAP_INSTALL_PATH' in os.environ:
         convert_cmd = [os.path.join(os.environ['ZAP_INSTALL_PATH'], 'zap-cli'), 'convert']
         working_directory = None
diff --git a/scripts/tools/zap/generate.py b/scripts/tools/zap/generate.py
index bd12075..30f60aa 100755
--- a/scripts/tools/zap/generate.py
+++ b/scripts/tools/zap/generate.py
@@ -164,6 +164,8 @@
     if 'ZAP_DEVELOPMENT_PATH' in os.environ:
         generate_cmd = ['node', 'src-script/zap-start.js', 'generate']
         working_directory = os.environ['ZAP_DEVELOPMENT_PATH']
+        # Make sure we don't try to munge the package.json in the ZAP repo.
+        os.environ['ZAP_SKIP_REAL_VERSION'] = '1'
     elif 'ZAP_INSTALL_PATH' in os.environ:
         generate_cmd = [os.path.join(os.environ['ZAP_INSTALL_PATH'], 'zap-cli'), 'generate']
         working_directory = None
diff --git a/scripts/tools/zap/run_zaptool.sh b/scripts/tools/zap/run_zaptool.sh
index 5e7a185..8885cdd 100755
--- a/scripts/tools/zap/run_zaptool.sh
+++ b/scripts/tools/zap/run_zaptool.sh
@@ -34,6 +34,8 @@
 if [ ! -z "$ZAP_DEVELOPMENT_PATH" ]; then
     WORKING_DIR=$ZAP_DEVELOPMENT_PATH
     ZAP_CMD="node src-script/zap-start.js"
+    # Make sure we don't try to munge the package.json in the ZAP repo.
+    export ZAP_SKIP_REAL_VERSION=1
 
     "$CHIP_ROOT"/scripts/tools/zap/zap_bootstrap.sh
 elif [ ! -z "$ZAP_INSTALL_PATH" ]; then
diff --git a/scripts/tools/zap_convert_all.py b/scripts/tools/zap_convert_all.py
index 15a68cf..a626a97 100755
--- a/scripts/tools/zap_convert_all.py
+++ b/scripts/tools/zap_convert_all.py
@@ -20,6 +20,7 @@
 import sys
 import subprocess
 import argparse
+import multiprocessing
 
 CHIP_ROOT_DIR = os.path.realpath(
     os.path.join(os.path.dirname(__file__), '../..'))
@@ -59,9 +60,20 @@
         description='Convert all .zap files to the current zap version')
     parser.add_argument('--run-bootstrap', default=None, action='store_true',
                         help='Automatically run ZAP bootstrap. By default the bootstrap is not triggered')
+    parser.add_argument('--parallel', action='store_true')
+    parser.add_argument('--no-parallel', action='store_false', dest='parallel')
+    parser.set_defaults(parallel=True)
+
     return parser.parse_args()
 
 
+def convertOne(target):
+    """
+    Helper method that may be run in parallel to convert a single target.
+    """
+    subprocess.check_call(['./scripts/tools/zap/convert.py'] + target)
+
+
 def main():
     args = runArgumentsParser()
     checkPythonVersion()
@@ -72,8 +84,16 @@
     os.chdir(CHIP_ROOT_DIR)
 
     targets = getTargets()
-    for target in targets:
-        subprocess.check_call(['./scripts/tools/zap/convert.py'] + target)
+
+    if args.parallel:
+        # Ensure each zap run is independent
+        os.environ['ZAP_TEMPSTATE'] = '1'
+        with multiprocessing.Pool() as pool:
+            for _ in pool.imap_unordered(convertOne, targets):
+                pass
+    else:
+        for target in targets:
+            generateOne(target)
 
 
 if __name__ == '__main__':