1# SPDX-License-Identifier: GPL-2.0 2# Copyright 2025 Mauro Carvalho Chehab <mchehab+huawei@kernel.org> 3 4""" 5Sphinx extension for processing YAML files 6""" 7 8import os 9import re 10import sys 11 12from pprint import pformat 13 14from docutils.parsers.rst import Parser as RSTParser 15from docutils.statemachine import ViewList 16 17from sphinx.util import logging 18from sphinx.parsers import Parser 19 20srctree = os.path.abspath(os.environ["srctree"]) 21sys.path.insert(0, os.path.join(srctree, "tools/net/ynl/pyynl/lib")) 22 23from doc_generator import YnlDocGenerator # pylint: disable=C0413 24 25logger = logging.getLogger(__name__) 26 27class YamlParser(Parser): 28 """ 29 Kernel parser for YAML files. 30 31 This is a simple sphinx.Parser to handle yaml files inside the 32 Kernel tree that will be part of the built documentation. 33 34 The actual parser function is not contained here: the code was 35 written in a way that parsing yaml for different subsystems 36 can be done from a single dispatcher. 37 38 All it takes to have parse YAML patches is to have an import line: 39 40 from some_parser_code import NewYamlGenerator 41 42 To this module. Then add an instance of the parser with: 43 44 new_parser = NewYamlGenerator() 45 46 and add a logic inside parse() to handle it based on the path, 47 like this: 48 49 if "/foo" in fname: 50 msg = self.new_parser.parse_yaml_file(fname) 51 """ 52 53 supported = ('yaml', ) 54 55 netlink_parser = YnlDocGenerator() 56 57 re_lineno = re.compile(r"\.\. LINENO ([0-9]+)$") 58 59 def rst_parse(self, inputstring, document, msg): 60 """ 61 Receives a ReST content that was previously converted by the 62 YAML parser, adding it to the document tree. 63 """ 64 65 self.setup_parse(inputstring, document) 66 67 result = ViewList() 68 69 try: 70 # Parse message with RSTParser 71 lineoffset = 0; 72 for line in msg.split('\n'): 73 match = self.re_lineno.match(line) 74 if match: 75 lineoffset = int(match.group(1)) 76 continue 77 78 result.append(line, document.current_source, lineoffset) 79 80 # Fix backward compatibility with docutils < 0.17.1 81 if "tab_width" not in vars(document.settings): 82 document.settings.tab_width = 8 83 84 rst_parser = RSTParser() 85 rst_parser.parse('\n'.join(result), document) 86 87 except Exception as e: 88 document.reporter.error("YAML parsing error: %s" % pformat(e)) 89 90 self.finish_parse() 91 92 # Overrides docutils.parsers.Parser. See sphinx.parsers.RSTParser 93 def parse(self, inputstring, document): 94 """Check if a YAML is meant to be parsed.""" 95 96 fname = document.current_source 97 98 # Handle netlink yaml specs 99 if "/netlink/specs/" in fname: 100 msg = self.netlink_parser.parse_yaml_file(fname) 101 self.rst_parse(inputstring, document, msg) 102 103 # All other yaml files are ignored 104 105def setup(app): 106 """Setup function for the Sphinx extension.""" 107 108 # Add YAML parser 109 app.add_source_parser(YamlParser) 110 app.add_source_suffix('.yaml', 'yaml') 111 112 return { 113 'version': '1.0', 114 'parallel_read_safe': True, 115 'parallel_write_safe': True, 116 } 117