History

docs: add a new file to write kernel-doc output to a YAML file

Storing kernel-doc output is helpful to allow debugging problems on it and to preparate unit tests. Add a class to store such contents at the same format as defined at kdoc-test-schema.yaml.

Mauro Carvalho Chehab committed 8 months ago

Commit b37b3cb1 parent eea0d801 file · +155 −0Browse files

Showing the changes to tools/lib/python (1 of 1 file). Show all

Unified · Split

tools/lib/python/kdoc/kdoc_yaml_file.py+155−0
@@ -0,0 +1,155 @@
1+#!/usr/bin/env python3
2+# SPDX-License-Identifier: GPL-2.0
3+# Copyright(c) 2026: Mauro Carvalho Chehab <mchehab@kernel.org>.
4+
5+import os
6+
7+from kdoc.kdoc_output import ManFormat, RestFormat
8+
9+
10+class KDocTestFile():
11+ """
12+ Handles the logic needed to store kernel‑doc output inside a YAML file.
13+ Useful for unit tests and regression tests.
14+ """
15+
16+ def __init__(self, config, yaml_file, yaml_content):
17+ #
18+ # Bail out early if yaml is not available
19+ #
20+ try:
21+ import yaml
22+ except ImportError:
23+ sys.exit("Warning: yaml package not available. Aborting it.")
24+
25+ self.config = config
26+ self.test_file = os.path.expanduser(yaml_file)
27+ self.yaml_content = yaml_content
28+
29+ self.tests = []
30+
31+ out_dir = os.path.dirname(self.test_file)
32+ if out_dir and not os.path.isdir(out_dir):
33+ sys.exit(f"Directory {out_dir} doesn't exist.")
34+
35+ self.out_style = []
36+
37+ if "man" in self.yaml_content:
38+ out_style = ManFormat()
39+ out_style.set_config(self.config)
40+
41+ self.out_style.append(out_style)
42+
43+ if "rst" in self.yaml_content:
44+ out_style = RestFormat()
45+ out_style.set_config(self.config)
46+
47+ self.out_style.append(out_style)
48+
49+ def set_filter(self, export, internal, symbol, nosymbol,
50+ function_table, enable_lineno, no_doc_sections):
51+ """
52+ Set filters at the output classes.
53+ """
54+ for out_style in self.out_style:
55+ out_style.set_filter(export, internal, symbol,
56+ nosymbol, function_table,
57+ enable_lineno, no_doc_sections)
58+
59+ @staticmethod
60+ def get_kdoc_item(arg, start_line=1):
61+
62+ d = vars(arg)
63+
64+ declaration_start_line = d.get("declaration_start_line")
65+ if not declaration_start_line:
66+ return d
67+
68+ d["declaration_start_line"] = start_line
69+
70+ parameterdesc_start_lines = d.get("parameterdesc_start_lines")
71+ if parameterdesc_start_lines:
72+ for key in parameterdesc_start_lines:
73+ ln = parameterdesc_start_lines[key]
74+ ln += start_line - declaration_start_line
75+
76+ parameterdesc_start_lines[key] = ln
77+
78+ sections_start_lines = d.get("sections_start_lines")
79+ if sections_start_lines:
80+ for key in sections_start_lines:
81+ ln = sections_start_lines[key]
82+ ln += start_line - declaration_start_line
83+
84+ sections_start_lines[key] = ln
85+
86+ return d
87+
88+ def output_symbols(self, fname, symbols, source):
89+ """
90+ Store source, symbols and output strings at self.tests.
91+ """
92+
93+ #
94+ # KdocItem needs to be converted into dicts
95+ #
96+ kdoc_item = []
97+ expected = []
98+
99+ if not symbols and not source:
100+ return
101+
102+ if not source or len(symbols) != len(source):
103+ print(f"Warning: lengths are different. Ignoring {fname}")
104+
105+ # Folding without line numbers is too hard.
106+ # The right thing to do here to proceed would be to delete
107+ # not-handled source blocks, as len(source) should be bigger
108+ # than len(symbols)
109+ return
110+
111+ base_name = "test_" + fname.replace(".", "_").replace("/", "_")
112+ expected_dict = {}
113+ start_line=1
114+
115+ for i in range(0, len(symbols)):
116+ arg = symbols[i]
117+
118+ if "KdocItem" in self.yaml_content:
119+ msg = self.get_kdoc_item(arg)
120+
121+ expected_dict["kdoc_item"] = msg
122+
123+ for out_style in self.out_style:
124+ if isinstance(out_style, ManFormat):
125+ key = "man"
126+ else:
127+ key = "rst"
128+
129+ expected_dict[key]= out_style.output_symbols(fname, [arg])
130+
131+ name = f"{base_name}_{i:03d}"
132+
133+ test = {
134+ "name": name,
135+ "description": f"{fname} line {source[i]["ln"]}",
136+ "fname": fname,
137+ "source": source[i]["data"],
138+ "expected": [expected_dict]
139+ }
140+
141+ self.tests.append(test)
142+
143+ expected_dict = {}
144+
145+ def write(self):
146+ """
147+ Output the content of self.tests to self.test_file.
148+ """
149+ import yaml
150+
151+ data = {"tests": self.tests}
152+
153+ with open(self.test_file, "w", encoding="utf-8") as fp:
154+ yaml.safe_dump(data, fp, sort_keys=False, default_style="|",
155+ default_flow_style=False, allow_unicode=True)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t