Auto-generate maintainer profile entries
Subsystems (4)
v3 cover Auto-generate maintainer profile entries
Hi Jon,
This is basically the same patch series I sent during the merge window, rebased on the top of post 7.1-rc1 docs-next branch. It is tested both with and without O=DOCS.
It contains just one extra trivial patch adding a missing SPDX header.
This patch series change the way maintainer entry profile links are added to the documentation. Instead of having an entry for each of them at an ReST file, get them from MAINTAINERS content.
That should likely make easier to maintain, as there will be a single point to place all such profiles.
The output is a per-subsystem sorted (*) series of links shown as a list like this:
- Arm And Arm64 Soc Sub-Architectures (Common Parts)
- Arm/Samsung S3C, S5P And Exynos Arm Architectures
- Arm/Tesla Fsd Soc Support
...
- Xfs Filesystem
Please notice that the series is doing one logical change per patch. I could have merged some changes altogether, but I opted doing it in small steps to help reviews. If you prefer, feel free to merge maintainers_include changes on merge.
There is one interesting side effect of this series: there is no need to add rst files containing profiles inside a TOC tree: Just creating the file anywhere inside Documentation and adding a P entry is enough. Adding them to a TOC won't hurt.
(*) At the end, I opted to use sorted(), just to ensure it, even
knowing that MAINTAINER entries are supposed to be sorted, as the cost of sorting ~20 already-sorted entries is negligible.
---
v3:
- Added SPDX entry to process/maintainers.rst file;
- rebased after 7.1-rc1 release.
v2:
- I placed the to MAINTAINERS changes at the beginning.
- fix a bug when O=DOCS is used;
- proper handle glob "P" entries (just in case, no profiles use it ATM);
- when SPHINXDIRS=process, instead of producing warnings, point to
entries at https://docs.kernel.org; - MAINTAINERS parsing now happens just once; - The output won't be numered for entries inside numered TOC trees; - TOC tree is now hidden; - instead of display a TOC tree, it shows a list of profiles, ordered and named after file system name taken from MAINTAINERS file;
- At the output list, both https and file profiles are shown the same way.
Mauro Carvalho Chehab (12):
MAINTAINERS: add an entry for media maintainers profile
MAINTAINERS: add maintainer-tip.rst to X86
docs: maintainers: add SPDX license to the file
docs: maintainers_include: auto-generate maintainer profile TOC
docs: auto-generate maintainer entry profile links
docs: maintainers_include: use a better title for profiles
docs: maintainers_include: add external profile URLs
docs: maintainers_include: preserve names for files under process/
docs: maintainers_include: Only show main entry for profiles
docs: maintainers_include: improve its output
docs: maintainers_include: fix support for O=dir
docs: maintainers_include: parse MAINTAINERS just once
.../maintainer/maintainer-entry-profile.rst | 24 +-- .../process/maintainer-handbooks.rst | 17 +- Documentation/process/maintainers.rst | 2 + Documentation/sphinx/maintainers_include.py | 161 +++++++++++++++--- MAINTAINERS | 2 + 5 files changed, 152 insertions(+), 54 deletions(-)
Signature · 1 line
2.53.0
PATCH v3 1/12 MAINTAINERS: add an entry for media maintainers profile
The media subsystem has a maintainers entry profile, but its entry is missing at MAINTAINERS.
Add it.
Message-ID: <5af4aa6a716228eea4d59dc26b97d642e1e7d419.1776176108.git.mchehab+huawei@kernel.org>
--- MAINTAINERS | 1 + 1 file changed, 1 insertion(+)
MAINTAINERS +1 -0
@@ -16223,6 +16223,7 @@ P: Documentation/driver-api/media/maintainer-entry-profile.rst W: https://linuxtv.org Q: https://patchwork.linuxtv.org/project/linux-media/list/ T: git git://linuxtv.org/media.git +P: Documentation/driver-api/media/maintainer-entry-profile.rst F: Documentation/admin-guide/media/ F: Documentation/devicetree/bindings/media/ F: Documentation/driver-api/media/
Signature · 1 line
2.53.0
PATCH v3 2/12 MAINTAINERS: add maintainer-tip.rst to X86
In reply to Mauro Carvalho ChehabThe X86 subsystem has a maintainers entry profile, but its entry is missing at MAINTAINERS.
Add it.
Message-ID: <970434c647aa1e1e9a81c87b4d5fed934d4018a7.1776176108.git.mchehab+huawei@kernel.org>
--- MAINTAINERS | 1 + 1 file changed, 1 insertion(+)
MAINTAINERS +1 -0
@@ -28808,6 +28808,7 @@ M: Ingo Molnar <[email protected]> M: Borislav Petkov <[email protected]> M: Dave Hansen <[email protected]> M: [email protected] +P: Documentation/process/maintainer-tip.rst R: "H. Peter Anvin" <[email protected]> L: [email protected] S: Maintained
Signature · 1 line
2.53.0
PATCH v3 3/12 docs: maintainers: add SPDX license to the file
In reply to Mauro Carvalho ChehabWhile this file is really trivial, add a SPDX license line on it.
--- Documentation/process/maintainers.rst | 2 ++ 1 file changed, 2 insertions(+)
Documentation/process/maintainers.rst +2 -0
@@ -1 +1,3 @@ +.. SPDX-License-Identifier: GPL-2.0 + .. maintainers-include::
Signature · 1 line
2.53.0
PATCH v3 4/12 docs: maintainers_include: auto-generate maintainer profile TOC
In reply to Mauro Carvalho ChehabAdd a feature to allow auto-generating media entry profiles from the corresponding field inside MAINTAINERS file(s).
Message-ID: <4e9512a3d05942c98361d06d60a118d7c78762b6.1776176108.git.mchehab+huawei@kernel.org>
--- Documentation/sphinx/maintainers_include.py | 93 +++++++++++++++++---- 1 file changed, 76 insertions(+), 17 deletions(-)
Documentation/sphinx/maintainers_include.py +76 -17
@@ -21,6 +21,8 @@ import sys import re import os.path +from textwrap import indent + from docutils import statemachine from docutils.parsers.rst import Directive from docutils.parsers.rst.directives.misc import Include
@@ -30,20 +32,11 @@ def ErrorString(exc): # Shamelessly stolen from docutils __version__ = '1.0' -def setup(app): - app.add_directive("maintainers-include", MaintainersInclude) - return dict( - version = __version__, - parallel_read_safe = True, - parallel_write_safe = True - ) +class MaintainersParser: + """Parse MAINTAINERS file(s) content""" -class MaintainersInclude(Include): - """MaintainersInclude (``maintainers-include``) directive""" - required_arguments = 0 - - def parse_maintainers(self, path): - """Parse all the MAINTAINERS lines into ReST for human-readability""" + def __init__(self, base_path, path): + self.profiles = list() result = list() result.append(".. _maintainers:")
@@ -78,6 +71,12 @@ class MaintainersInclude(Include): # Drop needless input whitespace. line = line.rstrip() + match = re.match(r"P:\s*(Documentation/\S+)\.rst", line) + if match: + fname = os.path.relpath(match.group(1), base_path) + if fname not in self.profiles: + self.profiles.append(fname) + # Linkify all non-wildcard refs to ReST files in Documentation/. pat = r'(Documentation/([^\s\?\*]*)\.rst)' m = re.search(pat, line)
@@ -165,12 +164,23 @@ class MaintainersInclude(Include): for separated in field_content.split('\n'): result.append(separated) - output = "\n".join(result) + self.output = "\n".join(result) + + # Create a TOC class + +class MaintainersInclude(Include): + """MaintainersInclude (``maintainers-include``) directive""" + required_arguments = 0 + + def emit(self, base_path, path): + """Parse all the MAINTAINERS lines into ReST for human-readability""" + + output = MaintainersParser(base_path, path).output + # For debugging the pre-rendered results... #print(output, file=open("/tmp/MAINTAINERS.rst", "w")) - self.state_machine.insert_input( - statemachine.string2lines(output), path) + self.state_machine.insert_input(statemachine.string2lines(output), path) def run(self): """Include the MAINTAINERS file as part of this reST file."""
@@ -186,12 +196,61 @@ class MaintainersInclude(Include): # Append "MAINTAINERS" path = os.path.join(path, "MAINTAINERS") + base_path = os.path.dirname(self.state.document.document.current_source) try: self.state.document.settings.record_dependencies.add(path) - lines = self.parse_maintainers(path) + lines = self.emit(base_path, path) except IOError as error: raise self.severe('Problems with "%s" directive path:\n%s.' % (self.name, ErrorString(error))) return [] + +class MaintainersProfile(Include): + required_arguments = 0 + + def emit(self, base_path, path): + """Parse all the MAINTAINERS lines looking for profile entries""" + + profiles = MaintainersParser(base_path, path).profiles + + output = ".. toctree::\n" + output += " :maxdepth: 2\n\n" + output += indent("\n".join(profiles), " ") + + self.state_machine.insert_input(statemachine.string2lines(output), path) + + def run(self): + """Include the MAINTAINERS file as part of this reST file.""" + if not self.state.document.settings.file_insertion_enabled: + raise self.warning('"%s" directive disabled.' % self.name) + + # Walk up source path directories to find Documentation/../ + path = self.state_machine.document.attributes['source'] + path = os.path.realpath(path) + tail = path + while tail != "Documentation" and tail != "": + (path, tail) = os.path.split(path) + + # Append "MAINTAINERS" + path = os.path.join(path, "MAINTAINERS") + base_path = os.path.dirname(self.state.document.document.current_source) + + try: + self.state.document.settings.record_dependencies.add(path) + lines = self.emit(base_path, path) + except IOError as error: + raise self.severe('Problems with "%s" directive path:\n%s.' % + (self.name, ErrorString(error))) + + return [] + +def setup(app): + app.add_directive("maintainers-include", MaintainersInclude) + app.add_directive("maintainers-profile-toc", MaintainersProfile) + return dict( + version = __version__, + parallel_read_safe = True, + parallel_write_safe = True + )
Signature · 1 line
2.53.0
PATCH v3 5/12 docs: auto-generate maintainer entry profile links
In reply to Mauro Carvalho ChehabInstead of manually creating a TOC tree for them, use the new tag to auto-generate its TOC.
Message-ID: <9228f77b0339b8e5dea4a201ab6d4feb30cef5c2.1776176108.git.mchehab+huawei@kernel.org>
--- .../maintainer/maintainer-entry-profile.rst | 24 ++++--------------- .../process/maintainer-handbooks.rst | 19 ++++++++------- 2 files changed, 14 insertions(+), 29 deletions(-)
Documentation/maintainer/maintainer-entry-profile.rst +4 -20
@@ -92,24 +92,8 @@ full series, or privately send a reminder email. This section might also list how review works for this code area and methods to get feedback that are not directly from the maintainer. -Existing profiles ------------------ +Maintainer Handbooks +-------------------- -For now, existing maintainer profiles are listed here; we will likely want -to do something different in the near future. - -.. toctree:: - :maxdepth: 1 - - ../doc-guide/maintainer-profile - ../nvdimm/maintainer-entry-profile - ../arch/riscv/patch-acceptance - ../process/maintainer-soc - ../process/maintainer-soc-clean-dts - ../driver-api/media/maintainer-entry-profile - ../process/maintainer-netdev - ../driver-api/vfio-pci-device-specific-driver-acceptance - ../nvme/feature-and-quirk-policy - ../filesystems/nfs/nfsd-maintainer-entry-profile - ../filesystems/xfs/xfs-maintainer-entry-profile - ../mm/damon/maintainer-profile +For examples of other subsystem handbooks see +Documentation/process/maintainer-handbooks.rst.
Documentation/process/maintainer-handbooks.rst +10 -9
@@ -7,14 +7,15 @@ The purpose of this document is to provide subsystem specific information which is supplementary to the general development process handbook :ref:`Documentation/process <development_process_main>`. +For developers, see below for all the known subsystem specific guides. +If the subsystem you are contributing to does not have a guide listed +here, it is fair to seek clarification of questions raised in +Documentation/maintainer/maintainer-entry-profile.rst. + +For maintainers, consider documenting additional requirements and +expectations if submissions routinely overlook specific submission +criteria. See Documentation/maintainer/maintainer-entry-profile.rst. + Contents: -.. toctree:: - :numbered: - :maxdepth: 2 - - maintainer-netdev - maintainer-soc - maintainer-soc-clean-dts - maintainer-tip - maintainer-kvm-x86 +.. maintainers-profile-toc::
Signature · 1 line
2.53.0
PATCH v3 6/12 docs: maintainers_include: use a better title for profiles
In reply to Mauro Carvalho ChehabAs we're picking the name of the subsystem from MAINTAINERS, also use its subsystem name for the titles.
--- Documentation/sphinx/maintainers_include.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-)
Documentation/sphinx/maintainers_include.py +15 -3
@@ -36,7 +36,7 @@ class MaintainersParser: """Parse MAINTAINERS file(s) content""" def __init__(self, base_path, path): - self.profiles = list() + self.profiles = {} result = list() result.append(".. _maintainers:")
@@ -54,6 +54,7 @@ class MaintainersParser: prev = None field_prev = "" field_content = "" + subsystem_name = None for line in open(path): # Have we reached the end of the preformatted Descriptions text?
@@ -75,7 +76,10 @@ class MaintainersParser: if match: fname = os.path.relpath(match.group(1), base_path) if fname not in self.profiles: - self.profiles.append(fname) + if self.profiles.get(fname) is None: + self.profiles[fname] = subsystem_name + else: + self.profiles[fname] += f", {subsystem_name}" # Linkify all non-wildcard refs to ReST files in Documentation/. pat = r'(Documentation/([^\s\?\*]*)\.rst)'
@@ -112,6 +116,8 @@ class MaintainersParser: output = field_content + "\n\n" field_content = "" + subsystem_name = line.title() + # Collapse whitespace in subsystem name. heading = re.sub(r"\s+", " ", line) output = output + "%s\n%s" % (heading, "~" * len(heading))
@@ -217,7 +223,13 @@ class MaintainersProfile(Include): output = ".. toctree::\n" output += " :maxdepth: 2\n\n" - output += indent("\n".join(profiles), " ") + + items = sorted(profiles.items(), key=lambda kv: (kv[1] or "", kv[0])) + for fname, profile in items: + if profile: + output += f" {profile} <{fname}>\n" + else: + output += f" {fname}\n" self.state_machine.insert_input(statemachine.string2lines(output), path)
Signature · 1 line
2.53.0
PATCH v3 7/12 docs: maintainers_include: add external profile URLs
In reply to Mauro Carvalho ChehabSome subsystem profiles are maintained elsewhere. Add them to the output.
--- Documentation/sphinx/maintainers_include.py | 28 +++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-)
Documentation/sphinx/maintainers_include.py +26 -2
@@ -37,6 +37,7 @@ class MaintainersParser: def __init__(self, base_path, path): self.profiles = {} + self.profile_urls = {} result = list() result.append(".. _maintainers:")
@@ -81,6 +82,16 @@ class MaintainersParser: else: self.profiles[fname] += f", {subsystem_name}" + match = re.match(r"P:\s*(https?://.*)", line) + if match: + url = match.group(1).strip() + if url not in self.profile_urls: + if self.profile_urls.get(url) is None: + self.profile_urls[url] = subsystem_name + else: + self.profile_urls[url] += f", {subsystem_name}" + + # Linkify all non-wildcard refs to ReST files in Documentation/. pat = r'(Documentation/([^\s\?\*]*)\.rst)' m = re.search(pat, line)
@@ -219,18 +230,31 @@ class MaintainersProfile(Include): def emit(self, base_path, path): """Parse all the MAINTAINERS lines looking for profile entries""" - profiles = MaintainersParser(base_path, path).profiles + maint = MaintainersParser(base_path, path) output = ".. toctree::\n" output += " :maxdepth: 2\n\n" - items = sorted(profiles.items(), key=lambda kv: (kv[1] or "", kv[0])) + items = sorted(maint.profiles.items(), + key=lambda kv: (kv[1] or "", kv[0])) for fname, profile in items: if profile: output += f" {profile} <{fname}>\n" else: output += f" {fname}\n" + output += "\n**External profiles**\n\n" + + items = sorted(maint.profile_urls.items(), + key=lambda kv: (kv[1] or "", kv[0])) + for url, profile in items: + if profile: + output += f"- {profile} <{url}>\n" + else: + output += f"- {url}\n" + + output += "\n" + self.state_machine.insert_input(statemachine.string2lines(output), path) def run(self):
Signature · 1 line
2.53.0
PATCH v3 8/12 docs: maintainers_include: preserve names for files under process/
In reply to Mauro Carvalho ChehabWhen a maintainer's profile is stored outside process, they're already included on some other book and the name of the filesystem may not be there. That's why the logic picks the name from the subsystem's name.
However, files directly placed together with maintainers-handbooks.rst (e.g. under Documentation/process/) is a different history: those aren't placed anywhere, so we can keep using their own names, letting Sphinx do his thing.
--- Documentation/sphinx/maintainers_include.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
Documentation/sphinx/maintainers_include.py +3 -1
@@ -76,11 +76,13 @@ class MaintainersParser: match = re.match(r"P:\s*(Documentation/\S+)\.rst", line) if match: fname = os.path.relpath(match.group(1), base_path) - if fname not in self.profiles: + if fname.startswith("../"): if self.profiles.get(fname) is None: self.profiles[fname] = subsystem_name else: self.profiles[fname] += f", {subsystem_name}" + else: + self.profiles[fname] = None match = re.match(r"P:\s*(https?://.*)", line) if match:
Signature · 1 line
2.53.0
PATCH v3 9/12 docs: maintainers_include: Only show main entry for profiles
In reply to Mauro Carvalho ChehabInstead of showing as a "Contents:" with 2 identation levels, drop its title and show profiles as a list of entries.
--- Documentation/process/maintainer-handbooks.rst | 2 -- Documentation/sphinx/maintainers_include.py | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-)
Documentation/process/maintainer-handbooks.rst +0 -2
@@ -16,6 +16,4 @@ For maintainers, consider documenting additional requirements and expectations if submissions routinely overlook specific submission criteria. See Documentation/maintainer/maintainer-entry-profile.rst. -Contents: - .. maintainers-profile-toc::
Documentation/sphinx/maintainers_include.py +1 -1
@@ -235,7 +235,7 @@ class MaintainersProfile(Include): maint = MaintainersParser(base_path, path) output = ".. toctree::\n" - output += " :maxdepth: 2\n\n" + output += " :maxdepth: 1\n\n" items = sorted(maint.profiles.items(), key=lambda kv: (kv[1] or "", kv[0]))
Signature · 1 line
2.53.0
PATCH v3 10/12 docs: maintainers_include: improve its output
In reply to Mauro Carvalho ChehabThere are three "types" of profiles:
1. Profiles already included inside subsystem-specific documentation. This is the most common case;
2. Profiles that are hosted externally;
3. Profiles that are at the same location as maintainer-handbooks.rst.
For (3), we need to create a TOC, as they don't exist elsewhere.
Change the logic to create TOC just for (3), prepending the content of maintainer-handbooks with a sorted entry of all types, before the TOC.
With such change, we can have an unique sorted list of profiles, having the subsystem names used there listed.
--- Documentation/sphinx/maintainers_include.py | 76 +++++++++++---------- 1 file changed, 40 insertions(+), 36 deletions(-)
Documentation/sphinx/maintainers_include.py +40 -36
@@ -21,7 +21,7 @@ import sys import re import os.path -from textwrap import indent +from glob import glob from docutils import statemachine from docutils.parsers.rst import Directive
@@ -36,8 +36,8 @@ class MaintainersParser: """Parse MAINTAINERS file(s) content""" def __init__(self, base_path, path): - self.profiles = {} - self.profile_urls = {} + self.profile_toc = set() + self.profile_entries = {} result = list() result.append(".. _maintainers:")
@@ -73,26 +73,24 @@ class MaintainersParser: # Drop needless input whitespace. line = line.rstrip() + # + # Handle profile entries - either as files or as https refs + # match = re.match(r"P:\s*(Documentation/\S+)\.rst", line) if match: - fname = os.path.relpath(match.group(1), base_path) - if fname.startswith("../"): - if self.profiles.get(fname) is None: - self.profiles[fname] = subsystem_name - else: - self.profiles[fname] += f", {subsystem_name}" + entry = os.path.relpath(match.group(1), base_path) + if "*" in entry: + for e in glob(entry): + self.profile_toc.add(e) + self.profile_entries[subsystem_name] = e else: - self.profiles[fname] = None - - match = re.match(r"P:\s*(https?://.*)", line) - if match: - url = match.group(1).strip() - if url not in self.profile_urls: - if self.profile_urls.get(url) is None: - self.profile_urls[url] = subsystem_name - else: - self.profile_urls[url] += f", {subsystem_name}" - + self.profile_toc.add(entry) + self.profile_entries[subsystem_name] = entry + else: + match = re.match(r"P:\s*(https?://.*)", line) + if match: + entry = match.group(1).strip() + self.profile_entries[subsystem_name] = entry # Linkify all non-wildcard refs to ReST files in Documentation/. pat = r'(Documentation/([^\s\?\*]*)\.rst)'
@@ -234,26 +232,32 @@ class MaintainersProfile(Include): maint = MaintainersParser(base_path, path) - output = ".. toctree::\n" - output += " :maxdepth: 1\n\n" + # + # Produce a list with all maintainer profiles, sorted by subsystem name + # + output = "" - items = sorted(maint.profiles.items(), - key=lambda kv: (kv[1] or "", kv[0])) - for fname, profile in items: - if profile: - output += f" {profile} <{fname}>\n" + for profile, entry in maint.profile_entries.items(): + if entry.startswith("http"): + if profile: + output += f"- `{profile} <{entry}>`_\n" + else: + output += f"- `<{entry}>_`\n" else: - output += f" {fname}\n" + if profile: + output += f"- :doc:`{profile} <{entry}>`\n" + else: + output += f"- :doc:`<{entry}>`\n" - output += "\n**External profiles**\n\n" + # + # Create a hidden TOC table with all profiles. That allows adding + # profiles without needing to add them on any index.rst file. + # + output += "\n.. toctree::\n" + output += " :hidden:\n\n" - items = sorted(maint.profile_urls.items(), - key=lambda kv: (kv[1] or "", kv[0])) - for url, profile in items: - if profile: - output += f"- {profile} <{url}>\n" - else: - output += f"- {url}\n" + for fname in maint.profile_toc: + output += f" {fname}\n" output += "\n"
Signature · 1 line
2.53.0
PATCH v3 11/12 docs: maintainers_include: fix support for O=dir
In reply to Mauro Carvalho Chehabos.path.relpath() will do the wrong thing with O=dir, as the build system uses "cd <dir>" internally.
Solve it by using app.srcdir, which, on normal cases, point to Documentation/, or, when SPHINXDIRS=process, it will be set with Documentation/process.
While here, remove a dead code while writing maintainer profiles, as now all entries should have both profile and entry.
--- Documentation/sphinx/maintainers_include.py | 71 +++++++++++++++------ 1 file changed, 50 insertions(+), 21 deletions(-)
Documentation/sphinx/maintainers_include.py +50 -21
@@ -27,15 +27,24 @@ from docutils import statemachine from docutils.parsers.rst import Directive from docutils.parsers.rst.directives.misc import Include +# +# Base URL for intersphinx-like links to maintainer profiles +# +KERNELDOC_URL = "https://docs.kernel.org/" + def ErrorString(exc): # Shamelessly stolen from docutils return f'{exc.__class__.__name}: {exc}' __version__ = '1.0' +app_dir = "." + class MaintainersParser: """Parse MAINTAINERS file(s) content""" - def __init__(self, base_path, path): + def __init__(self, path): + global app_dir + self.profile_toc = set() self.profile_entries = {}
@@ -57,6 +66,9 @@ class MaintainersParser: field_content = "" subsystem_name = None + base_dir, doc_dir, sphinx_dir = app_dir.partition("Documentation") + print("BASE DIR", base_dir) + for line in open(path): # Have we reached the end of the preformatted Descriptions text? if descriptions and line.startswith('Maintainers'):
@@ -76,9 +88,25 @@ class MaintainersParser: # # Handle profile entries - either as files or as https refs # - match = re.match(r"P:\s*(Documentation/\S+)\.rst", line) + match = re.match(rf"P:\s*({doc_dir})(/\S+)\.rst", line) if match: - entry = os.path.relpath(match.group(1), base_path) + name = "".join(match.groups()) + entry = os.path.relpath(base_dir + name, app_dir) + + full_name = os.path.join(base_dir, name) + path = os.path.relpath(full_name, app_dir) + # + # When SPHINXDIRS is used, it will try to reference files + # outside srctree, causing warnings. To avoid that, point + # to the latest official documentation + # + if path.startswith("../"): + entry = KERNELDOC_URL + match.group(2) + ".html" + else: + entry = "/" + entry + + print(f"{name}: entry: {entry} FULL: {full_name} path: {path}") + if "*" in entry: for e in glob(entry): self.profile_toc.add(e)
@@ -189,10 +217,10 @@ class MaintainersInclude(Include): """MaintainersInclude (``maintainers-include``) directive""" required_arguments = 0 - def emit(self, base_path, path): + def emit(self, path): """Parse all the MAINTAINERS lines into ReST for human-readability""" - output = MaintainersParser(base_path, path).output + output = MaintainersParser(path).output # For debugging the pre-rendered results... #print(output, file=open("/tmp/MAINTAINERS.rst", "w"))
@@ -213,11 +241,10 @@ class MaintainersInclude(Include): # Append "MAINTAINERS" path = os.path.join(path, "MAINTAINERS") - base_path = os.path.dirname(self.state.document.document.current_source) try: self.state.document.settings.record_dependencies.add(path) - lines = self.emit(base_path, path) + lines = self.emit(path) except IOError as error: raise self.severe('Problems with "%s" directive path:\n%s.' % (self.name, ErrorString(error)))
@@ -227,27 +254,20 @@ class MaintainersInclude(Include): class MaintainersProfile(Include): required_arguments = 0 - def emit(self, base_path, path): + def emit(self, path): """Parse all the MAINTAINERS lines looking for profile entries""" - maint = MaintainersParser(base_path, path) + maint = MaintainersParser(path) # # Produce a list with all maintainer profiles, sorted by subsystem name # output = "" - - for profile, entry in maint.profile_entries.items(): + for profile, entry in sorted(maint.profile_entries.items()): if entry.startswith("http"): - if profile: - output += f"- `{profile} <{entry}>`_\n" - else: - output += f"- `<{entry}>_`\n" + output += f"- `{profile} <{entry}>`_\n" else: - if profile: - output += f"- :doc:`{profile} <{entry}>`\n" - else: - output += f"- :doc:`<{entry}>`\n" + output += f"- :doc:`{profile} <{entry}>`\n" # # Create a hidden TOC table with all profiles. That allows adding
@@ -261,6 +281,8 @@ class MaintainersProfile(Include): output += "\n" + print(output) + self.state_machine.insert_input(statemachine.string2lines(output), path) def run(self):
@@ -277,11 +299,10 @@ class MaintainersProfile(Include): # Append "MAINTAINERS" path = os.path.join(path, "MAINTAINERS") - base_path = os.path.dirname(self.state.document.document.current_source) try: self.state.document.settings.record_dependencies.add(path) - lines = self.emit(base_path, path) + lines = self.emit(path) except IOError as error: raise self.severe('Problems with "%s" directive path:\n%s.' % (self.name, ErrorString(error)))
@@ -289,6 +310,14 @@ class MaintainersProfile(Include): return [] def setup(app): + global app_dir + + # + # NOTE: we're using os.fspath() here because of a Sphinx warning: + # RemovedInSphinx90Warning: Sphinx 9 will drop support for representing paths as strings. Use "pathlib.Path" or "os.fspath" instead. + # + app_dir = os.fspath(app.srcdir) + app.add_directive("maintainers-include", MaintainersInclude) app.add_directive("maintainers-profile-toc", MaintainersProfile) return dict(
Signature · 1 line
2.53.0
PATCH v3 12/12 docs: maintainers_include: parse MAINTAINERS just once
In reply to Mauro Carvalho ChehabChange the logic to parse MAINTAINERS file content just once, while still allowing using it multiple times.
--- Documentation/sphinx/maintainers_include.py | 61 +++++++-------------- 1 file changed, 21 insertions(+), 40 deletions(-)
Documentation/sphinx/maintainers_include.py +21 -40
@@ -37,14 +37,13 @@ def ErrorString(exc): # Shamelessly stolen from docutils __version__ = '1.0' -app_dir = "." +maint_parser = None class MaintainersParser: """Parse MAINTAINERS file(s) content""" - def __init__(self, path): - global app_dir - + def __init__(self, app_dir, path): + self.path = path self.profile_toc = set() self.profile_entries = {}
@@ -67,7 +66,6 @@ class MaintainersParser: subsystem_name = None base_dir, doc_dir, sphinx_dir = app_dir.partition("Documentation") - print("BASE DIR", base_dir) for line in open(path): # Have we reached the end of the preformatted Descriptions text?
@@ -105,8 +103,6 @@ class MaintainersParser: else: entry = "/" + entry - print(f"{name}: entry: {entry} FULL: {full_name} path: {path}") - if "*" in entry: for e in glob(entry): self.profile_toc.add(e)
@@ -217,14 +213,17 @@ class MaintainersInclude(Include): """MaintainersInclude (``maintainers-include``) directive""" required_arguments = 0 - def emit(self, path): + def emit(self): """Parse all the MAINTAINERS lines into ReST for human-readability""" + global maint_parser - output = MaintainersParser(path).output + path = maint_parser.path + output = maint_parser.output # For debugging the pre-rendered results... #print(output, file=open("/tmp/MAINTAINERS.rst", "w")) + self.state.document.settings.record_dependencies.add(path) self.state_machine.insert_input(statemachine.string2lines(output), path) def run(self):
@@ -232,19 +231,8 @@ class MaintainersInclude(Include): if not self.state.document.settings.file_insertion_enabled: raise self.warning('"%s" directive disabled.' % self.name) - # Walk up source path directories to find Documentation/../ - path = self.state_machine.document.attributes['source'] - path = os.path.realpath(path) - tail = path - while tail != "Documentation" and tail != "": - (path, tail) = os.path.split(path) - - # Append "MAINTAINERS" - path = os.path.join(path, "MAINTAINERS") - try: - self.state.document.settings.record_dependencies.add(path) - lines = self.emit(path) + lines = self.emit() except IOError as error: raise self.severe('Problems with "%s" directive path:\n%s.' % (self.name, ErrorString(error)))
@@ -254,16 +242,17 @@ class MaintainersInclude(Include): class MaintainersProfile(Include): required_arguments = 0 - def emit(self, path): + def emit(self): """Parse all the MAINTAINERS lines looking for profile entries""" + global maint_parser - maint = MaintainersParser(path) + path = maint_parser.path # # Produce a list with all maintainer profiles, sorted by subsystem name # output = "" - for profile, entry in sorted(maint.profile_entries.items()): + for profile, entry in sorted(maint_parser.profile_entries.items()): if entry.startswith("http"): output += f"- `{profile} <{entry}>`_\n" else:
@@ -276,13 +265,12 @@ class MaintainersProfile(Include): output += "\n.. toctree::\n" output += " :hidden:\n\n" - for fname in maint.profile_toc: + for fname in maint_parser.profile_toc: output += f" {fname}\n" output += "\n" - print(output) - + self.state.document.settings.record_dependencies.add(path) self.state_machine.insert_input(statemachine.string2lines(output), path) def run(self):
@@ -290,19 +278,8 @@ class MaintainersProfile(Include): if not self.state.document.settings.file_insertion_enabled: raise self.warning('"%s" directive disabled.' % self.name) - # Walk up source path directories to find Documentation/../ - path = self.state_machine.document.attributes['source'] - path = os.path.realpath(path) - tail = path - while tail != "Documentation" and tail != "": - (path, tail) = os.path.split(path) - - # Append "MAINTAINERS" - path = os.path.join(path, "MAINTAINERS") - try: - self.state.document.settings.record_dependencies.add(path) - lines = self.emit(path) + lines = self.emit() except IOError as error: raise self.severe('Problems with "%s" directive path:\n%s.' % (self.name, ErrorString(error)))
@@ -310,13 +287,17 @@ class MaintainersProfile(Include): return [] def setup(app): - global app_dir + global maint_parser # # NOTE: we're using os.fspath() here because of a Sphinx warning: # RemovedInSphinx90Warning: Sphinx 9 will drop support for representing paths as strings. Use "pathlib.Path" or "os.fspath" instead. # app_dir = os.fspath(app.srcdir) + srctree = os.path.abspath(os.environ["srctree"]) + path = os.path.join(srctree, "MAINTAINERS") + + maint_parser = MaintainersParser(app_dir, path) app.add_directive("maintainers-include", MaintainersInclude) app.add_directive("maintainers-profile-toc", MaintainersProfile)
Signature · 1 line
2.53.0
Quoted 5 lines · On Mon, 27 Apr 2026 15:00:00 +0200 Mauro Carvalho Chehab…
Hi Jon,
This is basically the same patch series I sent during the merge window, rebased on the top of post 7.1-rc1 docs-next branch. It is tested both with and without O=DOCS.
Please ignore it...
Quoted 3 lines
Mauro Carvalho Chehab (12):
MAINTAINERS: add an entry for media maintainers profile
MAINTAINERS: addmaintainer-tip.rstto X86
... I forgot to drop those two. They aren't needed anymore. Will resend it soon enough.
Signature · 2 lines
Thanks, Mauro