chore: start cleaning up 3.9 usage from examples (#3419)

Summary:
- **example: stop using 3.9 in multi-python-versions**
- **chore: cleanup unused code**

There is more to go, but this is a good start remaining of #2704

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
index 1cb3a01..256961b 100644
--- a/.bazelci/presubmit.yml
+++ b/.bazelci/presubmit.yml
@@ -81,11 +81,15 @@
   coverage_targets:
     - //tests:my_lib_3_10_test
     - //tests:my_lib_3_11_test
-    - //tests:my_lib_3_9_test
+    - //tests:my_lib_3_12_test
+    - //tests:my_lib_3_13_test
+    - //tests:my_lib_3_14_test
     - //tests:my_lib_default_test
     - //tests:version_3_10_test
     - //tests:version_3_11_test
-    - //tests:version_3_9_test
+    - //tests:version_3_12_test
+    - //tests:version_3_13_test
+    - //tests:version_3_14_test
     - //tests:version_default_test
 tasks:
   gazelle_extension_min:
diff --git a/examples/bzlmod/other_module/MODULE.bazel b/examples/bzlmod/other_module/MODULE.bazel
index 7b88bd7..a128c39 100644
--- a/examples/bzlmod/other_module/MODULE.bazel
+++ b/examples/bzlmod/other_module/MODULE.bazel
@@ -10,10 +10,6 @@
     path = "../../..",
 )
 
-PYTHON_NAME_39 = "python_3_9"
-
-PYTHON_NAME_311 = "python_3_11"
-
 python = use_extension("@rules_python//python/extensions:python.bzl", "python")
 python.defaults(
     # In a submodule this is ignored
@@ -21,21 +17,13 @@
 )
 python.toolchain(
     configure_coverage_tool = True,
-    python_version = "3.9",
+    python_version = "3.12",
 )
 python.toolchain(
     configure_coverage_tool = True,
     python_version = "3.11",
 )
 
-# created by the above python.toolchain calls.
-use_repo(
-    python,
-    "python_versions",
-    PYTHON_NAME_39,
-    PYTHON_NAME_311,
-)
-
 pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
 pip.parse(
     hub_name = "other_module_pip",
diff --git a/examples/multi_python_versions/MODULE.bazel b/examples/multi_python_versions/MODULE.bazel
index eeb1dfc..2ef09ad 100644
--- a/examples/multi_python_versions/MODULE.bazel
+++ b/examples/multi_python_versions/MODULE.bazel
@@ -12,21 +12,29 @@
 python = use_extension("@rules_python//python/extensions:python.bzl", "python")
 python.defaults(
     # The environment variable takes precedence if set.
-    python_version = "3.9",
+    python_version = "3.10",
     python_version_env = "BAZEL_PYTHON_VERSION",
 )
 python.toolchain(
     configure_coverage_tool = True,
-    python_version = "3.9",
-)
-python.toolchain(
-    configure_coverage_tool = True,
     python_version = "3.10",
 )
 python.toolchain(
     configure_coverage_tool = True,
     python_version = "3.11",
 )
+python.toolchain(
+    configure_coverage_tool = True,
+    python_version = "3.12",
+)
+python.toolchain(
+    configure_coverage_tool = True,
+    python_version = "3.13",
+)
+python.toolchain(
+    configure_coverage_tool = True,
+    python_version = "3.14",
+)
 use_repo(
     python,
     "pythons_hub",
@@ -38,11 +46,6 @@
 
 pip.parse(
     hub_name = "pypi",
-    python_version = "3.9",
-    requirements_lock = "//requirements:requirements_lock_3_9.txt",
-)
-pip.parse(
-    hub_name = "pypi",
     python_version = "3.10",
     requirements_lock = "//requirements:requirements_lock_3_10.txt",
 )
@@ -51,6 +54,21 @@
     python_version = "3.11",
     requirements_lock = "//requirements:requirements_lock_3_11.txt",
 )
+pip.parse(
+    hub_name = "pypi",
+    python_version = "3.12",
+    requirements_lock = "//requirements:requirements_lock_3_12.txt",
+)
+pip.parse(
+    hub_name = "pypi",
+    python_version = "3.13",
+    requirements_lock = "//requirements:requirements_lock_3_13.txt",
+)
+pip.parse(
+    hub_name = "pypi",
+    python_version = "3.14",
+    requirements_lock = "//requirements:requirements_lock_3_14.txt",
+)
 
 # example test dependencies
 bazel_dep(name = "rules_shell", version = "0.2.0", dev_dependency = True)
diff --git a/examples/multi_python_versions/WORKSPACE b/examples/multi_python_versions/WORKSPACE
index 6b69e0a..0b6b8a0 100644
--- a/examples/multi_python_versions/WORKSPACE
+++ b/examples/multi_python_versions/WORKSPACE
@@ -9,15 +9,17 @@
 
 py_repositories()
 
-default_python_version = "3.9"
+default_python_version = "3.10"
 
 python_register_multi_toolchains(
     name = "python",
     default_version = default_python_version,
     python_versions = [
-        "3.9",
         "3.10",
         "3.11",
+        "3.12",
+        "3.13",
+        "3.14",
     ],
     register_coverage_tool = True,
 )
@@ -30,12 +32,16 @@
     python_interpreter_target = {
         "3.10": "@python_3_10_host//:python",
         "3.11": "@python_3_11_host//:python",
-        "3.9": "@python_3_9_host//:python",
+        "3.12": "@python_3_12_host//:python",
+        "3.13": "@python_3_13_host//:python",
+        "3.14": "@python_3_14_host//:python",
     },
     requirements_lock = {
         "3.10": "//requirements:requirements_lock_3_10.txt",
         "3.11": "//requirements:requirements_lock_3_11.txt",
-        "3.9": "//requirements:requirements_lock_3_9.txt",
+        "3.12": "//requirements:requirements_lock_3_12.txt",
+        "3.13": "//requirements:requirements_lock_3_13.txt",
+        "3.14": "//requirements:requirements_lock_3_14.txt",
     },
 )
 
diff --git a/examples/multi_python_versions/requirements/BUILD.bazel b/examples/multi_python_versions/requirements/BUILD.bazel
index 516a378..ee8ff02 100644
--- a/examples/multi_python_versions/requirements/BUILD.bazel
+++ b/examples/multi_python_versions/requirements/BUILD.bazel
@@ -1,13 +1,6 @@
 load("@rules_python//python:pip.bzl", "compile_pip_requirements")
 
 compile_pip_requirements(
-    name = "requirements_3_9",
-    src = "requirements.in",
-    python_version = "3.9",
-    requirements_txt = "requirements_lock_3_9.txt",
-)
-
-compile_pip_requirements(
     name = "requirements_3_10",
     src = "requirements.in",
     python_version = "3.10",
@@ -20,3 +13,24 @@
     python_version = "3.11",
     requirements_txt = "requirements_lock_3_11.txt",
 )
+
+compile_pip_requirements(
+    name = "requirements_3_12",
+    src = "requirements.in",
+    python_version = "3.12",
+    requirements_txt = "requirements_lock_3_12.txt",
+)
+
+compile_pip_requirements(
+    name = "requirements_3_13",
+    src = "requirements.in",
+    python_version = "3.13",
+    requirements_txt = "requirements_lock_3_13.txt",
+)
+
+compile_pip_requirements(
+    name = "requirements_3_14",
+    src = "requirements.in",
+    python_version = "3.14",
+    requirements_txt = "requirements_lock_3_14.txt",
+)
diff --git a/examples/multi_python_versions/requirements/requirements_lock_3_9.txt b/examples/multi_python_versions/requirements/requirements_lock_3_12.txt
similarity index 97%
rename from examples/multi_python_versions/requirements/requirements_lock_3_9.txt
rename to examples/multi_python_versions/requirements/requirements_lock_3_12.txt
index 3c696a8..818b20e 100644
--- a/examples/multi_python_versions/requirements/requirements_lock_3_9.txt
+++ b/examples/multi_python_versions/requirements/requirements_lock_3_12.txt
@@ -1,8 +1,8 @@
 #
-# This file is autogenerated by pip-compile with Python 3.9
+# This file is autogenerated by pip-compile with Python 3.12
 # by the following command:
 #
-#    bazel run //requirements:requirements_3_9.update
+#    bazel run //requirements:requirements_3_12.update
 #
 websockets==11.0.3 ; python_full_version > "3.9.1" \
     --hash=sha256:01f5567d9cf6f502d655151645d4e8b72b453413d3819d2b6f1185abc23e82dd \
