public inbox for lkmm@lists.linux.dev
 help / color / mirror / Atom feed
From: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
To: Donald Hunter <donald.hunter@gmail.com>
Cc: Linux Doc Mailing List <linux-doc@vger.kernel.org>,
	Jonathan Corbet <corbet@lwn.net>,
	"Akira Yokosawa" <akiyks@gmail.com>,
	"Breno Leitao" <leitao@debian.org>,
	"David S. Miller" <davem@davemloft.net>,
	"Eric Dumazet" <edumazet@google.com>,
	"Ignacio Encinas Rubio" <ignacio@iencinas.com>,
	"Jan Stancek" <jstancek@redhat.com>,
	"Marco Elver" <elver@google.com>,
	"Paolo Abeni" <pabeni@redhat.com>,
	"Ruben Wauters" <rubenru09@aol.com>,
	"Shuah Khan" <skhan@linuxfoundation.org>,
	joel@joelfernandes.org, linux-kernel-mentees@lists.linux.dev,
	linux-kernel@vger.kernel.org, lkmm@lists.linux.dev,
	netdev@vger.kernel.org, peterz@infradead.org,
	stern@rowland.harvard.edu
Subject: Re: [PATCH v5 10/15] docs: sphinx: add a parser for yaml files for Netlink specs
Date: Tue, 17 Jun 2025 18:00:01 +0200	[thread overview]
Message-ID: <20250617180001.46931ba9@sal.lan> (raw)
In-Reply-To: <20250617154049.104ef6ff@sal.lan>

Em Tue, 17 Jun 2025 15:40:49 +0200
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> escreveu:

> > > +            # Parse message with RSTParser
> > > +            for i, line in enumerate(msg.split('\n')):
> > > +                result.append(line, document.current_source, i)    
> > 
> > This has the effect of associating line numbers from the generated ReST
> > with the source .yaml file, right? So errors will be reported against
> > the wrong place in the file. Is there any way to show the cause of the
> > error in the intermediate ReST?  
> 
> Yes, but this will require modifying the parser. I prefer merging this
> series without such change, and then having a separate changeset
> addressing it.
> 
> There are two ways we can do that:
> 
> 1. The parser can add a ReST comment with the line number. This
>    is what it is done by kerneldoc.py Sphinx extension:
> 
> 	lineoffset = 0
> 	line_regex = re.compile(r"^\.\. LINENO ([0-9]+)$")
>         for line in lines:
>             match = line_regex.search(line)
>             if match:
>                 lineoffset = int(match.group(1)) - 1 # sphinx counts lines from 0
>             else:
>                 doc = str(env.srcdir) + "/" + env.docname + ":" + str(self.lineno)
>                 result.append(line, doc + ": " + filename, lineoffset)
>                 lineoffset += 1
> 
>    I kept the same way after its conversion to Python, as right now,
>    it supports both a Python class and a command lin command. I may
>    eventually clean it up in the future.
> 
> 2. making the parser return a tuple. At kernel_abi.py, as the parser
>    returns content from multiple files, such tuple is:
> 
> 		 (rst_output, filename, line_number)
> 
>    and the code for it is (cleaned up):
> 
> 	for msg, f, ln in kernel_abi.doc(show_file=show_file,
>                                          show_symbols=show_symbols,
>                                          filter_path=abi_type):
> 
>             lines = statemachine.string2lines(msg, tab_width,
>                                               convert_whitespace=True)
> 
>             for line in lines:
>                 content.append(line, f, ln - 1) # sphinx counts lines from 0
> 
> (2) is cleaner and faster, but (1) is easier to implement on an 
> already-existing code.

The logic below implements (1). This seems to be the easiest way for
pyyaml. I will submit as 2 separate patches at the end of the next
version.

Please notice that I didn't check yet for the "quality" of the
line numbers. Some tweaks could be needed later on.

Regards,
Mauro

---

From 750daebebadcd156b5fe9b516f4fae4bd42b9d2c Mon Sep 17 00:00:00 2001
From: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Date: Tue, 17 Jun 2025 17:54:03 +0200
Subject: [PATCH] docs: parser_yaml.py: add support for line numbers from the
 parser

Instead of printing line numbers from the temp converted ReST
file, get them from the original source.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

diff --git a/Documentation/sphinx/parser_yaml.py b/Documentation/sphinx/parser_yaml.py
index 635945e1c5ba..15c642fc0bd5 100755
--- a/Documentation/sphinx/parser_yaml.py
+++ b/Documentation/sphinx/parser_yaml.py
@@ -29,6 +29,8 @@ class YamlParser(Parser):
 
     netlink_parser = YnlDocGenerator()
 
+    re_lineno = re.compile(r"\.\. LINENO ([0-9]+)$")
+
     def do_parse(self, inputstring, document, msg):
         """Parse YAML and generate a document tree."""
 
