1d43cd965SMauro Carvalho Chehab#!/usr/bin/env python3 2d43cd965SMauro Carvalho Chehab# SPDX-License-Identifier: GPL-2.0-or-later 3d43cd965SMauro Carvalho Chehab# Copyright (c) 2017-2025 Mauro Carvalho Chehab <mchehab+huawei@kernel.org> 4d43cd965SMauro Carvalho Chehab# 5d43cd965SMauro Carvalho Chehab# pylint: disable=C0103,C0114,C0115,C0116,C0301,C0302 6d43cd965SMauro Carvalho Chehab# pylint: disable=R0902,R0904,R0911,R0912,R0914,R0915,R1705,R1710,E1121 7d43cd965SMauro Carvalho Chehab 8d43cd965SMauro Carvalho Chehab# Note: this script requires at least Python 3.6 to run. 9d43cd965SMauro Carvalho Chehab# Don't add changes not compatible with it, it is meant to report 10d43cd965SMauro Carvalho Chehab# incompatible python versions. 11d43cd965SMauro Carvalho Chehab 12d43cd965SMauro Carvalho Chehab""" 13d43cd965SMauro Carvalho ChehabDependency checker for Sphinx documentation Kernel build. 14d43cd965SMauro Carvalho Chehab 15d43cd965SMauro Carvalho ChehabThis module provides tools to check for all required dependencies needed to 16d43cd965SMauro Carvalho Chehabbuild documentation using Sphinx, including system packages, Python modules 17d43cd965SMauro Carvalho Chehaband LaTeX packages for PDF generation. 18d43cd965SMauro Carvalho Chehab 19d43cd965SMauro Carvalho ChehabIt detect packages for a subset of Linux distributions used by Kernel 20d43cd965SMauro Carvalho Chehabmaintainers, showing hints and missing dependencies. 21d43cd965SMauro Carvalho Chehab 22d43cd965SMauro Carvalho ChehabThe main class SphinxDependencyChecker handles the dependency checking logic 23d43cd965SMauro Carvalho Chehaband provides recommendations for installing missing packages. It supports both 24d43cd965SMauro Carvalho Chehabsystem package installations and Python virtual environments. By default, 25d43cd965SMauro Carvalho Chehabsystem pacage install is recommended. 26d43cd965SMauro Carvalho Chehab""" 27d43cd965SMauro Carvalho Chehab 28d43cd965SMauro Carvalho Chehabimport argparse 29d43cd965SMauro Carvalho Chehabimport os 30d43cd965SMauro Carvalho Chehabimport re 31d43cd965SMauro Carvalho Chehabimport subprocess 32d43cd965SMauro Carvalho Chehabimport sys 33d43cd965SMauro Carvalho Chehabfrom glob import glob 34d43cd965SMauro Carvalho Chehab 35d43cd965SMauro Carvalho Chehab 36d43cd965SMauro Carvalho Chehabdef parse_version(version): 37d43cd965SMauro Carvalho Chehab """Convert a major.minor.patch version into a tuple""" 38d43cd965SMauro Carvalho Chehab return tuple(int(x) for x in version.split(".")) 39d43cd965SMauro Carvalho Chehab 40d43cd965SMauro Carvalho Chehab 41d43cd965SMauro Carvalho Chehabdef ver_str(version): 42d43cd965SMauro Carvalho Chehab """Returns a version tuple as major.minor.patch""" 43d43cd965SMauro Carvalho Chehab 44d43cd965SMauro Carvalho Chehab return ".".join([str(x) for x in version]) 45d43cd965SMauro Carvalho Chehab 46d43cd965SMauro Carvalho Chehab 47d43cd965SMauro Carvalho ChehabRECOMMENDED_VERSION = parse_version("3.4.3") 48d43cd965SMauro Carvalho ChehabMIN_PYTHON_VERSION = parse_version("3.7") 49d43cd965SMauro Carvalho Chehab 50d43cd965SMauro Carvalho Chehab 51d43cd965SMauro Carvalho Chehabclass DepManager: 52d43cd965SMauro Carvalho Chehab """ 53d43cd965SMauro Carvalho Chehab Manage package dependencies. There are three types of dependencies: 54d43cd965SMauro Carvalho Chehab 55d43cd965SMauro Carvalho Chehab - System: dependencies required for docs build; 56d43cd965SMauro Carvalho Chehab - Python: python dependencies for a native distro Sphinx install; 57d43cd965SMauro Carvalho Chehab - PDF: dependencies needed by PDF builds. 58d43cd965SMauro Carvalho Chehab 59d43cd965SMauro Carvalho Chehab Each dependency can be mandatory or optional. Not installing an optional 60d43cd965SMauro Carvalho Chehab dependency won't break the build, but will cause degradation at the 61d43cd965SMauro Carvalho Chehab docs output. 62d43cd965SMauro Carvalho Chehab """ 63d43cd965SMauro Carvalho Chehab 64d43cd965SMauro Carvalho Chehab # Internal types of dependencies. Don't use them outside DepManager class. 65d43cd965SMauro Carvalho Chehab _SYS_TYPE = 0 66d43cd965SMauro Carvalho Chehab _PHY_TYPE = 1 67d43cd965SMauro Carvalho Chehab _PDF_TYPE = 2 68d43cd965SMauro Carvalho Chehab 69d43cd965SMauro Carvalho Chehab # Dependencies visible outside the class. 70d43cd965SMauro Carvalho Chehab # The keys are tuple with: (type, is_mandatory flag). 71d43cd965SMauro Carvalho Chehab # 72d43cd965SMauro Carvalho Chehab # Currently we're not using all optional dep types. Yet, we'll keep all 73d43cd965SMauro Carvalho Chehab # possible combinations here. They're not many, and that makes easier 74d43cd965SMauro Carvalho Chehab # if later needed and for the name() method below 75d43cd965SMauro Carvalho Chehab 76d43cd965SMauro Carvalho Chehab SYSTEM_MANDATORY = (_SYS_TYPE, True) 77d43cd965SMauro Carvalho Chehab PYTHON_MANDATORY = (_PHY_TYPE, True) 78d43cd965SMauro Carvalho Chehab PDF_MANDATORY = (_PDF_TYPE, True) 79d43cd965SMauro Carvalho Chehab 80d43cd965SMauro Carvalho Chehab SYSTEM_OPTIONAL = (_SYS_TYPE, False) 81d43cd965SMauro Carvalho Chehab PYTHON_OPTIONAL = (_PHY_TYPE, False) 82d43cd965SMauro Carvalho Chehab PDF_OPTIONAL = (_PDF_TYPE, True) 83d43cd965SMauro Carvalho Chehab 84d43cd965SMauro Carvalho Chehab def __init__(self, pdf): 85d43cd965SMauro Carvalho Chehab """ 86d43cd965SMauro Carvalho Chehab Initialize internal vars: 87d43cd965SMauro Carvalho Chehab 88d43cd965SMauro Carvalho Chehab - missing: missing dependencies list, containing a distro-independent 89d43cd965SMauro Carvalho Chehab name for a missing dependency and its type. 90d43cd965SMauro Carvalho Chehab - missing_pkg: ancillary dict containing missing dependencies in 91d43cd965SMauro Carvalho Chehab distro namespace, organized by type. 92d43cd965SMauro Carvalho Chehab - need: total number of needed dependencies. Never cleaned. 93d43cd965SMauro Carvalho Chehab - optional: total number of optional dependencies. Never cleaned. 94d43cd965SMauro Carvalho Chehab - pdf: Is PDF support enabled? 95d43cd965SMauro Carvalho Chehab """ 96d43cd965SMauro Carvalho Chehab self.missing = {} 97d43cd965SMauro Carvalho Chehab self.missing_pkg = {} 98d43cd965SMauro Carvalho Chehab self.need = 0 99d43cd965SMauro Carvalho Chehab self.optional = 0 100d43cd965SMauro Carvalho Chehab self.pdf = pdf 101d43cd965SMauro Carvalho Chehab 102d43cd965SMauro Carvalho Chehab @staticmethod 103d43cd965SMauro Carvalho Chehab def name(dtype): 104d43cd965SMauro Carvalho Chehab """ 105d43cd965SMauro Carvalho Chehab Ancillary routine to output a warn/error message reporting 106d43cd965SMauro Carvalho Chehab missing dependencies. 107d43cd965SMauro Carvalho Chehab """ 108d43cd965SMauro Carvalho Chehab if dtype[0] == DepManager._SYS_TYPE: 109d43cd965SMauro Carvalho Chehab msg = "build" 110d43cd965SMauro Carvalho Chehab elif dtype[0] == DepManager._PHY_TYPE: 111d43cd965SMauro Carvalho Chehab msg = "Python" 112d43cd965SMauro Carvalho Chehab else: 113d43cd965SMauro Carvalho Chehab msg = "PDF" 114d43cd965SMauro Carvalho Chehab 115d43cd965SMauro Carvalho Chehab if dtype[1]: 116d43cd965SMauro Carvalho Chehab return f"ERROR: {msg} mandatory deps missing" 117d43cd965SMauro Carvalho Chehab else: 118d43cd965SMauro Carvalho Chehab return f"Warning: {msg} optional deps missing" 119d43cd965SMauro Carvalho Chehab 120d43cd965SMauro Carvalho Chehab @staticmethod 121d43cd965SMauro Carvalho Chehab def is_optional(dtype): 122d43cd965SMauro Carvalho Chehab """Ancillary routine to report if a dependency is optional""" 123d43cd965SMauro Carvalho Chehab return not dtype[1] 124d43cd965SMauro Carvalho Chehab 125d43cd965SMauro Carvalho Chehab @staticmethod 126d43cd965SMauro Carvalho Chehab def is_pdf(dtype): 127d43cd965SMauro Carvalho Chehab """Ancillary routine to report if a dependency is for PDF generation""" 128d43cd965SMauro Carvalho Chehab if dtype[0] == DepManager._PDF_TYPE: 129d43cd965SMauro Carvalho Chehab return True 130d43cd965SMauro Carvalho Chehab 131d43cd965SMauro Carvalho Chehab return False 132d43cd965SMauro Carvalho Chehab 133d43cd965SMauro Carvalho Chehab def add_package(self, package, dtype): 134d43cd965SMauro Carvalho Chehab """ 135d43cd965SMauro Carvalho Chehab Add a package at the self.missing() dictionary. 136d43cd965SMauro Carvalho Chehab Doesn't update missing_pkg. 137d43cd965SMauro Carvalho Chehab """ 138d43cd965SMauro Carvalho Chehab is_optional = DepManager.is_optional(dtype) 139d43cd965SMauro Carvalho Chehab self.missing[package] = dtype 140d43cd965SMauro Carvalho Chehab if is_optional: 141d43cd965SMauro Carvalho Chehab self.optional += 1 142d43cd965SMauro Carvalho Chehab else: 143d43cd965SMauro Carvalho Chehab self.need += 1 144d43cd965SMauro Carvalho Chehab 145d43cd965SMauro Carvalho Chehab def del_package(self, package): 146d43cd965SMauro Carvalho Chehab """ 147d43cd965SMauro Carvalho Chehab Remove a package at the self.missing() dictionary. 148d43cd965SMauro Carvalho Chehab Doesn't update missing_pkg. 149d43cd965SMauro Carvalho Chehab """ 150d43cd965SMauro Carvalho Chehab if package in self.missing: 151d43cd965SMauro Carvalho Chehab del self.missing[package] 152d43cd965SMauro Carvalho Chehab 153d43cd965SMauro Carvalho Chehab def clear_deps(self): 154d43cd965SMauro Carvalho Chehab """ 155d43cd965SMauro Carvalho Chehab Clear dependencies without changing needed/optional. 156d43cd965SMauro Carvalho Chehab 157d43cd965SMauro Carvalho Chehab This is an ackward way to have a separate section to recommend 158d43cd965SMauro Carvalho Chehab a package after system main dependencies. 159d43cd965SMauro Carvalho Chehab 160d43cd965SMauro Carvalho Chehab TODO: rework the logic to prevent needing it. 161d43cd965SMauro Carvalho Chehab """ 162d43cd965SMauro Carvalho Chehab 163d43cd965SMauro Carvalho Chehab self.missing = {} 164d43cd965SMauro Carvalho Chehab self.missing_pkg = {} 165d43cd965SMauro Carvalho Chehab 166d43cd965SMauro Carvalho Chehab def check_missing(self, progs): 167d43cd965SMauro Carvalho Chehab """ 168d43cd965SMauro Carvalho Chehab Update self.missing_pkg, using progs dict to convert from the 169d43cd965SMauro Carvalho Chehab agnostic package name to distro-specific one. 170d43cd965SMauro Carvalho Chehab 171d43cd965SMauro Carvalho Chehab Returns an string with the packages to be installed, sorted and 172d43cd965SMauro Carvalho Chehab with eventual duplicates removed. 173d43cd965SMauro Carvalho Chehab """ 174d43cd965SMauro Carvalho Chehab 175d43cd965SMauro Carvalho Chehab self.missing_pkg = {} 176d43cd965SMauro Carvalho Chehab 177d43cd965SMauro Carvalho Chehab for prog, dtype in sorted(self.missing.items()): 178d43cd965SMauro Carvalho Chehab # At least on some LTS distros like CentOS 7, texlive doesn't 179d43cd965SMauro Carvalho Chehab # provide all packages we need. When such distros are 180d43cd965SMauro Carvalho Chehab # detected, we have to disable PDF output. 181d43cd965SMauro Carvalho Chehab # 182d43cd965SMauro Carvalho Chehab # So, we need to ignore the packages that distros would 183d43cd965SMauro Carvalho Chehab # need for LaTeX to work 184d43cd965SMauro Carvalho Chehab if DepManager.is_pdf(dtype) and not self.pdf: 185d43cd965SMauro Carvalho Chehab self.optional -= 1 186d43cd965SMauro Carvalho Chehab continue 187d43cd965SMauro Carvalho Chehab 188d43cd965SMauro Carvalho Chehab if not dtype in self.missing_pkg: 189d43cd965SMauro Carvalho Chehab self.missing_pkg[dtype] = [] 190d43cd965SMauro Carvalho Chehab 191d43cd965SMauro Carvalho Chehab self.missing_pkg[dtype].append(progs.get(prog, prog)) 192d43cd965SMauro Carvalho Chehab 193d43cd965SMauro Carvalho Chehab install = [] 194d43cd965SMauro Carvalho Chehab for dtype, pkgs in self.missing_pkg.items(): 195d43cd965SMauro Carvalho Chehab install += pkgs 196d43cd965SMauro Carvalho Chehab 197d43cd965SMauro Carvalho Chehab return " ".join(sorted(set(install))) 198d43cd965SMauro Carvalho Chehab 199d43cd965SMauro Carvalho Chehab def warn_install(self): 200d43cd965SMauro Carvalho Chehab """ 201d43cd965SMauro Carvalho Chehab Emit warnings/errors related to missing packages. 202d43cd965SMauro Carvalho Chehab """ 203d43cd965SMauro Carvalho Chehab 204d43cd965SMauro Carvalho Chehab output_msg = "" 205d43cd965SMauro Carvalho Chehab 206d43cd965SMauro Carvalho Chehab for dtype in sorted(self.missing_pkg.keys()): 207d43cd965SMauro Carvalho Chehab progs = " ".join(sorted(set(self.missing_pkg[dtype]))) 208d43cd965SMauro Carvalho Chehab 209d43cd965SMauro Carvalho Chehab try: 210d43cd965SMauro Carvalho Chehab name = DepManager.name(dtype) 211d43cd965SMauro Carvalho Chehab output_msg += f'{name}:\t{progs}\n' 212d43cd965SMauro Carvalho Chehab except KeyError: 213d43cd965SMauro Carvalho Chehab raise KeyError(f"ERROR!!!: invalid dtype for {progs}: {dtype}") 214d43cd965SMauro Carvalho Chehab 215d43cd965SMauro Carvalho Chehab if output_msg: 216d43cd965SMauro Carvalho Chehab print(f"\n{output_msg}") 217d43cd965SMauro Carvalho Chehab 218d43cd965SMauro Carvalho Chehabclass AncillaryMethods: 219d43cd965SMauro Carvalho Chehab """ 220d43cd965SMauro Carvalho Chehab Ancillary methods that checks for missing dependencies for different 221d43cd965SMauro Carvalho Chehab types of types, like binaries, python modules, rpm deps, etc. 222d43cd965SMauro Carvalho Chehab """ 223d43cd965SMauro Carvalho Chehab 224d43cd965SMauro Carvalho Chehab @staticmethod 225d43cd965SMauro Carvalho Chehab def which(prog): 226d43cd965SMauro Carvalho Chehab """ 227d43cd965SMauro Carvalho Chehab Our own implementation of which(). We could instead use 228d43cd965SMauro Carvalho Chehab shutil.which(), but this function is simple enough. 229d43cd965SMauro Carvalho Chehab Probably faster to use this implementation than to import shutil. 230d43cd965SMauro Carvalho Chehab """ 231d43cd965SMauro Carvalho Chehab for path in os.environ.get("PATH", "").split(":"): 232d43cd965SMauro Carvalho Chehab full_path = os.path.join(path, prog) 233d43cd965SMauro Carvalho Chehab if os.access(full_path, os.X_OK): 234d43cd965SMauro Carvalho Chehab return full_path 235d43cd965SMauro Carvalho Chehab 236d43cd965SMauro Carvalho Chehab return None 237d43cd965SMauro Carvalho Chehab 238d43cd965SMauro Carvalho Chehab @staticmethod 239d43cd965SMauro Carvalho Chehab def get_python_version(cmd): 240d43cd965SMauro Carvalho Chehab """ 241d43cd965SMauro Carvalho Chehab Get python version from a Python binary. As we need to detect if 242d43cd965SMauro Carvalho Chehab are out there newer python binaries, we can't rely on sys.release here. 243d43cd965SMauro Carvalho Chehab """ 244d43cd965SMauro Carvalho Chehab 245d43cd965SMauro Carvalho Chehab result = SphinxDependencyChecker.run([cmd, "--version"], 246d43cd965SMauro Carvalho Chehab capture_output=True, text=True) 247d43cd965SMauro Carvalho Chehab version = result.stdout.strip() 248d43cd965SMauro Carvalho Chehab 249d43cd965SMauro Carvalho Chehab match = re.search(r"(\d+\.\d+\.\d+)", version) 250d43cd965SMauro Carvalho Chehab if match: 251d43cd965SMauro Carvalho Chehab return parse_version(match.group(1)) 252d43cd965SMauro Carvalho Chehab 253d43cd965SMauro Carvalho Chehab print(f"Can't parse version {version}") 254d43cd965SMauro Carvalho Chehab return (0, 0, 0) 255d43cd965SMauro Carvalho Chehab 256d43cd965SMauro Carvalho Chehab @staticmethod 257d43cd965SMauro Carvalho Chehab def find_python(): 258d43cd965SMauro Carvalho Chehab """ 259d43cd965SMauro Carvalho Chehab Detect if are out there any python 3.xy version newer than the 260d43cd965SMauro Carvalho Chehab current one. 261d43cd965SMauro Carvalho Chehab 262d43cd965SMauro Carvalho Chehab Note: this routine is limited to up to 2 digits for python3. We 263d43cd965SMauro Carvalho Chehab may need to update it one day, hopefully on a distant future. 264d43cd965SMauro Carvalho Chehab """ 265d43cd965SMauro Carvalho Chehab patterns = [ 266d43cd965SMauro Carvalho Chehab "python3.[0-9]", 267d43cd965SMauro Carvalho Chehab "python3.[0-9][0-9]", 268d43cd965SMauro Carvalho Chehab ] 269d43cd965SMauro Carvalho Chehab 270d43cd965SMauro Carvalho Chehab # Seek for a python binary newer than MIN_PYTHON_VERSION 271d43cd965SMauro Carvalho Chehab for path in os.getenv("PATH", "").split(":"): 272d43cd965SMauro Carvalho Chehab for pattern in patterns: 273d43cd965SMauro Carvalho Chehab for cmd in glob(os.path.join(path, pattern)): 274d43cd965SMauro Carvalho Chehab if os.path.isfile(cmd) and os.access(cmd, os.X_OK): 275d43cd965SMauro Carvalho Chehab version = SphinxDependencyChecker.get_python_version(cmd) 276d43cd965SMauro Carvalho Chehab if version >= MIN_PYTHON_VERSION: 277d43cd965SMauro Carvalho Chehab return cmd 278d43cd965SMauro Carvalho Chehab 279d43cd965SMauro Carvalho Chehab @staticmethod 280d43cd965SMauro Carvalho Chehab def check_python(): 281d43cd965SMauro Carvalho Chehab """ 282d43cd965SMauro Carvalho Chehab Check if the current python binary satisfies our minimal requirement 283d43cd965SMauro Carvalho Chehab for Sphinx build. If not, re-run with a newer version if found. 284d43cd965SMauro Carvalho Chehab """ 285d43cd965SMauro Carvalho Chehab cur_ver = sys.version_info[:3] 286d43cd965SMauro Carvalho Chehab if cur_ver >= MIN_PYTHON_VERSION: 287d43cd965SMauro Carvalho Chehab ver = ver_str(cur_ver) 288d43cd965SMauro Carvalho Chehab print(f"Python version: {ver}") 289d43cd965SMauro Carvalho Chehab 290d43cd965SMauro Carvalho Chehab # This could be useful for debugging purposes 291d43cd965SMauro Carvalho Chehab if SphinxDependencyChecker.which("docutils"): 292d43cd965SMauro Carvalho Chehab result = SphinxDependencyChecker.run(["docutils", "--version"], 293d43cd965SMauro Carvalho Chehab capture_output=True, text=True) 294d43cd965SMauro Carvalho Chehab ver = result.stdout.strip() 295d43cd965SMauro Carvalho Chehab match = re.search(r"(\d+\.\d+\.\d+)", ver) 296d43cd965SMauro Carvalho Chehab if match: 297d43cd965SMauro Carvalho Chehab ver = match.group(1) 298d43cd965SMauro Carvalho Chehab 299d43cd965SMauro Carvalho Chehab print(f"Docutils version: {ver}") 300d43cd965SMauro Carvalho Chehab 301d43cd965SMauro Carvalho Chehab return 302d43cd965SMauro Carvalho Chehab 303d43cd965SMauro Carvalho Chehab python_ver = ver_str(cur_ver) 304d43cd965SMauro Carvalho Chehab 305d43cd965SMauro Carvalho Chehab new_python_cmd = SphinxDependencyChecker.find_python() 306d43cd965SMauro Carvalho Chehab if not new_python_cmd: 307d43cd965SMauro Carvalho Chehab print(f"ERROR: Python version {python_ver} is not spported anymore\n") 308d43cd965SMauro Carvalho Chehab print(" Can't find a new version. This script may fail") 309d43cd965SMauro Carvalho Chehab return 310d43cd965SMauro Carvalho Chehab 311d43cd965SMauro Carvalho Chehab # Restart script using the newer version 312d43cd965SMauro Carvalho Chehab script_path = os.path.abspath(sys.argv[0]) 313d43cd965SMauro Carvalho Chehab args = [new_python_cmd, script_path] + sys.argv[1:] 314d43cd965SMauro Carvalho Chehab 315d43cd965SMauro Carvalho Chehab print(f"Python {python_ver} not supported. Changing to {new_python_cmd}") 316d43cd965SMauro Carvalho Chehab 317d43cd965SMauro Carvalho Chehab try: 318d43cd965SMauro Carvalho Chehab os.execv(new_python_cmd, args) 319d43cd965SMauro Carvalho Chehab except OSError as e: 320d43cd965SMauro Carvalho Chehab sys.exit(f"Failed to restart with {new_python_cmd}: {e}") 321d43cd965SMauro Carvalho Chehab 322d43cd965SMauro Carvalho Chehab @staticmethod 323d43cd965SMauro Carvalho Chehab def run(*args, **kwargs): 324d43cd965SMauro Carvalho Chehab """ 325d43cd965SMauro Carvalho Chehab Excecute a command, hiding its output by default. 326d43cd965SMauro Carvalho Chehab Preserve comatibility with older Python versions. 327d43cd965SMauro Carvalho Chehab """ 328d43cd965SMauro Carvalho Chehab 329d43cd965SMauro Carvalho Chehab capture_output = kwargs.pop('capture_output', False) 330d43cd965SMauro Carvalho Chehab 331d43cd965SMauro Carvalho Chehab if capture_output: 332d43cd965SMauro Carvalho Chehab if 'stdout' not in kwargs: 333d43cd965SMauro Carvalho Chehab kwargs['stdout'] = subprocess.PIPE 334d43cd965SMauro Carvalho Chehab if 'stderr' not in kwargs: 335d43cd965SMauro Carvalho Chehab kwargs['stderr'] = subprocess.PIPE 336d43cd965SMauro Carvalho Chehab else: 337d43cd965SMauro Carvalho Chehab if 'stdout' not in kwargs: 338d43cd965SMauro Carvalho Chehab kwargs['stdout'] = subprocess.DEVNULL 339d43cd965SMauro Carvalho Chehab if 'stderr' not in kwargs: 340d43cd965SMauro Carvalho Chehab kwargs['stderr'] = subprocess.DEVNULL 341d43cd965SMauro Carvalho Chehab 342d43cd965SMauro Carvalho Chehab # Don't break with older Python versions 343d43cd965SMauro Carvalho Chehab if 'text' in kwargs and sys.version_info < (3, 7): 344d43cd965SMauro Carvalho Chehab kwargs['universal_newlines'] = kwargs.pop('text') 345d43cd965SMauro Carvalho Chehab 346d43cd965SMauro Carvalho Chehab return subprocess.run(*args, **kwargs) 347d43cd965SMauro Carvalho Chehab 348d43cd965SMauro Carvalho Chehabclass MissingCheckers(AncillaryMethods): 349d43cd965SMauro Carvalho Chehab """ 350d43cd965SMauro Carvalho Chehab Contains some ancillary checkers for different types of binaries and 351d43cd965SMauro Carvalho Chehab package managers. 352d43cd965SMauro Carvalho Chehab """ 353d43cd965SMauro Carvalho Chehab 354d43cd965SMauro Carvalho Chehab def __init__(self, args, texlive): 355d43cd965SMauro Carvalho Chehab """ 356d43cd965SMauro Carvalho Chehab Initialize its internal variables 357d43cd965SMauro Carvalho Chehab """ 358d43cd965SMauro Carvalho Chehab self.pdf = args.pdf 359d43cd965SMauro Carvalho Chehab self.virtualenv = args.virtualenv 360d43cd965SMauro Carvalho Chehab self.version_check = args.version_check 361d43cd965SMauro Carvalho Chehab self.texlive = texlive 362d43cd965SMauro Carvalho Chehab 363d43cd965SMauro Carvalho Chehab self.min_version = (0, 0, 0) 364d43cd965SMauro Carvalho Chehab self.cur_version = (0, 0, 0) 365d43cd965SMauro Carvalho Chehab 366d43cd965SMauro Carvalho Chehab self.deps = DepManager(self.pdf) 367d43cd965SMauro Carvalho Chehab 368d43cd965SMauro Carvalho Chehab self.need_symlink = 0 369d43cd965SMauro Carvalho Chehab self.need_sphinx = 0 370d43cd965SMauro Carvalho Chehab 371d43cd965SMauro Carvalho Chehab self.verbose_warn_install = 1 372d43cd965SMauro Carvalho Chehab 373d43cd965SMauro Carvalho Chehab self.virtenv_dir = "" 374d43cd965SMauro Carvalho Chehab self.install = "" 375d43cd965SMauro Carvalho Chehab self.python_cmd = "" 376d43cd965SMauro Carvalho Chehab 377d43cd965SMauro Carvalho Chehab self.virtenv_prefix = ["sphinx_", "Sphinx_" ] 378d43cd965SMauro Carvalho Chehab 379d43cd965SMauro Carvalho Chehab def check_missing_file(self, files, package, dtype): 380d43cd965SMauro Carvalho Chehab """ 381d43cd965SMauro Carvalho Chehab Does the file exists? If not, add it to missing dependencies. 382d43cd965SMauro Carvalho Chehab """ 383d43cd965SMauro Carvalho Chehab for f in files: 384d43cd965SMauro Carvalho Chehab if os.path.exists(f): 385d43cd965SMauro Carvalho Chehab return 386d43cd965SMauro Carvalho Chehab self.deps.add_package(package, dtype) 387d43cd965SMauro Carvalho Chehab 388d43cd965SMauro Carvalho Chehab def check_program(self, prog, dtype): 389d43cd965SMauro Carvalho Chehab """ 390d43cd965SMauro Carvalho Chehab Does the program exists and it is at the PATH? 391d43cd965SMauro Carvalho Chehab If not, add it to missing dependencies. 392d43cd965SMauro Carvalho Chehab """ 393d43cd965SMauro Carvalho Chehab found = self.which(prog) 394d43cd965SMauro Carvalho Chehab if found: 395d43cd965SMauro Carvalho Chehab return found 396d43cd965SMauro Carvalho Chehab 397d43cd965SMauro Carvalho Chehab self.deps.add_package(prog, dtype) 398d43cd965SMauro Carvalho Chehab 399d43cd965SMauro Carvalho Chehab return None 400d43cd965SMauro Carvalho Chehab 401d43cd965SMauro Carvalho Chehab def check_perl_module(self, prog, dtype): 402d43cd965SMauro Carvalho Chehab """ 403d43cd965SMauro Carvalho Chehab Does perl have a dependency? Is it available? 404d43cd965SMauro Carvalho Chehab If not, add it to missing dependencies. 405d43cd965SMauro Carvalho Chehab 406d43cd965SMauro Carvalho Chehab Right now, we still need Perl for doc build, as it is required 407d43cd965SMauro Carvalho Chehab by some tools called at docs or kernel build time, like: 408d43cd965SMauro Carvalho Chehab 409d43cd965SMauro Carvalho Chehab scripts/documentation-file-ref-check 410d43cd965SMauro Carvalho Chehab 411d43cd965SMauro Carvalho Chehab Also, checkpatch is on Perl. 412d43cd965SMauro Carvalho Chehab """ 413d43cd965SMauro Carvalho Chehab 414d43cd965SMauro Carvalho Chehab # While testing with lxc download template, one of the 415d43cd965SMauro Carvalho Chehab # distros (Oracle) didn't have perl - nor even an option to install 416d43cd965SMauro Carvalho Chehab # before installing oraclelinux-release-el9 package. 417d43cd965SMauro Carvalho Chehab # 418d43cd965SMauro Carvalho Chehab # Check it before running an error. If perl is not there, 419d43cd965SMauro Carvalho Chehab # add it as a mandatory package, as some parts of the doc builder 420d43cd965SMauro Carvalho Chehab # needs it. 421d43cd965SMauro Carvalho Chehab if not self.which("perl"): 422d43cd965SMauro Carvalho Chehab self.deps.add_package("perl", DepManager.SYSTEM_MANDATORY) 423d43cd965SMauro Carvalho Chehab self.deps.add_package(prog, dtype) 424d43cd965SMauro Carvalho Chehab return 425d43cd965SMauro Carvalho Chehab 426d43cd965SMauro Carvalho Chehab try: 427d43cd965SMauro Carvalho Chehab self.run(["perl", f"-M{prog}", "-e", "1"], check=True) 428d43cd965SMauro Carvalho Chehab except subprocess.CalledProcessError: 429d43cd965SMauro Carvalho Chehab self.deps.add_package(prog, dtype) 430d43cd965SMauro Carvalho Chehab 431d43cd965SMauro Carvalho Chehab def check_python_module(self, module, is_optional=False): 432d43cd965SMauro Carvalho Chehab """ 433d43cd965SMauro Carvalho Chehab Does a python module exists outside venv? If not, add it to missing 434d43cd965SMauro Carvalho Chehab dependencies. 435d43cd965SMauro Carvalho Chehab """ 436d43cd965SMauro Carvalho Chehab if is_optional: 437d43cd965SMauro Carvalho Chehab dtype = DepManager.PYTHON_OPTIONAL 438d43cd965SMauro Carvalho Chehab else: 439d43cd965SMauro Carvalho Chehab dtype = DepManager.PYTHON_MANDATORY 440d43cd965SMauro Carvalho Chehab 441d43cd965SMauro Carvalho Chehab try: 442d43cd965SMauro Carvalho Chehab self.run([self.python_cmd, "-c", f"import {module}"], check=True) 443d43cd965SMauro Carvalho Chehab except subprocess.CalledProcessError: 444d43cd965SMauro Carvalho Chehab self.deps.add_package(module, dtype) 445d43cd965SMauro Carvalho Chehab 446d43cd965SMauro Carvalho Chehab def check_rpm_missing(self, pkgs, dtype): 447d43cd965SMauro Carvalho Chehab """ 448d43cd965SMauro Carvalho Chehab Does a rpm package exists? If not, add it to missing dependencies. 449d43cd965SMauro Carvalho Chehab """ 450d43cd965SMauro Carvalho Chehab for prog in pkgs: 451d43cd965SMauro Carvalho Chehab try: 452d43cd965SMauro Carvalho Chehab self.run(["rpm", "-q", prog], check=True) 453d43cd965SMauro Carvalho Chehab except subprocess.CalledProcessError: 454d43cd965SMauro Carvalho Chehab self.deps.add_package(prog, dtype) 455d43cd965SMauro Carvalho Chehab 456d43cd965SMauro Carvalho Chehab def check_pacman_missing(self, pkgs, dtype): 457d43cd965SMauro Carvalho Chehab """ 458d43cd965SMauro Carvalho Chehab Does a pacman package exists? If not, add it to missing dependencies. 459d43cd965SMauro Carvalho Chehab """ 460d43cd965SMauro Carvalho Chehab for prog in pkgs: 461d43cd965SMauro Carvalho Chehab try: 462d43cd965SMauro Carvalho Chehab self.run(["pacman", "-Q", prog], check=True) 463d43cd965SMauro Carvalho Chehab except subprocess.CalledProcessError: 464d43cd965SMauro Carvalho Chehab self.deps.add_package(prog, dtype) 465d43cd965SMauro Carvalho Chehab 466d43cd965SMauro Carvalho Chehab def check_missing_tex(self, is_optional=False): 467d43cd965SMauro Carvalho Chehab """ 468d43cd965SMauro Carvalho Chehab Does a LaTeX package exists? If not, add it to missing dependencies. 469d43cd965SMauro Carvalho Chehab """ 470d43cd965SMauro Carvalho Chehab if is_optional: 471d43cd965SMauro Carvalho Chehab dtype = DepManager.PDF_OPTIONAL 472d43cd965SMauro Carvalho Chehab else: 473d43cd965SMauro Carvalho Chehab dtype = DepManager.PDF_MANDATORY 474d43cd965SMauro Carvalho Chehab 475d43cd965SMauro Carvalho Chehab kpsewhich = self.which("kpsewhich") 476d43cd965SMauro Carvalho Chehab for prog, package in self.texlive.items(): 477d43cd965SMauro Carvalho Chehab 478d43cd965SMauro Carvalho Chehab # If kpsewhich is not there, just add it to deps 479d43cd965SMauro Carvalho Chehab if not kpsewhich: 480d43cd965SMauro Carvalho Chehab self.deps.add_package(package, dtype) 481d43cd965SMauro Carvalho Chehab continue 482d43cd965SMauro Carvalho Chehab 483d43cd965SMauro Carvalho Chehab # Check if the package is needed 484d43cd965SMauro Carvalho Chehab try: 485d43cd965SMauro Carvalho Chehab result = self.run( 486d43cd965SMauro Carvalho Chehab [kpsewhich, prog], stdout=subprocess.PIPE, text=True, check=True 487d43cd965SMauro Carvalho Chehab ) 488d43cd965SMauro Carvalho Chehab 489d43cd965SMauro Carvalho Chehab # Didn't find. Add it 490d43cd965SMauro Carvalho Chehab if not result.stdout.strip(): 491d43cd965SMauro Carvalho Chehab self.deps.add_package(package, dtype) 492d43cd965SMauro Carvalho Chehab 493d43cd965SMauro Carvalho Chehab except subprocess.CalledProcessError: 494d43cd965SMauro Carvalho Chehab # kpsewhich returned an error. Add it, just in case 495d43cd965SMauro Carvalho Chehab self.deps.add_package(package, dtype) 496d43cd965SMauro Carvalho Chehab 497d43cd965SMauro Carvalho Chehab def get_sphinx_fname(self): 498d43cd965SMauro Carvalho Chehab """ 499d43cd965SMauro Carvalho Chehab Gets the binary filename for sphinx-build. 500d43cd965SMauro Carvalho Chehab """ 501d43cd965SMauro Carvalho Chehab if "SPHINXBUILD" in os.environ: 502d43cd965SMauro Carvalho Chehab return os.environ["SPHINXBUILD"] 503d43cd965SMauro Carvalho Chehab 504d43cd965SMauro Carvalho Chehab fname = "sphinx-build" 505d43cd965SMauro Carvalho Chehab if self.which(fname): 506d43cd965SMauro Carvalho Chehab return fname 507d43cd965SMauro Carvalho Chehab 508d43cd965SMauro Carvalho Chehab fname = "sphinx-build-3" 509d43cd965SMauro Carvalho Chehab if self.which(fname): 510d43cd965SMauro Carvalho Chehab self.need_symlink = 1 511d43cd965SMauro Carvalho Chehab return fname 512d43cd965SMauro Carvalho Chehab 513d43cd965SMauro Carvalho Chehab return "" 514d43cd965SMauro Carvalho Chehab 515d43cd965SMauro Carvalho Chehab def get_sphinx_version(self, cmd): 516d43cd965SMauro Carvalho Chehab """ 517d43cd965SMauro Carvalho Chehab Gets sphinx-build version. 518d43cd965SMauro Carvalho Chehab """ 519d43cd965SMauro Carvalho Chehab try: 520d43cd965SMauro Carvalho Chehab result = self.run([cmd, "--version"], 521d43cd965SMauro Carvalho Chehab stdout=subprocess.PIPE, 522d43cd965SMauro Carvalho Chehab stderr=subprocess.STDOUT, 523d43cd965SMauro Carvalho Chehab text=True, check=True) 524d43cd965SMauro Carvalho Chehab except (subprocess.CalledProcessError, FileNotFoundError): 525d43cd965SMauro Carvalho Chehab return None 526d43cd965SMauro Carvalho Chehab 527d43cd965SMauro Carvalho Chehab for line in result.stdout.split("\n"): 528d43cd965SMauro Carvalho Chehab match = re.match(r"^sphinx-build\s+([\d\.]+)(?:\+(?:/[\da-f]+)|b\d+)?\s*$", line) 529d43cd965SMauro Carvalho Chehab if match: 530d43cd965SMauro Carvalho Chehab return parse_version(match.group(1)) 531d43cd965SMauro Carvalho Chehab 532d43cd965SMauro Carvalho Chehab match = re.match(r"^Sphinx.*\s+([\d\.]+)\s*$", line) 533d43cd965SMauro Carvalho Chehab if match: 534d43cd965SMauro Carvalho Chehab return parse_version(match.group(1)) 535d43cd965SMauro Carvalho Chehab 536d43cd965SMauro Carvalho Chehab def check_sphinx(self, conf): 537d43cd965SMauro Carvalho Chehab """ 538d43cd965SMauro Carvalho Chehab Checks Sphinx minimal requirements 539d43cd965SMauro Carvalho Chehab """ 540d43cd965SMauro Carvalho Chehab try: 541d43cd965SMauro Carvalho Chehab with open(conf, "r", encoding="utf-8") as f: 542d43cd965SMauro Carvalho Chehab for line in f: 543d43cd965SMauro Carvalho Chehab match = re.match(r"^\s*needs_sphinx\s*=\s*[\'\"]([\d\.]+)[\'\"]", line) 544d43cd965SMauro Carvalho Chehab if match: 545d43cd965SMauro Carvalho Chehab self.min_version = parse_version(match.group(1)) 546d43cd965SMauro Carvalho Chehab break 547d43cd965SMauro Carvalho Chehab except IOError: 548d43cd965SMauro Carvalho Chehab sys.exit(f"Can't open {conf}") 549d43cd965SMauro Carvalho Chehab 550d43cd965SMauro Carvalho Chehab if not self.min_version: 551d43cd965SMauro Carvalho Chehab sys.exit(f"Can't get needs_sphinx version from {conf}") 552d43cd965SMauro Carvalho Chehab 553d43cd965SMauro Carvalho Chehab self.virtenv_dir = self.virtenv_prefix[0] + "latest" 554d43cd965SMauro Carvalho Chehab 555d43cd965SMauro Carvalho Chehab sphinx = self.get_sphinx_fname() 556d43cd965SMauro Carvalho Chehab if not sphinx: 557d43cd965SMauro Carvalho Chehab self.need_sphinx = 1 558d43cd965SMauro Carvalho Chehab return 559d43cd965SMauro Carvalho Chehab 560d43cd965SMauro Carvalho Chehab self.cur_version = self.get_sphinx_version(sphinx) 561d43cd965SMauro Carvalho Chehab if not self.cur_version: 562d43cd965SMauro Carvalho Chehab sys.exit(f"{sphinx} didn't return its version") 563d43cd965SMauro Carvalho Chehab 564d43cd965SMauro Carvalho Chehab if self.cur_version < self.min_version: 565d43cd965SMauro Carvalho Chehab curver = ver_str(self.cur_version) 566d43cd965SMauro Carvalho Chehab minver = ver_str(self.min_version) 567d43cd965SMauro Carvalho Chehab 568d43cd965SMauro Carvalho Chehab print(f"ERROR: Sphinx version is {curver}. It should be >= {minver}") 569d43cd965SMauro Carvalho Chehab self.need_sphinx = 1 570d43cd965SMauro Carvalho Chehab return 571d43cd965SMauro Carvalho Chehab 572d43cd965SMauro Carvalho Chehab # On version check mode, just assume Sphinx has all mandatory deps 573d43cd965SMauro Carvalho Chehab if self.version_check and self.cur_version >= RECOMMENDED_VERSION: 574d43cd965SMauro Carvalho Chehab sys.exit(0) 575d43cd965SMauro Carvalho Chehab 576d43cd965SMauro Carvalho Chehab def catcheck(self, filename): 577d43cd965SMauro Carvalho Chehab """ 578d43cd965SMauro Carvalho Chehab Reads a file if it exists, returning as string. 579d43cd965SMauro Carvalho Chehab If not found, returns an empty string. 580d43cd965SMauro Carvalho Chehab """ 581d43cd965SMauro Carvalho Chehab if os.path.exists(filename): 582d43cd965SMauro Carvalho Chehab with open(filename, "r", encoding="utf-8") as f: 583d43cd965SMauro Carvalho Chehab return f.read().strip() 584d43cd965SMauro Carvalho Chehab return "" 585d43cd965SMauro Carvalho Chehab 586d43cd965SMauro Carvalho Chehab def get_system_release(self): 587d43cd965SMauro Carvalho Chehab """ 588d43cd965SMauro Carvalho Chehab Determine the system type. There's no unique way that would work 589d43cd965SMauro Carvalho Chehab with all distros with a minimal package install. So, several 590d43cd965SMauro Carvalho Chehab methods are used here. 591d43cd965SMauro Carvalho Chehab 592d43cd965SMauro Carvalho Chehab By default, it will use lsb_release function. If not available, it will 593d43cd965SMauro Carvalho Chehab fail back to reading the known different places where the distro name 594d43cd965SMauro Carvalho Chehab is stored. 595d43cd965SMauro Carvalho Chehab 596d43cd965SMauro Carvalho Chehab Several modern distros now have /etc/os-release, which usually have 597d43cd965SMauro Carvalho Chehab a decent coverage. 598d43cd965SMauro Carvalho Chehab """ 599d43cd965SMauro Carvalho Chehab 600d43cd965SMauro Carvalho Chehab system_release = "" 601d43cd965SMauro Carvalho Chehab 602d43cd965SMauro Carvalho Chehab if self.which("lsb_release"): 603d43cd965SMauro Carvalho Chehab result = self.run(["lsb_release", "-d"], capture_output=True, text=True) 604d43cd965SMauro Carvalho Chehab system_release = result.stdout.replace("Description:", "").strip() 605d43cd965SMauro Carvalho Chehab 606d43cd965SMauro Carvalho Chehab release_files = [ 607d43cd965SMauro Carvalho Chehab "/etc/system-release", 608d43cd965SMauro Carvalho Chehab "/etc/redhat-release", 609d43cd965SMauro Carvalho Chehab "/etc/lsb-release", 610d43cd965SMauro Carvalho Chehab "/etc/gentoo-release", 611d43cd965SMauro Carvalho Chehab ] 612d43cd965SMauro Carvalho Chehab 613d43cd965SMauro Carvalho Chehab if not system_release: 614d43cd965SMauro Carvalho Chehab for f in release_files: 615d43cd965SMauro Carvalho Chehab system_release = self.catcheck(f) 616d43cd965SMauro Carvalho Chehab if system_release: 617d43cd965SMauro Carvalho Chehab break 618d43cd965SMauro Carvalho Chehab 619d43cd965SMauro Carvalho Chehab # This seems more common than LSB these days 620d43cd965SMauro Carvalho Chehab if not system_release: 621d43cd965SMauro Carvalho Chehab os_var = {} 622d43cd965SMauro Carvalho Chehab try: 623d43cd965SMauro Carvalho Chehab with open("/etc/os-release", "r", encoding="utf-8") as f: 624d43cd965SMauro Carvalho Chehab for line in f: 625d43cd965SMauro Carvalho Chehab match = re.match(r"^([\w\d\_]+)=\"?([^\"]*)\"?\n", line) 626d43cd965SMauro Carvalho Chehab if match: 627d43cd965SMauro Carvalho Chehab os_var[match.group(1)] = match.group(2) 628d43cd965SMauro Carvalho Chehab 629d43cd965SMauro Carvalho Chehab system_release = os_var.get("NAME", "") 630d43cd965SMauro Carvalho Chehab if "VERSION_ID" in os_var: 631d43cd965SMauro Carvalho Chehab system_release += " " + os_var["VERSION_ID"] 632d43cd965SMauro Carvalho Chehab elif "VERSION" in os_var: 633d43cd965SMauro Carvalho Chehab system_release += " " + os_var["VERSION"] 634d43cd965SMauro Carvalho Chehab except IOError: 635d43cd965SMauro Carvalho Chehab pass 636d43cd965SMauro Carvalho Chehab 637d43cd965SMauro Carvalho Chehab if not system_release: 638d43cd965SMauro Carvalho Chehab system_release = self.catcheck("/etc/issue") 639d43cd965SMauro Carvalho Chehab 640d43cd965SMauro Carvalho Chehab system_release = system_release.strip() 641d43cd965SMauro Carvalho Chehab 642d43cd965SMauro Carvalho Chehab return system_release 643d43cd965SMauro Carvalho Chehab 644d43cd965SMauro Carvalho Chehabclass SphinxDependencyChecker(MissingCheckers): 645d43cd965SMauro Carvalho Chehab """ 646d43cd965SMauro Carvalho Chehab Main class for checking Sphinx documentation build dependencies. 647d43cd965SMauro Carvalho Chehab 648d43cd965SMauro Carvalho Chehab - Check for missing system packages; 649d43cd965SMauro Carvalho Chehab - Check for missing Python modules; 650d43cd965SMauro Carvalho Chehab - Check for missing LaTeX packages needed by PDF generation; 651d43cd965SMauro Carvalho Chehab - Propose Sphinx install via Python Virtual environment; 652d43cd965SMauro Carvalho Chehab - Propose Sphinx install via distro-specific package install. 653d43cd965SMauro Carvalho Chehab """ 654d43cd965SMauro Carvalho Chehab def __init__(self, args): 655d43cd965SMauro Carvalho Chehab """Initialize checker variables""" 656d43cd965SMauro Carvalho Chehab 657d43cd965SMauro Carvalho Chehab # List of required texlive packages on Fedora and OpenSuse 658d43cd965SMauro Carvalho Chehab texlive = { 659d43cd965SMauro Carvalho Chehab "amsfonts.sty": "texlive-amsfonts", 660d43cd965SMauro Carvalho Chehab "amsmath.sty": "texlive-amsmath", 661d43cd965SMauro Carvalho Chehab "amssymb.sty": "texlive-amsfonts", 662d43cd965SMauro Carvalho Chehab "amsthm.sty": "texlive-amscls", 663d43cd965SMauro Carvalho Chehab "anyfontsize.sty": "texlive-anyfontsize", 664d43cd965SMauro Carvalho Chehab "atbegshi.sty": "texlive-oberdiek", 665d43cd965SMauro Carvalho Chehab "bm.sty": "texlive-tools", 666d43cd965SMauro Carvalho Chehab "capt-of.sty": "texlive-capt-of", 667d43cd965SMauro Carvalho Chehab "cmap.sty": "texlive-cmap", 668d43cd965SMauro Carvalho Chehab "ctexhook.sty": "texlive-ctex", 669d43cd965SMauro Carvalho Chehab "ecrm1000.tfm": "texlive-ec", 670d43cd965SMauro Carvalho Chehab "eqparbox.sty": "texlive-eqparbox", 671d43cd965SMauro Carvalho Chehab "eu1enc.def": "texlive-euenc", 672d43cd965SMauro Carvalho Chehab "fancybox.sty": "texlive-fancybox", 673d43cd965SMauro Carvalho Chehab "fancyvrb.sty": "texlive-fancyvrb", 674d43cd965SMauro Carvalho Chehab "float.sty": "texlive-float", 675d43cd965SMauro Carvalho Chehab "fncychap.sty": "texlive-fncychap", 676d43cd965SMauro Carvalho Chehab "footnote.sty": "texlive-mdwtools", 677d43cd965SMauro Carvalho Chehab "framed.sty": "texlive-framed", 678d43cd965SMauro Carvalho Chehab "luatex85.sty": "texlive-luatex85", 679d43cd965SMauro Carvalho Chehab "multirow.sty": "texlive-multirow", 680d43cd965SMauro Carvalho Chehab "needspace.sty": "texlive-needspace", 681d43cd965SMauro Carvalho Chehab "palatino.sty": "texlive-psnfss", 682d43cd965SMauro Carvalho Chehab "parskip.sty": "texlive-parskip", 683d43cd965SMauro Carvalho Chehab "polyglossia.sty": "texlive-polyglossia", 684d43cd965SMauro Carvalho Chehab "tabulary.sty": "texlive-tabulary", 685d43cd965SMauro Carvalho Chehab "threeparttable.sty": "texlive-threeparttable", 686d43cd965SMauro Carvalho Chehab "titlesec.sty": "texlive-titlesec", 687d43cd965SMauro Carvalho Chehab "ucs.sty": "texlive-ucs", 688d43cd965SMauro Carvalho Chehab "upquote.sty": "texlive-upquote", 689d43cd965SMauro Carvalho Chehab "wrapfig.sty": "texlive-wrapfig", 690d43cd965SMauro Carvalho Chehab } 691d43cd965SMauro Carvalho Chehab 692d43cd965SMauro Carvalho Chehab super().__init__(args, texlive) 693d43cd965SMauro Carvalho Chehab 6949f51a1d6SMauro Carvalho Chehab self.need_pip = False 695d43cd965SMauro Carvalho Chehab self.rec_sphinx_upgrade = 0 696d43cd965SMauro Carvalho Chehab 697d43cd965SMauro Carvalho Chehab self.system_release = self.get_system_release() 698d43cd965SMauro Carvalho Chehab self.activate_cmd = "" 699d43cd965SMauro Carvalho Chehab 700d43cd965SMauro Carvalho Chehab # Some distros may not have a Sphinx shipped package compatible with 701d43cd965SMauro Carvalho Chehab # our minimal requirements 702d43cd965SMauro Carvalho Chehab self.package_supported = True 703d43cd965SMauro Carvalho Chehab 704d43cd965SMauro Carvalho Chehab # Recommend a new python version 705d43cd965SMauro Carvalho Chehab self.recommend_python = None 706d43cd965SMauro Carvalho Chehab 707d43cd965SMauro Carvalho Chehab # Certain hints are meant to be shown only once 708d43cd965SMauro Carvalho Chehab self.distro_msg = None 709d43cd965SMauro Carvalho Chehab 710d43cd965SMauro Carvalho Chehab self.latest_avail_ver = (0, 0, 0) 711d43cd965SMauro Carvalho Chehab self.venv_ver = (0, 0, 0) 712d43cd965SMauro Carvalho Chehab 713d43cd965SMauro Carvalho Chehab prefix = os.environ.get("srctree", ".") + "/" 714d43cd965SMauro Carvalho Chehab 715d43cd965SMauro Carvalho Chehab self.conf = prefix + "Documentation/conf.py" 716d43cd965SMauro Carvalho Chehab self.requirement_file = prefix + "Documentation/sphinx/requirements.txt" 717d43cd965SMauro Carvalho Chehab 718d43cd965SMauro Carvalho Chehab def get_install_progs(self, progs, cmd, extra=None): 719d43cd965SMauro Carvalho Chehab """ 720d43cd965SMauro Carvalho Chehab Check for missing dependencies using the provided program mapping. 721d43cd965SMauro Carvalho Chehab 722d43cd965SMauro Carvalho Chehab The actual distro-specific programs are mapped via progs argument. 723d43cd965SMauro Carvalho Chehab """ 724d43cd965SMauro Carvalho Chehab install = self.deps.check_missing(progs) 725d43cd965SMauro Carvalho Chehab 726d43cd965SMauro Carvalho Chehab if self.verbose_warn_install: 727d43cd965SMauro Carvalho Chehab self.deps.warn_install() 728d43cd965SMauro Carvalho Chehab 729d43cd965SMauro Carvalho Chehab if not install: 730d43cd965SMauro Carvalho Chehab return 731d43cd965SMauro Carvalho Chehab 732d43cd965SMauro Carvalho Chehab if cmd: 733d43cd965SMauro Carvalho Chehab if self.verbose_warn_install: 734d43cd965SMauro Carvalho Chehab msg = "You should run:" 735d43cd965SMauro Carvalho Chehab else: 736d43cd965SMauro Carvalho Chehab msg = "" 737d43cd965SMauro Carvalho Chehab 738d43cd965SMauro Carvalho Chehab if extra: 739d43cd965SMauro Carvalho Chehab msg += "\n\t" + extra.replace("\n", "\n\t") 740d43cd965SMauro Carvalho Chehab 741d43cd965SMauro Carvalho Chehab return(msg + "\n\tsudo " + cmd + " " + install) 742d43cd965SMauro Carvalho Chehab 743d43cd965SMauro Carvalho Chehab return None 744d43cd965SMauro Carvalho Chehab 745d43cd965SMauro Carvalho Chehab # 746d43cd965SMauro Carvalho Chehab # Distro-specific hints methods 747d43cd965SMauro Carvalho Chehab # 748d43cd965SMauro Carvalho Chehab 749d43cd965SMauro Carvalho Chehab def give_debian_hints(self): 750d43cd965SMauro Carvalho Chehab """ 751d43cd965SMauro Carvalho Chehab Provide package installation hints for Debian-based distros. 752d43cd965SMauro Carvalho Chehab """ 753d43cd965SMauro Carvalho Chehab progs = { 754d43cd965SMauro Carvalho Chehab "Pod::Usage": "perl-modules", 755d43cd965SMauro Carvalho Chehab "convert": "imagemagick", 756d43cd965SMauro Carvalho Chehab "dot": "graphviz", 757d43cd965SMauro Carvalho Chehab "ensurepip": "python3-venv", 758d43cd965SMauro Carvalho Chehab "python-sphinx": "python3-sphinx", 759d43cd965SMauro Carvalho Chehab "rsvg-convert": "librsvg2-bin", 760d43cd965SMauro Carvalho Chehab "virtualenv": "virtualenv", 761d43cd965SMauro Carvalho Chehab "xelatex": "texlive-xetex", 762d43cd965SMauro Carvalho Chehab "yaml": "python3-yaml", 763d43cd965SMauro Carvalho Chehab } 764d43cd965SMauro Carvalho Chehab 765d43cd965SMauro Carvalho Chehab if self.pdf: 766d43cd965SMauro Carvalho Chehab pdf_pkgs = { 767d43cd965SMauro Carvalho Chehab "fonts-dejavu": [ 768d43cd965SMauro Carvalho Chehab "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 769d43cd965SMauro Carvalho Chehab ], 770d43cd965SMauro Carvalho Chehab "fonts-noto-cjk": [ 771d43cd965SMauro Carvalho Chehab "/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc", 772d43cd965SMauro Carvalho Chehab "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc", 773d43cd965SMauro Carvalho Chehab "/usr/share/fonts/opentype/noto/NotoSerifCJK-Regular.ttc", 774d43cd965SMauro Carvalho Chehab ], 7754e9a563fSMauro Carvalho Chehab "tex-gyre": [ 7764e9a563fSMauro Carvalho Chehab "/usr/share/texmf/tex/latex/tex-gyre/tgtermes.sty" 7774e9a563fSMauro Carvalho Chehab ], 7784e9a563fSMauro Carvalho Chehab "texlive-fonts-recommended": [ 7794e9a563fSMauro Carvalho Chehab "/usr/share/texlive/texmf-dist/fonts/tfm/adobe/zapfding/pzdr.tfm", 7804e9a563fSMauro Carvalho Chehab ], 7814e9a563fSMauro Carvalho Chehab "texlive-lang-chinese": [ 7824e9a563fSMauro Carvalho Chehab "/usr/share/texlive/texmf-dist/tex/latex/ctex/ctexhook.sty", 7834e9a563fSMauro Carvalho Chehab ], 784d43cd965SMauro Carvalho Chehab } 785d43cd965SMauro Carvalho Chehab 786d43cd965SMauro Carvalho Chehab for package, files in pdf_pkgs.items(): 787d43cd965SMauro Carvalho Chehab self.check_missing_file(files, package, DepManager.PDF_MANDATORY) 788d43cd965SMauro Carvalho Chehab 789d43cd965SMauro Carvalho Chehab self.check_program("dvipng", DepManager.PDF_MANDATORY) 790d43cd965SMauro Carvalho Chehab 791491a9951SMauro Carvalho Chehab if not self.distro_msg: 792491a9951SMauro Carvalho Chehab self.distro_msg = \ 793491a9951SMauro Carvalho Chehab "Note: ImageMagick is broken on some distros, affecting PDF output. For more details:\n" \ 794491a9951SMauro Carvalho Chehab "\thttps://askubuntu.com/questions/1158894/imagemagick-still-broken-using-with-usr-bin-convert" 795491a9951SMauro Carvalho Chehab 796d43cd965SMauro Carvalho Chehab return self.get_install_progs(progs, "apt-get install") 797d43cd965SMauro Carvalho Chehab 798d43cd965SMauro Carvalho Chehab def give_redhat_hints(self): 799d43cd965SMauro Carvalho Chehab """ 800d43cd965SMauro Carvalho Chehab Provide package installation hints for RedHat-based distros 801d43cd965SMauro Carvalho Chehab (Fedora, RHEL and RHEL-based variants). 802d43cd965SMauro Carvalho Chehab """ 803d43cd965SMauro Carvalho Chehab progs = { 804d43cd965SMauro Carvalho Chehab "Pod::Usage": "perl-Pod-Usage", 805d43cd965SMauro Carvalho Chehab "convert": "ImageMagick", 806d43cd965SMauro Carvalho Chehab "dot": "graphviz", 807d43cd965SMauro Carvalho Chehab "python-sphinx": "python3-sphinx", 808d43cd965SMauro Carvalho Chehab "rsvg-convert": "librsvg2-tools", 809d43cd965SMauro Carvalho Chehab "virtualenv": "python3-virtualenv", 810d43cd965SMauro Carvalho Chehab "xelatex": "texlive-xetex-bin", 811d43cd965SMauro Carvalho Chehab "yaml": "python3-pyyaml", 812d43cd965SMauro Carvalho Chehab } 813d43cd965SMauro Carvalho Chehab 814d43cd965SMauro Carvalho Chehab fedora_tex_pkgs = [ 815d43cd965SMauro Carvalho Chehab "dejavu-sans-fonts", 816d43cd965SMauro Carvalho Chehab "dejavu-sans-mono-fonts", 817d43cd965SMauro Carvalho Chehab "dejavu-serif-fonts", 818d43cd965SMauro Carvalho Chehab "texlive-collection-fontsrecommended", 819d43cd965SMauro Carvalho Chehab "texlive-collection-latex", 820d43cd965SMauro Carvalho Chehab "texlive-xecjk", 821d43cd965SMauro Carvalho Chehab ] 822d43cd965SMauro Carvalho Chehab 823d43cd965SMauro Carvalho Chehab fedora = False 824d43cd965SMauro Carvalho Chehab rel = None 825d43cd965SMauro Carvalho Chehab 826d43cd965SMauro Carvalho Chehab match = re.search(r"(release|Linux)\s+(\d+)", self.system_release) 827d43cd965SMauro Carvalho Chehab if match: 828d43cd965SMauro Carvalho Chehab rel = int(match.group(2)) 829d43cd965SMauro Carvalho Chehab 830d43cd965SMauro Carvalho Chehab if not rel: 831d43cd965SMauro Carvalho Chehab print("Couldn't identify release number") 832d43cd965SMauro Carvalho Chehab noto_sans_redhat = None 833d43cd965SMauro Carvalho Chehab self.pdf = False 834d43cd965SMauro Carvalho Chehab elif re.search("Fedora", self.system_release): 835d43cd965SMauro Carvalho Chehab # Fedora 38 and upper use this CJK font 836d43cd965SMauro Carvalho Chehab 837d43cd965SMauro Carvalho Chehab noto_sans_redhat = "google-noto-sans-cjk-fonts" 838d43cd965SMauro Carvalho Chehab fedora = True 839d43cd965SMauro Carvalho Chehab else: 840d43cd965SMauro Carvalho Chehab # Almalinux, CentOS, RHEL, ... 841d43cd965SMauro Carvalho Chehab 842d43cd965SMauro Carvalho Chehab # at least up to version 9 (and Fedora < 38), that's the CJK font 843d43cd965SMauro Carvalho Chehab noto_sans_redhat = "google-noto-sans-cjk-ttc-fonts" 844d43cd965SMauro Carvalho Chehab 845d43cd965SMauro Carvalho Chehab progs["virtualenv"] = "python-virtualenv" 846d43cd965SMauro Carvalho Chehab 847d43cd965SMauro Carvalho Chehab if not rel or rel < 8: 848d43cd965SMauro Carvalho Chehab print("ERROR: Distro not supported. Too old?") 849d43cd965SMauro Carvalho Chehab return 850d43cd965SMauro Carvalho Chehab 851d43cd965SMauro Carvalho Chehab # RHEL 8 uses Python 3.6, which is not compatible with 852d43cd965SMauro Carvalho Chehab # the build system anymore. Suggest Python 3.11 853d43cd965SMauro Carvalho Chehab if rel == 8: 8549f51a1d6SMauro Carvalho Chehab self.check_program("python3.9", DepManager.SYSTEM_MANDATORY) 8559f51a1d6SMauro Carvalho Chehab progs["python3.9"] = "python39" 8569f51a1d6SMauro Carvalho Chehab progs["yaml"] = "python39-pyyaml" 8579f51a1d6SMauro Carvalho Chehab 858d43cd965SMauro Carvalho Chehab self.recommend_python = True 859d43cd965SMauro Carvalho Chehab 8609f51a1d6SMauro Carvalho Chehab # There's no python39-sphinx package. Only pip is supported 8619f51a1d6SMauro Carvalho Chehab self.package_supported = False 8629f51a1d6SMauro Carvalho Chehab 863d43cd965SMauro Carvalho Chehab if not self.distro_msg: 864d43cd965SMauro Carvalho Chehab self.distro_msg = \ 865d43cd965SMauro Carvalho Chehab "Note: RHEL-based distros typically require extra repositories.\n" \ 866d43cd965SMauro Carvalho Chehab "For most, enabling epel and crb are enough:\n" \ 867d43cd965SMauro Carvalho Chehab "\tsudo dnf install -y epel-release\n" \ 868d43cd965SMauro Carvalho Chehab "\tsudo dnf config-manager --set-enabled crb\n" \ 869d43cd965SMauro Carvalho Chehab "Yet, some may have other required repositories. Those commands could be useful:\n" \ 870d43cd965SMauro Carvalho Chehab "\tsudo dnf repolist all\n" \ 871d43cd965SMauro Carvalho Chehab "\tsudo dnf repoquery --available --info <pkgs>\n" \ 872d43cd965SMauro Carvalho Chehab "\tsudo dnf config-manager --set-enabled '*' # enable all - probably not what you want" 873d43cd965SMauro Carvalho Chehab 874d43cd965SMauro Carvalho Chehab if self.pdf: 875d43cd965SMauro Carvalho Chehab pdf_pkgs = [ 876d43cd965SMauro Carvalho Chehab "/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc", 877d43cd965SMauro Carvalho Chehab "/usr/share/fonts/google-noto-sans-cjk-fonts/NotoSansCJK-Regular.ttc", 878d43cd965SMauro Carvalho Chehab ] 879d43cd965SMauro Carvalho Chehab 880d43cd965SMauro Carvalho Chehab self.check_missing_file(pdf_pkgs, noto_sans_redhat, DepManager.PDF_MANDATORY) 881d43cd965SMauro Carvalho Chehab 882d43cd965SMauro Carvalho Chehab self.check_rpm_missing(fedora_tex_pkgs, DepManager.PDF_MANDATORY) 883d43cd965SMauro Carvalho Chehab 884d43cd965SMauro Carvalho Chehab self.check_missing_tex(DepManager.PDF_MANDATORY) 885d43cd965SMauro Carvalho Chehab 886d43cd965SMauro Carvalho Chehab # There's no texlive-ctex on RHEL 8 repositories. This will 887d43cd965SMauro Carvalho Chehab # likely affect CJK pdf build only. 888d43cd965SMauro Carvalho Chehab if not fedora and rel == 8: 889d43cd965SMauro Carvalho Chehab self.deps.del_package("texlive-ctex") 890d43cd965SMauro Carvalho Chehab 891d43cd965SMauro Carvalho Chehab return self.get_install_progs(progs, "dnf install") 892d43cd965SMauro Carvalho Chehab 893d43cd965SMauro Carvalho Chehab def give_opensuse_hints(self): 894d43cd965SMauro Carvalho Chehab """ 895d43cd965SMauro Carvalho Chehab Provide package installation hints for openSUSE-based distros 896d43cd965SMauro Carvalho Chehab (Leap and Tumbleweed). 897d43cd965SMauro Carvalho Chehab """ 898d43cd965SMauro Carvalho Chehab progs = { 899d43cd965SMauro Carvalho Chehab "Pod::Usage": "perl-Pod-Usage", 900d43cd965SMauro Carvalho Chehab "convert": "ImageMagick", 901d43cd965SMauro Carvalho Chehab "dot": "graphviz", 902d43cd965SMauro Carvalho Chehab "python-sphinx": "python3-sphinx", 903d43cd965SMauro Carvalho Chehab "virtualenv": "python3-virtualenv", 904b2d5d61cSMauro Carvalho Chehab "xelatex": "texlive-xetex-bin texlive-dejavu", 905d43cd965SMauro Carvalho Chehab "yaml": "python3-pyyaml", 906d43cd965SMauro Carvalho Chehab } 907d43cd965SMauro Carvalho Chehab 908d43cd965SMauro Carvalho Chehab suse_tex_pkgs = [ 909d43cd965SMauro Carvalho Chehab "texlive-babel-english", 910d43cd965SMauro Carvalho Chehab "texlive-caption", 911d43cd965SMauro Carvalho Chehab "texlive-colortbl", 912d43cd965SMauro Carvalho Chehab "texlive-courier", 913d43cd965SMauro Carvalho Chehab "texlive-dvips", 914d43cd965SMauro Carvalho Chehab "texlive-helvetic", 915d43cd965SMauro Carvalho Chehab "texlive-makeindex", 916d43cd965SMauro Carvalho Chehab "texlive-metafont", 917d43cd965SMauro Carvalho Chehab "texlive-metapost", 918d43cd965SMauro Carvalho Chehab "texlive-palatino", 919d43cd965SMauro Carvalho Chehab "texlive-preview", 920d43cd965SMauro Carvalho Chehab "texlive-times", 921d43cd965SMauro Carvalho Chehab "texlive-zapfchan", 922d43cd965SMauro Carvalho Chehab "texlive-zapfding", 923d43cd965SMauro Carvalho Chehab ] 924d43cd965SMauro Carvalho Chehab 925d43cd965SMauro Carvalho Chehab progs["latexmk"] = "texlive-latexmk-bin" 926d43cd965SMauro Carvalho Chehab 927d43cd965SMauro Carvalho Chehab match = re.search(r"(Leap)\s+(\d+).(\d)", self.system_release) 928d43cd965SMauro Carvalho Chehab if match: 929d43cd965SMauro Carvalho Chehab rel = int(match.group(2)) 930d43cd965SMauro Carvalho Chehab 931d43cd965SMauro Carvalho Chehab # Leap 15.x uses Python 3.6, which is not compatible with 932d43cd965SMauro Carvalho Chehab # the build system anymore. Suggest Python 3.11 933d43cd965SMauro Carvalho Chehab if rel == 15: 934d43cd965SMauro Carvalho Chehab if not self.which(self.python_cmd): 9359f51a1d6SMauro Carvalho Chehab self.check_program("python3.11", DepManager.SYSTEM_MANDATORY) 9369f51a1d6SMauro Carvalho Chehab progs["python3.11"] = "python311" 937d43cd965SMauro Carvalho Chehab self.recommend_python = True 938d43cd965SMauro Carvalho Chehab 939d43cd965SMauro Carvalho Chehab progs.update({ 940b2d5d61cSMauro Carvalho Chehab "python-sphinx": "python311-Sphinx python311-Sphinx-latex", 941d43cd965SMauro Carvalho Chehab "virtualenv": "python311-virtualenv", 942d43cd965SMauro Carvalho Chehab "yaml": "python311-PyYAML", 943d43cd965SMauro Carvalho Chehab }) 944d43cd965SMauro Carvalho Chehab else: 945d43cd965SMauro Carvalho Chehab # Tumbleweed defaults to Python 3.11 946d43cd965SMauro Carvalho Chehab 947d43cd965SMauro Carvalho Chehab progs.update({ 948b2d5d61cSMauro Carvalho Chehab "python-sphinx": "python313-Sphinx python313-Sphinx-latex", 949d43cd965SMauro Carvalho Chehab "virtualenv": "python313-virtualenv", 950d43cd965SMauro Carvalho Chehab "yaml": "python313-PyYAML", 951d43cd965SMauro Carvalho Chehab }) 952d43cd965SMauro Carvalho Chehab 953d43cd965SMauro Carvalho Chehab # FIXME: add support for installing CJK fonts 954d43cd965SMauro Carvalho Chehab # 955d43cd965SMauro Carvalho Chehab # I tried hard, but was unable to find a way to install 956d43cd965SMauro Carvalho Chehab # "Noto Sans CJK SC" on openSUSE 957d43cd965SMauro Carvalho Chehab 958d43cd965SMauro Carvalho Chehab if self.pdf: 959d43cd965SMauro Carvalho Chehab self.check_rpm_missing(suse_tex_pkgs, DepManager.PDF_MANDATORY) 960d43cd965SMauro Carvalho Chehab if self.pdf: 961d43cd965SMauro Carvalho Chehab self.check_missing_tex() 962d43cd965SMauro Carvalho Chehab 963d43cd965SMauro Carvalho Chehab return self.get_install_progs(progs, "zypper install --no-recommends") 964d43cd965SMauro Carvalho Chehab 965d43cd965SMauro Carvalho Chehab def give_mageia_hints(self): 966d43cd965SMauro Carvalho Chehab """ 967d43cd965SMauro Carvalho Chehab Provide package installation hints for Mageia and OpenMandriva. 968d43cd965SMauro Carvalho Chehab """ 969d43cd965SMauro Carvalho Chehab progs = { 970d43cd965SMauro Carvalho Chehab "Pod::Usage": "perl-Pod-Usage", 971d43cd965SMauro Carvalho Chehab "convert": "ImageMagick", 972d43cd965SMauro Carvalho Chehab "dot": "graphviz", 973d43cd965SMauro Carvalho Chehab "python-sphinx": "python3-sphinx", 974d43cd965SMauro Carvalho Chehab "rsvg-convert": "librsvg2", 975d43cd965SMauro Carvalho Chehab "virtualenv": "python3-virtualenv", 976d43cd965SMauro Carvalho Chehab "xelatex": "texlive", 977d43cd965SMauro Carvalho Chehab "yaml": "python3-yaml", 978d43cd965SMauro Carvalho Chehab } 979d43cd965SMauro Carvalho Chehab 980d43cd965SMauro Carvalho Chehab tex_pkgs = [ 981d43cd965SMauro Carvalho Chehab "texlive-fontsextra", 982c71c5d6dSMauro Carvalho Chehab "texlive-fonts-asian", 983c71c5d6dSMauro Carvalho Chehab "fonts-ttf-dejavu", 984d43cd965SMauro Carvalho Chehab ] 985d43cd965SMauro Carvalho Chehab 986d43cd965SMauro Carvalho Chehab if re.search(r"OpenMandriva", self.system_release): 987d43cd965SMauro Carvalho Chehab packager_cmd = "dnf install" 988d43cd965SMauro Carvalho Chehab noto_sans = "noto-sans-cjk-fonts" 989b51f8c12SMauro Carvalho Chehab tex_pkgs = [ 990b51f8c12SMauro Carvalho Chehab "texlive-collection-basic", 991b51f8c12SMauro Carvalho Chehab "texlive-collection-langcjk", 992b51f8c12SMauro Carvalho Chehab "texlive-collection-fontsextra", 993b51f8c12SMauro Carvalho Chehab "texlive-collection-fontsrecommended" 994b51f8c12SMauro Carvalho Chehab ] 995d43cd965SMauro Carvalho Chehab 996d43cd965SMauro Carvalho Chehab # Tested on OpenMandriva Lx 4.3 997d43cd965SMauro Carvalho Chehab progs["convert"] = "imagemagick" 998d43cd965SMauro Carvalho Chehab progs["yaml"] = "python-pyyaml" 9996170b1eaSMauro Carvalho Chehab progs["python-virtualenv"] = "python-virtualenv" 10006170b1eaSMauro Carvalho Chehab progs["python-sphinx"] = "python-sphinx" 1001b51f8c12SMauro Carvalho Chehab progs["xelatex"] = "texlive" 10026170b1eaSMauro Carvalho Chehab 10036170b1eaSMauro Carvalho Chehab self.check_program("python-virtualenv", DepManager.PYTHON_MANDATORY) 10046170b1eaSMauro Carvalho Chehab 10056170b1eaSMauro Carvalho Chehab # On my tests with openMandriva LX 4.0 docker image, upgraded 10066170b1eaSMauro Carvalho Chehab # to 4.3, python-virtualenv package is broken: it is missing 10076170b1eaSMauro Carvalho Chehab # ensurepip. Without it, the alternative would be to run: 10086170b1eaSMauro Carvalho Chehab # python3 -m venv --without-pip ~/sphinx_latest, but running 10096170b1eaSMauro Carvalho Chehab # pip there won't install sphinx at venv. 10106170b1eaSMauro Carvalho Chehab # 10116170b1eaSMauro Carvalho Chehab # Add a note about that. 10126170b1eaSMauro Carvalho Chehab 10136170b1eaSMauro Carvalho Chehab if not self.distro_msg: 10146170b1eaSMauro Carvalho Chehab self.distro_msg = \ 1015b51f8c12SMauro Carvalho Chehab "Notes:\n"\ 1016b51f8c12SMauro Carvalho Chehab "1. for venv, ensurepip could be broken, preventing its install method.\n" \ 1017b51f8c12SMauro Carvalho Chehab "2. at least on OpenMandriva LX 4.3, texlive packages seem broken" 1018d43cd965SMauro Carvalho Chehab 1019d43cd965SMauro Carvalho Chehab else: 1020d43cd965SMauro Carvalho Chehab packager_cmd = "urpmi" 1021d43cd965SMauro Carvalho Chehab noto_sans = "google-noto-sans-cjk-ttc-fonts" 1022d43cd965SMauro Carvalho Chehab 1023d43cd965SMauro Carvalho Chehab progs["latexmk"] = "texlive-collection-basic" 1024d43cd965SMauro Carvalho Chehab 1025d43cd965SMauro Carvalho Chehab if self.pdf: 1026d43cd965SMauro Carvalho Chehab pdf_pkgs = [ 1027d43cd965SMauro Carvalho Chehab "/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc", 1028d43cd965SMauro Carvalho Chehab "/usr/share/fonts/TTF/NotoSans-Regular.ttf", 1029d43cd965SMauro Carvalho Chehab ] 1030d43cd965SMauro Carvalho Chehab 1031d43cd965SMauro Carvalho Chehab self.check_missing_file(pdf_pkgs, noto_sans, DepManager.PDF_MANDATORY) 1032d43cd965SMauro Carvalho Chehab self.check_rpm_missing(tex_pkgs, DepManager.PDF_MANDATORY) 1033d43cd965SMauro Carvalho Chehab 1034d43cd965SMauro Carvalho Chehab return self.get_install_progs(progs, packager_cmd) 1035d43cd965SMauro Carvalho Chehab 1036d43cd965SMauro Carvalho Chehab def give_arch_linux_hints(self): 1037d43cd965SMauro Carvalho Chehab """ 1038d43cd965SMauro Carvalho Chehab Provide package installation hints for ArchLinux. 1039d43cd965SMauro Carvalho Chehab """ 1040d43cd965SMauro Carvalho Chehab progs = { 1041d43cd965SMauro Carvalho Chehab "convert": "imagemagick", 1042d43cd965SMauro Carvalho Chehab "dot": "graphviz", 1043d43cd965SMauro Carvalho Chehab "latexmk": "texlive-core", 1044d43cd965SMauro Carvalho Chehab "rsvg-convert": "extra/librsvg", 1045d43cd965SMauro Carvalho Chehab "virtualenv": "python-virtualenv", 1046d43cd965SMauro Carvalho Chehab "xelatex": "texlive-xetex", 1047d43cd965SMauro Carvalho Chehab "yaml": "python-yaml", 1048d43cd965SMauro Carvalho Chehab } 1049d43cd965SMauro Carvalho Chehab 1050d43cd965SMauro Carvalho Chehab archlinux_tex_pkgs = [ 1051*c6e23912SMauro Carvalho Chehab "texlive-basic", 1052*c6e23912SMauro Carvalho Chehab "texlive-binextra", 1053d43cd965SMauro Carvalho Chehab "texlive-core", 1054*c6e23912SMauro Carvalho Chehab "texlive-fontsrecommended", 1055*c6e23912SMauro Carvalho Chehab "texlive-langchinese", 1056*c6e23912SMauro Carvalho Chehab "texlive-langcjk", 1057d43cd965SMauro Carvalho Chehab "texlive-latexextra", 1058d43cd965SMauro Carvalho Chehab "ttf-dejavu", 1059d43cd965SMauro Carvalho Chehab ] 1060d43cd965SMauro Carvalho Chehab 1061d43cd965SMauro Carvalho Chehab if self.pdf: 1062d43cd965SMauro Carvalho Chehab self.check_pacman_missing(archlinux_tex_pkgs, 1063d43cd965SMauro Carvalho Chehab DepManager.PDF_MANDATORY) 1064d43cd965SMauro Carvalho Chehab 1065d43cd965SMauro Carvalho Chehab self.check_missing_file(["/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc"], 1066d43cd965SMauro Carvalho Chehab "noto-fonts-cjk", 1067d43cd965SMauro Carvalho Chehab DepManager.PDF_MANDATORY) 1068d43cd965SMauro Carvalho Chehab 1069d43cd965SMauro Carvalho Chehab 1070d43cd965SMauro Carvalho Chehab return self.get_install_progs(progs, "pacman -S") 1071d43cd965SMauro Carvalho Chehab 1072d43cd965SMauro Carvalho Chehab def give_gentoo_hints(self): 1073d43cd965SMauro Carvalho Chehab """ 1074d43cd965SMauro Carvalho Chehab Provide package installation hints for Gentoo. 1075d43cd965SMauro Carvalho Chehab """ 10769ff5c2f5SMauro Carvalho Chehab texlive_deps = [ 10774509d36cSMauro Carvalho Chehab "dev-texlive/texlive-fontsrecommended", 10789ff5c2f5SMauro Carvalho Chehab "dev-texlive/texlive-latexextra", 10799ff5c2f5SMauro Carvalho Chehab "dev-texlive/texlive-xetex", 10809ff5c2f5SMauro Carvalho Chehab "media-fonts/dejavu", 10819ff5c2f5SMauro Carvalho Chehab ] 10829ff5c2f5SMauro Carvalho Chehab 1083d43cd965SMauro Carvalho Chehab progs = { 1084d43cd965SMauro Carvalho Chehab "convert": "media-gfx/imagemagick", 1085d43cd965SMauro Carvalho Chehab "dot": "media-gfx/graphviz", 1086d43cd965SMauro Carvalho Chehab "rsvg-convert": "gnome-base/librsvg", 1087d43cd965SMauro Carvalho Chehab "virtualenv": "dev-python/virtualenv", 10889ff5c2f5SMauro Carvalho Chehab "xelatex": " ".join(texlive_deps), 1089d43cd965SMauro Carvalho Chehab "yaml": "dev-python/pyyaml", 1090d43cd965SMauro Carvalho Chehab "python-sphinx": "dev-python/sphinx", 1091d43cd965SMauro Carvalho Chehab } 1092d43cd965SMauro Carvalho Chehab 1093d43cd965SMauro Carvalho Chehab if self.pdf: 1094d43cd965SMauro Carvalho Chehab pdf_pkgs = { 1095d43cd965SMauro Carvalho Chehab "media-fonts/dejavu": [ 1096d43cd965SMauro Carvalho Chehab "/usr/share/fonts/dejavu/DejaVuSans.ttf", 1097d43cd965SMauro Carvalho Chehab ], 1098d43cd965SMauro Carvalho Chehab "media-fonts/noto-cjk": [ 1099d43cd965SMauro Carvalho Chehab "/usr/share/fonts/noto-cjk/NotoSansCJKsc-Regular.otf", 1100d43cd965SMauro Carvalho Chehab "/usr/share/fonts/noto-cjk/NotoSerifCJK-Regular.ttc", 1101d43cd965SMauro Carvalho Chehab ], 1102d43cd965SMauro Carvalho Chehab } 1103d43cd965SMauro Carvalho Chehab for package, files in pdf_pkgs.items(): 1104d43cd965SMauro Carvalho Chehab self.check_missing_file(files, package, DepManager.PDF_MANDATORY) 1105d43cd965SMauro Carvalho Chehab 1106d43cd965SMauro Carvalho Chehab # Handling dependencies is a nightmare, as Gentoo refuses to emerge 1107d43cd965SMauro Carvalho Chehab # some packages if there's no package.use file describing them. 1108d43cd965SMauro Carvalho Chehab # To make it worse, compilation flags shall also be present there 1109d43cd965SMauro Carvalho Chehab # for some packages. If USE is not perfect, error/warning messages 1110d43cd965SMauro Carvalho Chehab # like those are shown: 1111d43cd965SMauro Carvalho Chehab # 1112d43cd965SMauro Carvalho Chehab # !!! The following binary packages have been ignored due to non matching USE: 1113d43cd965SMauro Carvalho Chehab # 1114d43cd965SMauro Carvalho Chehab # =media-gfx/graphviz-12.2.1-r1 X pdf -python_single_target_python3_13 qt6 svg 1115d43cd965SMauro Carvalho Chehab # =media-gfx/graphviz-12.2.1-r1 X pdf python_single_target_python3_12 -python_single_target_python3_13 qt6 svg 1116d43cd965SMauro Carvalho Chehab # =media-gfx/graphviz-12.2.1-r1 X pdf qt6 svg 1117d43cd965SMauro Carvalho Chehab # =media-gfx/graphviz-12.2.1-r1 X pdf -python_single_target_python3_10 qt6 svg 1118d43cd965SMauro Carvalho Chehab # =media-gfx/graphviz-12.2.1-r1 X pdf -python_single_target_python3_10 python_single_target_python3_12 -python_single_target_python3_13 qt6 svg 1119d43cd965SMauro Carvalho Chehab # =media-fonts/noto-cjk-20190416 X 1120d43cd965SMauro Carvalho Chehab # =app-text/texlive-core-2024-r1 X cjk -xetex 1121d43cd965SMauro Carvalho Chehab # =app-text/texlive-core-2024-r1 X -xetex 1122d43cd965SMauro Carvalho Chehab # =app-text/texlive-core-2024-r1 -xetex 1123d43cd965SMauro Carvalho Chehab # =dev-libs/zziplib-0.13.79-r1 sdl 1124d43cd965SMauro Carvalho Chehab # 1125d43cd965SMauro Carvalho Chehab # And will ignore such packages, installing the remaining ones. That 1126d43cd965SMauro Carvalho Chehab # affects mostly the image extension and PDF generation. 1127d43cd965SMauro Carvalho Chehab 1128d43cd965SMauro Carvalho Chehab # Package dependencies and the minimal needed args: 1129d43cd965SMauro Carvalho Chehab portages = { 1130d43cd965SMauro Carvalho Chehab "graphviz": "media-gfx/graphviz", 1131d43cd965SMauro Carvalho Chehab "imagemagick": "media-gfx/imagemagick", 1132d43cd965SMauro Carvalho Chehab "media-libs": "media-libs/harfbuzz icu", 1133d43cd965SMauro Carvalho Chehab "media-fonts": "media-fonts/noto-cjk", 1134d43cd965SMauro Carvalho Chehab "texlive": "app-text/texlive-core xetex", 1135d43cd965SMauro Carvalho Chehab "zziblib": "dev-libs/zziplib sdl", 1136d43cd965SMauro Carvalho Chehab } 1137d43cd965SMauro Carvalho Chehab 1138d43cd965SMauro Carvalho Chehab extra_cmds = "" 1139d43cd965SMauro Carvalho Chehab if not self.distro_msg: 1140d43cd965SMauro Carvalho Chehab self.distro_msg = "Note: Gentoo requires package.use to be adjusted before emerging packages" 1141d43cd965SMauro Carvalho Chehab 1142d43cd965SMauro Carvalho Chehab use_base = "/etc/portage/package.use" 1143d43cd965SMauro Carvalho Chehab files = glob(f"{use_base}/*") 1144d43cd965SMauro Carvalho Chehab 1145d43cd965SMauro Carvalho Chehab for fname, portage in portages.items(): 1146d43cd965SMauro Carvalho Chehab install = False 1147d43cd965SMauro Carvalho Chehab 1148d43cd965SMauro Carvalho Chehab while install is False: 1149d43cd965SMauro Carvalho Chehab if not files: 1150d43cd965SMauro Carvalho Chehab # No files under package.usage. Install all 1151d43cd965SMauro Carvalho Chehab install = True 1152d43cd965SMauro Carvalho Chehab break 1153d43cd965SMauro Carvalho Chehab 1154d43cd965SMauro Carvalho Chehab args = portage.split(" ") 1155d43cd965SMauro Carvalho Chehab 1156d43cd965SMauro Carvalho Chehab name = args.pop(0) 1157d43cd965SMauro Carvalho Chehab 1158d43cd965SMauro Carvalho Chehab cmd = ["grep", "-l", "-E", rf"^{name}\b" ] + files 1159d43cd965SMauro Carvalho Chehab result = self.run(cmd, stdout=subprocess.PIPE, text=True) 1160d43cd965SMauro Carvalho Chehab if result.returncode or not result.stdout.strip(): 1161d43cd965SMauro Carvalho Chehab # File containing portage name not found 1162d43cd965SMauro Carvalho Chehab install = True 1163d43cd965SMauro Carvalho Chehab break 1164d43cd965SMauro Carvalho Chehab 1165d43cd965SMauro Carvalho Chehab # Ensure that needed USE flags are present 1166d43cd965SMauro Carvalho Chehab if args: 1167d43cd965SMauro Carvalho Chehab match_fname = result.stdout.strip() 1168d43cd965SMauro Carvalho Chehab with open(match_fname, 'r', encoding='utf8', 1169d43cd965SMauro Carvalho Chehab errors='backslashreplace') as fp: 1170d43cd965SMauro Carvalho Chehab for line in fp: 1171d43cd965SMauro Carvalho Chehab for arg in args: 1172d43cd965SMauro Carvalho Chehab if arg.startswith("-"): 1173d43cd965SMauro Carvalho Chehab continue 1174d43cd965SMauro Carvalho Chehab 1175d43cd965SMauro Carvalho Chehab if not re.search(rf"\s*{arg}\b", line): 1176d43cd965SMauro Carvalho Chehab # Needed file argument not found 1177d43cd965SMauro Carvalho Chehab install = True 1178d43cd965SMauro Carvalho Chehab break 1179d43cd965SMauro Carvalho Chehab 1180d43cd965SMauro Carvalho Chehab # Everything looks ok, don't install 1181d43cd965SMauro Carvalho Chehab break 1182d43cd965SMauro Carvalho Chehab 1183d43cd965SMauro Carvalho Chehab # emit a code to setup missing USE 1184d43cd965SMauro Carvalho Chehab if install: 1185d43cd965SMauro Carvalho Chehab extra_cmds += (f"sudo su -c 'echo \"{portage}\" > {use_base}/{fname}'\n") 1186d43cd965SMauro Carvalho Chehab 1187d43cd965SMauro Carvalho Chehab # Now, we can use emerge and let it respect USE 1188d43cd965SMauro Carvalho Chehab return self.get_install_progs(progs, 1189d43cd965SMauro Carvalho Chehab "emerge --ask --changed-use --binpkg-respect-use=y", 1190d43cd965SMauro Carvalho Chehab extra_cmds) 1191d43cd965SMauro Carvalho Chehab 1192d43cd965SMauro Carvalho Chehab def get_install(self): 1193d43cd965SMauro Carvalho Chehab """ 1194d43cd965SMauro Carvalho Chehab OS-specific hints logic. Seeks for a hinter. If found, use it to 1195d43cd965SMauro Carvalho Chehab provide package-manager specific install commands. 1196d43cd965SMauro Carvalho Chehab 1197d43cd965SMauro Carvalho Chehab Otherwise, outputs install instructions for the meta-packages. 1198d43cd965SMauro Carvalho Chehab 1199d43cd965SMauro Carvalho Chehab Returns a string with the command to be executed to install the 1200d43cd965SMauro Carvalho Chehab the needed packages, if distro found. Otherwise, return just a 1201d43cd965SMauro Carvalho Chehab list of packages that require installation. 1202d43cd965SMauro Carvalho Chehab """ 1203d43cd965SMauro Carvalho Chehab os_hints = { 1204d43cd965SMauro Carvalho Chehab re.compile("Red Hat Enterprise Linux"): self.give_redhat_hints, 1205d43cd965SMauro Carvalho Chehab re.compile("Fedora"): self.give_redhat_hints, 1206d43cd965SMauro Carvalho Chehab re.compile("AlmaLinux"): self.give_redhat_hints, 1207d43cd965SMauro Carvalho Chehab re.compile("Amazon Linux"): self.give_redhat_hints, 1208d43cd965SMauro Carvalho Chehab re.compile("CentOS"): self.give_redhat_hints, 1209d43cd965SMauro Carvalho Chehab re.compile("openEuler"): self.give_redhat_hints, 1210d43cd965SMauro Carvalho Chehab re.compile("Oracle Linux Server"): self.give_redhat_hints, 1211d43cd965SMauro Carvalho Chehab re.compile("Rocky Linux"): self.give_redhat_hints, 1212d43cd965SMauro Carvalho Chehab re.compile("Springdale Open Enterprise"): self.give_redhat_hints, 1213d43cd965SMauro Carvalho Chehab 1214d43cd965SMauro Carvalho Chehab re.compile("Ubuntu"): self.give_debian_hints, 1215d43cd965SMauro Carvalho Chehab re.compile("Debian"): self.give_debian_hints, 1216d43cd965SMauro Carvalho Chehab re.compile("Devuan"): self.give_debian_hints, 1217d43cd965SMauro Carvalho Chehab re.compile("Kali"): self.give_debian_hints, 1218d43cd965SMauro Carvalho Chehab re.compile("Mint"): self.give_debian_hints, 1219d43cd965SMauro Carvalho Chehab 1220d43cd965SMauro Carvalho Chehab re.compile("openSUSE"): self.give_opensuse_hints, 1221d43cd965SMauro Carvalho Chehab 1222d43cd965SMauro Carvalho Chehab re.compile("Mageia"): self.give_mageia_hints, 1223d43cd965SMauro Carvalho Chehab re.compile("OpenMandriva"): self.give_mageia_hints, 1224d43cd965SMauro Carvalho Chehab 1225d43cd965SMauro Carvalho Chehab re.compile("Arch Linux"): self.give_arch_linux_hints, 1226d43cd965SMauro Carvalho Chehab re.compile("Gentoo"): self.give_gentoo_hints, 1227d43cd965SMauro Carvalho Chehab } 1228d43cd965SMauro Carvalho Chehab 1229d43cd965SMauro Carvalho Chehab # If the OS is detected, use per-OS hint logic 1230d43cd965SMauro Carvalho Chehab for regex, os_hint in os_hints.items(): 1231d43cd965SMauro Carvalho Chehab if regex.search(self.system_release): 1232d43cd965SMauro Carvalho Chehab return os_hint() 1233d43cd965SMauro Carvalho Chehab 1234d43cd965SMauro Carvalho Chehab # 1235d43cd965SMauro Carvalho Chehab # Fall-back to generic hint code for other distros 1236d43cd965SMauro Carvalho Chehab # That's far from ideal, specially for LaTeX dependencies. 1237d43cd965SMauro Carvalho Chehab # 1238d43cd965SMauro Carvalho Chehab progs = {"sphinx-build": "sphinx"} 1239d43cd965SMauro Carvalho Chehab if self.pdf: 1240d43cd965SMauro Carvalho Chehab self.check_missing_tex() 1241d43cd965SMauro Carvalho Chehab 1242d43cd965SMauro Carvalho Chehab self.distro_msg = \ 1243d43cd965SMauro Carvalho Chehab f"I don't know distro {self.system_release}.\n" \ 1244d43cd965SMauro Carvalho Chehab "So, I can't provide you a hint with the install procedure.\n" \ 1245491a9951SMauro Carvalho Chehab "There are likely missing dependencies." 1246d43cd965SMauro Carvalho Chehab 1247d43cd965SMauro Carvalho Chehab return self.get_install_progs(progs, None) 1248d43cd965SMauro Carvalho Chehab 1249d43cd965SMauro Carvalho Chehab # 1250d43cd965SMauro Carvalho Chehab # Common dependencies 1251d43cd965SMauro Carvalho Chehab # 1252d43cd965SMauro Carvalho Chehab def deactivate_help(self): 1253d43cd965SMauro Carvalho Chehab """ 1254d43cd965SMauro Carvalho Chehab Print a helper message to disable a virtual environment. 1255d43cd965SMauro Carvalho Chehab """ 1256d43cd965SMauro Carvalho Chehab 1257d43cd965SMauro Carvalho Chehab print("\n If you want to exit the virtualenv, you can use:") 1258d43cd965SMauro Carvalho Chehab print("\tdeactivate") 1259d43cd965SMauro Carvalho Chehab 1260d43cd965SMauro Carvalho Chehab def get_virtenv(self): 1261d43cd965SMauro Carvalho Chehab """ 1262d43cd965SMauro Carvalho Chehab Give a hint about how to activate an already-existing virtual 1263d43cd965SMauro Carvalho Chehab environment containing sphinx-build. 1264d43cd965SMauro Carvalho Chehab 1265d43cd965SMauro Carvalho Chehab Returns a tuble with (activate_cmd_path, sphinx_version) with 1266d43cd965SMauro Carvalho Chehab the newest available virtual env. 1267d43cd965SMauro Carvalho Chehab """ 1268d43cd965SMauro Carvalho Chehab 1269d43cd965SMauro Carvalho Chehab cwd = os.getcwd() 1270d43cd965SMauro Carvalho Chehab 1271d43cd965SMauro Carvalho Chehab activates = [] 1272d43cd965SMauro Carvalho Chehab 1273d43cd965SMauro Carvalho Chehab # Add all sphinx prefixes with possible version numbers 1274d43cd965SMauro Carvalho Chehab for p in self.virtenv_prefix: 1275d43cd965SMauro Carvalho Chehab activates += glob(f"{cwd}/{p}[0-9]*/bin/activate") 1276d43cd965SMauro Carvalho Chehab 1277d43cd965SMauro Carvalho Chehab activates.sort(reverse=True, key=str.lower) 1278d43cd965SMauro Carvalho Chehab 1279d43cd965SMauro Carvalho Chehab # Place sphinx_latest first, if it exists 1280d43cd965SMauro Carvalho Chehab for p in self.virtenv_prefix: 1281d43cd965SMauro Carvalho Chehab activates = glob(f"{cwd}/{p}*latest/bin/activate") + activates 1282d43cd965SMauro Carvalho Chehab 1283d43cd965SMauro Carvalho Chehab ver = (0, 0, 0) 1284d43cd965SMauro Carvalho Chehab for f in activates: 1285d43cd965SMauro Carvalho Chehab # Discard too old Sphinx virtual environments 1286d43cd965SMauro Carvalho Chehab match = re.search(r"(\d+)\.(\d+)\.(\d+)", f) 1287d43cd965SMauro Carvalho Chehab if match: 1288d43cd965SMauro Carvalho Chehab ver = (int(match.group(1)), int(match.group(2)), int(match.group(3))) 1289d43cd965SMauro Carvalho Chehab 1290d43cd965SMauro Carvalho Chehab if ver < self.min_version: 1291d43cd965SMauro Carvalho Chehab continue 1292d43cd965SMauro Carvalho Chehab 1293d43cd965SMauro Carvalho Chehab sphinx_cmd = f.replace("activate", "sphinx-build") 1294d43cd965SMauro Carvalho Chehab if not os.path.isfile(sphinx_cmd): 1295d43cd965SMauro Carvalho Chehab continue 1296d43cd965SMauro Carvalho Chehab 1297d43cd965SMauro Carvalho Chehab ver = self.get_sphinx_version(sphinx_cmd) 1298d43cd965SMauro Carvalho Chehab 1299d43cd965SMauro Carvalho Chehab if not ver: 1300d43cd965SMauro Carvalho Chehab venv_dir = f.replace("/bin/activate", "") 1301d43cd965SMauro Carvalho Chehab print(f"Warning: virtual environment {venv_dir} is not working.\n" \ 1302d43cd965SMauro Carvalho Chehab "Python version upgrade? Remove it with:\n\n" \ 1303d43cd965SMauro Carvalho Chehab "\trm -rf {venv_dir}\n\n") 1304d43cd965SMauro Carvalho Chehab else: 1305d43cd965SMauro Carvalho Chehab if self.need_sphinx and ver >= self.min_version: 1306d43cd965SMauro Carvalho Chehab return (f, ver) 1307d43cd965SMauro Carvalho Chehab elif parse_version(ver) > self.cur_version: 1308d43cd965SMauro Carvalho Chehab return (f, ver) 1309d43cd965SMauro Carvalho Chehab 1310d43cd965SMauro Carvalho Chehab return ("", ver) 1311d43cd965SMauro Carvalho Chehab 1312d43cd965SMauro Carvalho Chehab def recommend_sphinx_upgrade(self): 1313d43cd965SMauro Carvalho Chehab """ 1314d43cd965SMauro Carvalho Chehab Check if Sphinx needs to be upgraded. 1315d43cd965SMauro Carvalho Chehab 1316d43cd965SMauro Carvalho Chehab Returns a tuple with the higest available Sphinx version if found. 1317d43cd965SMauro Carvalho Chehab Otherwise, returns None to indicate either that no upgrade is needed 1318d43cd965SMauro Carvalho Chehab or no venv was found. 1319d43cd965SMauro Carvalho Chehab """ 1320d43cd965SMauro Carvalho Chehab 1321d43cd965SMauro Carvalho Chehab # Avoid running sphinx-builds from venv if cur_version is good 1322d43cd965SMauro Carvalho Chehab if self.cur_version and self.cur_version >= RECOMMENDED_VERSION: 1323d43cd965SMauro Carvalho Chehab self.latest_avail_ver = self.cur_version 1324d43cd965SMauro Carvalho Chehab return None 1325d43cd965SMauro Carvalho Chehab 1326d43cd965SMauro Carvalho Chehab # Get the highest version from sphinx_*/bin/sphinx-build and the 1327d43cd965SMauro Carvalho Chehab # corresponding command to activate the venv/virtenv 1328d43cd965SMauro Carvalho Chehab self.activate_cmd, self.venv_ver = self.get_virtenv() 1329d43cd965SMauro Carvalho Chehab 1330d43cd965SMauro Carvalho Chehab # Store the highest version from Sphinx existing virtualenvs 1331d43cd965SMauro Carvalho Chehab if self.activate_cmd and self.venv_ver > self.cur_version: 1332d43cd965SMauro Carvalho Chehab self.latest_avail_ver = self.venv_ver 1333d43cd965SMauro Carvalho Chehab else: 1334d43cd965SMauro Carvalho Chehab if self.cur_version: 1335d43cd965SMauro Carvalho Chehab self.latest_avail_ver = self.cur_version 1336d43cd965SMauro Carvalho Chehab else: 1337d43cd965SMauro Carvalho Chehab self.latest_avail_ver = (0, 0, 0) 1338d43cd965SMauro Carvalho Chehab 1339d43cd965SMauro Carvalho Chehab # As we don't know package version of Sphinx, and there's no 1340d43cd965SMauro Carvalho Chehab # virtual environments, don't check if upgrades are needed 1341d43cd965SMauro Carvalho Chehab if not self.virtualenv: 1342d43cd965SMauro Carvalho Chehab if not self.latest_avail_ver: 1343d43cd965SMauro Carvalho Chehab return None 1344d43cd965SMauro Carvalho Chehab 1345d43cd965SMauro Carvalho Chehab return self.latest_avail_ver 1346d43cd965SMauro Carvalho Chehab 1347d43cd965SMauro Carvalho Chehab # Either there are already a virtual env or a new one should be created 13489f51a1d6SMauro Carvalho Chehab self.need_pip = True 1349d43cd965SMauro Carvalho Chehab 1350d43cd965SMauro Carvalho Chehab if not self.latest_avail_ver: 1351d43cd965SMauro Carvalho Chehab return None 1352d43cd965SMauro Carvalho Chehab 1353d43cd965SMauro Carvalho Chehab # Return if the reason is due to an upgrade or not 1354d43cd965SMauro Carvalho Chehab if self.latest_avail_ver != (0, 0, 0): 1355d43cd965SMauro Carvalho Chehab if self.latest_avail_ver < RECOMMENDED_VERSION: 1356d43cd965SMauro Carvalho Chehab self.rec_sphinx_upgrade = 1 1357d43cd965SMauro Carvalho Chehab 1358d43cd965SMauro Carvalho Chehab return self.latest_avail_ver 1359d43cd965SMauro Carvalho Chehab 1360d43cd965SMauro Carvalho Chehab def recommend_package(self): 1361d43cd965SMauro Carvalho Chehab """ 1362d43cd965SMauro Carvalho Chehab Recommend installing Sphinx as a distro-specific package. 1363d43cd965SMauro Carvalho Chehab """ 1364d43cd965SMauro Carvalho Chehab 1365d43cd965SMauro Carvalho Chehab print("\n2) As a package with:") 1366d43cd965SMauro Carvalho Chehab 1367d43cd965SMauro Carvalho Chehab old_need = self.deps.need 1368d43cd965SMauro Carvalho Chehab old_optional = self.deps.optional 1369d43cd965SMauro Carvalho Chehab 1370d43cd965SMauro Carvalho Chehab self.pdf = False 1371d43cd965SMauro Carvalho Chehab self.deps.optional = 0 1372d43cd965SMauro Carvalho Chehab old_verbose = self.verbose_warn_install 1373d43cd965SMauro Carvalho Chehab self.verbose_warn_install = 0 1374d43cd965SMauro Carvalho Chehab 1375d43cd965SMauro Carvalho Chehab self.deps.clear_deps() 1376d43cd965SMauro Carvalho Chehab 1377d43cd965SMauro Carvalho Chehab self.deps.add_package("python-sphinx", DepManager.PYTHON_MANDATORY) 1378d43cd965SMauro Carvalho Chehab 1379d43cd965SMauro Carvalho Chehab cmd = self.get_install() 1380d43cd965SMauro Carvalho Chehab if cmd: 1381d43cd965SMauro Carvalho Chehab print(cmd) 1382d43cd965SMauro Carvalho Chehab 1383d43cd965SMauro Carvalho Chehab self.deps.need = old_need 1384d43cd965SMauro Carvalho Chehab self.deps.optional = old_optional 1385d43cd965SMauro Carvalho Chehab self.verbose_warn_install = old_verbose 1386d43cd965SMauro Carvalho Chehab 1387d43cd965SMauro Carvalho Chehab def recommend_sphinx_version(self, virtualenv_cmd): 1388d43cd965SMauro Carvalho Chehab """ 1389d43cd965SMauro Carvalho Chehab Provide recommendations for installing or upgrading Sphinx based 1390d43cd965SMauro Carvalho Chehab on current version. 1391d43cd965SMauro Carvalho Chehab 1392d43cd965SMauro Carvalho Chehab The logic here is complex, as it have to deal with different versions: 1393d43cd965SMauro Carvalho Chehab 1394d43cd965SMauro Carvalho Chehab - minimal supported version; 1395d43cd965SMauro Carvalho Chehab - minimal PDF version; 1396d43cd965SMauro Carvalho Chehab - recommended version. 1397d43cd965SMauro Carvalho Chehab 1398d43cd965SMauro Carvalho Chehab It also needs to work fine with both distro's package and 1399d43cd965SMauro Carvalho Chehab venv/virtualenv 1400d43cd965SMauro Carvalho Chehab """ 1401d43cd965SMauro Carvalho Chehab 1402d43cd965SMauro Carvalho Chehab if self.recommend_python: 14039f51a1d6SMauro Carvalho Chehab cur_ver = sys.version_info[:3] 14049f51a1d6SMauro Carvalho Chehab if cur_ver < MIN_PYTHON_VERSION: 14059f51a1d6SMauro Carvalho Chehab print(f"\nPython version {cur_ver} is incompatible with doc build.\n" \ 1406d43cd965SMauro Carvalho Chehab "Please upgrade it and re-run.\n") 1407d43cd965SMauro Carvalho Chehab return 1408d43cd965SMauro Carvalho Chehab 1409d43cd965SMauro Carvalho Chehab # Version is OK. Nothing to do. 1410d43cd965SMauro Carvalho Chehab if self.cur_version != (0, 0, 0) and self.cur_version >= RECOMMENDED_VERSION: 1411d43cd965SMauro Carvalho Chehab return 1412d43cd965SMauro Carvalho Chehab 1413d43cd965SMauro Carvalho Chehab if self.latest_avail_ver: 1414d43cd965SMauro Carvalho Chehab latest_avail_ver = ver_str(self.latest_avail_ver) 1415d43cd965SMauro Carvalho Chehab 1416d43cd965SMauro Carvalho Chehab if not self.need_sphinx: 1417d43cd965SMauro Carvalho Chehab # sphinx-build is present and its version is >= $min_version 1418d43cd965SMauro Carvalho Chehab 1419d43cd965SMauro Carvalho Chehab # only recommend enabling a newer virtenv version if makes sense. 1420d43cd965SMauro Carvalho Chehab if self.latest_avail_ver and self.latest_avail_ver > self.cur_version: 1421d43cd965SMauro Carvalho Chehab print(f"\nYou may also use the newer Sphinx version {latest_avail_ver} with:") 1422d43cd965SMauro Carvalho Chehab if f"{self.virtenv_prefix}" in os.getcwd(): 1423d43cd965SMauro Carvalho Chehab print("\tdeactivate") 1424d43cd965SMauro Carvalho Chehab print(f"\t. {self.activate_cmd}") 1425d43cd965SMauro Carvalho Chehab self.deactivate_help() 1426d43cd965SMauro Carvalho Chehab return 1427d43cd965SMauro Carvalho Chehab 1428d43cd965SMauro Carvalho Chehab if self.latest_avail_ver and self.latest_avail_ver >= RECOMMENDED_VERSION: 1429d43cd965SMauro Carvalho Chehab return 1430d43cd965SMauro Carvalho Chehab 1431d43cd965SMauro Carvalho Chehab if not self.virtualenv: 1432d43cd965SMauro Carvalho Chehab # No sphinx either via package or via virtenv. As we can't 1433d43cd965SMauro Carvalho Chehab # Compare the versions here, just return, recommending the 1434d43cd965SMauro Carvalho Chehab # user to install it from the package distro. 1435d43cd965SMauro Carvalho Chehab if not self.latest_avail_ver or self.latest_avail_ver == (0, 0, 0): 1436d43cd965SMauro Carvalho Chehab return 1437d43cd965SMauro Carvalho Chehab 1438d43cd965SMauro Carvalho Chehab # User doesn't want a virtenv recommendation, but he already 1439d43cd965SMauro Carvalho Chehab # installed one via virtenv with a newer version. 1440d43cd965SMauro Carvalho Chehab # So, print commands to enable it 1441d43cd965SMauro Carvalho Chehab if self.latest_avail_ver > self.cur_version: 1442d43cd965SMauro Carvalho Chehab print(f"\nYou may also use the Sphinx virtualenv version {latest_avail_ver} with:") 1443d43cd965SMauro Carvalho Chehab if f"{self.virtenv_prefix}" in os.getcwd(): 1444d43cd965SMauro Carvalho Chehab print("\tdeactivate") 1445d43cd965SMauro Carvalho Chehab print(f"\t. {self.activate_cmd}") 1446d43cd965SMauro Carvalho Chehab self.deactivate_help() 1447d43cd965SMauro Carvalho Chehab return 1448d43cd965SMauro Carvalho Chehab print("\n") 1449d43cd965SMauro Carvalho Chehab else: 1450d43cd965SMauro Carvalho Chehab if self.need_sphinx: 1451d43cd965SMauro Carvalho Chehab self.deps.need += 1 1452d43cd965SMauro Carvalho Chehab 1453d43cd965SMauro Carvalho Chehab # Suggest newer versions if current ones are too old 1454d43cd965SMauro Carvalho Chehab if self.latest_avail_ver and self.latest_avail_ver >= self.min_version: 1455d43cd965SMauro Carvalho Chehab if self.latest_avail_ver >= RECOMMENDED_VERSION: 1456d43cd965SMauro Carvalho Chehab print(f"\nNeed to activate Sphinx (version {latest_avail_ver}) on virtualenv with:") 1457d43cd965SMauro Carvalho Chehab print(f"\t. {self.activate_cmd}") 1458d43cd965SMauro Carvalho Chehab self.deactivate_help() 1459d43cd965SMauro Carvalho Chehab return 1460d43cd965SMauro Carvalho Chehab 1461d43cd965SMauro Carvalho Chehab # Version is above the minimal required one, but may be 1462d43cd965SMauro Carvalho Chehab # below the recommended one. So, print warnings/notes 1463d43cd965SMauro Carvalho Chehab if self.latest_avail_ver < RECOMMENDED_VERSION: 1464d43cd965SMauro Carvalho Chehab print(f"Warning: It is recommended at least Sphinx version {RECOMMENDED_VERSION}.") 1465d43cd965SMauro Carvalho Chehab 1466d43cd965SMauro Carvalho Chehab # At this point, either it needs Sphinx or upgrade is recommended, 1467d43cd965SMauro Carvalho Chehab # both via pip 1468d43cd965SMauro Carvalho Chehab 1469d43cd965SMauro Carvalho Chehab if self.rec_sphinx_upgrade: 1470d43cd965SMauro Carvalho Chehab if not self.virtualenv: 1471d43cd965SMauro Carvalho Chehab print("Instead of install/upgrade Python Sphinx pkg, you could use pip/pypi with:\n\n") 1472d43cd965SMauro Carvalho Chehab else: 1473d43cd965SMauro Carvalho Chehab print("To upgrade Sphinx, use:\n\n") 1474d43cd965SMauro Carvalho Chehab else: 1475d43cd965SMauro Carvalho Chehab print("\nSphinx needs to be installed either:\n1) via pip/pypi with:\n") 1476d43cd965SMauro Carvalho Chehab 1477d43cd965SMauro Carvalho Chehab if not virtualenv_cmd: 1478d43cd965SMauro Carvalho Chehab print(" Currently not possible.\n") 1479d43cd965SMauro Carvalho Chehab print(" Please upgrade Python to a newer version and run this script again") 1480d43cd965SMauro Carvalho Chehab else: 1481d43cd965SMauro Carvalho Chehab print(f"\t{virtualenv_cmd} {self.virtenv_dir}") 1482d43cd965SMauro Carvalho Chehab print(f"\t. {self.virtenv_dir}/bin/activate") 1483d43cd965SMauro Carvalho Chehab print(f"\tpip install -r {self.requirement_file}") 1484d43cd965SMauro Carvalho Chehab self.deactivate_help() 1485d43cd965SMauro Carvalho Chehab 1486d43cd965SMauro Carvalho Chehab if self.package_supported: 1487d43cd965SMauro Carvalho Chehab self.recommend_package() 1488d43cd965SMauro Carvalho Chehab 1489d43cd965SMauro Carvalho Chehab print("\n" \ 1490d43cd965SMauro Carvalho Chehab " Please note that Sphinx currentlys produce false-positive\n" \ 1491d43cd965SMauro Carvalho Chehab " warnings when the same name is used for more than one type (functions,\n" \ 1492d43cd965SMauro Carvalho Chehab " structs, enums,...). This is known Sphinx bug. For more details, see:\n" \ 1493d43cd965SMauro Carvalho Chehab "\thttps://github.com/sphinx-doc/sphinx/pull/8313") 1494d43cd965SMauro Carvalho Chehab 1495d43cd965SMauro Carvalho Chehab def check_needs(self): 1496d43cd965SMauro Carvalho Chehab """ 1497d43cd965SMauro Carvalho Chehab Main method that checks needed dependencies and provides 1498d43cd965SMauro Carvalho Chehab recommendations. 1499d43cd965SMauro Carvalho Chehab """ 1500d43cd965SMauro Carvalho Chehab self.python_cmd = sys.executable 1501d43cd965SMauro Carvalho Chehab 1502d43cd965SMauro Carvalho Chehab # Check if Sphinx is already accessible from current environment 1503d43cd965SMauro Carvalho Chehab self.check_sphinx(self.conf) 1504d43cd965SMauro Carvalho Chehab 1505d43cd965SMauro Carvalho Chehab if self.system_release: 1506d43cd965SMauro Carvalho Chehab print(f"Detected OS: {self.system_release}.") 1507d43cd965SMauro Carvalho Chehab else: 1508d43cd965SMauro Carvalho Chehab print("Unknown OS") 1509d43cd965SMauro Carvalho Chehab if self.cur_version != (0, 0, 0): 1510d43cd965SMauro Carvalho Chehab ver = ver_str(self.cur_version) 1511d43cd965SMauro Carvalho Chehab print(f"Sphinx version: {ver}\n") 1512d43cd965SMauro Carvalho Chehab 1513d43cd965SMauro Carvalho Chehab # Check the type of virtual env, depending on Python version 1514d43cd965SMauro Carvalho Chehab virtualenv_cmd = None 1515d43cd965SMauro Carvalho Chehab 1516d43cd965SMauro Carvalho Chehab if sys.version_info < MIN_PYTHON_VERSION: 1517d43cd965SMauro Carvalho Chehab min_ver = ver_str(MIN_PYTHON_VERSION) 1518d43cd965SMauro Carvalho Chehab print(f"ERROR: at least python {min_ver} is required to build the kernel docs") 1519d43cd965SMauro Carvalho Chehab self.need_sphinx = 1 1520d43cd965SMauro Carvalho Chehab 1521d43cd965SMauro Carvalho Chehab self.venv_ver = self.recommend_sphinx_upgrade() 1522d43cd965SMauro Carvalho Chehab 1523d43cd965SMauro Carvalho Chehab if self.need_pip: 1524d43cd965SMauro Carvalho Chehab if sys.version_info < MIN_PYTHON_VERSION: 1525d43cd965SMauro Carvalho Chehab self.need_pip = False 1526d43cd965SMauro Carvalho Chehab print("Warning: python version is not supported.") 1527d43cd965SMauro Carvalho Chehab else: 1528d43cd965SMauro Carvalho Chehab virtualenv_cmd = f"{self.python_cmd} -m venv" 1529d43cd965SMauro Carvalho Chehab self.check_python_module("ensurepip") 1530d43cd965SMauro Carvalho Chehab 1531d43cd965SMauro Carvalho Chehab # Check for needed programs/tools 1532d43cd965SMauro Carvalho Chehab self.check_perl_module("Pod::Usage", DepManager.SYSTEM_MANDATORY) 1533d43cd965SMauro Carvalho Chehab 1534d43cd965SMauro Carvalho Chehab self.check_program("make", DepManager.SYSTEM_MANDATORY) 1535df4d2f96SMauro Carvalho Chehab self.check_program("which", DepManager.SYSTEM_MANDATORY) 1536d43cd965SMauro Carvalho Chehab 1537d43cd965SMauro Carvalho Chehab self.check_program("dot", DepManager.SYSTEM_OPTIONAL) 1538d43cd965SMauro Carvalho Chehab self.check_program("convert", DepManager.SYSTEM_OPTIONAL) 1539d43cd965SMauro Carvalho Chehab 1540d43cd965SMauro Carvalho Chehab self.check_python_module("yaml") 1541d43cd965SMauro Carvalho Chehab 1542d43cd965SMauro Carvalho Chehab if self.pdf: 1543d43cd965SMauro Carvalho Chehab self.check_program("xelatex", DepManager.PDF_MANDATORY) 1544d43cd965SMauro Carvalho Chehab self.check_program("rsvg-convert", DepManager.PDF_MANDATORY) 1545d43cd965SMauro Carvalho Chehab self.check_program("latexmk", DepManager.PDF_MANDATORY) 1546d43cd965SMauro Carvalho Chehab 1547d43cd965SMauro Carvalho Chehab # Do distro-specific checks and output distro-install commands 1548d43cd965SMauro Carvalho Chehab cmd = self.get_install() 1549d43cd965SMauro Carvalho Chehab if cmd: 1550d43cd965SMauro Carvalho Chehab print(cmd) 1551d43cd965SMauro Carvalho Chehab 1552d43cd965SMauro Carvalho Chehab # If distro requires some special instructions, print here. 1553d43cd965SMauro Carvalho Chehab # Please notice that get_install() needs to be called first. 1554d43cd965SMauro Carvalho Chehab if self.distro_msg: 1555d43cd965SMauro Carvalho Chehab print("\n" + self.distro_msg) 1556d43cd965SMauro Carvalho Chehab 1557d43cd965SMauro Carvalho Chehab if not self.python_cmd: 1558d43cd965SMauro Carvalho Chehab if self.need == 1: 1559d43cd965SMauro Carvalho Chehab sys.exit("Can't build as 1 mandatory dependency is missing") 1560d43cd965SMauro Carvalho Chehab elif self.need: 1561d43cd965SMauro Carvalho Chehab sys.exit(f"Can't build as {self.need} mandatory dependencies are missing") 1562d43cd965SMauro Carvalho Chehab 1563d43cd965SMauro Carvalho Chehab # Check if sphinx-build is called sphinx-build-3 1564d43cd965SMauro Carvalho Chehab if self.need_symlink: 1565d43cd965SMauro Carvalho Chehab sphinx_path = self.which("sphinx-build-3") 1566d43cd965SMauro Carvalho Chehab if sphinx_path: 1567d43cd965SMauro Carvalho Chehab print(f"\tsudo ln -sf {sphinx_path} /usr/bin/sphinx-build\n") 1568d43cd965SMauro Carvalho Chehab 1569d43cd965SMauro Carvalho Chehab self.recommend_sphinx_version(virtualenv_cmd) 1570d43cd965SMauro Carvalho Chehab print("") 1571d43cd965SMauro Carvalho Chehab 1572d43cd965SMauro Carvalho Chehab if not self.deps.optional: 1573d43cd965SMauro Carvalho Chehab print("All optional dependencies are met.") 1574d43cd965SMauro Carvalho Chehab 1575d43cd965SMauro Carvalho Chehab if self.deps.need == 1: 1576d43cd965SMauro Carvalho Chehab sys.exit("Can't build as 1 mandatory dependency is missing") 1577d43cd965SMauro Carvalho Chehab elif self.deps.need: 1578d43cd965SMauro Carvalho Chehab sys.exit(f"Can't build as {self.deps.need} mandatory dependencies are missing") 1579d43cd965SMauro Carvalho Chehab 1580d43cd965SMauro Carvalho Chehab print("Needed package dependencies are met.") 1581d43cd965SMauro Carvalho Chehab 1582d43cd965SMauro Carvalho ChehabDESCRIPTION = """ 1583d43cd965SMauro Carvalho ChehabProcess some flags related to Sphinx installation and documentation build. 1584d43cd965SMauro Carvalho Chehab""" 1585d43cd965SMauro Carvalho Chehab 1586d43cd965SMauro Carvalho Chehab 1587d43cd965SMauro Carvalho Chehabdef main(): 1588d43cd965SMauro Carvalho Chehab """Main function""" 1589d43cd965SMauro Carvalho Chehab parser = argparse.ArgumentParser(description=DESCRIPTION) 1590d43cd965SMauro Carvalho Chehab 1591d43cd965SMauro Carvalho Chehab parser.add_argument( 1592d43cd965SMauro Carvalho Chehab "--no-virtualenv", 1593d43cd965SMauro Carvalho Chehab action="store_false", 1594d43cd965SMauro Carvalho Chehab dest="virtualenv", 1595d43cd965SMauro Carvalho Chehab help="Recommend installing Sphinx instead of using a virtualenv", 1596d43cd965SMauro Carvalho Chehab ) 1597d43cd965SMauro Carvalho Chehab 1598d43cd965SMauro Carvalho Chehab parser.add_argument( 1599d43cd965SMauro Carvalho Chehab "--no-pdf", 1600d43cd965SMauro Carvalho Chehab action="store_false", 1601d43cd965SMauro Carvalho Chehab dest="pdf", 1602d43cd965SMauro Carvalho Chehab help="Don't check for dependencies required to build PDF docs", 1603d43cd965SMauro Carvalho Chehab ) 1604d43cd965SMauro Carvalho Chehab 1605d43cd965SMauro Carvalho Chehab parser.add_argument( 1606d43cd965SMauro Carvalho Chehab "--version-check", 1607d43cd965SMauro Carvalho Chehab action="store_true", 1608d43cd965SMauro Carvalho Chehab dest="version_check", 1609d43cd965SMauro Carvalho Chehab help="If version is compatible, don't check for missing dependencies", 1610d43cd965SMauro Carvalho Chehab ) 1611d43cd965SMauro Carvalho Chehab 1612d43cd965SMauro Carvalho Chehab args = parser.parse_args() 1613d43cd965SMauro Carvalho Chehab 1614d43cd965SMauro Carvalho Chehab checker = SphinxDependencyChecker(args) 1615d43cd965SMauro Carvalho Chehab 1616d43cd965SMauro Carvalho Chehab checker.check_python() 1617d43cd965SMauro Carvalho Chehab checker.check_needs() 1618d43cd965SMauro Carvalho Chehab 1619d43cd965SMauro Carvalho Chehab# Call main if not used as module 1620d43cd965SMauro Carvalho Chehabif __name__ == "__main__": 1621d43cd965SMauro Carvalho Chehab main() 1622