diff --git a/examples/multi_python_versions/requirements/requirements_lock_3_9.txt b/examples/multi_python_versions/requirements/requirements_lock_3_13.txt
similarity index 97%
copy from examples/multi_python_versions/requirements/requirements_lock_3_9.txt
copy to examples/multi_python_versions/requirements/requirements_lock_3_13.txt
index 3c696a8..8dc44b8 100644
--- a/examples/multi_python_versions/requirements/requirements_lock_3_9.txt
+++ b/examples/multi_python_versions/requirements/requirements_lock_3_13.txt
@@ -1,8 +1,8 @@
 #
-# This file is autogenerated by pip-compile with Python 3.9
+# This file is autogenerated by pip-compile with Python 3.13
 # by the following command:
 #
-#    bazel run //requirements:requirements_3_9.update
+#    bazel run //requirements:requirements_3_13.update
 #
 websockets==11.0.3 ; python_full_version > "3.9.1" \
     --hash=sha256:01f5567d9cf6f502d655151645d4e8b72b453413d3819d2b6f1185abc23e82dd \
diff --git a/examples/multi_python_versions/requirements/requirements_lock_3_9.txt b/examples/multi_python_versions/requirements/requirements_lock_3_14.txt
similarity index 97%
copy from examples/multi_python_versions/requirements/requirements_lock_3_9.txt
copy to examples/multi_python_versions/requirements/requirements_lock_3_14.txt
index 3c696a8..f0aaaa9 100644
--- a/examples/multi_python_versions/requirements/requirements_lock_3_9.txt
+++ b/examples/multi_python_versions/requirements/requirements_lock_3_14.txt
@@ -1,8 +1,8 @@
 #
-# This file is autogenerated by pip-compile with Python 3.9
+# This file is autogenerated by pip-compile with Python 3.14
 # by the following command:
 #
-#    bazel run //requirements:requirements_3_9.update
+#    bazel run //requirements:requirements_3_14.update
 #
 websockets==11.0.3 ; python_full_version > "3.9.1" \
     --hash=sha256:01f5567d9cf6f502d655151645d4e8b72b453413d3819d2b6f1185abc23e82dd \
diff --git a/examples/multi_python_versions/tests/BUILD.bazel b/examples/multi_python_versions/tests/BUILD.bazel
index 11fb98c..607058d 100644
--- a/examples/multi_python_versions/tests/BUILD.bazel
+++ b/examples/multi_python_versions/tests/BUILD.bazel
@@ -23,13 +23,6 @@
 )
 
 py_binary(
-    name = "version_3_9",
-    srcs = ["version.py"],
-    main = "version.py",
-    python_version = "3.9",
-)
-
-py_binary(
     name = "version_3_10",
     srcs = ["version.py"],
     main = "version.py",
@@ -43,6 +36,27 @@
     python_version = "3.11",
 )
 
+py_binary(
+    name = "version_3_12",
+    srcs = ["version.py"],
+    main = "version.py",
+    python_version = "3.12",
+)
+
+py_binary(
+    name = "version_3_13",
+    srcs = ["version.py"],
+    main = "version.py",
+    python_version = "3.13",
+)
+
+py_binary(
+    name = "version_3_14",
+    srcs = ["version.py"],
+    main = "version.py",
+    python_version = "3.14",
+)
+
 py_test(
     name = "my_lib_default_test",
     srcs = ["my_lib_test.py"],
@@ -51,14 +65,6 @@
 )
 
 py_test(
-    name = "my_lib_3_9_test",
-    srcs = ["my_lib_test.py"],
-    main = "my_lib_test.py",
-    python_version = "3.9",
-    deps = ["//libs/my_lib"],
-)
-
-py_test(
     name = "my_lib_3_10_test",
     srcs = ["my_lib_test.py"],
     main = "my_lib_test.py",
@@ -74,6 +80,30 @@
     deps = ["//libs/my_lib"],
 )
 