@@ -38,8 +40,14 @@ class YamlParser(Parser):
 
         try:
             # Parse message with RSTParser
-            for i, line in enumerate(msg.split('\n')):
-                result.append(line, document.current_source, i)
+            lineoffset = 0;
+            for line in msg.split('\n'):
+                match = self.re_lineno.match(line)
+                if match:
+                    lineoffset = int(match.group(1))
+                    continue
+
+                result.append(line, document.current_source, lineoffset)
 
             rst_parser = RSTParser()
             rst_parser.parse('\n'.join(result), document)

From 15c1f9db30f3abdce110e19788d87f9fe1417781 Mon Sep 17 00:00:00 2001
From: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Date: Tue, 17 Jun 2025 17:28:04 +0200
Subject: [PATCH] tools: netlink_yml_parser.py: add line numbers to parsed data

When something goes wrong, we want Sphinx error to point to the
right line number from the original source, not from the
processed ReST data.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

diff --git a/tools/net/ynl/pyynl/netlink_yml_parser.py b/tools/net/ynl/pyynl/netlink_yml_parser.py
index 866551726723..a9d8ab6f2639 100755
--- a/tools/net/ynl/pyynl/netlink_yml_parser.py
+++ b/tools/net/ynl/pyynl/netlink_yml_parser.py
@@ -20,6 +20,16 @@
 from typing import Any, Dict, List
 import yaml
 
+LINE_STR = '__lineno__'
+
+class NumberedSafeLoader(yaml.SafeLoader):
+    """Override the SafeLoader class to add line number to parsed data"""
+
+    def construct_mapping(self, node):
+        mapping = super().construct_mapping(node)
+        mapping[LINE_STR] = node.start_mark.line
+
+        return mapping
 
 class RstFormatters:
     """RST Formatters"""
@@ -127,6 +137,11 @@ class RstFormatters:
         """Return a formatted label"""
         return f".. _{title}:\n\n"
 
+    @staticmethod
+    def rst_lineno(lineno: int) -> str:
+        """Return a lineno comment"""
+        return f".. LINENO {lineno}\n"
+
 class YnlDocGenerator:
     """YAML Netlink specs Parser"""
 
@@ -144,6 +159,9 @@ class YnlDocGenerator:
         """Parse 'do' section and return a formatted string"""
         lines = []
         for key in do_dict.keys():
+            if key == LINE_STR:
+                lines.append(self.fmt.rst_lineno(do_dict[key]))
+                continue
             lines.append(self.fmt.rst_paragraph(self.fmt.bold(key), level + 1))
             if key in ['request', 'reply']:
                 lines.append(self.parse_do_attributes(do_dict[key], level + 1) + "\n")
@@ -174,6 +192,10 @@ class YnlDocGenerator:
             lines.append(self.fmt.rst_paragraph(operation["doc"]) + "\n")
 
             for key in operation.keys():
+                if key == LINE_STR:
+                    lines.append(self.fmt.rst_lineno(operation[key]))
+                    continue
+
                 if key in preprocessed:
                     # Skip the special fields
                     continue
@@ -233,6 +255,9 @@ class YnlDocGenerator:
         for definition in defs:
             lines.append(self.fmt.rst_section(namespace, 'definition', definition["name"]))
             for k in definition.keys():
+                if k == LINE_STR:
+                    lines.append(self.fmt.rst_lineno(definition[k]))
+                    continue
                 if k in preprocessed + ignored:
                     continue
                 lines.append(self.fmt.rst_fields(k, self.fmt.sanitize(definition[k]), 0))
@@ -268,6 +293,9 @@ class YnlDocGenerator:
                 lines.append(self.fmt.rst_subsubsection(attr_line))
 
                 for k in attr.keys():
+                    if k == LINE_STR:
+                        lines.append(self.fmt.rst_lineno(attr[k]))
+                        continue
                     if k in preprocessed + ignored:
                         continue
                     if k in linkable:
@@ -306,6 +334,8 @@ class YnlDocGenerator:
         lines = []
 
         # Main header
+        lineno = obj.get('__lineno__', 0)
+        lines.append(self.fmt.rst_lineno(lineno))
 
         family = obj['name']
 
@@ -354,7 +384,7 @@ class YnlDocGenerator:
     def parse_yaml_file(self, filename: str) -> str:
         """Transform the YAML specified by filename into an RST-formatted string"""
         with open(filename, "r", encoding="utf-8") as spec_file:
