1ca9087f5SMauro Carvalho Chehab#!/usr/bin/env python3 2ca9087f5SMauro Carvalho Chehab# SPDX-License-Identifier: GPL-2.0-or-later 3ca9087f5SMauro Carvalho Chehab# Copyright (c) 2017-2025 Mauro Carvalho Chehab <mchehab+huawei@kernel.org> 4ca9087f5SMauro Carvalho Chehab# 58b45effaSMauro Carvalho Chehab# pylint: disable=C0103,C0114,C0115,C0116,C0301,C0302 68b45effaSMauro Carvalho Chehab# pylint: disable=R0902,R0904,R0911,R0912,R0914,R0915,R1705,R1710,E1121 7ca9087f5SMauro Carvalho Chehab 8728648b6SMauro Carvalho Chehab# Note: this script requires at least Python 3.6 to run. 9728648b6SMauro Carvalho Chehab# Don't add changes not compatible with it, it is meant to report 10728648b6SMauro Carvalho Chehab# incompatible python versions. 11ca9087f5SMauro Carvalho Chehab 126d5f4f3dSMauro Carvalho Chehab""" 136d5f4f3dSMauro Carvalho ChehabDependency checker for Sphinx documentation Kernel build. 146d5f4f3dSMauro Carvalho Chehab 156d5f4f3dSMauro Carvalho ChehabThis module provides tools to check for all required dependencies needed to 166d5f4f3dSMauro Carvalho Chehabbuild documentation using Sphinx, including system packages, Python modules 176d5f4f3dSMauro Carvalho Chehaband LaTeX packages for PDF generation. 186d5f4f3dSMauro Carvalho Chehab 196d5f4f3dSMauro Carvalho ChehabIt detect packages for a subset of Linux distributions used by Kernel 206d5f4f3dSMauro Carvalho Chehabmaintainers, showing hints and missing dependencies. 216d5f4f3dSMauro Carvalho Chehab 226d5f4f3dSMauro Carvalho ChehabThe main class SphinxDependencyChecker handles the dependency checking logic 236d5f4f3dSMauro Carvalho Chehaband provides recommendations for installing missing packages. It supports both 246d5f4f3dSMauro Carvalho Chehabsystem package installations and Python virtual environments. By default, 256d5f4f3dSMauro Carvalho Chehabsystem pacage install is recommended. 266d5f4f3dSMauro Carvalho Chehab""" 276d5f4f3dSMauro Carvalho Chehab 28ca9087f5SMauro Carvalho Chehabimport argparse 29ca9087f5SMauro Carvalho Chehabimport os 30ca9087f5SMauro Carvalho Chehabimport re 31ca9087f5SMauro Carvalho Chehabimport subprocess 32ca9087f5SMauro Carvalho Chehabimport sys 33ca9087f5SMauro Carvalho Chehabfrom glob import glob 34ca9087f5SMauro Carvalho Chehab 35ca9087f5SMauro Carvalho Chehab 36ca9087f5SMauro Carvalho Chehabdef parse_version(version): 37ca9087f5SMauro Carvalho Chehab """Convert a major.minor.patch version into a tuple""" 38ca9087f5SMauro Carvalho Chehab return tuple(int(x) for x in version.split(".")) 39ca9087f5SMauro Carvalho Chehab 40ca9087f5SMauro Carvalho Chehab 41ca9087f5SMauro Carvalho Chehabdef ver_str(version): 42ca9087f5SMauro Carvalho Chehab """Returns a version tuple as major.minor.patch""" 43ca9087f5SMauro Carvalho Chehab 44ca9087f5SMauro Carvalho Chehab return ".".join([str(x) for x in version]) 45ca9087f5SMauro Carvalho Chehab 46ca9087f5SMauro Carvalho Chehab 47ca9087f5SMauro Carvalho ChehabRECOMMENDED_VERSION = parse_version("3.4.3") 48728648b6SMauro Carvalho ChehabMIN_PYTHON_VERSION = parse_version("3.7") 49ca9087f5SMauro Carvalho Chehab 50ca9087f5SMauro Carvalho Chehab 512cab00fbSMauro Carvalho Chehabclass DepManager: 52f477c6d7SMauro Carvalho Chehab """ 53f477c6d7SMauro Carvalho Chehab Manage package dependencies. There are three types of dependencies: 549ecda2e1SMauro Carvalho Chehab 55f477c6d7SMauro Carvalho Chehab - System: dependencies required for docs build; 56f477c6d7SMauro Carvalho Chehab - Python: python dependencies for a native distro Sphinx install; 57f477c6d7SMauro Carvalho Chehab - PDF: dependencies needed by PDF builds. 58f477c6d7SMauro Carvalho Chehab 59f477c6d7SMauro Carvalho Chehab Each dependency can be mandatory or optional. Not installing an optional 60f477c6d7SMauro Carvalho Chehab dependency won't break the build, but will cause degradation at the 61f477c6d7SMauro Carvalho Chehab docs output. 62f477c6d7SMauro Carvalho Chehab """ 63f477c6d7SMauro Carvalho Chehab 64f477c6d7SMauro Carvalho Chehab # Internal types of dependencies. Don't use them outside DepManager class. 659ecda2e1SMauro Carvalho Chehab _SYS_TYPE = 0 669ecda2e1SMauro Carvalho Chehab _PHY_TYPE = 1 679ecda2e1SMauro Carvalho Chehab _PDF_TYPE = 2 689ecda2e1SMauro Carvalho Chehab 69f477c6d7SMauro Carvalho Chehab # Dependencies visible outside the class. 70f477c6d7SMauro Carvalho Chehab # The keys are tuple with: (type, is_mandatory flag). 71f477c6d7SMauro Carvalho Chehab # 72f477c6d7SMauro Carvalho Chehab # Currently we're not using all optional dep types. Yet, we'll keep all 73f477c6d7SMauro Carvalho Chehab # possible combinations here. They're not many, and that makes easier 74f477c6d7SMauro Carvalho Chehab # if later needed and for the name() method below 759ecda2e1SMauro Carvalho Chehab 769ecda2e1SMauro Carvalho Chehab SYSTEM_MANDATORY = (_SYS_TYPE, True) 779ecda2e1SMauro Carvalho Chehab PYTHON_MANDATORY = (_PHY_TYPE, True) 789ecda2e1SMauro Carvalho Chehab PDF_MANDATORY = (_PDF_TYPE, True) 799ecda2e1SMauro Carvalho Chehab 809ecda2e1SMauro Carvalho Chehab SYSTEM_OPTIONAL = (_SYS_TYPE, False) 819ecda2e1SMauro Carvalho Chehab PYTHON_OPTIONAL = (_PHY_TYPE, False) 829ecda2e1SMauro Carvalho Chehab PDF_OPTIONAL = (_PDF_TYPE, True) 839ecda2e1SMauro Carvalho Chehab 842cab00fbSMauro Carvalho Chehab def __init__(self, pdf): 85f477c6d7SMauro Carvalho Chehab """ 86f477c6d7SMauro Carvalho Chehab Initialize internal vars: 87f477c6d7SMauro Carvalho Chehab 88f477c6d7SMauro Carvalho Chehab - missing: missing dependencies list, containing a distro-independent 89f477c6d7SMauro Carvalho Chehab name for a missing dependency and its type. 90f477c6d7SMauro Carvalho Chehab - missing_pkg: ancillary dict containing missing dependencies in 91f477c6d7SMauro Carvalho Chehab distro namespace, organized by type. 92f477c6d7SMauro Carvalho Chehab - need: total number of needed dependencies. Never cleaned. 93f477c6d7SMauro Carvalho Chehab - optional: total number of optional dependencies. Never cleaned. 946d5f4f3dSMauro Carvalho Chehab - pdf: Is PDF support enabled? 95f477c6d7SMauro Carvalho Chehab """ 962cab00fbSMauro Carvalho Chehab self.missing = {} 97f477c6d7SMauro Carvalho Chehab self.missing_pkg = {} 982cab00fbSMauro Carvalho Chehab self.need = 0 992cab00fbSMauro Carvalho Chehab self.optional = 0 1002cab00fbSMauro Carvalho Chehab self.pdf = pdf 1012cab00fbSMauro Carvalho Chehab 1029ecda2e1SMauro Carvalho Chehab @staticmethod 1039ecda2e1SMauro Carvalho Chehab def name(dtype): 104f477c6d7SMauro Carvalho Chehab """ 105f477c6d7SMauro Carvalho Chehab Ancillary routine to output a warn/error message reporting 106f477c6d7SMauro Carvalho Chehab missing dependencies. 107f477c6d7SMauro Carvalho Chehab """ 1082cab00fbSMauro Carvalho Chehab if dtype[0] == DepManager._SYS_TYPE: 1099ecda2e1SMauro Carvalho Chehab msg = "build" 1102cab00fbSMauro Carvalho Chehab elif dtype[0] == DepManager._PHY_TYPE: 1119ecda2e1SMauro Carvalho Chehab msg = "Python" 1129ecda2e1SMauro Carvalho Chehab else: 1139ecda2e1SMauro Carvalho Chehab msg = "PDF" 1149ecda2e1SMauro Carvalho Chehab 1159ecda2e1SMauro Carvalho Chehab if dtype[1]: 1169ecda2e1SMauro Carvalho Chehab return f"ERROR: {msg} mandatory deps missing" 1179ecda2e1SMauro Carvalho Chehab else: 1188b45effaSMauro Carvalho Chehab return f"Warning: {msg} optional deps missing" 1199ecda2e1SMauro Carvalho Chehab 1209ecda2e1SMauro Carvalho Chehab @staticmethod 1219ecda2e1SMauro Carvalho Chehab def is_optional(dtype): 122f477c6d7SMauro Carvalho Chehab """Ancillary routine to report if a dependency is optional""" 1239ecda2e1SMauro Carvalho Chehab return not dtype[1] 1249ecda2e1SMauro Carvalho Chehab 1259ecda2e1SMauro Carvalho Chehab @staticmethod 1269ecda2e1SMauro Carvalho Chehab def is_pdf(dtype): 127f477c6d7SMauro Carvalho Chehab """Ancillary routine to report if a dependency is for PDF generation""" 1288b45effaSMauro Carvalho Chehab if dtype[0] == DepManager._PDF_TYPE: 1299ecda2e1SMauro Carvalho Chehab return True 1309ecda2e1SMauro Carvalho Chehab 1319ecda2e1SMauro Carvalho Chehab return False 1329ecda2e1SMauro Carvalho Chehab 1332cab00fbSMauro Carvalho Chehab def add_package(self, package, dtype): 134f477c6d7SMauro Carvalho Chehab """ 135f477c6d7SMauro Carvalho Chehab Add a package at the self.missing() dictionary. 136f477c6d7SMauro Carvalho Chehab Doesn't update missing_pkg. 137f477c6d7SMauro Carvalho Chehab """ 1382cab00fbSMauro Carvalho Chehab is_optional = DepManager.is_optional(dtype) 1392cab00fbSMauro Carvalho Chehab self.missing[package] = dtype 1402cab00fbSMauro Carvalho Chehab if is_optional: 1412cab00fbSMauro Carvalho Chehab self.optional += 1 1422cab00fbSMauro Carvalho Chehab else: 1432cab00fbSMauro Carvalho Chehab self.need += 1 1442cab00fbSMauro Carvalho Chehab 1452cab00fbSMauro Carvalho Chehab def del_package(self, package): 146f477c6d7SMauro Carvalho Chehab """ 147f477c6d7SMauro Carvalho Chehab Remove a package at the self.missing() dictionary. 148f477c6d7SMauro Carvalho Chehab Doesn't update missing_pkg. 149f477c6d7SMauro Carvalho Chehab """ 1502cab00fbSMauro Carvalho Chehab if package in self.missing: 1512cab00fbSMauro Carvalho Chehab del self.missing[package] 1522cab00fbSMauro Carvalho Chehab 1532cab00fbSMauro Carvalho Chehab def clear_deps(self): 1542cab00fbSMauro Carvalho Chehab """ 1552cab00fbSMauro Carvalho Chehab Clear dependencies without changing needed/optional. 1562cab00fbSMauro Carvalho Chehab 1572cab00fbSMauro Carvalho Chehab This is an ackward way to have a separate section to recommend 1582cab00fbSMauro Carvalho Chehab a package after system main dependencies. 1592cab00fbSMauro Carvalho Chehab 160f477c6d7SMauro Carvalho Chehab TODO: rework the logic to prevent needing it. 1612cab00fbSMauro Carvalho Chehab """ 1622cab00fbSMauro Carvalho Chehab 1632cab00fbSMauro Carvalho Chehab self.missing = {} 164f477c6d7SMauro Carvalho Chehab self.missing_pkg = {} 1652cab00fbSMauro Carvalho Chehab 1662cab00fbSMauro Carvalho Chehab def check_missing(self, progs): 167f477c6d7SMauro Carvalho Chehab """ 168f477c6d7SMauro Carvalho Chehab Update self.missing_pkg, using progs dict to convert from the 169f477c6d7SMauro Carvalho Chehab agnostic package name to distro-specific one. 170f477c6d7SMauro Carvalho Chehab 171f477c6d7SMauro Carvalho Chehab Returns an string with the packages to be installed, sorted and 172f477c6d7SMauro Carvalho Chehab with eventual duplicates removed. 173f477c6d7SMauro Carvalho Chehab """ 174f477c6d7SMauro Carvalho Chehab 175f477c6d7SMauro Carvalho Chehab self.missing_pkg = {} 1762cab00fbSMauro Carvalho Chehab 1772cab00fbSMauro Carvalho Chehab for prog, dtype in sorted(self.missing.items()): 1782cab00fbSMauro Carvalho Chehab # At least on some LTS distros like CentOS 7, texlive doesn't 1792cab00fbSMauro Carvalho Chehab # provide all packages we need. When such distros are 1802cab00fbSMauro Carvalho Chehab # detected, we have to disable PDF output. 1812cab00fbSMauro Carvalho Chehab # 1822cab00fbSMauro Carvalho Chehab # So, we need to ignore the packages that distros would 1832cab00fbSMauro Carvalho Chehab # need for LaTeX to work 1842cab00fbSMauro Carvalho Chehab if DepManager.is_pdf(dtype) and not self.pdf: 1852cab00fbSMauro Carvalho Chehab self.optional -= 1 1862cab00fbSMauro Carvalho Chehab continue 1872cab00fbSMauro Carvalho Chehab 188f477c6d7SMauro Carvalho Chehab if not dtype in self.missing_pkg: 189f477c6d7SMauro Carvalho Chehab self.missing_pkg[dtype] = [] 1902cab00fbSMauro Carvalho Chehab 191f477c6d7SMauro Carvalho Chehab self.missing_pkg[dtype].append(progs.get(prog, prog)) 1922cab00fbSMauro Carvalho Chehab 1932cab00fbSMauro Carvalho Chehab install = [] 1948b45effaSMauro Carvalho Chehab for dtype, pkgs in self.missing_pkg.items(): 1958b45effaSMauro Carvalho Chehab install += pkgs 1962cab00fbSMauro Carvalho Chehab 1972cab00fbSMauro Carvalho Chehab return " ".join(sorted(set(install))) 1982cab00fbSMauro Carvalho Chehab 1992cab00fbSMauro Carvalho Chehab def warn_install(self): 200f477c6d7SMauro Carvalho Chehab """ 201f477c6d7SMauro Carvalho Chehab Emit warnings/errors related to missing packages. 202f477c6d7SMauro Carvalho Chehab """ 2032cab00fbSMauro Carvalho Chehab 2042cab00fbSMauro Carvalho Chehab output_msg = "" 2052cab00fbSMauro Carvalho Chehab 206f477c6d7SMauro Carvalho Chehab for dtype in sorted(self.missing_pkg.keys()): 207f477c6d7SMauro Carvalho Chehab progs = " ".join(sorted(set(self.missing_pkg[dtype]))) 2082cab00fbSMauro Carvalho Chehab 2092cab00fbSMauro Carvalho Chehab try: 2102cab00fbSMauro Carvalho Chehab name = DepManager.name(dtype) 2112cab00fbSMauro Carvalho Chehab output_msg += f'{name}:\t{progs}\n' 2122cab00fbSMauro Carvalho Chehab except KeyError: 2132cab00fbSMauro Carvalho Chehab raise KeyError(f"ERROR!!!: invalid dtype for {progs}: {dtype}") 2142cab00fbSMauro Carvalho Chehab 2152cab00fbSMauro Carvalho Chehab if output_msg: 21624a34b3bSMauro Carvalho Chehab print(f"\n{output_msg}") 2179ecda2e1SMauro Carvalho Chehab 2189bb5f0dcSMauro Carvalho Chehabclass AncillaryMethods: 2191e9ba3b6SMauro Carvalho Chehab """ 2201e9ba3b6SMauro Carvalho Chehab Ancillary methods that checks for missing dependencies for different 2211e9ba3b6SMauro Carvalho Chehab types of types, like binaries, python modules, rpm deps, etc. 2221e9ba3b6SMauro Carvalho Chehab """ 223ca9087f5SMauro Carvalho Chehab 224ca9087f5SMauro Carvalho Chehab @staticmethod 225ca9087f5SMauro Carvalho Chehab def which(prog): 226f477c6d7SMauro Carvalho Chehab """ 227f477c6d7SMauro Carvalho Chehab Our own implementation of which(). We could instead use 228f477c6d7SMauro Carvalho Chehab shutil.which(), but this function is simple enough. 229f477c6d7SMauro Carvalho Chehab Probably faster to use this implementation than to import shutil. 230f477c6d7SMauro Carvalho Chehab """ 231ca9087f5SMauro Carvalho Chehab for path in os.environ.get("PATH", "").split(":"): 232ca9087f5SMauro Carvalho Chehab full_path = os.path.join(path, prog) 233ca9087f5SMauro Carvalho Chehab if os.access(full_path, os.X_OK): 234ca9087f5SMauro Carvalho Chehab return full_path 235ca9087f5SMauro Carvalho Chehab 236ca9087f5SMauro Carvalho Chehab return None 237ca9087f5SMauro Carvalho Chehab 238ca9087f5SMauro Carvalho Chehab @staticmethod 239728648b6SMauro Carvalho Chehab def get_python_version(cmd): 240f477c6d7SMauro Carvalho Chehab """ 241f477c6d7SMauro Carvalho Chehab Get python version from a Python binary. As we need to detect if 242f477c6d7SMauro Carvalho Chehab are out there newer python binaries, we can't rely on sys.release here. 243f477c6d7SMauro Carvalho Chehab """ 244728648b6SMauro Carvalho Chehab 245728648b6SMauro Carvalho Chehab result = SphinxDependencyChecker.run([cmd, "--version"], 246728648b6SMauro Carvalho Chehab capture_output=True, text=True) 247728648b6SMauro Carvalho Chehab version = result.stdout.strip() 248728648b6SMauro Carvalho Chehab 249728648b6SMauro Carvalho Chehab match = re.search(r"(\d+\.\d+\.\d+)", version) 250728648b6SMauro Carvalho Chehab if match: 251728648b6SMauro Carvalho Chehab return parse_version(match.group(1)) 252728648b6SMauro Carvalho Chehab 253728648b6SMauro Carvalho Chehab print(f"Can't parse version {version}") 254728648b6SMauro Carvalho Chehab return (0, 0, 0) 255728648b6SMauro Carvalho Chehab 256728648b6SMauro Carvalho Chehab @staticmethod 257728648b6SMauro Carvalho Chehab def find_python(): 258f477c6d7SMauro Carvalho Chehab """ 259f477c6d7SMauro Carvalho Chehab Detect if are out there any python 3.xy version newer than the 260f477c6d7SMauro Carvalho Chehab current one. 261728648b6SMauro Carvalho Chehab 262f477c6d7SMauro Carvalho Chehab Note: this routine is limited to up to 2 digits for python3. We 263f477c6d7SMauro Carvalho Chehab may need to update it one day, hopefully on a distant future. 264f477c6d7SMauro Carvalho Chehab """ 265728648b6SMauro Carvalho Chehab patterns = [ 266728648b6SMauro Carvalho Chehab "python3.[0-9]", 267728648b6SMauro Carvalho Chehab "python3.[0-9][0-9]", 268728648b6SMauro Carvalho Chehab ] 269728648b6SMauro Carvalho Chehab 270728648b6SMauro Carvalho Chehab # Seek for a python binary newer than MIN_PYTHON_VERSION 271728648b6SMauro Carvalho Chehab for path in os.getenv("PATH", "").split(":"): 272728648b6SMauro Carvalho Chehab for pattern in patterns: 273728648b6SMauro Carvalho Chehab for cmd in glob(os.path.join(path, pattern)): 274728648b6SMauro Carvalho Chehab if os.path.isfile(cmd) and os.access(cmd, os.X_OK): 275728648b6SMauro Carvalho Chehab version = SphinxDependencyChecker.get_python_version(cmd) 276728648b6SMauro Carvalho Chehab if version >= MIN_PYTHON_VERSION: 2778b45effaSMauro Carvalho Chehab return cmd 278728648b6SMauro Carvalho Chehab 279728648b6SMauro Carvalho Chehab @staticmethod 280728648b6SMauro Carvalho Chehab def check_python(): 281f477c6d7SMauro Carvalho Chehab """ 282f477c6d7SMauro Carvalho Chehab Check if the current python binary satisfies our minimal requirement 283f477c6d7SMauro Carvalho Chehab for Sphinx build. If not, re-run with a newer version if found. 284f477c6d7SMauro Carvalho Chehab """ 285728648b6SMauro Carvalho Chehab cur_ver = sys.version_info[:3] 286728648b6SMauro Carvalho Chehab if cur_ver >= MIN_PYTHON_VERSION: 287637fa6b3SMauro Carvalho Chehab ver = ver_str(cur_ver) 288637fa6b3SMauro Carvalho Chehab print(f"Python version: {ver}") 289637fa6b3SMauro Carvalho Chehab 290637fa6b3SMauro Carvalho Chehab # This could be useful for debugging purposes 291637fa6b3SMauro Carvalho Chehab if SphinxDependencyChecker.which("docutils"): 292637fa6b3SMauro Carvalho Chehab result = SphinxDependencyChecker.run(["docutils", "--version"], 293637fa6b3SMauro Carvalho Chehab capture_output=True, text=True) 294637fa6b3SMauro Carvalho Chehab ver = result.stdout.strip() 295637fa6b3SMauro Carvalho Chehab match = re.search(r"(\d+\.\d+\.\d+)", ver) 296637fa6b3SMauro Carvalho Chehab if match: 297637fa6b3SMauro Carvalho Chehab ver = match.group(1) 298637fa6b3SMauro Carvalho Chehab 299637fa6b3SMauro Carvalho Chehab print(f"Docutils version: {ver}") 300637fa6b3SMauro Carvalho Chehab 301728648b6SMauro Carvalho Chehab return 302728648b6SMauro Carvalho Chehab 303728648b6SMauro Carvalho Chehab python_ver = ver_str(cur_ver) 304728648b6SMauro Carvalho Chehab 305728648b6SMauro Carvalho Chehab new_python_cmd = SphinxDependencyChecker.find_python() 306728648b6SMauro Carvalho Chehab if not new_python_cmd: 3078b45effaSMauro Carvalho Chehab print(f"ERROR: Python version {python_ver} is not spported anymore\n") 3088b45effaSMauro Carvalho Chehab print(" Can't find a new version. This script may fail") 309728648b6SMauro Carvalho Chehab return 310728648b6SMauro Carvalho Chehab 311728648b6SMauro Carvalho Chehab # Restart script using the newer version 312728648b6SMauro Carvalho Chehab script_path = os.path.abspath(sys.argv[0]) 313728648b6SMauro Carvalho Chehab args = [new_python_cmd, script_path] + sys.argv[1:] 314728648b6SMauro Carvalho Chehab 315728648b6SMauro Carvalho Chehab print(f"Python {python_ver} not supported. Changing to {new_python_cmd}") 316728648b6SMauro Carvalho Chehab 317728648b6SMauro Carvalho Chehab try: 318728648b6SMauro Carvalho Chehab os.execv(new_python_cmd, args) 319728648b6SMauro Carvalho Chehab except OSError as e: 320728648b6SMauro Carvalho Chehab sys.exit(f"Failed to restart with {new_python_cmd}: {e}") 321728648b6SMauro Carvalho Chehab 322728648b6SMauro Carvalho Chehab @staticmethod 323ca9087f5SMauro Carvalho Chehab def run(*args, **kwargs): 324f477c6d7SMauro Carvalho Chehab """ 325f477c6d7SMauro Carvalho Chehab Excecute a command, hiding its output by default. 326f477c6d7SMauro Carvalho Chehab Preserve comatibility with older Python versions. 327f477c6d7SMauro Carvalho Chehab """ 328ca9087f5SMauro Carvalho Chehab 32956a87677SMauro Carvalho Chehab capture_output = kwargs.pop('capture_output', False) 33056a87677SMauro Carvalho Chehab 33156a87677SMauro Carvalho Chehab if capture_output: 33256a87677SMauro Carvalho Chehab if 'stdout' not in kwargs: 33356a87677SMauro Carvalho Chehab kwargs['stdout'] = subprocess.PIPE 33456a87677SMauro Carvalho Chehab if 'stderr' not in kwargs: 33556a87677SMauro Carvalho Chehab kwargs['stderr'] = subprocess.PIPE 33656a87677SMauro Carvalho Chehab else: 337ca9087f5SMauro Carvalho Chehab if 'stdout' not in kwargs: 338ca9087f5SMauro Carvalho Chehab kwargs['stdout'] = subprocess.DEVNULL 339ca9087f5SMauro Carvalho Chehab if 'stderr' not in kwargs: 340ca9087f5SMauro Carvalho Chehab kwargs['stderr'] = subprocess.DEVNULL 341ca9087f5SMauro Carvalho Chehab 34256a87677SMauro Carvalho Chehab # Don't break with older Python versions 34356a87677SMauro Carvalho Chehab if 'text' in kwargs and sys.version_info < (3, 7): 34456a87677SMauro Carvalho Chehab kwargs['universal_newlines'] = kwargs.pop('text') 34556a87677SMauro Carvalho Chehab 346ca9087f5SMauro Carvalho Chehab return subprocess.run(*args, **kwargs) 347ca9087f5SMauro Carvalho Chehab 3489bb5f0dcSMauro Carvalho Chehabclass MissingCheckers(AncillaryMethods): 349f477c6d7SMauro Carvalho Chehab """ 350f477c6d7SMauro Carvalho Chehab Contains some ancillary checkers for different types of binaries and 351f477c6d7SMauro Carvalho Chehab package managers. 352f477c6d7SMauro Carvalho Chehab """ 3531e9ba3b6SMauro Carvalho Chehab 3549bb5f0dcSMauro Carvalho Chehab def __init__(self, args, texlive): 355f477c6d7SMauro Carvalho Chehab """ 356f477c6d7SMauro Carvalho Chehab Initialize its internal variables 357f477c6d7SMauro Carvalho Chehab """ 3581e9ba3b6SMauro Carvalho Chehab self.pdf = args.pdf 3591e9ba3b6SMauro Carvalho Chehab self.virtualenv = args.virtualenv 3601e9ba3b6SMauro Carvalho Chehab self.version_check = args.version_check 3619bb5f0dcSMauro Carvalho Chehab self.texlive = texlive 3621e9ba3b6SMauro Carvalho Chehab 3638b45effaSMauro Carvalho Chehab self.min_version = (0, 0, 0) 3648b45effaSMauro Carvalho Chehab self.cur_version = (0, 0, 0) 3658b45effaSMauro Carvalho Chehab 3661e9ba3b6SMauro Carvalho Chehab self.deps = DepManager(self.pdf) 3671e9ba3b6SMauro Carvalho Chehab 3681e9ba3b6SMauro Carvalho Chehab self.need_symlink = 0 3691e9ba3b6SMauro Carvalho Chehab self.need_sphinx = 0 3709bb5f0dcSMauro Carvalho Chehab 3711e9ba3b6SMauro Carvalho Chehab self.verbose_warn_install = 1 3721e9ba3b6SMauro Carvalho Chehab 3731e9ba3b6SMauro Carvalho Chehab self.virtenv_dir = "" 3749bb5f0dcSMauro Carvalho Chehab self.install = "" 3758b45effaSMauro Carvalho Chehab self.python_cmd = "" 3768b45effaSMauro Carvalho Chehab 3778b45effaSMauro Carvalho Chehab self.virtenv_prefix = ["sphinx_", "Sphinx_" ] 3781e9ba3b6SMauro Carvalho Chehab 3799ecda2e1SMauro Carvalho Chehab def check_missing_file(self, files, package, dtype): 380f477c6d7SMauro Carvalho Chehab """ 381f477c6d7SMauro Carvalho Chehab Does the file exists? If not, add it to missing dependencies. 382f477c6d7SMauro Carvalho Chehab """ 383ca9087f5SMauro Carvalho Chehab for f in files: 384ca9087f5SMauro Carvalho Chehab if os.path.exists(f): 385ca9087f5SMauro Carvalho Chehab return 3862cab00fbSMauro Carvalho Chehab self.deps.add_package(package, dtype) 387ca9087f5SMauro Carvalho Chehab 3889ecda2e1SMauro Carvalho Chehab def check_program(self, prog, dtype): 389f477c6d7SMauro Carvalho Chehab """ 390f477c6d7SMauro Carvalho Chehab Does the program exists and it is at the PATH? 391f477c6d7SMauro Carvalho Chehab If not, add it to missing dependencies. 392f477c6d7SMauro Carvalho Chehab """ 393ca9087f5SMauro Carvalho Chehab found = self.which(prog) 394ca9087f5SMauro Carvalho Chehab if found: 395ca9087f5SMauro Carvalho Chehab return found 396ca9087f5SMauro Carvalho Chehab 3972cab00fbSMauro Carvalho Chehab self.deps.add_package(prog, dtype) 398ca9087f5SMauro Carvalho Chehab 399ca9087f5SMauro Carvalho Chehab return None 400ca9087f5SMauro Carvalho Chehab 4019ecda2e1SMauro Carvalho Chehab def check_perl_module(self, prog, dtype): 402f477c6d7SMauro Carvalho Chehab """ 403f477c6d7SMauro Carvalho Chehab Does perl have a dependency? Is it available? 404f477c6d7SMauro Carvalho Chehab If not, add it to missing dependencies. 405f477c6d7SMauro Carvalho Chehab 406f477c6d7SMauro Carvalho Chehab Right now, we still need Perl for doc build, as it is required 407f477c6d7SMauro Carvalho Chehab by some tools called at docs or kernel build time, like: 408f477c6d7SMauro Carvalho Chehab 409f477c6d7SMauro Carvalho Chehab scripts/documentation-file-ref-check 410f477c6d7SMauro Carvalho Chehab 411f477c6d7SMauro Carvalho Chehab Also, checkpatch is on Perl. 412f477c6d7SMauro Carvalho Chehab """ 413f477c6d7SMauro Carvalho Chehab 414ca9087f5SMauro Carvalho Chehab # While testing with lxc download template, one of the 415ca9087f5SMauro Carvalho Chehab # distros (Oracle) didn't have perl - nor even an option to install 416ca9087f5SMauro Carvalho Chehab # before installing oraclelinux-release-el9 package. 417ca9087f5SMauro Carvalho Chehab # 418ca9087f5SMauro Carvalho Chehab # Check it before running an error. If perl is not there, 419ca9087f5SMauro Carvalho Chehab # add it as a mandatory package, as some parts of the doc builder 420ca9087f5SMauro Carvalho Chehab # needs it. 421ca9087f5SMauro Carvalho Chehab if not self.which("perl"): 4222cab00fbSMauro Carvalho Chehab self.deps.add_package("perl", DepManager.SYSTEM_MANDATORY) 4232cab00fbSMauro Carvalho Chehab self.deps.add_package(prog, dtype) 424ca9087f5SMauro Carvalho Chehab return 425ca9087f5SMauro Carvalho Chehab 426ca9087f5SMauro Carvalho Chehab try: 427ca9087f5SMauro Carvalho Chehab self.run(["perl", f"-M{prog}", "-e", "1"], check=True) 428ca9087f5SMauro Carvalho Chehab except subprocess.CalledProcessError: 4292cab00fbSMauro Carvalho Chehab self.deps.add_package(prog, dtype) 430ca9087f5SMauro Carvalho Chehab 4319ecda2e1SMauro Carvalho Chehab def check_python_module(self, module, is_optional=False): 432f477c6d7SMauro Carvalho Chehab """ 433f477c6d7SMauro Carvalho Chehab Does a python module exists outside venv? If not, add it to missing 434f477c6d7SMauro Carvalho Chehab dependencies. 435f477c6d7SMauro Carvalho Chehab """ 4369ecda2e1SMauro Carvalho Chehab if is_optional: 4372cab00fbSMauro Carvalho Chehab dtype = DepManager.PYTHON_OPTIONAL 4389ecda2e1SMauro Carvalho Chehab else: 4392cab00fbSMauro Carvalho Chehab dtype = DepManager.PYTHON_MANDATORY 440ca9087f5SMauro Carvalho Chehab 441ca9087f5SMauro Carvalho Chehab try: 442ca9087f5SMauro Carvalho Chehab self.run([self.python_cmd, "-c", f"import {module}"], check=True) 443ca9087f5SMauro Carvalho Chehab except subprocess.CalledProcessError: 4442cab00fbSMauro Carvalho Chehab self.deps.add_package(module, dtype) 445ca9087f5SMauro Carvalho Chehab 4469ecda2e1SMauro Carvalho Chehab def check_rpm_missing(self, pkgs, dtype): 447f477c6d7SMauro Carvalho Chehab """ 448f477c6d7SMauro Carvalho Chehab Does a rpm package exists? If not, add it to missing dependencies. 449f477c6d7SMauro Carvalho Chehab """ 450ca9087f5SMauro Carvalho Chehab for prog in pkgs: 451ca9087f5SMauro Carvalho Chehab try: 452ca9087f5SMauro Carvalho Chehab self.run(["rpm", "-q", prog], check=True) 453ca9087f5SMauro Carvalho Chehab except subprocess.CalledProcessError: 4542cab00fbSMauro Carvalho Chehab self.deps.add_package(prog, dtype) 455ca9087f5SMauro Carvalho Chehab 4569ecda2e1SMauro Carvalho Chehab def check_pacman_missing(self, pkgs, dtype): 457f477c6d7SMauro Carvalho Chehab """ 458f477c6d7SMauro Carvalho Chehab Does a pacman package exists? If not, add it to missing dependencies. 459f477c6d7SMauro Carvalho Chehab """ 460ca9087f5SMauro Carvalho Chehab for prog in pkgs: 461ca9087f5SMauro Carvalho Chehab try: 462ca9087f5SMauro Carvalho Chehab self.run(["pacman", "-Q", prog], check=True) 463ca9087f5SMauro Carvalho Chehab except subprocess.CalledProcessError: 4642cab00fbSMauro Carvalho Chehab self.deps.add_package(prog, dtype) 465ca9087f5SMauro Carvalho Chehab 4669ecda2e1SMauro Carvalho Chehab def check_missing_tex(self, is_optional=False): 467f477c6d7SMauro Carvalho Chehab """ 468f477c6d7SMauro Carvalho Chehab Does a LaTeX package exists? If not, add it to missing dependencies. 469f477c6d7SMauro Carvalho Chehab """ 4709ecda2e1SMauro Carvalho Chehab if is_optional: 4712cab00fbSMauro Carvalho Chehab dtype = DepManager.PDF_OPTIONAL 4729ecda2e1SMauro Carvalho Chehab else: 4732cab00fbSMauro Carvalho Chehab dtype = DepManager.PDF_MANDATORY 4749ecda2e1SMauro Carvalho Chehab 475ca9087f5SMauro Carvalho Chehab kpsewhich = self.which("kpsewhich") 476ca9087f5SMauro Carvalho Chehab for prog, package in self.texlive.items(): 477ca9087f5SMauro Carvalho Chehab 478ca9087f5SMauro Carvalho Chehab # If kpsewhich is not there, just add it to deps 479ca9087f5SMauro Carvalho Chehab if not kpsewhich: 4802cab00fbSMauro Carvalho Chehab self.deps.add_package(package, dtype) 481ca9087f5SMauro Carvalho Chehab continue 482ca9087f5SMauro Carvalho Chehab 483ca9087f5SMauro Carvalho Chehab # Check if the package is needed 484ca9087f5SMauro Carvalho Chehab try: 485ca9087f5SMauro Carvalho Chehab result = self.run( 486ca9087f5SMauro Carvalho Chehab [kpsewhich, prog], stdout=subprocess.PIPE, text=True, check=True 487ca9087f5SMauro Carvalho Chehab ) 488ca9087f5SMauro Carvalho Chehab 489ca9087f5SMauro Carvalho Chehab # Didn't find. Add it 490ca9087f5SMauro Carvalho Chehab if not result.stdout.strip(): 4912cab00fbSMauro Carvalho Chehab self.deps.add_package(package, dtype) 492ca9087f5SMauro Carvalho Chehab 493ca9087f5SMauro Carvalho Chehab except subprocess.CalledProcessError: 494ca9087f5SMauro Carvalho Chehab # kpsewhich returned an error. Add it, just in case 4952cab00fbSMauro Carvalho Chehab self.deps.add_package(package, dtype) 496ca9087f5SMauro Carvalho Chehab 497ca9087f5SMauro Carvalho Chehab def get_sphinx_fname(self): 498f477c6d7SMauro Carvalho Chehab """ 499f477c6d7SMauro Carvalho Chehab Gets the binary filename for sphinx-build. 500f477c6d7SMauro Carvalho Chehab """ 501ca9087f5SMauro Carvalho Chehab if "SPHINXBUILD" in os.environ: 502ca9087f5SMauro Carvalho Chehab return os.environ["SPHINXBUILD"] 503ca9087f5SMauro Carvalho Chehab 504ca9087f5SMauro Carvalho Chehab fname = "sphinx-build" 505ca9087f5SMauro Carvalho Chehab if self.which(fname): 506ca9087f5SMauro Carvalho Chehab return fname 507ca9087f5SMauro Carvalho Chehab 508ca9087f5SMauro Carvalho Chehab fname = "sphinx-build-3" 509ca9087f5SMauro Carvalho Chehab if self.which(fname): 510ca9087f5SMauro Carvalho Chehab self.need_symlink = 1 511ca9087f5SMauro Carvalho Chehab return fname 512ca9087f5SMauro Carvalho Chehab 513ca9087f5SMauro Carvalho Chehab return "" 514ca9087f5SMauro Carvalho Chehab 515ca9087f5SMauro Carvalho Chehab def get_sphinx_version(self, cmd): 516f477c6d7SMauro Carvalho Chehab """ 517f477c6d7SMauro Carvalho Chehab Gets sphinx-build version. 518f477c6d7SMauro Carvalho Chehab """ 519ca9087f5SMauro Carvalho Chehab try: 520ca9087f5SMauro Carvalho Chehab result = self.run([cmd, "--version"], 521ca9087f5SMauro Carvalho Chehab stdout=subprocess.PIPE, 522ca9087f5SMauro Carvalho Chehab stderr=subprocess.STDOUT, 523ca9087f5SMauro Carvalho Chehab text=True, check=True) 524ca9087f5SMauro Carvalho Chehab except (subprocess.CalledProcessError, FileNotFoundError): 525ca9087f5SMauro Carvalho Chehab return None 526ca9087f5SMauro Carvalho Chehab 527ca9087f5SMauro Carvalho Chehab for line in result.stdout.split("\n"): 528ca9087f5SMauro Carvalho Chehab match = re.match(r"^sphinx-build\s+([\d\.]+)(?:\+(?:/[\da-f]+)|b\d+)?\s*$", line) 529ca9087f5SMauro Carvalho Chehab if match: 530ca9087f5SMauro Carvalho Chehab return parse_version(match.group(1)) 531ca9087f5SMauro Carvalho Chehab 532ca9087f5SMauro Carvalho Chehab match = re.match(r"^Sphinx.*\s+([\d\.]+)\s*$", line) 533ca9087f5SMauro Carvalho Chehab if match: 534ca9087f5SMauro Carvalho Chehab return parse_version(match.group(1)) 535ca9087f5SMauro Carvalho Chehab 5369bb5f0dcSMauro Carvalho Chehab def check_sphinx(self, conf): 537f477c6d7SMauro Carvalho Chehab """ 538f477c6d7SMauro Carvalho Chehab Checks Sphinx minimal requirements 539f477c6d7SMauro Carvalho Chehab """ 540ca9087f5SMauro Carvalho Chehab try: 5419bb5f0dcSMauro Carvalho Chehab with open(conf, "r", encoding="utf-8") as f: 542ca9087f5SMauro Carvalho Chehab for line in f: 543ca9087f5SMauro Carvalho Chehab match = re.match(r"^\s*needs_sphinx\s*=\s*[\'\"]([\d\.]+)[\'\"]", line) 544ca9087f5SMauro Carvalho Chehab if match: 545ca9087f5SMauro Carvalho Chehab self.min_version = parse_version(match.group(1)) 546ca9087f5SMauro Carvalho Chehab break 547ca9087f5SMauro Carvalho Chehab except IOError: 5488b45effaSMauro Carvalho Chehab sys.exit(f"Can't open {conf}") 549ca9087f5SMauro Carvalho Chehab 550ca9087f5SMauro Carvalho Chehab if not self.min_version: 5518b45effaSMauro Carvalho Chehab sys.exit(f"Can't get needs_sphinx version from {conf}") 552ca9087f5SMauro Carvalho Chehab 553ca9087f5SMauro Carvalho Chehab self.virtenv_dir = self.virtenv_prefix[0] + "latest" 554ca9087f5SMauro Carvalho Chehab 555ca9087f5SMauro Carvalho Chehab sphinx = self.get_sphinx_fname() 556ca9087f5SMauro Carvalho Chehab if not sphinx: 557ca9087f5SMauro Carvalho Chehab self.need_sphinx = 1 558ca9087f5SMauro Carvalho Chehab return 559ca9087f5SMauro Carvalho Chehab 560ca9087f5SMauro Carvalho Chehab self.cur_version = self.get_sphinx_version(sphinx) 561ca9087f5SMauro Carvalho Chehab if not self.cur_version: 562ca9087f5SMauro Carvalho Chehab sys.exit(f"{sphinx} didn't return its version") 563ca9087f5SMauro Carvalho Chehab 564ca9087f5SMauro Carvalho Chehab if self.cur_version < self.min_version: 565ca9087f5SMauro Carvalho Chehab curver = ver_str(self.cur_version) 566ca9087f5SMauro Carvalho Chehab minver = ver_str(self.min_version) 567ca9087f5SMauro Carvalho Chehab 568ca9087f5SMauro Carvalho Chehab print(f"ERROR: Sphinx version is {curver}. It should be >= {minver}") 569ca9087f5SMauro Carvalho Chehab self.need_sphinx = 1 570ca9087f5SMauro Carvalho Chehab return 571ca9087f5SMauro Carvalho Chehab 572ca9087f5SMauro Carvalho Chehab # On version check mode, just assume Sphinx has all mandatory deps 573ca9087f5SMauro Carvalho Chehab if self.version_check and self.cur_version >= RECOMMENDED_VERSION: 574ca9087f5SMauro Carvalho Chehab sys.exit(0) 575ca9087f5SMauro Carvalho Chehab 576ca9087f5SMauro Carvalho Chehab def catcheck(self, filename): 577f477c6d7SMauro Carvalho Chehab """ 578f477c6d7SMauro Carvalho Chehab Reads a file if it exists, returning as string. 579f477c6d7SMauro Carvalho Chehab If not found, returns an empty string. 580f477c6d7SMauro Carvalho Chehab """ 581ca9087f5SMauro Carvalho Chehab if os.path.exists(filename): 582ca9087f5SMauro Carvalho Chehab with open(filename, "r", encoding="utf-8") as f: 583ca9087f5SMauro Carvalho Chehab return f.read().strip() 584ca9087f5SMauro Carvalho Chehab return "" 585ca9087f5SMauro Carvalho Chehab 586fb22e438SMauro Carvalho Chehab def get_system_release(self): 587fb22e438SMauro Carvalho Chehab """ 588fb22e438SMauro Carvalho Chehab Determine the system type. There's no unique way that would work 589fb22e438SMauro Carvalho Chehab with all distros with a minimal package install. So, several 590fb22e438SMauro Carvalho Chehab methods are used here. 591fb22e438SMauro Carvalho Chehab 592fb22e438SMauro Carvalho Chehab By default, it will use lsb_release function. If not available, it will 593fb22e438SMauro Carvalho Chehab fail back to reading the known different places where the distro name 594fb22e438SMauro Carvalho Chehab is stored. 595fb22e438SMauro Carvalho Chehab 596fb22e438SMauro Carvalho Chehab Several modern distros now have /etc/os-release, which usually have 597fb22e438SMauro Carvalho Chehab a decent coverage. 598fb22e438SMauro Carvalho Chehab """ 599fb22e438SMauro Carvalho Chehab 600fb22e438SMauro Carvalho Chehab system_release = "" 601fb22e438SMauro Carvalho Chehab 602fb22e438SMauro Carvalho Chehab if self.which("lsb_release"): 603fb22e438SMauro Carvalho Chehab result = self.run(["lsb_release", "-d"], capture_output=True, text=True) 604fb22e438SMauro Carvalho Chehab system_release = result.stdout.replace("Description:", "").strip() 605fb22e438SMauro Carvalho Chehab 606fb22e438SMauro Carvalho Chehab release_files = [ 607fb22e438SMauro Carvalho Chehab "/etc/system-release", 608fb22e438SMauro Carvalho Chehab "/etc/redhat-release", 609fb22e438SMauro Carvalho Chehab "/etc/lsb-release", 610fb22e438SMauro Carvalho Chehab "/etc/gentoo-release", 611fb22e438SMauro Carvalho Chehab ] 612fb22e438SMauro Carvalho Chehab 613fb22e438SMauro Carvalho Chehab if not system_release: 614fb22e438SMauro Carvalho Chehab for f in release_files: 615fb22e438SMauro Carvalho Chehab system_release = self.catcheck(f) 616fb22e438SMauro Carvalho Chehab if system_release: 617fb22e438SMauro Carvalho Chehab break 618fb22e438SMauro Carvalho Chehab 619fb22e438SMauro Carvalho Chehab # This seems more common than LSB these days 620fb22e438SMauro Carvalho Chehab if not system_release: 621fb22e438SMauro Carvalho Chehab os_var = {} 622fb22e438SMauro Carvalho Chehab try: 623fb22e438SMauro Carvalho Chehab with open("/etc/os-release", "r", encoding="utf-8") as f: 624fb22e438SMauro Carvalho Chehab for line in f: 625fb22e438SMauro Carvalho Chehab match = re.match(r"^([\w\d\_]+)=\"?([^\"]*)\"?\n", line) 626fb22e438SMauro Carvalho Chehab if match: 627fb22e438SMauro Carvalho Chehab os_var[match.group(1)] = match.group(2) 628fb22e438SMauro Carvalho Chehab 629fb22e438SMauro Carvalho Chehab system_release = os_var.get("NAME", "") 630fb22e438SMauro Carvalho Chehab if "VERSION_ID" in os_var: 631fb22e438SMauro Carvalho Chehab system_release += " " + os_var["VERSION_ID"] 632fb22e438SMauro Carvalho Chehab elif "VERSION" in os_var: 633fb22e438SMauro Carvalho Chehab system_release += " " + os_var["VERSION"] 634fb22e438SMauro Carvalho Chehab except IOError: 635fb22e438SMauro Carvalho Chehab pass 636fb22e438SMauro Carvalho Chehab 637fb22e438SMauro Carvalho Chehab if not system_release: 638fb22e438SMauro Carvalho Chehab system_release = self.catcheck("/etc/issue") 639fb22e438SMauro Carvalho Chehab 640fb22e438SMauro Carvalho Chehab system_release = system_release.strip() 641fb22e438SMauro Carvalho Chehab 642fb22e438SMauro Carvalho Chehab return system_release 643fb22e438SMauro Carvalho Chehab 6449bb5f0dcSMauro Carvalho Chehabclass SphinxDependencyChecker(MissingCheckers): 6456d5f4f3dSMauro Carvalho Chehab """ 6466d5f4f3dSMauro Carvalho Chehab Main class for checking Sphinx documentation build dependencies. 6479bb5f0dcSMauro Carvalho Chehab 6486d5f4f3dSMauro Carvalho Chehab - Check for missing system packages; 6496d5f4f3dSMauro Carvalho Chehab - Check for missing Python modules; 6506d5f4f3dSMauro Carvalho Chehab - Check for missing LaTeX packages needed by PDF generation; 6516d5f4f3dSMauro Carvalho Chehab - Propose Sphinx install via Python Virtual environment; 6526d5f4f3dSMauro Carvalho Chehab - Propose Sphinx install via distro-specific package install. 6536d5f4f3dSMauro Carvalho Chehab """ 6549bb5f0dcSMauro Carvalho Chehab def __init__(self, args): 6556d5f4f3dSMauro Carvalho Chehab """Initialize checker variables""" 6566d5f4f3dSMauro Carvalho Chehab 6579bb5f0dcSMauro Carvalho Chehab # List of required texlive packages on Fedora and OpenSuse 6589bb5f0dcSMauro Carvalho Chehab texlive = { 6599bb5f0dcSMauro Carvalho Chehab "amsfonts.sty": "texlive-amsfonts", 6609bb5f0dcSMauro Carvalho Chehab "amsmath.sty": "texlive-amsmath", 6619bb5f0dcSMauro Carvalho Chehab "amssymb.sty": "texlive-amsfonts", 6629bb5f0dcSMauro Carvalho Chehab "amsthm.sty": "texlive-amscls", 6639bb5f0dcSMauro Carvalho Chehab "anyfontsize.sty": "texlive-anyfontsize", 6649bb5f0dcSMauro Carvalho Chehab "atbegshi.sty": "texlive-oberdiek", 6659bb5f0dcSMauro Carvalho Chehab "bm.sty": "texlive-tools", 6669bb5f0dcSMauro Carvalho Chehab "capt-of.sty": "texlive-capt-of", 6679bb5f0dcSMauro Carvalho Chehab "cmap.sty": "texlive-cmap", 6689bb5f0dcSMauro Carvalho Chehab "ctexhook.sty": "texlive-ctex", 6699bb5f0dcSMauro Carvalho Chehab "ecrm1000.tfm": "texlive-ec", 6709bb5f0dcSMauro Carvalho Chehab "eqparbox.sty": "texlive-eqparbox", 6719bb5f0dcSMauro Carvalho Chehab "eu1enc.def": "texlive-euenc", 6729bb5f0dcSMauro Carvalho Chehab "fancybox.sty": "texlive-fancybox", 6739bb5f0dcSMauro Carvalho Chehab "fancyvrb.sty": "texlive-fancyvrb", 6749bb5f0dcSMauro Carvalho Chehab "float.sty": "texlive-float", 6759bb5f0dcSMauro Carvalho Chehab "fncychap.sty": "texlive-fncychap", 6769bb5f0dcSMauro Carvalho Chehab "footnote.sty": "texlive-mdwtools", 6779bb5f0dcSMauro Carvalho Chehab "framed.sty": "texlive-framed", 6789bb5f0dcSMauro Carvalho Chehab "luatex85.sty": "texlive-luatex85", 6799bb5f0dcSMauro Carvalho Chehab "multirow.sty": "texlive-multirow", 6809bb5f0dcSMauro Carvalho Chehab "needspace.sty": "texlive-needspace", 6819bb5f0dcSMauro Carvalho Chehab "palatino.sty": "texlive-psnfss", 6829bb5f0dcSMauro Carvalho Chehab "parskip.sty": "texlive-parskip", 6839bb5f0dcSMauro Carvalho Chehab "polyglossia.sty": "texlive-polyglossia", 6849bb5f0dcSMauro Carvalho Chehab "tabulary.sty": "texlive-tabulary", 6859bb5f0dcSMauro Carvalho Chehab "threeparttable.sty": "texlive-threeparttable", 6869bb5f0dcSMauro Carvalho Chehab "titlesec.sty": "texlive-titlesec", 6879bb5f0dcSMauro Carvalho Chehab "ucs.sty": "texlive-ucs", 6889bb5f0dcSMauro Carvalho Chehab "upquote.sty": "texlive-upquote", 6899bb5f0dcSMauro Carvalho Chehab "wrapfig.sty": "texlive-wrapfig", 6909bb5f0dcSMauro Carvalho Chehab } 6919bb5f0dcSMauro Carvalho Chehab 6929bb5f0dcSMauro Carvalho Chehab super().__init__(args, texlive) 6939bb5f0dcSMauro Carvalho Chehab 6949f51a1d6SMauro Carvalho Chehab self.need_pip = False 6959bb5f0dcSMauro Carvalho Chehab self.rec_sphinx_upgrade = 0 6969bb5f0dcSMauro Carvalho Chehab 697fb22e438SMauro Carvalho Chehab self.system_release = self.get_system_release() 6989bb5f0dcSMauro Carvalho Chehab self.activate_cmd = "" 6999bb5f0dcSMauro Carvalho Chehab 7009bb5f0dcSMauro Carvalho Chehab # Some distros may not have a Sphinx shipped package compatible with 7019bb5f0dcSMauro Carvalho Chehab # our minimal requirements 7029bb5f0dcSMauro Carvalho Chehab self.package_supported = True 7039bb5f0dcSMauro Carvalho Chehab 7049bb5f0dcSMauro Carvalho Chehab # Recommend a new python version 7059bb5f0dcSMauro Carvalho Chehab self.recommend_python = None 7069bb5f0dcSMauro Carvalho Chehab 7079bb5f0dcSMauro Carvalho Chehab # Certain hints are meant to be shown only once 70824a34b3bSMauro Carvalho Chehab self.distro_msg = None 7099bb5f0dcSMauro Carvalho Chehab 7109bb5f0dcSMauro Carvalho Chehab self.latest_avail_ver = (0, 0, 0) 7119bb5f0dcSMauro Carvalho Chehab self.venv_ver = (0, 0, 0) 7129bb5f0dcSMauro Carvalho Chehab 7139bb5f0dcSMauro Carvalho Chehab prefix = os.environ.get("srctree", ".") + "/" 7149bb5f0dcSMauro Carvalho Chehab 7159bb5f0dcSMauro Carvalho Chehab self.conf = prefix + "Documentation/conf.py" 7169bb5f0dcSMauro Carvalho Chehab self.requirement_file = prefix + "Documentation/sphinx/requirements.txt" 7172cab00fbSMauro Carvalho Chehab 71824a34b3bSMauro Carvalho Chehab def get_install_progs(self, progs, cmd, extra=None): 71924a34b3bSMauro Carvalho Chehab """ 72024a34b3bSMauro Carvalho Chehab Check for missing dependencies using the provided program mapping. 72124a34b3bSMauro Carvalho Chehab 72224a34b3bSMauro Carvalho Chehab The actual distro-specific programs are mapped via progs argument. 72324a34b3bSMauro Carvalho Chehab """ 72424a34b3bSMauro Carvalho Chehab install = self.deps.check_missing(progs) 72524a34b3bSMauro Carvalho Chehab 72624a34b3bSMauro Carvalho Chehab if self.verbose_warn_install: 72724a34b3bSMauro Carvalho Chehab self.deps.warn_install() 72824a34b3bSMauro Carvalho Chehab 72924a34b3bSMauro Carvalho Chehab if not install: 73024a34b3bSMauro Carvalho Chehab return 73124a34b3bSMauro Carvalho Chehab 73224a34b3bSMauro Carvalho Chehab if cmd: 73324a34b3bSMauro Carvalho Chehab if self.verbose_warn_install: 73424a34b3bSMauro Carvalho Chehab msg = "You should run:" 73524a34b3bSMauro Carvalho Chehab else: 73624a34b3bSMauro Carvalho Chehab msg = "" 73724a34b3bSMauro Carvalho Chehab 73824a34b3bSMauro Carvalho Chehab if extra: 73924a34b3bSMauro Carvalho Chehab msg += "\n\t" + extra.replace("\n", "\n\t") 74024a34b3bSMauro Carvalho Chehab 74124a34b3bSMauro Carvalho Chehab return(msg + "\n\tsudo " + cmd + " " + install) 74224a34b3bSMauro Carvalho Chehab 74324a34b3bSMauro Carvalho Chehab return None 74424a34b3bSMauro Carvalho Chehab 745ca9087f5SMauro Carvalho Chehab # 746ca9087f5SMauro Carvalho Chehab # Distro-specific hints methods 747ca9087f5SMauro Carvalho Chehab # 748ca9087f5SMauro Carvalho Chehab 749ca9087f5SMauro Carvalho Chehab def give_debian_hints(self): 7506d5f4f3dSMauro Carvalho Chehab """ 7516d5f4f3dSMauro Carvalho Chehab Provide package installation hints for Debian-based distros. 7526d5f4f3dSMauro Carvalho Chehab """ 753ca9087f5SMauro Carvalho Chehab progs = { 754ca9087f5SMauro Carvalho Chehab "Pod::Usage": "perl-modules", 755ca9087f5SMauro Carvalho Chehab "convert": "imagemagick", 756ca9087f5SMauro Carvalho Chehab "dot": "graphviz", 757ca9087f5SMauro Carvalho Chehab "ensurepip": "python3-venv", 758ca9087f5SMauro Carvalho Chehab "python-sphinx": "python3-sphinx", 759ca9087f5SMauro Carvalho Chehab "rsvg-convert": "librsvg2-bin", 760ca9087f5SMauro Carvalho Chehab "virtualenv": "virtualenv", 761ca9087f5SMauro Carvalho Chehab "xelatex": "texlive-xetex", 762ca9087f5SMauro Carvalho Chehab "yaml": "python3-yaml", 763ca9087f5SMauro Carvalho Chehab } 764ca9087f5SMauro Carvalho Chehab 765ca9087f5SMauro Carvalho Chehab if self.pdf: 766ca9087f5SMauro Carvalho Chehab pdf_pkgs = { 767ca9087f5SMauro Carvalho Chehab "fonts-dejavu": [ 768ca9087f5SMauro Carvalho Chehab "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 769ca9087f5SMauro Carvalho Chehab ], 770ca9087f5SMauro Carvalho Chehab "fonts-noto-cjk": [ 771ca9087f5SMauro Carvalho Chehab "/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc", 772ca9087f5SMauro Carvalho Chehab "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc", 773ca9087f5SMauro Carvalho Chehab "/usr/share/fonts/opentype/noto/NotoSerifCJK-Regular.ttc", 774ca9087f5SMauro 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 ], 784ca9087f5SMauro Carvalho Chehab } 785ca9087f5SMauro Carvalho Chehab 786ca9087f5SMauro Carvalho Chehab for package, files in pdf_pkgs.items(): 7872cab00fbSMauro Carvalho Chehab self.check_missing_file(files, package, DepManager.PDF_MANDATORY) 788ca9087f5SMauro Carvalho Chehab 7892cab00fbSMauro Carvalho Chehab self.check_program("dvipng", DepManager.PDF_MANDATORY) 790ca9087f5SMauro 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 79624a34b3bSMauro Carvalho Chehab return self.get_install_progs(progs, "apt-get install") 797ca9087f5SMauro Carvalho Chehab 798ca9087f5SMauro Carvalho Chehab def give_redhat_hints(self): 7996d5f4f3dSMauro Carvalho Chehab """ 8006d5f4f3dSMauro Carvalho Chehab Provide package installation hints for RedHat-based distros 8016d5f4f3dSMauro Carvalho Chehab (Fedora, RHEL and RHEL-based variants). 8026d5f4f3dSMauro Carvalho Chehab """ 803ca9087f5SMauro Carvalho Chehab progs = { 804ca9087f5SMauro Carvalho Chehab "Pod::Usage": "perl-Pod-Usage", 805ca9087f5SMauro Carvalho Chehab "convert": "ImageMagick", 806ca9087f5SMauro Carvalho Chehab "dot": "graphviz", 807ca9087f5SMauro Carvalho Chehab "python-sphinx": "python3-sphinx", 808ca9087f5SMauro Carvalho Chehab "rsvg-convert": "librsvg2-tools", 809ca9087f5SMauro Carvalho Chehab "virtualenv": "python3-virtualenv", 810ca9087f5SMauro Carvalho Chehab "xelatex": "texlive-xetex-bin", 811ca9087f5SMauro Carvalho Chehab "yaml": "python3-pyyaml", 812ca9087f5SMauro Carvalho Chehab } 813ca9087f5SMauro Carvalho Chehab 814ca9087f5SMauro Carvalho Chehab fedora_tex_pkgs = [ 815ca9087f5SMauro Carvalho Chehab "dejavu-sans-fonts", 816ca9087f5SMauro Carvalho Chehab "dejavu-sans-mono-fonts", 817ca9087f5SMauro Carvalho Chehab "dejavu-serif-fonts", 818ca9087f5SMauro Carvalho Chehab "texlive-collection-fontsrecommended", 819ca9087f5SMauro Carvalho Chehab "texlive-collection-latex", 820ca9087f5SMauro Carvalho Chehab "texlive-xecjk", 821ca9087f5SMauro Carvalho Chehab ] 822ca9087f5SMauro Carvalho Chehab 823272f5e03SMauro Carvalho Chehab fedora = False 824ca9087f5SMauro Carvalho Chehab rel = None 825ca9087f5SMauro Carvalho Chehab 826ca9087f5SMauro Carvalho Chehab match = re.search(r"(release|Linux)\s+(\d+)", self.system_release) 827ca9087f5SMauro Carvalho Chehab if match: 828ca9087f5SMauro Carvalho Chehab rel = int(match.group(2)) 829ca9087f5SMauro Carvalho Chehab 830ca9087f5SMauro Carvalho Chehab if not rel: 831ca9087f5SMauro Carvalho Chehab print("Couldn't identify release number") 8328b45effaSMauro Carvalho Chehab noto_sans_redhat = None 833ca9087f5SMauro Carvalho Chehab self.pdf = False 834ca9087f5SMauro Carvalho Chehab elif re.search("Fedora", self.system_release): 835ca9087f5SMauro Carvalho Chehab # Fedora 38 and upper use this CJK font 836ca9087f5SMauro Carvalho Chehab 837ca9087f5SMauro Carvalho Chehab noto_sans_redhat = "google-noto-sans-cjk-fonts" 838272f5e03SMauro Carvalho Chehab fedora = True 839ca9087f5SMauro Carvalho Chehab else: 840ca9087f5SMauro Carvalho Chehab # Almalinux, CentOS, RHEL, ... 841ca9087f5SMauro Carvalho Chehab 842ca9087f5SMauro Carvalho Chehab # at least up to version 9 (and Fedora < 38), that's the CJK font 843ca9087f5SMauro Carvalho Chehab noto_sans_redhat = "google-noto-sans-cjk-ttc-fonts" 844ca9087f5SMauro Carvalho Chehab 845ca9087f5SMauro Carvalho Chehab progs["virtualenv"] = "python-virtualenv" 846ca9087f5SMauro Carvalho Chehab 8478f6f54c4SMauro Carvalho Chehab if not rel or rel < 8: 8488f6f54c4SMauro Carvalho Chehab print("ERROR: Distro not supported. Too old?") 8498f6f54c4SMauro Carvalho Chehab return 850ca9087f5SMauro Carvalho Chehab 8518cd25652SMauro Carvalho Chehab # RHEL 8 uses Python 3.6, which is not compatible with 8528cd25652SMauro Carvalho Chehab # the build system anymore. Suggest Python 3.11 8538cd25652SMauro 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 8588cd25652SMauro Carvalho Chehab self.recommend_python = True 8598f6f54c4SMauro 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 86324a34b3bSMauro Carvalho Chehab if not self.distro_msg: 86424a34b3bSMauro Carvalho Chehab self.distro_msg = \ 86524a34b3bSMauro Carvalho Chehab "Note: RHEL-based distros typically require extra repositories.\n" \ 8668f6f54c4SMauro Carvalho Chehab "For most, enabling epel and crb are enough:\n" \ 86724a34b3bSMauro Carvalho Chehab "\tsudo dnf install -y epel-release\n" \ 8688f6f54c4SMauro Carvalho Chehab "\tsudo dnf config-manager --set-enabled crb\n" \ 869e53e6d39SMauro Carvalho Chehab "Yet, some may have other required repositories. Those commands could be useful:\n" \ 870e53e6d39SMauro Carvalho Chehab "\tsudo dnf repolist all\n" \ 87124a34b3bSMauro Carvalho Chehab "\tsudo dnf repoquery --available --info <pkgs>\n" \ 87224a34b3bSMauro Carvalho Chehab "\tsudo dnf config-manager --set-enabled '*' # enable all - probably not what you want" 873ca9087f5SMauro Carvalho Chehab 874ca9087f5SMauro Carvalho Chehab if self.pdf: 875ca9087f5SMauro Carvalho Chehab pdf_pkgs = [ 876ca9087f5SMauro Carvalho Chehab "/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc", 877ca9087f5SMauro Carvalho Chehab "/usr/share/fonts/google-noto-sans-cjk-fonts/NotoSansCJK-Regular.ttc", 878ca9087f5SMauro Carvalho Chehab ] 879ca9087f5SMauro Carvalho Chehab 8802cab00fbSMauro Carvalho Chehab self.check_missing_file(pdf_pkgs, noto_sans_redhat, DepManager.PDF_MANDATORY) 881ca9087f5SMauro Carvalho Chehab 8822cab00fbSMauro Carvalho Chehab self.check_rpm_missing(fedora_tex_pkgs, DepManager.PDF_MANDATORY) 883ca9087f5SMauro Carvalho Chehab 8842cab00fbSMauro Carvalho Chehab self.check_missing_tex(DepManager.PDF_MANDATORY) 885272f5e03SMauro Carvalho Chehab 886272f5e03SMauro Carvalho Chehab # There's no texlive-ctex on RHEL 8 repositories. This will 887272f5e03SMauro Carvalho Chehab # likely affect CJK pdf build only. 888272f5e03SMauro Carvalho Chehab if not fedora and rel == 8: 8892cab00fbSMauro Carvalho Chehab self.deps.del_package("texlive-ctex") 890272f5e03SMauro Carvalho Chehab 89124a34b3bSMauro Carvalho Chehab return self.get_install_progs(progs, "dnf install") 892ca9087f5SMauro Carvalho Chehab 893ca9087f5SMauro Carvalho Chehab def give_opensuse_hints(self): 8946d5f4f3dSMauro Carvalho Chehab """ 8956d5f4f3dSMauro Carvalho Chehab Provide package installation hints for openSUSE-based distros 8966d5f4f3dSMauro Carvalho Chehab (Leap and Tumbleweed). 8976d5f4f3dSMauro Carvalho Chehab """ 898ca9087f5SMauro Carvalho Chehab progs = { 899ca9087f5SMauro Carvalho Chehab "Pod::Usage": "perl-Pod-Usage", 900ca9087f5SMauro Carvalho Chehab "convert": "ImageMagick", 901ca9087f5SMauro Carvalho Chehab "dot": "graphviz", 902ca9087f5SMauro Carvalho Chehab "python-sphinx": "python3-sphinx", 903ca9087f5SMauro Carvalho Chehab "virtualenv": "python3-virtualenv", 904b2d5d61cSMauro Carvalho Chehab "xelatex": "texlive-xetex-bin texlive-dejavu", 905ca9087f5SMauro Carvalho Chehab "yaml": "python3-pyyaml", 906ca9087f5SMauro Carvalho Chehab } 907ca9087f5SMauro Carvalho Chehab 908ca9087f5SMauro Carvalho Chehab suse_tex_pkgs = [ 909ca9087f5SMauro Carvalho Chehab "texlive-babel-english", 910ca9087f5SMauro Carvalho Chehab "texlive-caption", 911ca9087f5SMauro Carvalho Chehab "texlive-colortbl", 912ca9087f5SMauro Carvalho Chehab "texlive-courier", 913ca9087f5SMauro Carvalho Chehab "texlive-dvips", 914ca9087f5SMauro Carvalho Chehab "texlive-helvetic", 915ca9087f5SMauro Carvalho Chehab "texlive-makeindex", 916ca9087f5SMauro Carvalho Chehab "texlive-metafont", 917ca9087f5SMauro Carvalho Chehab "texlive-metapost", 918ca9087f5SMauro Carvalho Chehab "texlive-palatino", 919ca9087f5SMauro Carvalho Chehab "texlive-preview", 920ca9087f5SMauro Carvalho Chehab "texlive-times", 921ca9087f5SMauro Carvalho Chehab "texlive-zapfchan", 922ca9087f5SMauro Carvalho Chehab "texlive-zapfding", 923ca9087f5SMauro Carvalho Chehab ] 924ca9087f5SMauro Carvalho Chehab 925ca9087f5SMauro Carvalho Chehab progs["latexmk"] = "texlive-latexmk-bin" 926ca9087f5SMauro Carvalho Chehab 9272cb4877bSMauro Carvalho Chehab match = re.search(r"(Leap)\s+(\d+).(\d)", self.system_release) 9282cb4877bSMauro Carvalho Chehab if match: 9292cb4877bSMauro Carvalho Chehab rel = int(match.group(2)) 9302cb4877bSMauro Carvalho Chehab 9312cb4877bSMauro Carvalho Chehab # Leap 15.x uses Python 3.6, which is not compatible with 9322cb4877bSMauro Carvalho Chehab # the build system anymore. Suggest Python 3.11 9332cb4877bSMauro Carvalho Chehab if rel == 15: 9342cb4877bSMauro 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" 9378cd25652SMauro Carvalho Chehab self.recommend_python = True 9382cb4877bSMauro Carvalho Chehab 9392cb4877bSMauro Carvalho Chehab progs.update({ 940b2d5d61cSMauro Carvalho Chehab "python-sphinx": "python311-Sphinx python311-Sphinx-latex", 9412cb4877bSMauro Carvalho Chehab "virtualenv": "python311-virtualenv", 942c5ffae0fSMauro Carvalho Chehab "yaml": "python311-PyYAML", 9432cb4877bSMauro Carvalho Chehab }) 94494a161d9SMauro Carvalho Chehab else: 94594a161d9SMauro Carvalho Chehab # Tumbleweed defaults to Python 3.11 94694a161d9SMauro Carvalho Chehab 94794a161d9SMauro Carvalho Chehab progs.update({ 948b2d5d61cSMauro Carvalho Chehab "python-sphinx": "python313-Sphinx python313-Sphinx-latex", 94994a161d9SMauro Carvalho Chehab "virtualenv": "python313-virtualenv", 95094a161d9SMauro Carvalho Chehab "yaml": "python313-PyYAML", 95194a161d9SMauro Carvalho Chehab }) 9522cb4877bSMauro Carvalho Chehab 953ca9087f5SMauro Carvalho Chehab # FIXME: add support for installing CJK fonts 954ca9087f5SMauro Carvalho Chehab # 955ca9087f5SMauro Carvalho Chehab # I tried hard, but was unable to find a way to install 956ca9087f5SMauro Carvalho Chehab # "Noto Sans CJK SC" on openSUSE 957ca9087f5SMauro Carvalho Chehab 958ca9087f5SMauro Carvalho Chehab if self.pdf: 9592cab00fbSMauro Carvalho Chehab self.check_rpm_missing(suse_tex_pkgs, DepManager.PDF_MANDATORY) 960ca9087f5SMauro Carvalho Chehab if self.pdf: 9619ecda2e1SMauro Carvalho Chehab self.check_missing_tex() 962ca9087f5SMauro Carvalho Chehab 96324a34b3bSMauro Carvalho Chehab return self.get_install_progs(progs, "zypper install --no-recommends") 964ca9087f5SMauro Carvalho Chehab 965ca9087f5SMauro Carvalho Chehab def give_mageia_hints(self): 9666d5f4f3dSMauro Carvalho Chehab """ 9676d5f4f3dSMauro Carvalho Chehab Provide package installation hints for Mageia and OpenMandriva. 9686d5f4f3dSMauro Carvalho Chehab """ 969ca9087f5SMauro Carvalho Chehab progs = { 970ca9087f5SMauro Carvalho Chehab "Pod::Usage": "perl-Pod-Usage", 971ca9087f5SMauro Carvalho Chehab "convert": "ImageMagick", 972ca9087f5SMauro Carvalho Chehab "dot": "graphviz", 973ca9087f5SMauro Carvalho Chehab "python-sphinx": "python3-sphinx", 974ca9087f5SMauro Carvalho Chehab "rsvg-convert": "librsvg2", 975ca9087f5SMauro Carvalho Chehab "virtualenv": "python3-virtualenv", 976ca9087f5SMauro Carvalho Chehab "xelatex": "texlive", 977ca9087f5SMauro Carvalho Chehab "yaml": "python3-yaml", 978ca9087f5SMauro Carvalho Chehab } 979ca9087f5SMauro Carvalho Chehab 980ca9087f5SMauro Carvalho Chehab tex_pkgs = [ 981ca9087f5SMauro Carvalho Chehab "texlive-fontsextra", 982c71c5d6dSMauro Carvalho Chehab "texlive-fonts-asian", 983c71c5d6dSMauro Carvalho Chehab "fonts-ttf-dejavu", 984ca9087f5SMauro Carvalho Chehab ] 985ca9087f5SMauro Carvalho Chehab 986ca9087f5SMauro Carvalho Chehab if re.search(r"OpenMandriva", self.system_release): 987ca9087f5SMauro Carvalho Chehab packager_cmd = "dnf install" 988ca9087f5SMauro 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 ] 995fb08659bSMauro Carvalho Chehab 996fb08659bSMauro Carvalho Chehab # Tested on OpenMandriva Lx 4.3 997fb08659bSMauro Carvalho Chehab progs["convert"] = "imagemagick" 998fb08659bSMauro 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" 1018fb08659bSMauro Carvalho Chehab 1019ca9087f5SMauro Carvalho Chehab else: 1020ca9087f5SMauro Carvalho Chehab packager_cmd = "urpmi" 1021ca9087f5SMauro Carvalho Chehab noto_sans = "google-noto-sans-cjk-ttc-fonts" 1022ca9087f5SMauro Carvalho Chehab 1023ca9087f5SMauro Carvalho Chehab progs["latexmk"] = "texlive-collection-basic" 1024ca9087f5SMauro Carvalho Chehab 1025ca9087f5SMauro Carvalho Chehab if self.pdf: 1026ca9087f5SMauro Carvalho Chehab pdf_pkgs = [ 1027ca9087f5SMauro Carvalho Chehab "/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc", 1028ca9087f5SMauro Carvalho Chehab "/usr/share/fonts/TTF/NotoSans-Regular.ttf", 1029ca9087f5SMauro Carvalho Chehab ] 1030ca9087f5SMauro Carvalho Chehab 10312cab00fbSMauro Carvalho Chehab self.check_missing_file(pdf_pkgs, noto_sans, DepManager.PDF_MANDATORY) 10322cab00fbSMauro Carvalho Chehab self.check_rpm_missing(tex_pkgs, DepManager.PDF_MANDATORY) 1033ca9087f5SMauro Carvalho Chehab 103424a34b3bSMauro Carvalho Chehab return self.get_install_progs(progs, packager_cmd) 1035ca9087f5SMauro Carvalho Chehab 1036ca9087f5SMauro Carvalho Chehab def give_arch_linux_hints(self): 10376d5f4f3dSMauro Carvalho Chehab """ 10386d5f4f3dSMauro Carvalho Chehab Provide package installation hints for ArchLinux. 10396d5f4f3dSMauro Carvalho Chehab """ 1040ca9087f5SMauro Carvalho Chehab progs = { 1041ca9087f5SMauro Carvalho Chehab "convert": "imagemagick", 1042ca9087f5SMauro Carvalho Chehab "dot": "graphviz", 1043ca9087f5SMauro Carvalho Chehab "latexmk": "texlive-core", 1044ca9087f5SMauro Carvalho Chehab "rsvg-convert": "extra/librsvg", 1045ca9087f5SMauro Carvalho Chehab "virtualenv": "python-virtualenv", 1046ca9087f5SMauro Carvalho Chehab "xelatex": "texlive-xetex", 1047ca9087f5SMauro Carvalho Chehab "yaml": "python-yaml", 1048ca9087f5SMauro Carvalho Chehab } 1049ca9087f5SMauro Carvalho Chehab 1050ca9087f5SMauro Carvalho Chehab archlinux_tex_pkgs = [ 1051*c6e23912SMauro Carvalho Chehab "texlive-basic", 1052*c6e23912SMauro Carvalho Chehab "texlive-binextra", 1053ca9087f5SMauro Carvalho Chehab "texlive-core", 1054*c6e23912SMauro Carvalho Chehab "texlive-fontsrecommended", 1055*c6e23912SMauro Carvalho Chehab "texlive-langchinese", 1056*c6e23912SMauro Carvalho Chehab "texlive-langcjk", 1057ca9087f5SMauro Carvalho Chehab "texlive-latexextra", 1058ca9087f5SMauro Carvalho Chehab "ttf-dejavu", 1059ca9087f5SMauro Carvalho Chehab ] 1060ca9087f5SMauro Carvalho Chehab 1061ca9087f5SMauro Carvalho Chehab if self.pdf: 106224a34b3bSMauro Carvalho Chehab self.check_pacman_missing(archlinux_tex_pkgs, 106324a34b3bSMauro Carvalho Chehab DepManager.PDF_MANDATORY) 1064ca9087f5SMauro Carvalho Chehab 106524a34b3bSMauro Carvalho Chehab self.check_missing_file(["/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc"], 1066ca9087f5SMauro Carvalho Chehab "noto-fonts-cjk", 106724a34b3bSMauro Carvalho Chehab DepManager.PDF_MANDATORY) 1068ca9087f5SMauro Carvalho Chehab 10692cab00fbSMauro Carvalho Chehab 107024a34b3bSMauro Carvalho Chehab return self.get_install_progs(progs, "pacman -S") 1071ca9087f5SMauro Carvalho Chehab 1072ca9087f5SMauro Carvalho Chehab def give_gentoo_hints(self): 10736d5f4f3dSMauro Carvalho Chehab """ 10746d5f4f3dSMauro Carvalho Chehab Provide package installation hints for Gentoo. 10756d5f4f3dSMauro 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 1083ca9087f5SMauro Carvalho Chehab progs = { 1084ca9087f5SMauro Carvalho Chehab "convert": "media-gfx/imagemagick", 1085ca9087f5SMauro Carvalho Chehab "dot": "media-gfx/graphviz", 1086ca9087f5SMauro Carvalho Chehab "rsvg-convert": "gnome-base/librsvg", 1087ca9087f5SMauro Carvalho Chehab "virtualenv": "dev-python/virtualenv", 10889ff5c2f5SMauro Carvalho Chehab "xelatex": " ".join(texlive_deps), 1089ca9087f5SMauro Carvalho Chehab "yaml": "dev-python/pyyaml", 1090582b0f95SMauro Carvalho Chehab "python-sphinx": "dev-python/sphinx", 1091ca9087f5SMauro Carvalho Chehab } 1092ca9087f5SMauro Carvalho Chehab 1093ca9087f5SMauro Carvalho Chehab if self.pdf: 1094ca9087f5SMauro Carvalho Chehab pdf_pkgs = { 1095ca9087f5SMauro Carvalho Chehab "media-fonts/dejavu": [ 1096ca9087f5SMauro Carvalho Chehab "/usr/share/fonts/dejavu/DejaVuSans.ttf", 1097ca9087f5SMauro Carvalho Chehab ], 1098ca9087f5SMauro Carvalho Chehab "media-fonts/noto-cjk": [ 1099ca9087f5SMauro Carvalho Chehab "/usr/share/fonts/noto-cjk/NotoSansCJKsc-Regular.otf", 1100ca9087f5SMauro Carvalho Chehab "/usr/share/fonts/noto-cjk/NotoSerifCJK-Regular.ttc", 1101ca9087f5SMauro Carvalho Chehab ], 1102ca9087f5SMauro Carvalho Chehab } 1103ca9087f5SMauro Carvalho Chehab for package, files in pdf_pkgs.items(): 11042cab00fbSMauro Carvalho Chehab self.check_missing_file(files, package, DepManager.PDF_MANDATORY) 1105ca9087f5SMauro Carvalho Chehab 11061a7da749SMauro Carvalho Chehab # Handling dependencies is a nightmare, as Gentoo refuses to emerge 11071a7da749SMauro Carvalho Chehab # some packages if there's no package.use file describing them. 11081a7da749SMauro Carvalho Chehab # To make it worse, compilation flags shall also be present there 11091a7da749SMauro Carvalho Chehab # for some packages. If USE is not perfect, error/warning messages 11101a7da749SMauro Carvalho Chehab # like those are shown: 11111a7da749SMauro Carvalho Chehab # 11121a7da749SMauro Carvalho Chehab # !!! The following binary packages have been ignored due to non matching USE: 11131a7da749SMauro Carvalho Chehab # 11141a7da749SMauro Carvalho Chehab # =media-gfx/graphviz-12.2.1-r1 X pdf -python_single_target_python3_13 qt6 svg 11151a7da749SMauro Carvalho Chehab # =media-gfx/graphviz-12.2.1-r1 X pdf python_single_target_python3_12 -python_single_target_python3_13 qt6 svg 11161a7da749SMauro Carvalho Chehab # =media-gfx/graphviz-12.2.1-r1 X pdf qt6 svg 11171a7da749SMauro Carvalho Chehab # =media-gfx/graphviz-12.2.1-r1 X pdf -python_single_target_python3_10 qt6 svg 11181a7da749SMauro 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 11191a7da749SMauro Carvalho Chehab # =media-fonts/noto-cjk-20190416 X 11201a7da749SMauro Carvalho Chehab # =app-text/texlive-core-2024-r1 X cjk -xetex 11211a7da749SMauro Carvalho Chehab # =app-text/texlive-core-2024-r1 X -xetex 11221a7da749SMauro Carvalho Chehab # =app-text/texlive-core-2024-r1 -xetex 11231a7da749SMauro Carvalho Chehab # =dev-libs/zziplib-0.13.79-r1 sdl 11241a7da749SMauro Carvalho Chehab # 11251a7da749SMauro Carvalho Chehab # And will ignore such packages, installing the remaining ones. That 11261a7da749SMauro Carvalho Chehab # affects mostly the image extension and PDF generation. 1127ca9087f5SMauro Carvalho Chehab 11281a7da749SMauro Carvalho Chehab # Package dependencies and the minimal needed args: 11291a7da749SMauro Carvalho Chehab portages = { 11301a7da749SMauro Carvalho Chehab "graphviz": "media-gfx/graphviz", 11311a7da749SMauro Carvalho Chehab "imagemagick": "media-gfx/imagemagick", 11321a7da749SMauro Carvalho Chehab "media-libs": "media-libs/harfbuzz icu", 11331a7da749SMauro Carvalho Chehab "media-fonts": "media-fonts/noto-cjk", 11341a7da749SMauro Carvalho Chehab "texlive": "app-text/texlive-core xetex", 11351a7da749SMauro Carvalho Chehab "zziblib": "dev-libs/zziplib sdl", 11361a7da749SMauro Carvalho Chehab } 1137582b0f95SMauro Carvalho Chehab 113824a34b3bSMauro Carvalho Chehab extra_cmds = "" 113924a34b3bSMauro Carvalho Chehab if not self.distro_msg: 114024a34b3bSMauro Carvalho Chehab self.distro_msg = "Note: Gentoo requires package.use to be adjusted before emerging packages" 114124a34b3bSMauro Carvalho Chehab 11421a7da749SMauro Carvalho Chehab use_base = "/etc/portage/package.use" 11431a7da749SMauro Carvalho Chehab files = glob(f"{use_base}/*") 11441a7da749SMauro Carvalho Chehab 11451a7da749SMauro Carvalho Chehab for fname, portage in portages.items(): 11461a7da749SMauro Carvalho Chehab install = False 11471a7da749SMauro Carvalho Chehab 11488b45effaSMauro Carvalho Chehab while install is False: 11491a7da749SMauro Carvalho Chehab if not files: 11501a7da749SMauro Carvalho Chehab # No files under package.usage. Install all 11511a7da749SMauro Carvalho Chehab install = True 11521a7da749SMauro Carvalho Chehab break 11531a7da749SMauro Carvalho Chehab 11541a7da749SMauro Carvalho Chehab args = portage.split(" ") 11551a7da749SMauro Carvalho Chehab 11561a7da749SMauro Carvalho Chehab name = args.pop(0) 11571a7da749SMauro Carvalho Chehab 11581a7da749SMauro Carvalho Chehab cmd = ["grep", "-l", "-E", rf"^{name}\b" ] + files 11591a7da749SMauro Carvalho Chehab result = self.run(cmd, stdout=subprocess.PIPE, text=True) 11601a7da749SMauro Carvalho Chehab if result.returncode or not result.stdout.strip(): 11611a7da749SMauro Carvalho Chehab # File containing portage name not found 11621a7da749SMauro Carvalho Chehab install = True 11631a7da749SMauro Carvalho Chehab break 11641a7da749SMauro Carvalho Chehab 11651a7da749SMauro Carvalho Chehab # Ensure that needed USE flags are present 11661a7da749SMauro Carvalho Chehab if args: 11671a7da749SMauro Carvalho Chehab match_fname = result.stdout.strip() 11681a7da749SMauro Carvalho Chehab with open(match_fname, 'r', encoding='utf8', 11691a7da749SMauro Carvalho Chehab errors='backslashreplace') as fp: 11701a7da749SMauro Carvalho Chehab for line in fp: 11711a7da749SMauro Carvalho Chehab for arg in args: 11721a7da749SMauro Carvalho Chehab if arg.startswith("-"): 11731a7da749SMauro Carvalho Chehab continue 11741a7da749SMauro Carvalho Chehab 11751a7da749SMauro Carvalho Chehab if not re.search(rf"\s*{arg}\b", line): 11761a7da749SMauro Carvalho Chehab # Needed file argument not found 11771a7da749SMauro Carvalho Chehab install = True 11781a7da749SMauro Carvalho Chehab break 11791a7da749SMauro Carvalho Chehab 11801a7da749SMauro Carvalho Chehab # Everything looks ok, don't install 11811a7da749SMauro Carvalho Chehab break 11821a7da749SMauro Carvalho Chehab 11831a7da749SMauro Carvalho Chehab # emit a code to setup missing USE 11841a7da749SMauro Carvalho Chehab if install: 118524a34b3bSMauro Carvalho Chehab extra_cmds += (f"sudo su -c 'echo \"{portage}\" > {use_base}/{fname}'\n") 118612bdcf89SMauro Carvalho Chehab 11871a7da749SMauro Carvalho Chehab # Now, we can use emerge and let it respect USE 118824a34b3bSMauro Carvalho Chehab return self.get_install_progs(progs, 118924a34b3bSMauro Carvalho Chehab "emerge --ask --changed-use --binpkg-respect-use=y", 119024a34b3bSMauro Carvalho Chehab extra_cmds) 1191ca9087f5SMauro Carvalho Chehab 119224a34b3bSMauro Carvalho Chehab def get_install(self): 11936d5f4f3dSMauro Carvalho Chehab """ 119424a34b3bSMauro Carvalho Chehab OS-specific hints logic. Seeks for a hinter. If found, use it to 119524a34b3bSMauro Carvalho Chehab provide package-manager specific install commands. 11966d5f4f3dSMauro Carvalho Chehab 119724a34b3bSMauro Carvalho Chehab Otherwise, outputs install instructions for the meta-packages. 119824a34b3bSMauro Carvalho Chehab 119924a34b3bSMauro Carvalho Chehab Returns a string with the command to be executed to install the 120024a34b3bSMauro Carvalho Chehab the needed packages, if distro found. Otherwise, return just a 120124a34b3bSMauro Carvalho Chehab list of packages that require installation. 12026d5f4f3dSMauro Carvalho Chehab """ 1203ca9087f5SMauro Carvalho Chehab os_hints = { 1204ca9087f5SMauro Carvalho Chehab re.compile("Red Hat Enterprise Linux"): self.give_redhat_hints, 1205ca9087f5SMauro Carvalho Chehab re.compile("Fedora"): self.give_redhat_hints, 1206ca9087f5SMauro Carvalho Chehab re.compile("AlmaLinux"): self.give_redhat_hints, 1207ca9087f5SMauro Carvalho Chehab re.compile("Amazon Linux"): self.give_redhat_hints, 1208ca9087f5SMauro Carvalho Chehab re.compile("CentOS"): self.give_redhat_hints, 1209ca9087f5SMauro Carvalho Chehab re.compile("openEuler"): self.give_redhat_hints, 1210ca9087f5SMauro Carvalho Chehab re.compile("Oracle Linux Server"): self.give_redhat_hints, 1211ca9087f5SMauro Carvalho Chehab re.compile("Rocky Linux"): self.give_redhat_hints, 1212ca9087f5SMauro Carvalho Chehab re.compile("Springdale Open Enterprise"): self.give_redhat_hints, 1213ca9087f5SMauro Carvalho Chehab 1214ca9087f5SMauro Carvalho Chehab re.compile("Ubuntu"): self.give_debian_hints, 1215ca9087f5SMauro Carvalho Chehab re.compile("Debian"): self.give_debian_hints, 1216ca9087f5SMauro Carvalho Chehab re.compile("Devuan"): self.give_debian_hints, 1217ca9087f5SMauro Carvalho Chehab re.compile("Kali"): self.give_debian_hints, 1218ca9087f5SMauro Carvalho Chehab re.compile("Mint"): self.give_debian_hints, 1219ca9087f5SMauro Carvalho Chehab 1220ca9087f5SMauro Carvalho Chehab re.compile("openSUSE"): self.give_opensuse_hints, 1221ca9087f5SMauro Carvalho Chehab 1222ca9087f5SMauro Carvalho Chehab re.compile("Mageia"): self.give_mageia_hints, 1223ca9087f5SMauro Carvalho Chehab re.compile("OpenMandriva"): self.give_mageia_hints, 1224ca9087f5SMauro Carvalho Chehab 1225ca9087f5SMauro Carvalho Chehab re.compile("Arch Linux"): self.give_arch_linux_hints, 1226ca9087f5SMauro Carvalho Chehab re.compile("Gentoo"): self.give_gentoo_hints, 1227ca9087f5SMauro Carvalho Chehab } 1228ca9087f5SMauro Carvalho Chehab 1229ca9087f5SMauro Carvalho Chehab # If the OS is detected, use per-OS hint logic 1230ca9087f5SMauro Carvalho Chehab for regex, os_hint in os_hints.items(): 1231ca9087f5SMauro Carvalho Chehab if regex.search(self.system_release): 123224a34b3bSMauro Carvalho Chehab return os_hint() 1233ca9087f5SMauro Carvalho Chehab 1234ca9087f5SMauro Carvalho Chehab # 1235ca9087f5SMauro Carvalho Chehab # Fall-back to generic hint code for other distros 1236ca9087f5SMauro Carvalho Chehab # That's far from ideal, specially for LaTeX dependencies. 1237ca9087f5SMauro Carvalho Chehab # 1238ca9087f5SMauro Carvalho Chehab progs = {"sphinx-build": "sphinx"} 1239ca9087f5SMauro Carvalho Chehab if self.pdf: 12409ecda2e1SMauro Carvalho Chehab self.check_missing_tex() 1241ca9087f5SMauro Carvalho Chehab 124224a34b3bSMauro Carvalho Chehab self.distro_msg = \ 124324a34b3bSMauro Carvalho Chehab f"I don't know distro {self.system_release}.\n" \ 124424a34b3bSMauro Carvalho Chehab "So, I can't provide you a hint with the install procedure.\n" \ 1245491a9951SMauro Carvalho Chehab "There are likely missing dependencies." 1246ca9087f5SMauro Carvalho Chehab 124724a34b3bSMauro Carvalho Chehab return self.get_install_progs(progs, None) 1248ca9087f5SMauro Carvalho Chehab 1249ca9087f5SMauro Carvalho Chehab # 1250ca9087f5SMauro Carvalho Chehab # Common dependencies 1251ca9087f5SMauro Carvalho Chehab # 1252ca9087f5SMauro Carvalho Chehab def deactivate_help(self): 12536d5f4f3dSMauro Carvalho Chehab """ 12546d5f4f3dSMauro Carvalho Chehab Print a helper message to disable a virtual environment. 12556d5f4f3dSMauro Carvalho Chehab """ 12566d5f4f3dSMauro Carvalho Chehab 1257ca9087f5SMauro Carvalho Chehab print("\n If you want to exit the virtualenv, you can use:") 1258ca9087f5SMauro Carvalho Chehab print("\tdeactivate") 1259ca9087f5SMauro Carvalho Chehab 1260ca9087f5SMauro Carvalho Chehab def get_virtenv(self): 12616d5f4f3dSMauro Carvalho Chehab """ 12626d5f4f3dSMauro Carvalho Chehab Give a hint about how to activate an already-existing virtual 12636d5f4f3dSMauro Carvalho Chehab environment containing sphinx-build. 12646d5f4f3dSMauro Carvalho Chehab 12656d5f4f3dSMauro Carvalho Chehab Returns a tuble with (activate_cmd_path, sphinx_version) with 12666d5f4f3dSMauro Carvalho Chehab the newest available virtual env. 12676d5f4f3dSMauro Carvalho Chehab """ 12686d5f4f3dSMauro Carvalho Chehab 1269ca9087f5SMauro Carvalho Chehab cwd = os.getcwd() 1270ca9087f5SMauro Carvalho Chehab 1271ca9087f5SMauro Carvalho Chehab activates = [] 1272ca9087f5SMauro Carvalho Chehab 1273ca9087f5SMauro Carvalho Chehab # Add all sphinx prefixes with possible version numbers 1274ca9087f5SMauro Carvalho Chehab for p in self.virtenv_prefix: 1275ca9087f5SMauro Carvalho Chehab activates += glob(f"{cwd}/{p}[0-9]*/bin/activate") 1276ca9087f5SMauro Carvalho Chehab 1277ca9087f5SMauro Carvalho Chehab activates.sort(reverse=True, key=str.lower) 1278ca9087f5SMauro Carvalho Chehab 1279ca9087f5SMauro Carvalho Chehab # Place sphinx_latest first, if it exists 1280ca9087f5SMauro Carvalho Chehab for p in self.virtenv_prefix: 1281ca9087f5SMauro Carvalho Chehab activates = glob(f"{cwd}/{p}*latest/bin/activate") + activates 1282ca9087f5SMauro Carvalho Chehab 1283ca9087f5SMauro Carvalho Chehab ver = (0, 0, 0) 1284ca9087f5SMauro Carvalho Chehab for f in activates: 1285ca9087f5SMauro Carvalho Chehab # Discard too old Sphinx virtual environments 1286ca9087f5SMauro Carvalho Chehab match = re.search(r"(\d+)\.(\d+)\.(\d+)", f) 1287ca9087f5SMauro Carvalho Chehab if match: 1288ca9087f5SMauro Carvalho Chehab ver = (int(match.group(1)), int(match.group(2)), int(match.group(3))) 1289ca9087f5SMauro Carvalho Chehab 1290ca9087f5SMauro Carvalho Chehab if ver < self.min_version: 1291ca9087f5SMauro Carvalho Chehab continue 1292ca9087f5SMauro Carvalho Chehab 1293ca9087f5SMauro Carvalho Chehab sphinx_cmd = f.replace("activate", "sphinx-build") 1294ca9087f5SMauro Carvalho Chehab if not os.path.isfile(sphinx_cmd): 1295ca9087f5SMauro Carvalho Chehab continue 1296ca9087f5SMauro Carvalho Chehab 1297ca9087f5SMauro Carvalho Chehab ver = self.get_sphinx_version(sphinx_cmd) 1298ca9087f5SMauro Carvalho Chehab 1299ca9087f5SMauro Carvalho Chehab if not ver: 1300ca9087f5SMauro Carvalho Chehab venv_dir = f.replace("/bin/activate", "") 1301ca9087f5SMauro Carvalho Chehab print(f"Warning: virtual environment {venv_dir} is not working.\n" \ 1302ca9087f5SMauro Carvalho Chehab "Python version upgrade? Remove it with:\n\n" \ 1303ca9087f5SMauro Carvalho Chehab "\trm -rf {venv_dir}\n\n") 1304ca9087f5SMauro Carvalho Chehab else: 1305ca9087f5SMauro Carvalho Chehab if self.need_sphinx and ver >= self.min_version: 1306ca9087f5SMauro Carvalho Chehab return (f, ver) 1307ca9087f5SMauro Carvalho Chehab elif parse_version(ver) > self.cur_version: 1308ca9087f5SMauro Carvalho Chehab return (f, ver) 1309ca9087f5SMauro Carvalho Chehab 1310ca9087f5SMauro Carvalho Chehab return ("", ver) 1311ca9087f5SMauro Carvalho Chehab 1312ca9087f5SMauro Carvalho Chehab def recommend_sphinx_upgrade(self): 13136d5f4f3dSMauro Carvalho Chehab """ 13146d5f4f3dSMauro Carvalho Chehab Check if Sphinx needs to be upgraded. 13156d5f4f3dSMauro Carvalho Chehab 13166d5f4f3dSMauro Carvalho Chehab Returns a tuple with the higest available Sphinx version if found. 13176d5f4f3dSMauro Carvalho Chehab Otherwise, returns None to indicate either that no upgrade is needed 13186d5f4f3dSMauro Carvalho Chehab or no venv was found. 13196d5f4f3dSMauro Carvalho Chehab """ 13206d5f4f3dSMauro Carvalho Chehab 1321ca9087f5SMauro Carvalho Chehab # Avoid running sphinx-builds from venv if cur_version is good 1322ca9087f5SMauro Carvalho Chehab if self.cur_version and self.cur_version >= RECOMMENDED_VERSION: 1323ca9087f5SMauro Carvalho Chehab self.latest_avail_ver = self.cur_version 1324ca9087f5SMauro Carvalho Chehab return None 1325ca9087f5SMauro Carvalho Chehab 1326ca9087f5SMauro Carvalho Chehab # Get the highest version from sphinx_*/bin/sphinx-build and the 1327ca9087f5SMauro Carvalho Chehab # corresponding command to activate the venv/virtenv 1328ca9087f5SMauro Carvalho Chehab self.activate_cmd, self.venv_ver = self.get_virtenv() 1329ca9087f5SMauro Carvalho Chehab 1330ca9087f5SMauro Carvalho Chehab # Store the highest version from Sphinx existing virtualenvs 1331ca9087f5SMauro Carvalho Chehab if self.activate_cmd and self.venv_ver > self.cur_version: 1332ca9087f5SMauro Carvalho Chehab self.latest_avail_ver = self.venv_ver 1333ca9087f5SMauro Carvalho Chehab else: 1334ca9087f5SMauro Carvalho Chehab if self.cur_version: 1335ca9087f5SMauro Carvalho Chehab self.latest_avail_ver = self.cur_version 1336ca9087f5SMauro Carvalho Chehab else: 1337ca9087f5SMauro Carvalho Chehab self.latest_avail_ver = (0, 0, 0) 1338ca9087f5SMauro Carvalho Chehab 1339ca9087f5SMauro Carvalho Chehab # As we don't know package version of Sphinx, and there's no 1340ca9087f5SMauro Carvalho Chehab # virtual environments, don't check if upgrades are needed 1341ca9087f5SMauro Carvalho Chehab if not self.virtualenv: 1342ca9087f5SMauro Carvalho Chehab if not self.latest_avail_ver: 1343ca9087f5SMauro Carvalho Chehab return None 1344ca9087f5SMauro Carvalho Chehab 1345ca9087f5SMauro Carvalho Chehab return self.latest_avail_ver 1346ca9087f5SMauro Carvalho Chehab 1347ca9087f5SMauro Carvalho Chehab # Either there are already a virtual env or a new one should be created 13489f51a1d6SMauro Carvalho Chehab self.need_pip = True 1349ca9087f5SMauro Carvalho Chehab 1350ca9087f5SMauro Carvalho Chehab if not self.latest_avail_ver: 1351ca9087f5SMauro Carvalho Chehab return None 1352ca9087f5SMauro Carvalho Chehab 1353ca9087f5SMauro Carvalho Chehab # Return if the reason is due to an upgrade or not 1354ca9087f5SMauro Carvalho Chehab if self.latest_avail_ver != (0, 0, 0): 1355ca9087f5SMauro Carvalho Chehab if self.latest_avail_ver < RECOMMENDED_VERSION: 1356ca9087f5SMauro Carvalho Chehab self.rec_sphinx_upgrade = 1 1357ca9087f5SMauro Carvalho Chehab 1358ca9087f5SMauro Carvalho Chehab return self.latest_avail_ver 1359ca9087f5SMauro Carvalho Chehab 13601ad72e9dSMauro Carvalho Chehab def recommend_package(self): 13616d5f4f3dSMauro Carvalho Chehab """ 13626d5f4f3dSMauro Carvalho Chehab Recommend installing Sphinx as a distro-specific package. 13636d5f4f3dSMauro Carvalho Chehab """ 13641ad72e9dSMauro Carvalho Chehab 13651ad72e9dSMauro Carvalho Chehab print("\n2) As a package with:") 13661ad72e9dSMauro Carvalho Chehab 13672cab00fbSMauro Carvalho Chehab old_need = self.deps.need 13682cab00fbSMauro Carvalho Chehab old_optional = self.deps.optional 13692cab00fbSMauro Carvalho Chehab 13701ad72e9dSMauro Carvalho Chehab self.pdf = False 13718b45effaSMauro Carvalho Chehab self.deps.optional = 0 13721ad72e9dSMauro Carvalho Chehab old_verbose = self.verbose_warn_install 13731ad72e9dSMauro Carvalho Chehab self.verbose_warn_install = 0 13741ad72e9dSMauro Carvalho Chehab 13752cab00fbSMauro Carvalho Chehab self.deps.clear_deps() 13762cab00fbSMauro Carvalho Chehab 13772cab00fbSMauro Carvalho Chehab self.deps.add_package("python-sphinx", DepManager.PYTHON_MANDATORY) 13781ad72e9dSMauro Carvalho Chehab 137924a34b3bSMauro Carvalho Chehab cmd = self.get_install() 138024a34b3bSMauro Carvalho Chehab if cmd: 138124a34b3bSMauro Carvalho Chehab print(cmd) 13821ad72e9dSMauro Carvalho Chehab 13838b45effaSMauro Carvalho Chehab self.deps.need = old_need 13848b45effaSMauro Carvalho Chehab self.deps.optional = old_optional 13851ad72e9dSMauro Carvalho Chehab self.verbose_warn_install = old_verbose 13861ad72e9dSMauro Carvalho Chehab 1387ca9087f5SMauro Carvalho Chehab def recommend_sphinx_version(self, virtualenv_cmd): 13886d5f4f3dSMauro Carvalho Chehab """ 13896d5f4f3dSMauro Carvalho Chehab Provide recommendations for installing or upgrading Sphinx based 13906d5f4f3dSMauro Carvalho Chehab on current version. 13916d5f4f3dSMauro Carvalho Chehab 13926d5f4f3dSMauro Carvalho Chehab The logic here is complex, as it have to deal with different versions: 13936d5f4f3dSMauro Carvalho Chehab 13946d5f4f3dSMauro Carvalho Chehab - minimal supported version; 13956d5f4f3dSMauro Carvalho Chehab - minimal PDF version; 13966d5f4f3dSMauro Carvalho Chehab - recommended version. 13976d5f4f3dSMauro Carvalho Chehab 13986d5f4f3dSMauro Carvalho Chehab It also needs to work fine with both distro's package and 13996d5f4f3dSMauro Carvalho Chehab venv/virtualenv 14006d5f4f3dSMauro Carvalho Chehab """ 1401ca9087f5SMauro Carvalho Chehab 14028cd25652SMauro 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" \ 14068cd25652SMauro Carvalho Chehab "Please upgrade it and re-run.\n") 14078cd25652SMauro Carvalho Chehab return 14088cd25652SMauro Carvalho Chehab 1409ca9087f5SMauro Carvalho Chehab # Version is OK. Nothing to do. 1410ca9087f5SMauro Carvalho Chehab if self.cur_version != (0, 0, 0) and self.cur_version >= RECOMMENDED_VERSION: 1411ca9087f5SMauro Carvalho Chehab return 1412ca9087f5SMauro Carvalho Chehab 1413cccc5389SMauro Carvalho Chehab if self.latest_avail_ver: 1414cccc5389SMauro Carvalho Chehab latest_avail_ver = ver_str(self.latest_avail_ver) 1415cccc5389SMauro Carvalho Chehab 1416ca9087f5SMauro Carvalho Chehab if not self.need_sphinx: 1417ca9087f5SMauro Carvalho Chehab # sphinx-build is present and its version is >= $min_version 1418ca9087f5SMauro Carvalho Chehab 1419ca9087f5SMauro Carvalho Chehab # only recommend enabling a newer virtenv version if makes sense. 1420ca9087f5SMauro Carvalho Chehab if self.latest_avail_ver and self.latest_avail_ver > self.cur_version: 1421cccc5389SMauro Carvalho Chehab print(f"\nYou may also use the newer Sphinx version {latest_avail_ver} with:") 1422ca9087f5SMauro Carvalho Chehab if f"{self.virtenv_prefix}" in os.getcwd(): 1423ca9087f5SMauro Carvalho Chehab print("\tdeactivate") 1424ca9087f5SMauro Carvalho Chehab print(f"\t. {self.activate_cmd}") 1425ca9087f5SMauro Carvalho Chehab self.deactivate_help() 1426ca9087f5SMauro Carvalho Chehab return 1427ca9087f5SMauro Carvalho Chehab 1428ca9087f5SMauro Carvalho Chehab if self.latest_avail_ver and self.latest_avail_ver >= RECOMMENDED_VERSION: 1429ca9087f5SMauro Carvalho Chehab return 1430ca9087f5SMauro Carvalho Chehab 1431ca9087f5SMauro Carvalho Chehab if not self.virtualenv: 1432ca9087f5SMauro Carvalho Chehab # No sphinx either via package or via virtenv. As we can't 1433ca9087f5SMauro Carvalho Chehab # Compare the versions here, just return, recommending the 1434ca9087f5SMauro Carvalho Chehab # user to install it from the package distro. 1435ca9087f5SMauro Carvalho Chehab if not self.latest_avail_ver or self.latest_avail_ver == (0, 0, 0): 1436ca9087f5SMauro Carvalho Chehab return 1437ca9087f5SMauro Carvalho Chehab 1438ca9087f5SMauro Carvalho Chehab # User doesn't want a virtenv recommendation, but he already 1439ca9087f5SMauro Carvalho Chehab # installed one via virtenv with a newer version. 1440ca9087f5SMauro Carvalho Chehab # So, print commands to enable it 1441ca9087f5SMauro Carvalho Chehab if self.latest_avail_ver > self.cur_version: 1442cccc5389SMauro Carvalho Chehab print(f"\nYou may also use the Sphinx virtualenv version {latest_avail_ver} with:") 1443ca9087f5SMauro Carvalho Chehab if f"{self.virtenv_prefix}" in os.getcwd(): 1444ca9087f5SMauro Carvalho Chehab print("\tdeactivate") 1445ca9087f5SMauro Carvalho Chehab print(f"\t. {self.activate_cmd}") 1446ca9087f5SMauro Carvalho Chehab self.deactivate_help() 1447ca9087f5SMauro Carvalho Chehab return 1448ca9087f5SMauro Carvalho Chehab print("\n") 1449ca9087f5SMauro Carvalho Chehab else: 1450ca9087f5SMauro Carvalho Chehab if self.need_sphinx: 14512cab00fbSMauro Carvalho Chehab self.deps.need += 1 1452ca9087f5SMauro Carvalho Chehab 1453ca9087f5SMauro Carvalho Chehab # Suggest newer versions if current ones are too old 1454ca9087f5SMauro Carvalho Chehab if self.latest_avail_ver and self.latest_avail_ver >= self.min_version: 1455ca9087f5SMauro Carvalho Chehab if self.latest_avail_ver >= RECOMMENDED_VERSION: 1456cccc5389SMauro Carvalho Chehab print(f"\nNeed to activate Sphinx (version {latest_avail_ver}) on virtualenv with:") 1457ca9087f5SMauro Carvalho Chehab print(f"\t. {self.activate_cmd}") 1458ca9087f5SMauro Carvalho Chehab self.deactivate_help() 1459ca9087f5SMauro Carvalho Chehab return 1460ca9087f5SMauro Carvalho Chehab 1461ca9087f5SMauro Carvalho Chehab # Version is above the minimal required one, but may be 1462ca9087f5SMauro Carvalho Chehab # below the recommended one. So, print warnings/notes 1463ca9087f5SMauro Carvalho Chehab if self.latest_avail_ver < RECOMMENDED_VERSION: 1464ca9087f5SMauro Carvalho Chehab print(f"Warning: It is recommended at least Sphinx version {RECOMMENDED_VERSION}.") 1465ca9087f5SMauro Carvalho Chehab 1466ca9087f5SMauro Carvalho Chehab # At this point, either it needs Sphinx or upgrade is recommended, 1467ca9087f5SMauro Carvalho Chehab # both via pip 1468ca9087f5SMauro Carvalho Chehab 1469ca9087f5SMauro Carvalho Chehab if self.rec_sphinx_upgrade: 1470ca9087f5SMauro Carvalho Chehab if not self.virtualenv: 1471ca9087f5SMauro Carvalho Chehab print("Instead of install/upgrade Python Sphinx pkg, you could use pip/pypi with:\n\n") 1472ca9087f5SMauro Carvalho Chehab else: 1473ca9087f5SMauro Carvalho Chehab print("To upgrade Sphinx, use:\n\n") 1474ca9087f5SMauro Carvalho Chehab else: 1475ca9087f5SMauro Carvalho Chehab print("\nSphinx needs to be installed either:\n1) via pip/pypi with:\n") 1476ca9087f5SMauro Carvalho Chehab 1477f25bf12aSMauro Carvalho Chehab if not virtualenv_cmd: 1478f25bf12aSMauro Carvalho Chehab print(" Currently not possible.\n") 1479f25bf12aSMauro Carvalho Chehab print(" Please upgrade Python to a newer version and run this script again") 1480f25bf12aSMauro Carvalho Chehab else: 1481ca9087f5SMauro Carvalho Chehab print(f"\t{virtualenv_cmd} {self.virtenv_dir}") 1482ca9087f5SMauro Carvalho Chehab print(f"\t. {self.virtenv_dir}/bin/activate") 1483ca9087f5SMauro Carvalho Chehab print(f"\tpip install -r {self.requirement_file}") 1484ca9087f5SMauro Carvalho Chehab self.deactivate_help() 1485ca9087f5SMauro Carvalho Chehab 14861ad72e9dSMauro Carvalho Chehab if self.package_supported: 14871ad72e9dSMauro Carvalho Chehab self.recommend_package() 1488ca9087f5SMauro Carvalho Chehab 1489ca9087f5SMauro Carvalho Chehab print("\n" \ 14906db1d397SMauro Carvalho Chehab " Please note that Sphinx currentlys produce false-positive\n" \ 14916db1d397SMauro Carvalho Chehab " warnings when the same name is used for more than one type (functions,\n" \ 1492ca9087f5SMauro Carvalho Chehab " structs, enums,...). This is known Sphinx bug. For more details, see:\n" \ 1493ca9087f5SMauro Carvalho Chehab "\thttps://github.com/sphinx-doc/sphinx/pull/8313") 1494ca9087f5SMauro Carvalho Chehab 1495ca9087f5SMauro Carvalho Chehab def check_needs(self): 14966d5f4f3dSMauro Carvalho Chehab """ 14976d5f4f3dSMauro Carvalho Chehab Main method that checks needed dependencies and provides 14986d5f4f3dSMauro Carvalho Chehab recommendations. 14996d5f4f3dSMauro Carvalho Chehab """ 1500f25bf12aSMauro Carvalho Chehab self.python_cmd = sys.executable 1501ca9087f5SMauro Carvalho Chehab 1502ca9087f5SMauro Carvalho Chehab # Check if Sphinx is already accessible from current environment 15039bb5f0dcSMauro Carvalho Chehab self.check_sphinx(self.conf) 1504ca9087f5SMauro Carvalho Chehab 1505ca9087f5SMauro Carvalho Chehab if self.system_release: 1506ca9087f5SMauro Carvalho Chehab print(f"Detected OS: {self.system_release}.") 1507ca9087f5SMauro Carvalho Chehab else: 1508ca9087f5SMauro Carvalho Chehab print("Unknown OS") 1509ca9087f5SMauro Carvalho Chehab if self.cur_version != (0, 0, 0): 1510ca9087f5SMauro Carvalho Chehab ver = ver_str(self.cur_version) 1511ca9087f5SMauro Carvalho Chehab print(f"Sphinx version: {ver}\n") 1512ca9087f5SMauro Carvalho Chehab 1513ca9087f5SMauro Carvalho Chehab # Check the type of virtual env, depending on Python version 1514f25bf12aSMauro Carvalho Chehab virtualenv_cmd = None 1515ca9087f5SMauro Carvalho Chehab 1516f25bf12aSMauro Carvalho Chehab if sys.version_info < MIN_PYTHON_VERSION: 1517f25bf12aSMauro Carvalho Chehab min_ver = ver_str(MIN_PYTHON_VERSION) 1518f25bf12aSMauro Carvalho Chehab print(f"ERROR: at least python {min_ver} is required to build the kernel docs") 1519f25bf12aSMauro Carvalho Chehab self.need_sphinx = 1 1520ca9087f5SMauro Carvalho Chehab 1521ca9087f5SMauro Carvalho Chehab self.venv_ver = self.recommend_sphinx_upgrade() 1522ca9087f5SMauro Carvalho Chehab 1523ca9087f5SMauro Carvalho Chehab if self.need_pip: 1524f25bf12aSMauro Carvalho Chehab if sys.version_info < MIN_PYTHON_VERSION: 1525f25bf12aSMauro Carvalho Chehab self.need_pip = False 1526f25bf12aSMauro Carvalho Chehab print("Warning: python version is not supported.") 1527ca9087f5SMauro Carvalho Chehab else: 1528ca9087f5SMauro Carvalho Chehab virtualenv_cmd = f"{self.python_cmd} -m venv" 15299ecda2e1SMauro Carvalho Chehab self.check_python_module("ensurepip") 1530ca9087f5SMauro Carvalho Chehab 1531ca9087f5SMauro Carvalho Chehab # Check for needed programs/tools 15322cab00fbSMauro Carvalho Chehab self.check_perl_module("Pod::Usage", DepManager.SYSTEM_MANDATORY) 15339ecda2e1SMauro Carvalho Chehab 15342cab00fbSMauro Carvalho Chehab self.check_program("make", DepManager.SYSTEM_MANDATORY) 1535df4d2f96SMauro Carvalho Chehab self.check_program("which", DepManager.SYSTEM_MANDATORY) 15369ecda2e1SMauro Carvalho Chehab 15372cab00fbSMauro Carvalho Chehab self.check_program("dot", DepManager.SYSTEM_OPTIONAL) 15382cab00fbSMauro Carvalho Chehab self.check_program("convert", DepManager.SYSTEM_OPTIONAL) 15399ecda2e1SMauro Carvalho Chehab 15409ecda2e1SMauro Carvalho Chehab self.check_python_module("yaml") 1541ca9087f5SMauro Carvalho Chehab 1542ca9087f5SMauro Carvalho Chehab if self.pdf: 15432cab00fbSMauro Carvalho Chehab self.check_program("xelatex", DepManager.PDF_MANDATORY) 15442cab00fbSMauro Carvalho Chehab self.check_program("rsvg-convert", DepManager.PDF_MANDATORY) 15452cab00fbSMauro Carvalho Chehab self.check_program("latexmk", DepManager.PDF_MANDATORY) 1546ca9087f5SMauro Carvalho Chehab 1547ca9087f5SMauro Carvalho Chehab # Do distro-specific checks and output distro-install commands 154824a34b3bSMauro Carvalho Chehab cmd = self.get_install() 154924a34b3bSMauro Carvalho Chehab if cmd: 155024a34b3bSMauro Carvalho Chehab print(cmd) 155124a34b3bSMauro Carvalho Chehab 155224a34b3bSMauro Carvalho Chehab # If distro requires some special instructions, print here. 155324a34b3bSMauro Carvalho Chehab # Please notice that get_install() needs to be called first. 155424a34b3bSMauro Carvalho Chehab if self.distro_msg: 155524a34b3bSMauro Carvalho Chehab print("\n" + self.distro_msg) 1556ca9087f5SMauro Carvalho Chehab 1557ca9087f5SMauro Carvalho Chehab if not self.python_cmd: 1558ca9087f5SMauro Carvalho Chehab if self.need == 1: 1559ca9087f5SMauro Carvalho Chehab sys.exit("Can't build as 1 mandatory dependency is missing") 1560ca9087f5SMauro Carvalho Chehab elif self.need: 1561ca9087f5SMauro Carvalho Chehab sys.exit(f"Can't build as {self.need} mandatory dependencies are missing") 1562ca9087f5SMauro Carvalho Chehab 1563ca9087f5SMauro Carvalho Chehab # Check if sphinx-build is called sphinx-build-3 1564ca9087f5SMauro Carvalho Chehab if self.need_symlink: 1565ca9087f5SMauro Carvalho Chehab sphinx_path = self.which("sphinx-build-3") 1566ca9087f5SMauro Carvalho Chehab if sphinx_path: 1567ca9087f5SMauro Carvalho Chehab print(f"\tsudo ln -sf {sphinx_path} /usr/bin/sphinx-build\n") 1568ca9087f5SMauro Carvalho Chehab 1569ca9087f5SMauro Carvalho Chehab self.recommend_sphinx_version(virtualenv_cmd) 1570ca9087f5SMauro Carvalho Chehab print("") 1571ca9087f5SMauro Carvalho Chehab 15728b45effaSMauro Carvalho Chehab if not self.deps.optional: 1573ca9087f5SMauro Carvalho Chehab print("All optional dependencies are met.") 1574ca9087f5SMauro Carvalho Chehab 15758b45effaSMauro Carvalho Chehab if self.deps.need == 1: 1576ca9087f5SMauro Carvalho Chehab sys.exit("Can't build as 1 mandatory dependency is missing") 15778b45effaSMauro Carvalho Chehab elif self.deps.need: 15788b45effaSMauro Carvalho Chehab sys.exit(f"Can't build as {self.deps.need} mandatory dependencies are missing") 1579ca9087f5SMauro Carvalho Chehab 1580ca9087f5SMauro Carvalho Chehab print("Needed package dependencies are met.") 1581ca9087f5SMauro Carvalho Chehab 1582ca9087f5SMauro Carvalho ChehabDESCRIPTION = """ 1583ca9087f5SMauro Carvalho ChehabProcess some flags related to Sphinx installation and documentation build. 1584ca9087f5SMauro Carvalho Chehab""" 1585ca9087f5SMauro Carvalho Chehab 1586ca9087f5SMauro Carvalho Chehab 1587ca9087f5SMauro Carvalho Chehabdef main(): 15886d5f4f3dSMauro Carvalho Chehab """Main function""" 1589ca9087f5SMauro Carvalho Chehab parser = argparse.ArgumentParser(description=DESCRIPTION) 1590ca9087f5SMauro Carvalho Chehab 1591ca9087f5SMauro Carvalho Chehab parser.add_argument( 1592ca9087f5SMauro Carvalho Chehab "--no-virtualenv", 1593ca9087f5SMauro Carvalho Chehab action="store_false", 1594ca9087f5SMauro Carvalho Chehab dest="virtualenv", 1595ca9087f5SMauro Carvalho Chehab help="Recommend installing Sphinx instead of using a virtualenv", 1596ca9087f5SMauro Carvalho Chehab ) 1597ca9087f5SMauro Carvalho Chehab 1598ca9087f5SMauro Carvalho Chehab parser.add_argument( 1599ca9087f5SMauro Carvalho Chehab "--no-pdf", 1600ca9087f5SMauro Carvalho Chehab action="store_false", 1601ca9087f5SMauro Carvalho Chehab dest="pdf", 1602ca9087f5SMauro Carvalho Chehab help="Don't check for dependencies required to build PDF docs", 1603ca9087f5SMauro Carvalho Chehab ) 1604ca9087f5SMauro Carvalho Chehab 1605ca9087f5SMauro Carvalho Chehab parser.add_argument( 1606ca9087f5SMauro Carvalho Chehab "--version-check", 1607ca9087f5SMauro Carvalho Chehab action="store_true", 1608ca9087f5SMauro Carvalho Chehab dest="version_check", 1609ca9087f5SMauro Carvalho Chehab help="If version is compatible, don't check for missing dependencies", 1610ca9087f5SMauro Carvalho Chehab ) 1611ca9087f5SMauro Carvalho Chehab 1612ca9087f5SMauro Carvalho Chehab args = parser.parse_args() 1613ca9087f5SMauro Carvalho Chehab 1614ca9087f5SMauro Carvalho Chehab checker = SphinxDependencyChecker(args) 1615ca9087f5SMauro Carvalho Chehab 1616728648b6SMauro Carvalho Chehab checker.check_python() 1617ca9087f5SMauro Carvalho Chehab checker.check_needs() 1618ca9087f5SMauro Carvalho Chehab 16196d5f4f3dSMauro Carvalho Chehab# Call main if not used as module 1620ca9087f5SMauro Carvalho Chehabif __name__ == "__main__": 1621ca9087f5SMauro Carvalho Chehab main() 1622