+py_test(
+    name = "my_lib_3_12_test",
+    srcs = ["my_lib_test.py"],
+    main = "my_lib_test.py",
+    python_version = "3.12",
+    deps = ["//libs/my_lib"],
+)
+
+py_test(
+    name = "my_lib_3_13_test",
+    srcs = ["my_lib_test.py"],
+    main = "my_lib_test.py",
+    python_version = "3.13",
+    deps = ["//libs/my_lib"],
+)
+
+py_test(
+    name = "my_lib_3_14_test",
+    srcs = ["my_lib_test.py"],
+    main = "my_lib_test.py",
+    python_version = "3.14",
+    deps = ["//libs/my_lib"],
+)
+
 copy_file(
     name = "copy_version_test",
     src = "version_test.py",
@@ -84,15 +114,7 @@
 py_test(
     name = "version_default_test",
     srcs = ["version_default_test.py"],
-    env = {"VERSION_CHECK": "3.9"},  # The default defined in the WORKSPACE.
-)
-
-py_test(
-    name = "version_3_9_test",
-    srcs = ["version_test.py"],
-    env = {"VERSION_CHECK": "3.9"},
-    main = "version_test.py",
-    python_version = "3.9",
+    env = {"VERSION_CHECK": "3.10"},  # The default defined in the WORKSPACE/MODULE
 )
 
 py_test(
@@ -112,28 +134,52 @@
 )
 
 py_test(
-    name = "version_default_takes_3_10_subprocess_test",
+    name = "version_3_12_test",
+    srcs = ["version_test.py"],
+    env = {"VERSION_CHECK": "3.12"},
+    main = "version_test.py",
+    python_version = "3.12",
+)
+
+py_test(
+    name = "version_3_13_test",
+    srcs = ["version_test.py"],
+    env = {"VERSION_CHECK": "3.13"},
+    main = "version_test.py",
+    python_version = "3.13",
+)
+
+py_test(
+    name = "version_3_14_test",
+    srcs = ["version_test.py"],
+    env = {"VERSION_CHECK": "3.14"},
+    main = "version_test.py",
+    python_version = "3.14",
+)
+
+py_test(
+    name = "version_default_takes_3_11_subprocess_test",
     srcs = ["cross_version_test.py"],
-    data = [":version_3_10"],
+    data = [":version_3_11"],
     env = {
-        "SUBPROCESS_VERSION_CHECK": "3.10",
-        "SUBPROCESS_VERSION_PY_BINARY": "$(rootpaths :version_3_10)",
-        "VERSION_CHECK": "3.9",
+        "SUBPROCESS_VERSION_CHECK": "3.11",
+        "SUBPROCESS_VERSION_PY_BINARY": "$(rootpaths :version_3_11)",
+        "VERSION_CHECK": "3.10",
     },
     main = "cross_version_test.py",
 )
 
 py_test(
-    name = "version_3_10_takes_3_9_subprocess_test",
+    name = "version_3_11_takes_3_10_subprocess_test",
     srcs = ["cross_version_test.py"],
-    data = [":version_3_9"],
+    data = [":version_3_10"],
     env = {
-        "SUBPROCESS_VERSION_CHECK": "3.9",
-        "SUBPROCESS_VERSION_PY_BINARY": "$(rootpaths :version_3_9)",
-        "VERSION_CHECK": "3.10",
+        "SUBPROCESS_VERSION_CHECK": "3.10",
+        "SUBPROCESS_VERSION_PY_BINARY": "$(rootpaths :version_3_10)",
+        "VERSION_CHECK": "3.11",
     },
     main = "cross_version_test.py",
-    python_version = "3.10",
+    python_version = "3.11",
 )
 
 sh_test(
@@ -141,22 +187,12 @@
     srcs = ["version_test.sh"],
     data = [":version_default"],
     env = {
-        "VERSION_CHECK": "3.9",  # The default defined in the WORKSPACE.
+        "VERSION_CHECK": "3.10",  # The default defined in the WORKSPACE/MODULE.
         "VERSION_PY_BINARY": "$(rootpaths :version_default)",
     },
 )
 
 sh_test(
-    name = "version_test_binary_3_9",
-    srcs = ["version_test.sh"],
-    data = [":version_3_9"],
-    env = {
-        "VERSION_CHECK": "3.9",
-        "VERSION_PY_BINARY": "$(rootpaths :version_3_9)",
-    },
-)
-
-sh_test(
     name = "version_test_binary_3_10",
     srcs = ["version_test.sh"],
     data = [":version_3_10"],
@@ -166,6 +202,16 @@
     },
 )
 
+sh_test(
+    name = "version_test_binary_3_11",
+    srcs = ["version_test.sh"],
+    data = [":version_3_11"],
+    env = {
+        "VERSION_CHECK": "3.11",
+        "VERSION_PY_BINARY": "$(rootpaths :version_3_11)",
+    },
+)
+
 # The following test ensures that default toolchain versions are the same as in
 # the TOOL_VERSIONS array.