-            yaml_data = yaml.safe_load(spec_file)
-            content = self.parse_yaml(yaml_data)
+            numbered_yaml = yaml.load(spec_file, Loader=NumberedSafeLoader)
+            content = self.parse_yaml(numbered_yaml)
 
         return content


  reply	other threads:[~2025-06-17 16:00 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-17  8:01 [PATCH v5 00/15] Don't generate netlink .rst files inside $(srctree) Mauro Carvalho Chehab
2025-06-17  8:01 ` [PATCH v5 01/15] docs: conf.py: properly handle include and exclude patterns Mauro Carvalho Chehab
2025-06-17 10:38   ` Donald Hunter
2025-06-18  6:59     ` Mauro Carvalho Chehab
2025-06-18  2:42   ` Akira Yokosawa
2025-06-18 11:44     ` Mauro Carvalho Chehab
2025-06-17  8:01 ` [PATCH v5 02/15] docs: Makefile: disable check rules on make cleandocs Mauro Carvalho Chehab
2025-06-17  9:53   ` Breno Leitao
2025-06-17 10:38   ` Donald Hunter
2025-06-17  8:02 ` [PATCH v5 03/15] tools: ynl_gen_rst.py: create a top-level reference Mauro Carvalho Chehab
2025-06-17 10:40   ` Donald Hunter
2025-06-17  8:02 ` [PATCH v5 04/15] docs: netlink: netlink-raw.rst: use :ref: instead of :doc: Mauro Carvalho Chehab
2025-06-17  8:02 ` [PATCH v5 05/15] tools: ynl_gen_rst.py: make the index parser more generic Mauro Carvalho Chehab
2025-06-17 10:55   ` Donald Hunter
2025-06-17 11:59   ` Simon Horman
2025-06-18  6:57     ` Mauro Carvalho Chehab
2025-06-18 12:40       ` Simon Horman
2025-06-17  8:02 ` [PATCH v5 06/15] tools: ynl_gen_rst.py: Split library from command line tool Mauro Carvalho Chehab
2025-06-17 11:08   ` Donald Hunter
2025-06-17  8:02 ` [PATCH v5 07/15] scripts: lib: netlink_yml_parser.py: use classes Mauro Carvalho Chehab
2025-06-17  8:02 ` [PATCH v5 08/15] docs: netlink: index.rst: add a netlink index file Mauro Carvalho Chehab
2025-06-17 10:43   ` Donald Hunter
2025-06-17  8:02 ` [PATCH v5 09/15] tools: ynl_gen_rst.py: clanup coding style Mauro Carvalho Chehab
2025-06-17  9:49   ` Breno Leitao
2025-06-17  9:50   ` Breno Leitao
2025-06-17 11:12   ` Donald Hunter
2025-06-17  8:02 ` [PATCH v5 10/15] docs: sphinx: add a parser for yaml files for Netlink specs Mauro Carvalho Chehab
2025-06-17 12:35   ` Donald Hunter
2025-06-17 13:40     ` Mauro Carvalho Chehab
2025-06-17 16:00       ` Mauro Carvalho Chehab [this message]
2025-06-17 17:23         ` Donald Hunter
2025-06-18  8:21           ` Mauro Carvalho Chehab
2025-06-17  8:02 ` [PATCH v5 11/15] docs: use parser_yaml extension to handle " Mauro Carvalho Chehab
2025-06-17 12:45   ` Donald Hunter
2025-06-17  8:02 ` [PATCH v5 12/15] docs: uapi: netlink: update netlink specs link Mauro Carvalho Chehab
2025-06-17 12:46   ` Donald Hunter
2025-06-17  8:02 ` [PATCH v5 13/15] tools: ynl_gen_rst.py: drop support for generating index files Mauro Carvalho Chehab
2025-06-17  8:02 ` [PATCH v5 14/15] docs: netlink: remove obsolete .gitignore from unused directory Mauro Carvalho Chehab
2025-06-17 12:38   ` Donald Hunter
2025-06-17  8:02 ` [PATCH v5 15/15] MAINTAINERS: add netlink_yml_parser.py to linux-doc Mauro Carvalho Chehab
2025-06-17  9:50   ` Breno Leitao
2025-06-17 12:58 ` [PATCH v5 00/15] Don't generate netlink .rst files inside $(srctree) Donald Hunter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250617180001.46931ba9@sal.lan \
    --to=mchehab+huawei@kernel.org \
    --cc=akiyks@gmail.com \
    --cc=corbet@lwn.net \
    --cc=davem@davemloft.net \
    --cc=donald.hunter@gmail.com \
    --cc=edumazet@google.com \
    --cc=elver@google.com \
    --cc=ignacio@iencinas.com \
    --cc=joel@joelfernandes.org \
    --cc=jstancek@redhat.com \
    --cc=leitao@debian.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel-mentees@lists.linux.dev \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lkmm@lists.linux.dev \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=peterz@infradead.org \
    --cc=rubenru09@aol.com \
    --cc=skhan@linuxfoundation.org \
    --cc=stern@rowland.harvard.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox