History

docs: sphinx/kernel_abi: reduce buffer usage for ABI messages

Instead of producing a big message with all ABI contents and then parse as a whole, simplify the code by handling each ABI symbol in separate. As an additional benefit, there's no need to place file/line nubers inlined at the data and use a regex to convert them.

Mauro Carvalho Chehab committed 1 year ago

Commit aea5e521 parent ee34f833 files · +51 −48Browse files

Unified · Split

3 files
  1. Documentation/sphinx/kernel_abi.py +42 −40
  2. scripts/get_abi.py +5 −2
  3. scripts/lib/abi/abi_parser.py +4 −6
Documentation/sphinx/kernel_abi.py+42−40
@@ -68,6 +68,7 @@ class KernelCmd(Directive): · 67 unmodified lines
6868 has_content = False
6969 final_argument_whitespace = True
7070 logger = logging.getLogger('kernel_abi')
71+ parser = None
7172
7273 option_spec = {
7374 "debug": directives.flag,
@@ -79,59 +80,60 @@ class KernelCmd(Directive): · 5 unmodified lines
7980 raise self.warning("docutils: file insertion disabled")
8081
8182 path = os.path.join(srctree, "Documentation", self.arguments[0])
82− parser = AbiParser(path, logger=self.logger)
83− parser.parse_abi()
84− parser.check_issues()
83+ self.parser = AbiParser(path, logger=self.logger)
84+ self.parser.parse_abi()
85+ self.parser.check_issues()
8586
86− msg = ""
87− for m in parser.doc(enable_lineno=True, show_file=True):
88− msg += m
89−
90− node = self.nested_parse(msg, self.arguments[0])
87+ node = self.nested_parse(None, self.arguments[0])
9188 return node
9289
93− def nested_parse(self, lines, fname):
90+ def nested_parse(self, data, fname):
9491 env = self.state.document.settings.env
9592 content = ViewList()
9693 node = nodes.section()
9794
98− if "debug" in self.options:
99− code_block = "\n\n.. code-block:: rst\n :linenos:\n"
100− for line in lines.split("\n"):
101− code_block += "\n " + line
102− lines = code_block + "\n\n"
103−
104− line_regex = re.compile(r"^\.\. LINENO (\S+)\#([0-9]+)$")
105− ln = 0
106− n = 0
107− f = fname
108−
109− for line in lines.split("\n"):
110− n = n + 1
111− match = line_regex.search(line)
112− if match:
113− new_f = match.group(1)
114−
115− # Sphinx parser is lazy: it stops parsing contents in the
116− # middle, if it is too big. So, handle it per input file
117− if new_f != f and content:
118− self.do_parse(content, node)
119− content = ViewList()
95+ if data is not None:
96+ # Handles the .rst file
97+ for line in data.split("\n"):
98+ content.append(line, fname, 0)
99+
100+ self.do_parse(content, node)
120101
102+ else:
103+ # Handles the ABI parser content, symbol by symbol
104+
105+ old_f = fname
106+ n = 0
107+ for msg, f, ln in self.parser.doc():
108+ msg_list = msg.split("\n")
109+ if "debug" in self.options:
110+ lines = [
111+ "", "", ".. code-block:: rst",
112+ " :linenos:", ""
113+ ]
114+ for m in msg_list:
115+ lines.append(" " + m)
116+ else:
117+ lines = msg_list
118+
119+ for line in lines:
120+ # sphinx counts lines from 0
121+ content.append(line, f, ln - 1)
122+ n += 1
123+
124+ if f != old_f:
121125 # Add the file to Sphinx build dependencies
122126 env.note_dependency(os.path.abspath(f))
123127
124− f = new_f
128+ old_f = f
125129
126− # sphinx counts lines from 0
127− ln = int(match.group(2)) - 1
128− else:
129− content.append(line, f, ln)
130−
131− self.logger.info("%s: parsed %i lines" % (fname, n))
130+ # Sphinx doesn't like to parse big messages. So, let's
131+ # add content symbol by symbol
132+ if content:
133+ self.do_parse(content, node)
134+ content = ViewList()
132135
133− if content:
134− self.do_parse(content, node)
136+ self.logger.info("%s: parsed %i lines" % (fname, n))
135137
136138 return node.children
137139
scripts/get_abi.py+5−2
@@ -63,8 +63,11 @@ class AbiRest: · 62 unmodified lines
6363 parser.parse_abi()
6464 parser.check_issues()
6565
66− for msg in parser.doc(args.enable_lineno, args.raw, not args.no_file):
67− print(msg)
66+ for t in parser.doc(args.raw, not args.no_file):
67+ if args.enable_lineno:
68+ print (f".. LINENO {t[1]}#{t[2]}\n\n")
69+
70+ print(t[0])
6871
6972 class AbiValidate:
7073 """Initialize an argparse subparser for ABI validation"""
scripts/lib/abi/abi_parser.py+4−6
@@ -427,7 +427,7 @@ class AbiParser: · 426 unmodified lines
427427
428428 return new_desc + "\n\n"
429429
430− def doc(self, enable_lineno, output_in_txt=False, show_file=False):
430+ def doc(self, output_in_txt=False, show_file=True):
431431 """Print ABI at stdout"""
432432
433433 part = None
@@ -444,10 +444,6 @@ class AbiParser: · 10 unmodified lines
444444
445445 msg = ""
446446
447− if enable_lineno:
448− ln = v.get("line_no", 1)
449− msg += f".. LINENO {file_ref[0][0]}#{ln}\n\n"
450−
451447 if wtype != "File":
452448 cur_part = names[0]
453449 if cur_part.find("/") >= 0:
@@ -508,7 +504,9 @@ class AbiParser: · 54 unmodified lines
508504 if users and users.strip(" \t\n"):
509505 msg += f"Users:\n\t{users.strip("\n").replace('\n', '\n\t')}\n\n"
510506
511− yield msg
507+ ln = v.get("line_no", 1)
508+
509+ yield (msg, file_ref[0][0], ln)
512510
513511 def check_issues(self):
514512 """Warn about duplicated ABI entries"""