Drop 'rcYYYYMMDD' suffix from packages when deploying to PyPI. (#19067)

This is part of rolling out the new versioning scheme proposed at
https://github.com/iree-org/iree/issues/18938.

During publishing to PyPI with the existing
`build_tools/python_deploy/pypi_deploy.sh` script, this converts
"nightly" packages with versions like `X.Y.ZrcYYYYMMDD` to "stable"
packages with versions like `X.Y.Z`.
* The version change is performed by
https://pypi.org/project/change-wheel-version/ (source here:
https://github.com/hauntsaninja/change_wheel_version/blob/master/change_wheel_version.py),
which handles editing package versions and renaming files.
* Note that binary tools like `iree-compile` still have versions stamped
in them that this is **not** modifying.

Test logs (on a draft release, with the upload step commented out):
https://gist.github.com/ScottTodd/e7342a7be9c1c4eb093e6d31bd9cebef
diff --git a/build_tools/python_deploy/compute_common_version.py b/build_tools/python_deploy/compute_common_version.py
old mode 100644
new mode 100755
index e940952..3dd824a
--- a/build_tools/python_deploy/compute_common_version.py
+++ b/build_tools/python_deploy/compute_common_version.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
 # Copyright 2024 The IREE Authors
 #
 # Licensed under the Apache License v2.0 with LLVM Exceptions.
diff --git a/build_tools/python_deploy/compute_local_version.py b/build_tools/python_deploy/compute_local_version.py
old mode 100644
new mode 100755
index 897e5dc..fc794b7
--- a/build_tools/python_deploy/compute_local_version.py
+++ b/build_tools/python_deploy/compute_local_version.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
 # Copyright 2024 The IREE Authors
 #
 # Licensed under the Apache License v2.0 with LLVM Exceptions.
diff --git a/build_tools/python_deploy/promote_whl_from_rc_to_final.py b/build_tools/python_deploy/promote_whl_from_rc_to_final.py
new file mode 100755
index 0000000..ae49c19
--- /dev/null
+++ b/build_tools/python_deploy/promote_whl_from_rc_to_final.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python3
+# Copyright 2024 The IREE Authors
+#
+# Licensed under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+# This scripts takes a file like
+# 'iree_base_runtime-2.9.0rc20241107-cp311-cp311-manylinux_2_28_x86_64.whl'
+# with embedded version '2.9.0rc20241107' as input and then drops the
+# 'rcYYYYMMDD' suffix from both the embedded version and file name.
+#
+# Typical usage:
+#   pip install -r pypi_deploy_requirements.txt
+#   ./promote_whl_from_rc_to_final.py /path/to/file.whl --delete-old-wheel
+
+import argparse
+from change_wheel_version import change_wheel_version
+from packaging.version import Version
+from pathlib import Path
+from pkginfo import Wheel
+
+
+def parse_arguments():
+    parser = argparse.ArgumentParser()
+    parser.add_argument(
+        "input_file",
+        help="Path to the input .whl file to promote",
+        type=Path,
+    )
+    parser.add_argument(
+        "--delete-old-wheel",
+        help="Deletes the original wheel after successfully promoting it",
+        action="store_true",
+        default=False,
+    )
+    return parser.parse_args()
+
+
+def main(args):
+    original_wheel_path = args.input_file
+    print(f"Promoting whl from rc to final: '{original_wheel_path}'")
+
+    original_wheel = Wheel(original_wheel_path)
+    original_version = Version(original_wheel.version)
+    base_version = original_version.base_version
+    print(
+        f"  Original wheel version is '{original_version}' with base '{base_version}'"
+    )
+
+    if str(base_version) == str(original_version):
+        print("  Version is already a release version, skipping")
+        return
+
+    print(f"  Changing to base version: '{base_version}'")
+    new_wheel_path = change_wheel_version(original_wheel_path, str(base_version), None)
+    print(f"  New wheel path is '{new_wheel_path}'")
+
+    new_wheel = Wheel(new_wheel_path)
+    new_version = Version(new_wheel.version)
+    print(f"  New wheel version is '{new_version}'")
+
+    if args.delete_old_wheel:
+        print("  Deleting original wheel")
+        original_wheel_path.unlink()
+
+
+if __name__ == "__main__":
+    main(parse_arguments())
diff --git a/build_tools/python_deploy/pypi_deploy.sh b/build_tools/python_deploy/pypi_deploy.sh
index 811b638..39b02b2 100755
--- a/build_tools/python_deploy/pypi_deploy.sh
+++ b/build_tools/python_deploy/pypi_deploy.sh
@@ -58,11 +58,29 @@
 
 function download_wheels() {
   echo ""
-  echo "Downloading wheels from '${RELEASE}'"
+  echo "Downloading wheels from '${RELEASE}'..."
   gh release download "${RELEASE}" --repo iree-org/iree --pattern "*.whl"
+
+  echo ""
+  echo "Downloaded wheels:"
+  ls
+}
+
+function edit_release_versions() {
+  echo ""
+  echo "Editing release versions..."
+  for file in *
+  do
+    ${SCRIPT_DIR}/promote_whl_from_rc_to_final.py ${file} --delete-old-wheel
+  done
+
+  echo "Edited wheels:"
+  ls
 }
 
 function upload_wheels() {
+  echo ""
+  echo "Uploading wheels..."
   twine upload --verbose *
 }
 
@@ -79,6 +97,7 @@
   fi
 
   download_wheels
+  edit_release_versions
   upload_wheels
 }
 
diff --git a/build_tools/python_deploy/pypi_deploy_requirements.txt b/build_tools/python_deploy/pypi_deploy_requirements.txt
index af996cf..dcc32d4 100644
--- a/build_tools/python_deploy/pypi_deploy_requirements.txt
+++ b/build_tools/python_deploy/pypi_deploy_requirements.txt
@@ -1 +1,4 @@
+change_wheel_version
+packaging
+pkginfo
 twine