Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/lib/python/kdoc/kdoc_yaml_file.py
170954 views
1
#!/usr/bin/env python3
2
# SPDX-License-Identifier: GPL-2.0
3
# Copyright(c) 2026: Mauro Carvalho Chehab <[email protected]>.
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
self.test_names = set()
29
30
self.tests = []
31
32
out_dir = os.path.dirname(self.test_file)
33
if out_dir and not os.path.isdir(out_dir):
34
sys.exit(f"Directory {out_dir} doesn't exist.")
35
36
self.out_style = []
37
38
if "man" in self.yaml_content:
39
out_style = ManFormat()
40
out_style.set_config(self.config)
41
42
self.out_style.append(out_style)
43
44
if "rst" in self.yaml_content:
45
out_style = RestFormat()
46
out_style.set_config(self.config)
47
48
self.out_style.append(out_style)
49
50
def set_filter(self, export, internal, symbol, nosymbol,
51
function_table, enable_lineno, no_doc_sections):
52
"""
53
Set filters at the output classes.
54
"""
55
for out_style in self.out_style:
56
out_style.set_filter(export, internal, symbol,
57
nosymbol, function_table,
58
enable_lineno, no_doc_sections)
59
60
@staticmethod
61
def get_kdoc_item(arg, start_line=1):
62
63
d = vars(arg)
64
65
declaration_start_line = d.get("declaration_start_line")
66
if not declaration_start_line:
67
return d
68
69
d["declaration_start_line"] = start_line
70
71
parameterdesc_start_lines = d.get("parameterdesc_start_lines")
72
if parameterdesc_start_lines:
73
for key in parameterdesc_start_lines:
74
ln = parameterdesc_start_lines[key]
75
ln += start_line - declaration_start_line
76
77
parameterdesc_start_lines[key] = ln
78
79
sections_start_lines = d.get("sections_start_lines")
80
if sections_start_lines:
81
for key in sections_start_lines:
82
ln = sections_start_lines[key]
83
ln += start_line - declaration_start_line
84
85
sections_start_lines[key] = ln
86
87
return d
88
89
def output_symbols(self, fname, symbols):
90
"""
91
Store source, symbols and output strings at self.tests.
92
"""
93
94
#
95
# KdocItem needs to be converted into dicts
96
#
97
kdoc_item = []
98
expected = []
99
100
#
101
# Source code didn't produce any symbol
102
#
103
if not symbols:
104
return
105
106
expected_dict = {}
107
start_line=1
108
109
for arg in symbols:
110
source = arg.get("source", "")
111
112
if arg and "KdocItem" in self.yaml_content:
113
msg = self.get_kdoc_item(arg)
114
115
other_stuff = msg.get("other_stuff", {})
116
if "source" in other_stuff:
117
del other_stuff["source"]
118
119
expected_dict["kdoc_item"] = msg
120
121
base_name = arg.name
122
if not base_name:
123
base_name = fname
124
base_name = base_name.lower().replace(".", "_").replace("/", "_")
125
126
127
# Don't add duplicated names
128
i = 0
129
name = base_name
130
while name in self.test_names:
131
i += 1
132
name = f"{base_name}_{i:03d}"
133
134
self.test_names.add(name)
135
136
for out_style in self.out_style:
137
if isinstance(out_style, ManFormat):
138
key = "man"
139
else:
140
key = "rst"
141
142
expected_dict[key]= out_style.output_symbols(fname, [arg]).strip()
143
144
test = {
145
"name": name,
146
"description": f"{fname} line {arg.declaration_start_line}",
147
"fname": fname,
148
"source": source,
149
"expected": [expected_dict]
150
}
151
152
self.tests.append(test)
153
154
expected_dict = {}
155
156
def write(self):
157
"""
158
Output the content of self.tests to self.test_file.
159
"""
160
import yaml
161
162
# Helper function to better handle multilines
163
def str_presenter(dumper, data):
164
if "\n" in data:
165
return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="|")
166
167
return dumper.represent_scalar("tag:yaml.org,2002:str", data)
168
169
# Register the representer
170
yaml.add_representer(str, str_presenter)
171
172
data = {"tests": self.tests}
173
174
with open(self.test_file, "w", encoding="utf-8") as fp:
175
yaml.dump(data, fp,
176
sort_keys=False, width=120, indent=2,
177
default_flow_style=False, allow_unicode=True,
178
explicit_start=False, explicit_end=False)
179
180