124 lines
3.5 KiB
Python
Executable File
124 lines
3.5 KiB
Python
Executable File
# SPDX-License-Identifier: GPL-2.0
|
|
# Copyright 2025 Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
|
|
|
"""
|
|
Sphinx extension for processing YAML files
|
|
"""
|
|
|
|
import os
|
|
import re
|
|
import sys
|
|
|
|
from pprint import pformat
|
|
|
|
from docutils import statemachine
|
|
from docutils.parsers.rst import Parser as RSTParser
|
|
from docutils.parsers.rst import states
|
|
from docutils.statemachine import ViewList
|
|
|
|
from sphinx.util import logging
|
|
from sphinx.parsers import Parser
|
|
|
|
srctree = os.path.abspath(os.environ["srctree"])
|
|
sys.path.insert(0, os.path.join(srctree, "tools/net/ynl/pyynl/lib"))
|
|
|
|
from doc_generator import YnlDocGenerator # pylint: disable=C0413
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class YamlParser(Parser):
|
|
"""
|
|
Kernel parser for YAML files.
|
|
|
|
This is a simple sphinx.Parser to handle yaml files inside the
|
|
Kernel tree that will be part of the built documentation.
|
|
|
|
The actual parser function is not contained here: the code was
|
|
written in a way that parsing yaml for different subsystems
|
|
can be done from a single dispatcher.
|
|
|
|
All it takes to have parse YAML patches is to have an import line:
|
|
|
|
from some_parser_code import NewYamlGenerator
|
|
|
|
To this module. Then add an instance of the parser with:
|
|
|
|
new_parser = NewYamlGenerator()
|
|
|
|
and add a logic inside parse() to handle it based on the path,
|
|
like this:
|
|
|
|
if "/foo" in fname:
|
|
msg = self.new_parser.parse_yaml_file(fname)
|
|
"""
|
|
|
|
supported = ('yaml', )
|
|
|
|
netlink_parser = YnlDocGenerator()
|
|
|
|
re_lineno = re.compile(r"\.\. LINENO ([0-9]+)$")
|
|
|
|
tab_width = 8
|
|
|
|
def rst_parse(self, inputstring, document, msg):
|
|
"""
|
|
Receives a ReST content that was previously converted by the
|
|
YAML parser, adding it to the document tree.
|
|
"""
|
|
|
|
self.setup_parse(inputstring, document)
|
|
|
|
result = ViewList()
|
|
|
|
self.statemachine = states.RSTStateMachine(state_classes=states.state_classes,
|
|
initial_state='Body',
|
|
debug=document.reporter.debug_flag)
|
|
|
|
try:
|
|
# Parse message with RSTParser
|
|
lineoffset = 0;
|
|
|
|
lines = statemachine.string2lines(msg, self.tab_width,
|
|
convert_whitespace=True)
|
|
|
|
for line in lines:
|
|
match = self.re_lineno.match(line)
|
|
if match:
|
|
lineoffset = int(match.group(1))
|
|
continue
|
|
|
|
result.append(line, document.current_source, lineoffset)
|
|
|
|
self.statemachine.run(result, document)
|
|
|
|
except Exception as e:
|
|
document.reporter.error("YAML parsing error: %s" % pformat(e))
|
|
|
|
self.finish_parse()
|
|
|
|
# Overrides docutils.parsers.Parser. See sphinx.parsers.RSTParser
|
|
def parse(self, inputstring, document):
|
|
"""Check if a YAML is meant to be parsed."""
|
|
|
|
fname = document.current_source
|
|
|
|
# Handle netlink yaml specs
|
|
if "/netlink/specs/" in fname:
|
|
msg = self.netlink_parser.parse_yaml_file(fname)
|
|
self.rst_parse(inputstring, document, msg)
|
|
|
|
# All other yaml files are ignored
|
|
|
|
def setup(app):
|
|
"""Setup function for the Sphinx extension."""
|
|
|
|
# Add YAML parser
|
|
app.add_source_parser(YamlParser)
|
|
app.add_source_suffix('.yaml', 'yaml')
|
|
|
|
return {
|
|
'version': '1.0',
|
|
'parallel_read_safe': True,
|
|
'parallel_write_safe': True,
|
|
}
|