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