Repository: nodejs/node
Pull request: build: drop support for Python 3.9

Fixes: https://github.com/nodejs/node/issues/60919

## Situation

Python version `3.9` reached end of life transition and has moved to the list of [Python unsupported versions](https://devguide.python.org/versions/#unsupported-versions):

| Python version | End of life |
| -------------- | ----------- |
| 3.9            | 2025-10-31  |

Build scripts for current release lines should continue to allow using this version for the sake of build environment continuity.

Future Node.js release lines should **not** include the now unsupported Python 3.9 in build scripts.

## Change

Remove Python 3.9 from build scripts. This is a `semver-major` change.

Similar to https://github.com/nodejs/node/pull/55239 which dropped support for Python 3.8

Changed files:
filename: android-configure
patch: @@ -9,7 +9,6 @@ command -v python3.13 >/dev/null && exec python3.13 "$0" "$@"
 command -v python3.12 >/dev/null && exec python3.12 "$0" "$@"
 command -v python3.11 >/dev/null && exec python3.11 "$0" "$@"
 command -v python3.10 >/dev/null && exec python3.10 "$0" "$@"
-command -v python3.9 >/dev/null && exec python3.9 "$0" "$@"
 command -v python3 >/dev/null && exec python3 "$0" "$@"
 exec python "$0" "$@"
 ''' "$0" "$@"
@@ -23,7 +22,7 @@ except ImportError:
   from distutils.spawn import find_executable as which
 
 print('Node.js android configure: Found Python {}.{}.{}...'.format(*sys.version_info))
-acceptable_pythons = ((3, 14), (3, 13), (3, 12), (3, 11), (3, 10), (3, 9))
+acceptable_pythons = ((3, 14), (3, 13), (3, 12), (3, 11), (3, 10))
 if sys.version_info[:2] in acceptable_pythons:
   import android_configure
 else:

filename: configure
patch: @@ -9,7 +9,6 @@ command -v python3.13 >/dev/null && exec python3.13 "$0" "$@"
 command -v python3.12 >/dev/null && exec python3.12 "$0" "$@"
 command -v python3.11 >/dev/null && exec python3.11 "$0" "$@"
 command -v python3.10 >/dev/null && exec python3.10 "$0" "$@"
-command -v python3.9 >/dev/null && exec python3.9 "$0" "$@"
 command -v python3 >/dev/null && exec python3 "$0" "$@"
 exec python "$0" "$@"
 ''' "$0" "$@"
@@ -23,7 +22,7 @@ except ImportError:
   from distutils.spawn import find_executable as which
 
 print('Node.js configure: Found Python {}.{}.{}...'.format(*sys.version_info))
-acceptable_pythons = ((3, 14), (3, 13), (3, 12), (3, 11), (3, 10), (3, 9))
+acceptable_pythons = ((3, 14), (3, 13), (3, 12), (3, 11), (3, 10))
 if sys.version_info[:2] in acceptable_pythons:
   import configure
 else:

filename: configure.py
patch: @@ -2409,7 +2409,7 @@ def make_bin_override():
   if sys.platform == 'win32':
     raise Exception('make_bin_override should not be called on win32.')
   # If the system python is not the python we are running (which should be
-  # python 3.9+), then create a directory with a symlink called `python` to our
+  # python 3.10+), then create a directory with a symlink called `python` to our
   # sys.executable. This directory will be prefixed to the PATH, so that
   # other tools that shell out to `python` will use the appropriate python
 

filename: pyproject.toml
patch: @@ -7,7 +7,7 @@ exclude = [
   "tools/eslint/node_modules"
 ]
 line-length = 172
-target-version = "py39"
+target-version = "py310"
 
 [tool.ruff.lint]
 select = [