Skip to content

Commit 9ca876f

Browse files
mchehabgregkh
authored andcommitted
docs: kernel_abi.py: add a script to parse ABI documentation
The ABI documentation is special: it is not plain text files, but, instead, files with an strict format, as specified by Documentation/ABI/README. Add a parser for it. Acked-by: Jonathan Corbet <corbet@lwn.net> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> Link: https://lore.kernel.org/r/48abf1a410237e63f85354a8cd7027fdf25657bf.1604042072.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 678a63f commit 9ca876f

1 file changed

Lines changed: 157 additions & 0 deletions

File tree

Documentation/sphinx/kernel_abi.py

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# -*- coding: utf-8; mode: python -*-
2+
# SPDX-License-Identifier: GPL-2.0
3+
u"""
4+
kernel-abi
5+
~~~~~~~~~~
6+
7+
Implementation of the ``kernel-abi`` reST-directive.
8+
9+
:copyright: Copyright (C) 2016 Markus Heiser
10+
:copyright: Copyright (C) 2016-2020 Mauro Carvalho Chehab
11+
:maintained-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
12+
:license: GPL Version 2, June 1991 see Linux/COPYING for details.
13+
14+
The ``kernel-abi`` (:py:class:`KernelCmd`) directive calls the
15+
scripts/get_abi.pl script to parse the Kernel ABI files.
16+
17+
Overview of directive's argument and options.
18+
19+
.. code-block:: rst
20+
21+
.. kernel-abi:: <ABI directory location>
22+
:debug:
23+
24+
The argument ``<ABI directory location>`` is required. It contains the
25+
location of the ABI files to be parsed.
26+
27+
``debug``
28+
Inserts a code-block with the *raw* reST. Sometimes it is helpful to see
29+
what reST is generated.
30+
31+
"""
32+
33+
import sys
34+
import os
35+
from os import path
36+
import subprocess
37+
38+
from sphinx.ext.autodoc import AutodocReporter
39+
40+
from docutils import nodes
41+
from docutils.parsers.rst import Directive, directives
42+
from docutils.statemachine import ViewList
43+
from docutils.utils.error_reporting import ErrorString
44+
45+
46+
__version__ = '1.0'
47+
48+
# We can't assume that six is installed
49+
PY3 = sys.version_info[0] == 3
50+
PY2 = sys.version_info[0] == 2
51+
if PY3:
52+
# pylint: disable=C0103, W0622
53+
unicode = str
54+
basestring = str
55+
56+
def setup(app):
57+
58+
app.add_directive("kernel-abi", KernelCmd)
59+
return dict(
60+
version = __version__
61+
, parallel_read_safe = True
62+
, parallel_write_safe = True
63+
)
64+
65+
class KernelCmd(Directive):
66+
67+
u"""KernelABI (``kernel-abi``) directive"""
68+
69+
required_arguments = 1
70+
optional_arguments = 0
71+
has_content = False
72+
final_argument_whitespace = True
73+
74+
option_spec = {
75+
"debug" : directives.flag
76+
}
77+
78+
def warn(self, message, **replace):
79+
replace["fname"] = self.state.document.current_source
80+
replace["line_no"] = replace.get("line_no", self.lineno)
81+
message = ("%(fname)s:%(line_no)s: [kernel-abi WARN] : " + message) % replace
82+
self.state.document.settings.env.app.warn(message, prefix="")
83+
84+
def run(self):
85+
86+
doc = self.state.document
87+
if not doc.settings.file_insertion_enabled:
88+
raise self.warning("docutils: file insertion disabled")
89+
90+
env = doc.settings.env
91+
cwd = path.dirname(doc.current_source)
92+
cmd = "get_abi.pl rest --dir "
93+
cmd += self.arguments[0]
94+
95+
srctree = path.abspath(os.environ["srctree"])
96+
97+
fname = cmd
98+
99+
# extend PATH with $(srctree)/scripts
100+
path_env = os.pathsep.join([
101+
srctree + os.sep + "scripts",
102+
os.environ["PATH"]
103+
])
104+
shell_env = os.environ.copy()
105+
shell_env["PATH"] = path_env
106+
shell_env["srctree"] = srctree
107+
108+
lines = self.runCmd(cmd, shell=True, cwd=cwd, env=shell_env)
109+
nodeList = self.nestedParse(lines, fname)
110+
return nodeList
111+
112+
def runCmd(self, cmd, **kwargs):
113+
u"""Run command ``cmd`` and return it's stdout as unicode."""
114+
115+
try:
116+
proc = subprocess.Popen(
117+
cmd
118+
, stdout = subprocess.PIPE
119+
, stderr = subprocess.PIPE
120+
, universal_newlines = True
121+
, **kwargs
122+
)
123+
out, err = proc.communicate()
124+
if err:
125+
self.warn(err)
126+
if proc.returncode != 0:
127+
raise self.severe(
128+
u"command '%s' failed with return code %d"
129+
% (cmd, proc.returncode)
130+
)
131+
except OSError as exc:
132+
raise self.severe(u"problems with '%s' directive: %s."
133+
% (self.name, ErrorString(exc)))
134+
return unicode(out)
135+
136+
def nestedParse(self, lines, fname):
137+
content = ViewList()
138+
node = nodes.section()
139+
140+
if "debug" in self.options:
141+
code_block = "\n\n.. code-block:: rst\n :linenos:\n"
142+
for l in lines.split("\n"):
143+
code_block += "\n " + l
144+
lines = code_block + "\n\n"
145+
146+
for c, l in enumerate(lines.split("\n")):
147+
content.append(l, fname, c)
148+
149+
buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
150+
self.state.memo.title_styles = []
151+
self.state.memo.section_level = 0
152+
self.state.memo.reporter = AutodocReporter(content, self.state.memo.reporter)
153+
try:
154+
self.state.nested_parse(content, 0, node, match_titles=1)
155+
finally:
156+
self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = buf
157+
return node.children

0 commit comments

Comments
 (0)