docs: maintainers_include: auto-generate maintainer profile TOC

Add a feature to allow auto-generating media entry profiles from the
corresponding field inside MAINTAINERS file(s).

Suggested-by: Dan Williams <djbw@kernel.org>
Closes: https://lore.kernel.org/linux-doc/69dd6299440be_147c801005b@djbw-dev.notmuch/
Acked-by: Dan Williams <djbw@kernel.org>
Reviewed-by: Randy Dunlap <rdunlap@infradead.org>
Tested-by: Randy Dunlap <rdunlap@infradead.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Message-ID: <4e9512a3d05942c98361d06d60a118d7c78762b6.1776176108.git.mchehab+huawei@kernel.org>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Message-ID: <eac5fb166bcbf0f267e762d72b150bbf248ff057.1777295258.git.mchehab+huawei@kernel.org>
This commit is contained in:
Mauro Carvalho Chehab 2026-04-27 16:22:20 +02:00 committed by Jonathan Corbet
parent 45a92c0b91
commit 6b6d73de37

View File

@ -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
)