diff --git a/tools/docs/test_doc_build.py b/tools/docs/test_doc_build.py index 47b4606569f9..4082317d581d 100755 --- a/tools/docs/test_doc_build.py +++ b/tools/docs/test_doc_build.py @@ -11,29 +11,47 @@ and optionally test the build. import argparse import asyncio +import glob import os.path -import shutil +import re import sys import time import subprocess -# Minimal python version supported by the building system. +MIN_PYTHON_SUBVER = 9 # Currently, Python 3.9 is the minimal supported version -PYTHON = os.path.basename(sys.executable) +RE_VERSION = re.compile(r"python3\.\d+$") -min_python_bin = None -for i in range(9, 13): - p = f"python3.{i}" - if shutil.which(p): - min_python_bin = p - break +def get_min_python_bin(min_subver): + """Get minimal python binary since 3.MIN_PYTHON_SUBVER""" + bins = set() -if not min_python_bin: - min_python_bin = PYTHON + paths = os.environ.get("PATH", "").split(os.pathsep) + for d in paths: + for p in glob.glob(os.path.join(d, "python3.[0-9]*")): + if not RE_VERSION.search(p): + continue -# Starting from 8.0, Python 3.9 is not supported anymore. -PYTHON_VER_CHANGES = {(8, 0, 0): PYTHON} + ver = int(p.split(".")[1]) + if ver < min_subver: + continue + + if os.path.isfile(p) and os.access(p, os.X_OK): + bins.add(p) + + if not bins: + return None + + return sorted(bins, key=lambda x: (3, int(x.split(".")[1])))[0] + +# Minimal python versions. Please notice that for 3.4.3, older python +# versions would work with Sphinx, but kernel doc build is not compatible +# with them anymore, due to Sphinx extensions and kernel-doc. +PYTHON_VER_CHANGES = { + (3, 4, 3): (3, MIN_PYTHON_SUBVER), + (8, 0, 0): (3, 10), +} DEFAULT_VERSIONS_TO_TEST = [ (3, 4, 3), # Minimal supported version @@ -173,7 +191,7 @@ class AsyncCommands: self.output = None self.fp = fp - def log(self, out, verbose, is_info=True): + def log(self, out, verbose=True, is_info=True): out = out.removesuffix('\n') if verbose: @@ -362,8 +380,19 @@ class SphinxVenv: if not args.verbose: args.verbose = True + cmd = AsyncCommands(fp) + cur_requirements = {} - python_bin = min_python_bin + python_bin = get_min_python_bin(MIN_PYTHON_SUBVER) + if not python_bin: + python_bin = os.path.basename(sys.executable) + python_ver = tuple(sys.version_info[:2]) + + if python_ver < (3, MIN_PYTHON_SUBVER): + sys.exit(f"Python {python_ver[0]}.{python_ver[1]} is too old.") + else: + ver = int(python_bin.split(".")[1]) + python_ver = tuple([3, ver]) vers = set(SPHINX_REQUIREMENTS.keys()) | set(args.versions) @@ -372,8 +401,14 @@ class SphinxVenv: new_reqs = SPHINX_REQUIREMENTS[cur_ver] cur_requirements.update(new_reqs) - if cur_ver in PYTHON_VER_CHANGES: # pylint: disable=R1715 - python_bin = PYTHON_VER_CHANGES[cur_ver] + if cur_ver in PYTHON_VER_CHANGES: + new_ver = PYTHON_VER_CHANGES[cur_ver] + if python_ver < new_ver: + python_bin = get_min_python_bin(new_ver[1]) + + if not python_bin: + cmd.log(f"Can't check {cur_ver}: {python_bin} not found.") + break if cur_ver not in args.versions: continue @@ -390,7 +425,6 @@ class SphinxVenv: python_bin) if args.build: - cmd = AsyncCommands(fp) cmd.log("\nSummary:", verbose=True) for ver, elapsed_time in sorted(self.built_time.items()): cmd.log(f"\tSphinx {ver} elapsed time: {elapsed_time}",