diff options
| author | Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 2025-09-18 13:54:44 +0200 |
|---|---|---|
| committer | Jonathan Corbet <corbet@lwn.net> | 2025-09-18 11:17:19 -0600 |
| commit | adf9dc2592aad3e66b09cb412e60337477bafb0d (patch) | |
| tree | 95d6b99e1eb4812fb7dcf4a24b57868978269a17 /tools/docs/sphinx-pre-install | |
| parent | 3f835cb123c30c1a60fa6e0ebbcda919d66fc142 (diff) | |
tools/docs: python_version: move version check from sphinx-pre-install
The sphinx-pre-install code has some logic to deal with Python
version, which ensures that a minimal version will be enforced
for documentation build logic.
Move it to a separate library to allow re-using its code.
No functional changes.
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Message-ID: <d134ace64b55c827565ce68f0527e20c735f0d2e.1758196090.git.mchehab+huawei@kernel.org>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Diffstat (limited to 'tools/docs/sphinx-pre-install')
| -rwxr-xr-x | tools/docs/sphinx-pre-install | 147 |
1 files changed, 13 insertions, 134 deletions
diff --git a/tools/docs/sphinx-pre-install b/tools/docs/sphinx-pre-install index 895220c6d4f8..d6d673b7945c 100755 --- a/tools/docs/sphinx-pre-install +++ b/tools/docs/sphinx-pre-install @@ -32,20 +32,10 @@ import subprocess import sys from glob import glob +from lib.python_version import PythonVersion -def parse_version(version): - """Convert a major.minor.patch version into a tuple""" - return tuple(int(x) for x in version.split(".")) - - -def ver_str(version): - """Returns a version tuple as major.minor.patch""" - - return ".".join([str(x) for x in version]) - - -RECOMMENDED_VERSION = parse_version("3.4.3") -MIN_PYTHON_VERSION = parse_version("3.7") +RECOMMENDED_VERSION = PythonVersion("3.4.3").version +MIN_PYTHON_VERSION = PythonVersion("3.7").version class DepManager: @@ -236,121 +226,10 @@ class AncillaryMethods: return None @staticmethod - def get_python_version(cmd): - """ - Get python version from a Python binary. As we need to detect if - are out there newer python binaries, we can't rely on sys.release here. - """ - - result = SphinxDependencyChecker.run([cmd, "--version"], - capture_output=True, text=True) - version = result.stdout.strip() - - match = re.search(r"(\d+\.\d+\.\d+)", version) - if match: - return parse_version(match.group(1)) - - print(f"Can't parse version {version}") - return (0, 0, 0) - - @staticmethod - def find_python(min_version): - """ - Detect if are out there any python 3.xy version newer than the - current one. - - Note: this routine is limited to up to 2 digits for python3. We - may need to update it one day, hopefully on a distant future. - """ - patterns = [ - "python3.[0-9][0-9]", - "python3.[0-9]", - ] - - # Seek for a python binary newer than MIN_PYTHON_VERSION - python_cmd = [] - for path in os.getenv("PATH", "").split(":"): - for pattern in patterns: - for cmd in glob(os.path.join(path, pattern)): - if os.path.isfile(cmd) and os.access(cmd, os.X_OK): - version = SphinxDependencyChecker.get_python_version(cmd) - if version >= min_version: - python_cmd.append((version, cmd)) - - return sorted(python_cmd, reverse=True) - - @staticmethod - def check_python(min_version, show_alternatives=False, bail_out=False, - success_on_error=False): - """ - Check if the current python binary satisfies our minimal requirement - for Sphinx build. If not, re-run with a newer version if found. - """ - cur_ver = sys.version_info[:3] - if cur_ver >= MIN_PYTHON_VERSION: - ver = ver_str(cur_ver) - - # This could be useful for debugging purposes - if SphinxDependencyChecker.which("docutils"): - result = SphinxDependencyChecker.run(["docutils", "--version"], - capture_output=True, text=True) - ver = result.stdout.strip() - match = re.search(r"(\d+\.\d+\.\d+)", ver) - if match: - ver = match.group(1) - - print(f"Docutils version: {ver}") - - return - - python_ver = ver_str(cur_ver) - - available_versions = SphinxDependencyChecker.find_python(min_version) - if not available_versions: - print(f"ERROR: Python version {python_ver} is not spported anymore\n") - print(" Can't find a new version. This script may fail") - return - - script_path = os.path.abspath(sys.argv[0]) - - # Check possible alternatives - if available_versions: - new_python_cmd = available_versions[0][1] - else: - new_python_cmd = None - - if show_alternatives: - print("You could run, instead:") - for _, cmd in available_versions: - args = [cmd, script_path] + sys.argv[1:] - - cmd_str = " ".join(args) - print(f" {cmd_str}") - print() - - if bail_out: - msg = f"Python {python_ver} not supported. Bailing out" - if success_on_error: - print(msg, file=sys.stderr) - sys.exit(0) - else: - sys.exit(msg) - - print(f"Python {python_ver} not supported. Changing to {new_python_cmd}") - - # Restart script using the newer version - args = [new_python_cmd, script_path] + sys.argv[1:] - - try: - os.execv(new_python_cmd, args) - except OSError as e: - sys.exit(f"Failed to restart with {new_python_cmd}: {e}") - - @staticmethod def run(*args, **kwargs): """ Excecute a command, hiding its output by default. - Preserve comatibility with older Python versions. + Preserve compatibility with older Python versions. """ capture_output = kwargs.pop('capture_output', False) @@ -554,11 +433,11 @@ class MissingCheckers(AncillaryMethods): for line in result.stdout.split("\n"): match = re.match(r"^sphinx-build\s+([\d\.]+)(?:\+(?:/[\da-f]+)|b\d+)?\s*$", line) if match: - return parse_version(match.group(1)) + return PythonVersion.parse_version(match.group(1)) match = re.match(r"^Sphinx.*\s+([\d\.]+)\s*$", line) if match: - return parse_version(match.group(1)) + return PythonVersion.parse_version(match.group(1)) def check_sphinx(self, conf): """ @@ -569,7 +448,7 @@ class MissingCheckers(AncillaryMethods): for line in f: match = re.match(r"^\s*needs_sphinx\s*=\s*[\'\"]([\d\.]+)[\'\"]", line) if match: - self.min_version = parse_version(match.group(1)) + self.min_version = PythonVersion.parse_version(match.group(1)) break except IOError: sys.exit(f"Can't open {conf}") @@ -589,8 +468,8 @@ class MissingCheckers(AncillaryMethods): sys.exit(f"{sphinx} didn't return its version") if self.cur_version < self.min_version: - curver = ver_str(self.cur_version) - minver = ver_str(self.min_version) + curver = PythonVersion.ver_str(self.cur_version) + minver = PythonVersion.ver_str(self.min_version) print(f"ERROR: Sphinx version is {curver}. It should be >= {minver}") self.need_sphinx = 1 @@ -1331,7 +1210,7 @@ class SphinxDependencyChecker(MissingCheckers): else: if self.need_sphinx and ver >= self.min_version: return (f, ver) - elif parse_version(ver) > self.cur_version: + elif PythonVersion.parse_version(ver) > self.cur_version: return (f, ver) return ("", ver) @@ -1438,7 +1317,7 @@ class SphinxDependencyChecker(MissingCheckers): return if self.latest_avail_ver: - latest_avail_ver = ver_str(self.latest_avail_ver) + latest_avail_ver = PythonVersion.ver_str(self.latest_avail_ver) if not self.need_sphinx: # sphinx-build is present and its version is >= $min_version @@ -1534,7 +1413,7 @@ class SphinxDependencyChecker(MissingCheckers): else: print("Unknown OS") if self.cur_version != (0, 0, 0): - ver = ver_str(self.cur_version) + ver = PythonVersion.ver_str(self.cur_version) print(f"Sphinx version: {ver}\n") # Check the type of virtual env, depending on Python version @@ -1640,7 +1519,7 @@ def main(): checker = SphinxDependencyChecker(args) - checker.check_python(MIN_PYTHON_VERSION) + PythonVersion.check_python(MIN_PYTHON_VERSION) checker.check_needs() # Call main if not used as module |