From: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
To: Linux Doc Mailing List <linux-doc@vger.kernel.org>
Cc: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>,
"Jonathan Corbet" <corbet@lwn.net>,
"Mauro Carvalho Chehab" <mchehab+huawei@kernel.org>,
linux-kernel@vger.kernel.org
Subject: [PATCH v2 30/39] scripts: sphinx-pre-install: add documentation for the ancillary classes.
Date: Tue, 12 Aug 2025 17:52:47 +0200 [thread overview]
Message-ID: <7421112b14edf5c21cc4cf0f2ee320fcaf874b40.1754992972.git.mchehab+huawei@kernel.org> (raw)
In-Reply-To: <cover.1754992972.git.mchehab+huawei@kernel.org>
While here, rename a parameter to have its usage better
documented.
No functional changes.
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
scripts/sphinx-pre-install.py | 162 +++++++++++++++++++++++++++++-----
1 file changed, 140 insertions(+), 22 deletions(-)
diff --git a/scripts/sphinx-pre-install.py b/scripts/sphinx-pre-install.py
index 593982f350b3..1dc3f19804ab 100755
--- a/scripts/sphinx-pre-install.py
+++ b/scripts/sphinx-pre-install.py
@@ -33,35 +33,62 @@ MIN_PYTHON_VERSION = parse_version("3.7")
class DepManager:
+ """
+ Manage package dependencies. There are three types of dependencies:
- # Internal types of dependencies.
+ - System: dependencies required for docs build;
+ - Python: python dependencies for a native distro Sphinx install;
+ - PDF: dependencies needed by PDF builds.
+
+ Each dependency can be mandatory or optional. Not installing an optional
+ dependency won't break the build, but will cause degradation at the
+ docs output.
+ """
+
+ # Internal types of dependencies. Don't use them outside DepManager class.
_SYS_TYPE = 0
_PHY_TYPE = 1
_PDF_TYPE = 2
- # Let's define keys as a tuple with the type and mandatory/optional.
- # This way, checking for optional or type is easy.
+ # Dependencies visible outside the class.
+ # The keys are tuple with: (type, is_mandatory flag).
+ #
+ # Currently we're not using all optional dep types. Yet, we'll keep all
+ # possible combinations here. They're not many, and that makes easier
+ # if later needed and for the name() method below
SYSTEM_MANDATORY = (_SYS_TYPE, True)
PYTHON_MANDATORY = (_PHY_TYPE, True)
PDF_MANDATORY = (_PDF_TYPE, True)
- # Currently we're not using all optional types, but let's keep all
- # combinations here, as we may end needing them in the future. Also,
- # it allows a name() function that handles all possibilities.
SYSTEM_OPTIONAL = (_SYS_TYPE, False)
PYTHON_OPTIONAL = (_PHY_TYPE, False)
PDF_OPTIONAL = (_PDF_TYPE, True)
def __init__(self, pdf):
+ """
+ Initialize internal vars:
+
+ - missing: missing dependencies list, containing a distro-independent
+ name for a missing dependency and its type.
+ - missing_pkg: ancillary dict containing missing dependencies in
+ distro namespace, organized by type.
+ - need: total number of needed dependencies. Never cleaned.
+ - optional: total number of optional dependencies. Never cleaned.
+ - pdf: PDF support is enabled?
+ """
self.missing = {}
- self.run = {}
+ self.missing_pkg = {}
self.need = 0
self.optional = 0
self.pdf = pdf
@staticmethod
def name(dtype):
+ """
+ Ancillary routine to output a warn/error message reporting
+ missing dependencies.
+ """
if dtype[0] == DepManager._SYS_TYPE:
msg = "build"
elif dtype[0] == DepManager._PHY_TYPE:
@@ -76,16 +103,22 @@ class DepManager:
@staticmethod
def is_optional(dtype):
+ """Ancillary routine to report if a dependency is optional"""
return not dtype[1]
@staticmethod
def is_pdf(dtype):
+ """Ancillary routine to report if a dependency is for PDF generation"""
if (dtype[0] == DepManager._PDF_TYPE):
return True
return False
def add_package(self, package, dtype):
+ """
+ Add a package at the self.missing() dictionary.
+ Doesn't update missing_pkg.
+ """
is_optional = DepManager.is_optional(dtype)
self.missing[package] = dtype
if is_optional:
@@ -94,6 +127,10 @@ class DepManager:
self.need += 1
def del_package(self, package):
+ """
+ Remove a package at the self.missing() dictionary.
+ Doesn't update missing_pkg.
+ """
if package in self.missing:
del self.missing[package]
@@ -104,13 +141,22 @@ class DepManager:
This is an ackward way to have a separate section to recommend
a package after system main dependencies.
- TODO: rework the logic to prevent needing it
+ TODO: rework the logic to prevent needing it.
"""
self.missing = {}
+ self.missing_pkg = {}
def check_missing(self, progs):
- self.run = {}
+ """
+ Update self.missing_pkg, using progs dict to convert from the
+ agnostic package name to distro-specific one.
+
+ Returns an string with the packages to be installed, sorted and
+ with eventual duplicates removed.
+ """
+
+ self.missing_pkg = {}
for prog, dtype in sorted(self.missing.items()):
# At least on some LTS distros like CentOS 7, texlive doesn't
@@ -123,23 +169,26 @@ class DepManager:
self.optional -= 1
continue
- if not dtype in self.run:
- self.run[dtype] = []
+ if not dtype in self.missing_pkg:
+ self.missing_pkg[dtype] = []
- self.run[dtype].append(progs.get(prog, prog))
+ self.missing_pkg[dtype].append(progs.get(prog, prog))
install = []
- for dtype in self.run.keys():
- install += self.run[dtype]
+ for dtype in self.missing_pkg.keys():
+ install += self.missing_pkg[dtype]
return " ".join(sorted(set(install)))
def warn_install(self):
+ """
+ Emit warnings/errors related to missing packages.
+ """
output_msg = ""
- for dtype in sorted(self.run.keys()):
- progs = " ".join(sorted(set(self.run[dtype])))
+ for dtype in sorted(self.missing_pkg.keys()):
+ progs = " ".join(sorted(set(self.missing_pkg[dtype])))
try:
name = DepManager.name(dtype)
@@ -158,6 +207,11 @@ class AncillaryMethods:
@staticmethod
def which(prog):
+ """
+ Our own implementation of which(). We could instead use
+ shutil.which(), but this function is simple enough.
+ Probably faster to use this implementation than to import shutil.
+ """
for path in os.environ.get("PATH", "").split(":"):
full_path = os.path.join(path, prog)
if os.access(full_path, os.X_OK):
@@ -167,6 +221,10 @@ class AncillaryMethods:
@staticmethod
def get_python_version(cmd):
+ """
+ Get python version from a Python binary. As we need to detect if
+ are out there newer python binaries, we can't rely on sys.release here.
+ """
result = SphinxDependencyChecker.run([cmd, "--version"],
capture_output=True, text=True)
@@ -181,7 +239,13 @@ class AncillaryMethods:
@staticmethod
def find_python():
+ """
+ Detect if are out there any python 3.xy version newer than the
+ current one.
+ Note: this routine is limited to up to 2 digits for python3. We
+ may need to update it one day, hopefully on a distant future.
+ """
patterns = [
"python3.[0-9]",
"python3.[0-9][0-9]",
@@ -200,7 +264,10 @@ class AncillaryMethods:
@staticmethod
def check_python():
-
+ """
+ Check if the current python binary satisfies our minimal requirement
+ for Sphinx build. If not, re-run with a newer version if found.
+ """
cur_ver = sys.version_info[:3]
if cur_ver >= MIN_PYTHON_VERSION:
ver = ver_str(cur_ver)
@@ -240,7 +307,10 @@ class AncillaryMethods:
@staticmethod
def run(*args, **kwargs):
- """Excecute a command, hiding its output by default"""
+ """
+ Excecute a command, hiding its output by default.
+ Preserve comatibility with older Python versions.
+ """
capture_output = kwargs.pop('capture_output', False)
@@ -262,8 +332,15 @@ class AncillaryMethods:
return subprocess.run(*args, **kwargs)
class MissingCheckers(AncillaryMethods):
+ """
+ Contains some ancillary checkers for different types of binaries and
+ package managers.
+ """
def __init__(self, args, texlive):
+ """
+ Initialize its internal variables
+ """
self.pdf = args.pdf
self.virtualenv = args.virtualenv
self.version_check = args.version_check
@@ -280,17 +357,20 @@ class MissingCheckers(AncillaryMethods):
self.install = ""
- #
- # Methods to check if a feature exists
- #
-
def check_missing_file(self, files, package, dtype):
+ """
+ Does the file exists? If not, add it to missing dependencies.
+ """
for f in files:
if os.path.exists(f):
return
self.deps.add_package(package, dtype)
def check_program(self, prog, dtype):
+ """
+ Does the program exists and it is at the PATH?
+ If not, add it to missing dependencies.
+ """
found = self.which(prog)
if found:
return found
@@ -300,6 +380,18 @@ class MissingCheckers(AncillaryMethods):
return None
def check_perl_module(self, prog, dtype):
+ """
+ Does perl have a dependency? Is it available?
+ If not, add it to missing dependencies.
+
+ Right now, we still need Perl for doc build, as it is required
+ by some tools called at docs or kernel build time, like:
+
+ scripts/documentation-file-ref-check
+
+ Also, checkpatch is on Perl.
+ """
+
# While testing with lxc download template, one of the
# distros (Oracle) didn't have perl - nor even an option to install
# before installing oraclelinux-release-el9 package.
@@ -318,6 +410,10 @@ class MissingCheckers(AncillaryMethods):
self.deps.add_package(prog, dtype)
def check_python_module(self, module, is_optional=False):
+ """
+ Does a python module exists outside venv? If not, add it to missing
+ dependencies.
+ """
if is_optional:
dtype = DepManager.PYTHON_OPTIONAL
else:
@@ -329,6 +425,9 @@ class MissingCheckers(AncillaryMethods):
self.deps.add_package(module, dtype)
def check_rpm_missing(self, pkgs, dtype):
+ """
+ Does a rpm package exists? If not, add it to missing dependencies.
+ """
for prog in pkgs:
try:
self.run(["rpm", "-q", prog], check=True)
@@ -336,6 +435,9 @@ class MissingCheckers(AncillaryMethods):
self.deps.add_package(prog, dtype)
def check_pacman_missing(self, pkgs, dtype):
+ """
+ Does a pacman package exists? If not, add it to missing dependencies.
+ """
for prog in pkgs:
try:
self.run(["pacman", "-Q", prog], check=True)
@@ -343,6 +445,9 @@ class MissingCheckers(AncillaryMethods):
self.deps.add_package(prog, dtype)
def check_missing_tex(self, is_optional=False):
+ """
+ Does a LaTeX package exists? If not, add it to missing dependencies.
+ """
if is_optional:
dtype = DepManager.PDF_OPTIONAL
else:
@@ -371,6 +476,9 @@ class MissingCheckers(AncillaryMethods):
self.deps.add_package(package, dtype)
def get_sphinx_fname(self):
+ """
+ Gets the binary filename for sphinx-build.
+ """
if "SPHINXBUILD" in os.environ:
return os.environ["SPHINXBUILD"]
@@ -386,6 +494,9 @@ class MissingCheckers(AncillaryMethods):
return ""
def get_sphinx_version(self, cmd):
+ """
+ Gets sphinx-build version.
+ """
try:
result = self.run([cmd, "--version"],
stdout=subprocess.PIPE,
@@ -404,6 +515,9 @@ class MissingCheckers(AncillaryMethods):
return parse_version(match.group(1))
def check_sphinx(self, conf):
+ """
+ Checks Sphinx minimal requirements
+ """
try:
with open(conf, "r", encoding="utf-8") as f:
for line in f:
@@ -441,6 +555,10 @@ class MissingCheckers(AncillaryMethods):
sys.exit(0)
def catcheck(self, filename):
+ """
+ Reads a file if it exists, returning as string.
+ If not found, returns an empty string.
+ """
if os.path.exists(filename):
with open(filename, "r", encoding="utf-8") as f:
return f.read().strip()
--
2.50.1
next prev parent reply other threads:[~2025-08-12 15:53 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-12 15:52 [PATCH v2 00/39] Translate sphinx-pre-install to Python Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 01/39] scripts: sphinx-pre-install: fix version check for Fedora Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 02/39] scripts: sphinx-pre-install: rename it to scripts/sphinx-pre-install.pl Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 03/39] scripts: sphinx-pre-install: Convert script to Python Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 04/39] scripts: sphinx-pre-install: Make it compatible with Python 3.6 Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 05/39] scripts: sphinx-pre-install: run on a supported version Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 06/39] scripts: sphinx-pre-install: drop obsolete routines Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 07/39] scripts: sphinx-pre-install: drop support for old virtualenv Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 08/39] scripts: sphinx-pre-install: Address issues with OpenSUSE Leap 15.x Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 09/39] scripts: sphinx-pre-install: fix opensuse Leap hint for PyYAML Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 10/39] scripts: sphinx-pre-install: fix support for gentoo Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 11/39] scripts: sphinx-pre-install: Address issues with OpenSUSE Tumbleweed Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 12/39] scripts: sphinx-pre-install: only show portage hints once Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 13/39] scripts: sphinx-pre-install: cleanup rhel support Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 14/39] scripts: sphinx-pre-install: output Python and docutils version Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 15/39] scripts: sphinx-pre-install: add a missing f-string marker Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 16/39] scripts: sphinx-pre-install: fix Leap support for rsvg-convert Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 17/39] scripts: sphinx-pre-install: fix rhel recomendations Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 18/39] scripts: sphinx-pre-install: remove Scientific Linux Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 19/39] scripts: sphinx-pre-install: improve Gentoo package deps logic Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 20/39] scripts: sphinx-pre-install: fix OpenMandriva support Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 21/39] scripts: sphinx-pre-install: move package instructions to a new func Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 22/39] scripts: sphinx-pre-install: adjust a warning message Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 23/39] scripts: sphinx-pre-install: better handle Python min version Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 24/39] scripts: sphinx-pre-install: convert is_optional to a class Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 25/39] scripts: sphinx-pre-install: better handle RHEL-based distros Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 26/39] scripts: sphinx-pre-install: move missing logic to a separate class Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 27/39] scripts: sphinx-pre-install: move ancillary checkers " Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 28/39] scripts: sphinx-pre-install: add more generic checkers on a class Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 29/39] scripts: sphinx-pre-install: move get_system_release() Mauro Carvalho Chehab
2025-08-12 15:52 ` Mauro Carvalho Chehab [this message]
2025-08-12 15:52 ` [PATCH v2 31/39] scripts: sphinx-pre-install: add docstring documentation Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 32/39] scripts: sphinx-pre-install: fix several codingstyle issues Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 33/39] scripts: sphinx-pre-install: rework install command logic Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 34/39] docs: Makefile: switch to the new scripts/sphinx-pre-install.py Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 35/39] scripts: sphinx-pre-install.pl: get rid of the old script Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 36/39] scripts: sphinx-pre-install: update mandatory system deps Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 37/39] scripts: sphinx-pre-install: add support for RHEL8-based distros Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 38/39] scripts: sphinx-pre-install: add a warning for Debian-based distros Mauro Carvalho Chehab
2025-08-12 15:52 ` [PATCH v2 39/39] scripts: sphinx-pre-install: some adjustments related to venv Mauro Carvalho Chehab
2025-08-13 16:23 ` [PATCH v2 00/39] Translate sphinx-pre-install to Python Jonathan Corbet
-- strict thread matches above, loose matches on Subject: below --
2025-07-09 13:51 Mauro Carvalho Chehab
2025-07-09 13:52 ` [PATCH v2 30/39] scripts: sphinx-pre-install: add documentation for the ancillary classes Mauro Carvalho Chehab
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7421112b14edf5c21cc4cf0f2ee320fcaf874b40.1754992972.git.mchehab+huawei@kernel.org \
--to=mchehab+huawei@kernel.org \
--cc=corbet@lwn.net \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).