Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

docs: sphinx: kerneldoc: Use python class if available

Better integrate with the new kernel-doc tool by calling the
Python classes directly if KERNELDOC=scripts/kernel-doc.py.

This way, warnings won't be duplicated anymore, as files
will be parsed only once.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Link: https://lore.kernel.org/r/1556a6c005d8e0fafa951f74725e984e1c7459bf.1744685912.git.mchehab+huawei@kernel.org

authored by

Mauro Carvalho Chehab and committed by
Jonathan Corbet
9d9bec3d 47c2d416

+130 -8
+130 -8
Documentation/sphinx/kerneldoc.py
··· 41 41 from sphinx.util.docutils import switch_source_input 42 42 from sphinx.util import logging 43 43 44 + srctree = os.path.abspath(os.environ["srctree"]) 45 + sys.path.insert(0, os.path.join(srctree, "scripts/lib/kdoc")) 46 + 47 + from kdoc_files import KernelFiles 48 + from kdoc_output import RestFormat 49 + 44 50 __version__ = '1.0' 51 + use_kfiles = False 45 52 46 53 def cmd_str(cmd): 47 54 """ ··· 89 82 logger = logging.getLogger('kerneldoc') 90 83 verbose = 0 91 84 92 - def run(self): 85 + parse_args = {} 86 + msg_args = {} 87 + 88 + def handle_args(self): 89 + 93 90 env = self.state.document.settings.env 94 91 cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno'] 95 92 96 93 filename = env.config.kerneldoc_srctree + '/' + self.arguments[0] 94 + 95 + # Arguments used by KernelFiles.parse() function 96 + self.parse_args = { 97 + "file_list": [filename], 98 + "export_file": [] 99 + } 100 + 101 + # Arguments used by KernelFiles.msg() function 102 + self.msg_args = { 103 + "enable_lineno": True, 104 + "export": False, 105 + "internal": False, 106 + "symbol": [], 107 + "nosymbol": [], 108 + "no_doc_sections": False 109 + } 110 + 97 111 export_file_patterns = [] 98 112 99 113 verbose = os.environ.get("V") ··· 127 99 # Tell sphinx of the dependency 128 100 env.note_dependency(os.path.abspath(filename)) 129 101 130 - tab_width = self.options.get('tab-width', self.state.document.settings.tab_width) 102 + self.tab_width = self.options.get('tab-width', 103 + self.state.document.settings.tab_width) 131 104 132 105 # 'function' is an alias of 'identifiers' 133 106 if 'functions' in self.options: ··· 137 108 # FIXME: make this nicer and more robust against errors 138 109 if 'export' in self.options: 139 110 cmd += ['-export'] 111 + self.msg_args["export"] = True 140 112 export_file_patterns = str(self.options.get('export')).split() 141 113 elif 'internal' in self.options: 142 114 cmd += ['-internal'] 115 + self.msg_args["internal"] = True 143 116 export_file_patterns = str(self.options.get('internal')).split() 144 117 elif 'doc' in self.options: 145 - cmd += ['-function', str(self.options.get('doc'))] 118 + func = str(self.options.get('doc')) 119 + cmd += ['-function', func] 120 + self.msg_args["symbol"].append(func) 146 121 elif 'identifiers' in self.options: 147 122 identifiers = self.options.get('identifiers').split() 148 123 if identifiers: ··· 156 123 continue 157 124 158 125 cmd += ['-function', i] 126 + self.msg_args["symbol"].append(i) 159 127 else: 160 128 cmd += ['-no-doc-sections'] 129 + self.msg_args["no_doc_sections"] = True 161 130 162 131 if 'no-identifiers' in self.options: 163 132 no_identifiers = self.options.get('no-identifiers').split() ··· 170 135 continue 171 136 172 137 cmd += ['-nosymbol', i] 138 + self.msg_args["nosymbol"].append(i) 173 139 174 140 for pattern in export_file_patterns: 175 141 pattern = pattern.rstrip("\\").strip() ··· 180 144 for f in glob.glob(env.config.kerneldoc_srctree + '/' + pattern): 181 145 env.note_dependency(os.path.abspath(f)) 182 146 cmd += ['-export-file', f] 147 + self.parse_args["export_file"].append(f) 148 + 149 + # Export file is needed by both parse and msg, as kernel-doc 150 + # cache exports. 151 + self.msg_args["export_file"] = self.parse_args["export_file"] 183 152 184 153 cmd += [filename] 185 154 155 + return cmd 156 + 157 + def run_cmd(self): 158 + """ 159 + Execute an external kernel-doc command. 160 + """ 161 + 162 + env = self.state.document.settings.env 163 + cmd = self.handle_args() 164 + 186 165 if self.verbose >= 1: 187 166 print(cmd_str(cmd)) 167 + 168 + node = nodes.section() 188 169 189 170 try: 190 171 self.logger.verbose("calling kernel-doc '%s'" % (" ".join(cmd))) ··· 220 167 elif env.config.kerneldoc_verbosity > 0: 221 168 sys.stderr.write(err) 222 169 223 - lines = statemachine.string2lines(out, tab_width, convert_whitespace=True) 170 + except Exception as e: # pylint: disable=W0703 171 + self.logger.warning("kernel-doc '%s' processing failed with: %s" % 172 + (" ".join(cmd), str(e))) 173 + return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))] 174 + 175 + filenames = self.parse_args["file_list"] 176 + for filename in filenames: 177 + ret = self.parse_msg(filename, node, out, cmd) 178 + if ret: 179 + return ret 180 + 181 + return node.children 182 + 183 + def parse_msg(self, filename, node, out, cmd): 184 + """ 185 + Handles a kernel-doc output for a given file 186 + """ 187 + 188 + env = self.state.document.settings.env 189 + 190 + try: 191 + lines = statemachine.string2lines(out, self.tab_width, 192 + convert_whitespace=True) 224 193 result = ViewList() 225 194 226 195 lineoffset = 0; ··· 258 183 result.append(line, doc + ": " + filename, lineoffset) 259 184 lineoffset += 1 260 185 261 - node = nodes.section() 262 186 self.do_parse(result, node) 263 - 264 - return node.children 265 187 266 188 except Exception as e: # pylint: disable=W0703 267 189 self.logger.warning("kernel-doc '%s' processing failed with: %s" % 268 - (" ".join(cmd), str(e))) 190 + (cmd_str(cmd), str(e))) 269 191 return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))] 192 + 193 + return None 194 + 195 + def run_kdoc(self, kfiles): 196 + """ 197 + Execute kernel-doc classes directly instead of running as a separate 198 + command. 199 + """ 200 + 201 + cmd = self.handle_args() 202 + env = self.state.document.settings.env 203 + 204 + node = nodes.section() 205 + 206 + kfiles.parse(**self.parse_args) 207 + filenames = self.parse_args["file_list"] 208 + 209 + for filename, out in kfiles.msg(**self.msg_args, filenames=filenames): 210 + if self.verbose >= 1: 211 + print(cmd_str(cmd)) 212 + 213 + ret = self.parse_msg(filename, node, out, cmd) 214 + if ret: 215 + return ret 216 + 217 + return node.children 218 + 219 + def run(self): 220 + global use_kfiles 221 + 222 + if use_kfiles: 223 + out_style = RestFormat() 224 + kfiles = KernelFiles(out_style=out_style, logger=self.logger) 225 + return self.run_kdoc(kfiles) 226 + else: 227 + return self.run_cmd() 270 228 271 229 def do_parse(self, result, node): 272 230 with switch_source_input(self.state, result): 273 231 self.state.nested_parse(result, 0, node, match_titles=1) 232 + 233 + def setup_kfiles(app): 234 + global use_kfiles 235 + 236 + kerneldoc_bin = app.env.config.kerneldoc_bin 237 + 238 + if kerneldoc_bin and kerneldoc_bin.endswith("kernel-doc.py"): 239 + print("Using Python kernel-doc") 240 + use_kfiles = True 241 + else: 242 + print(f"Using {kerneldoc_bin}") 243 + 274 244 275 245 def setup(app): 276 246 app.add_config_value('kerneldoc_bin', None, 'env') ··· 323 203 app.add_config_value('kerneldoc_verbosity', 1, 'env') 324 204 325 205 app.add_directive('kernel-doc', KernelDocDirective) 206 + 207 + app.connect('builder-inited', setup_kfiles) 326 208 327 209 return dict( 328 210 version = __version__,