From nobody Fri Oct 10 09:55:27 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D033BE65; Tue, 17 Jun 2025 08:02:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; cv=none; b=K0P76FyplsKOQNZGO+7MeNuYgwqATt1KAiHGlbWnBU8hr70WLdKtSY6GMGKJZQr2lqmuuk4bKJW32oPRrKgj1gbUOuY95ckEY5VlGiDxXsdmEbgaEdQtGvI7jVS38ZxR+H3QYHO+t3b3CXCQtrCvN+q4SFFZ16jiHFsrSx3ArPA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; c=relaxed/simple; bh=TQlUV26hUMBvQLESC8JIjjk9jVydpjRjIcMxZ7u1zZU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VuCkY209uh0QGfONN5tg2+023STnHU32wriIwPYRRIRXoOILyYs4AHZg/lYFtpdeBVE0y+VY2yho+6fZkgvwCaDPBedgpMXRuBURDKSFPc1keZRcQtiYG1kzdwdhAe5sZF/CQyI8X3vCkYPcsV8FWovsc9lTt9ehQuUUBZ+Hyxk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=t5vr77Nm; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="t5vr77Nm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DC6D0C4CEEE; Tue, 17 Jun 2025 08:02:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750147351; bh=TQlUV26hUMBvQLESC8JIjjk9jVydpjRjIcMxZ7u1zZU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=t5vr77Nm3T85lDkDCkTWO06PqpqrIayAe2sYq08oix+8bAeLj3xlY80wifnqiSFU9 qQwrTt4hZWLAnCrcX7JpUMQ+hADJOyEO9/fvErp2iinJaE4bO0HqbcHO5GzB7urHkE SyrleLbLpOXNxo+d23Y+d1RQMG42HS5kKA44I6G3agFivmQCEJ8dXjNFezStacqseK aSxd6wwDm1cXVtJ54cYElwpsc1YPwwjZO3lsWdsF3pLiJICbegvlV4gDFjg+KPf8F1 PQUFVD95zqZ4HCupLUP7IuWGq3QkY4vOlNw01toHzQ9YSUQ6p/r1EUQFJb86aYqbCf Omkib/K37qkHg== Received: from mchehab by mail.kernel.org with local (Exim 4.98.2) (envelope-from ) id 1uRRH3-00000001vcq-3jNb; Tue, 17 Jun 2025 10:02:29 +0200 From: Mauro Carvalho Chehab To: Linux Doc Mailing List , Jonathan Corbet Cc: Mauro Carvalho Chehab , "Akira Yokosawa" , "Breno Leitao" , "David S. Miller" , "Donald Hunter" , "Eric Dumazet" , "Ignacio Encinas Rubio" , "Jan Stancek" , "Marco Elver" , "Mauro Carvalho Chehab" , "Paolo Abeni" , "Ruben Wauters" , "Shuah Khan" , 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: [PATCH v5 01/15] docs: conf.py: properly handle include and exclude patterns Date: Tue, 17 Jun 2025 10:01:58 +0200 Message-ID: X-Mailer: git-send-email 2.49.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" When one does: make SPHINXDIRS=3D"foo" htmldocs All patterns would be relative to Documentation/foo, which causes the include/exclude patterns like: include_patterns =3D [ ... f'foo/*.{ext}', ] to break. This is not what it is expected. Address it by adding a logic to dynamically adjust the pattern when SPHINXDIRS is used. That allows adding parsers for other file types. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Donald Hunter --- Documentation/conf.py | 52 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/Documentation/conf.py b/Documentation/conf.py index 12de52a2b17e..e887c1b786a4 100644 --- a/Documentation/conf.py +++ b/Documentation/conf.py @@ -17,6 +17,54 @@ import os import sphinx import shutil =20 +# Location of Documentation/ directory +doctree =3D os.path.abspath('.') + +# List of patterns that don't contain directory names, in glob format. +include_patterns =3D ['**.rst'] +exclude_patterns =3D [] + +# List of patterns that contain directory names in glob format. +dyn_include_patterns =3D [] +dyn_exclude_patterns =3D ['output'] + +# Properly handle include/exclude patterns +# ---------------------------------------- + +def setup(app): + """ + On Sphinx, all directories are relative to what it is passed as + SOURCEDIR parameter for sphinx-build. Due to that, all patterns + that have directory names on it need to be dynamically set, after + converting them to a relative patch. + + As Sphinx doesn't include any patterns outside SOURCEDIR, we should + exclude relative patterns that start with "../". + """ + + sourcedir =3D app.srcdir # full path to the source directory + builddir =3D os.environ.get("BUILDDIR") + + # setup include_patterns dynamically + for p in dyn_include_patterns: + full =3D os.path.join(doctree, p) + + rel_path =3D os.path.relpath(full, start =3D app.srcdir) + if rel_path.startswith("../"): + continue + + app.config.include_patterns.append(rel_path) + + # setup exclude_patterns dynamically + for p in dyn_exclude_patterns: + full =3D os.path.join(doctree, p) + + rel_path =3D os.path.relpath(full, start =3D app.srcdir) + if rel_path.startswith("../"): + continue + + app.config.exclude_patterns.append(rel_path) + # helper # ------ =20 @@ -219,10 +267,6 @@ language =3D 'en' # Else, today_fmt is used as the format for a strftime call. #today_fmt =3D '%B %d, %Y' =20 -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns =3D ['output'] - # The reST default role (used for this markup: `text`) to use for all # documents. #default_role =3D None --=20 2.49.0 From nobody Fri Oct 10 09:55:27 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D18C1DE4F3; Tue, 17 Jun 2025 08:02:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; cv=none; b=qKDPHMbfZOoj0Ot55ZlVLx5fP7pJe7DCdQNN3xWZ70JXX2HjdMNhVJxOKtBMhRCBSnLcbzWKpAWXpisKKVY3Ki2Z8dVDK0NovjCMEIB6TwzNmeSw1eGsTKwDec6/SPLC+Likt1aXCJahaD0MeQILZMBYffrBHVNaapyzAHh6I/s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; c=relaxed/simple; bh=6g0yIQ00wX1zZxlyQNwgV3b8raB+qC4qKfp/RiMpLqg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VUsiMr7nJl1LH+V3wqTmh0ADOQGofLS1mwFEuK8/oAPUHcV/+xQa+0dCj7gZtj1d55OpAQcKByqJoaU7EbmzDMlduW0g4gAoNBlxXRA/acgDrF6Lf7FYBJYjwGSUrQ7Sy+PwFVhcbahlNJucsEANmrT9rFcuUX5/YZi/aJiiosg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pdAUzRNd; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="pdAUzRNd" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D1681C4CEED; Tue, 17 Jun 2025 08:02:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750147351; bh=6g0yIQ00wX1zZxlyQNwgV3b8raB+qC4qKfp/RiMpLqg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pdAUzRNdl/kLKTWq7AnH7OOdYVyT2kZ7KH8WACyDVeOiWFZC0dMl1jyUJado4NNFB kEcq1ZoqTy8fbGPQHkdSNfxGY99Dqer2p5/N3/6pgqCYleiveXwUomW5KmeviBWDzS GGYRfsPwA/q5W5TwTWwl0DJsuqLrZr5S0joPJmFvYrtKrsCS99do3WWGSUyvfDZ5la Mun/k/49kz7iR1BGuPpHJ0aNrZNmCy42jOg4AefCVkBaLrOFcKjMTwb2E7NTXuL7fB WgEO06RVyuAth4TSeaSo/hg5tvp2eMHhnDilkHvj2JvOM3vL05TEAH+ksyXPG5KmJp B1I7gLkCX0g4Q== Received: from mchehab by mail.kernel.org with local (Exim 4.98.2) (envelope-from ) id 1uRRH3-00000001vcu-3qqN; Tue, 17 Jun 2025 10:02:29 +0200 From: Mauro Carvalho Chehab To: Linux Doc Mailing List , Jonathan Corbet Cc: Mauro Carvalho Chehab , "Akira Yokosawa" , "Breno Leitao" , "David S. Miller" , "Donald Hunter" , "Eric Dumazet" , "Ignacio Encinas Rubio" , "Jan Stancek" , "Marco Elver" , "Mauro Carvalho Chehab" , "Paolo Abeni" , "Ruben Wauters" , "Shuah Khan" , 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: [PATCH v5 02/15] docs: Makefile: disable check rules on make cleandocs Date: Tue, 17 Jun 2025 10:01:59 +0200 Message-ID: X-Mailer: git-send-email 2.49.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" It doesn't make sense to check for missing ABI and documents when cleaning the tree. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Breno Leitao Reviewed-by: Donald Hunter --- Documentation/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/Makefile b/Documentation/Makefile index d30d66ddf1ad..b98477df5ddf 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -5,6 +5,7 @@ # for cleaning subdir- :=3D devicetree/bindings =20 +ifneq ($(MAKECMDGOALS),cleandocs) # Check for broken documentation file references ifeq ($(CONFIG_WARN_MISSING_DOCUMENTS),y) $(shell $(srctree)/scripts/documentation-file-ref-check --warn) @@ -14,6 +15,7 @@ endif ifeq ($(CONFIG_WARN_ABI_ERRORS),y) $(shell $(srctree)/scripts/get_abi.py --dir $(srctree)/Documentation/ABI v= alidate) endif +endif =20 # You can set these variables from the command line. SPHINXBUILD =3D sphinx-build --=20 2.49.0 From nobody Fri Oct 10 09:55:27 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D0D41B85FD; Tue, 17 Jun 2025 08:02:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; cv=none; b=uqjX6bLB73nD+GIrXJa/b+22ujiN9M80Q0gd4AlVxVySry86sBa5EJPgYsNBtaloYY6W7JLog99VZ0FwHPTWa2w6Th6lioaMTP2kbi12mrOystvhjVqNOUMpbKUYutW8CnAvk0Dj5o1AEWObu8N2W+S/cWfLAWOpdHlpchRz1E0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; c=relaxed/simple; bh=8JLj251EiGtS/E11n5n+267zLGC8qyxQhPvEcm7GqEQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YlcqgYgmAL/yPof1duzR/jWh6EaqsvEajMImBPBeXPRSA0EuZm9svAbr2GjKNRNCBx8lAvuVosDhYOSIeYxFM422Qnb09FrLb/qeL03vcfjShjotZ31nzGDLpn4UBwlmCVLmGtf0BGQ8f53zD+Xj4WDvSMbi5nEvmsUDJ4l5uZg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LosbNvJG; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LosbNvJG" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D3E78C4CEF0; Tue, 17 Jun 2025 08:02:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750147351; bh=8JLj251EiGtS/E11n5n+267zLGC8qyxQhPvEcm7GqEQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LosbNvJGOFfmhgxhsSFRMV5ac0gOEl4l2n3pJH8sSSiTZ+nzPTgkR5K86rV0H4mMV LMXJdUemwg6o2hJusVmsiJ1jmEQ1DvUdEakVB/OczbjujpU1fQEUQ4bC+9lKly3xVi RYNy558YXiahD79s2LInQScs8EIfwM5LqiJCsOGbqNAXSPNKbiNbQBXRLQSNW7241v wEOK3+DE9rtXwT8UIRZ1oDXn1v0gbdKJUpR/5rF5BkF6pV4FjCzZSfJimNukB5BWYw Bo2wZ8QLydrimYDgd9cx+5fusIhdWoUz7M5uw5nZsB8IVBK7McycUkhiAFQFPUkAmS k1UaIlrnYZ+LA== Received: from mchehab by mail.kernel.org with local (Exim 4.98.2) (envelope-from ) id 1uRRH3-00000001vcy-3yP4; Tue, 17 Jun 2025 10:02:29 +0200 From: Mauro Carvalho Chehab To: Linux Doc Mailing List , Jonathan Corbet Cc: Mauro Carvalho Chehab , "Akira Yokosawa" , "Breno Leitao" , "David S. Miller" , "Donald Hunter" , "Eric Dumazet" , "Ignacio Encinas Rubio" , "Jan Stancek" , "Marco Elver" , "Mauro Carvalho Chehab" , "Paolo Abeni" , "Ruben Wauters" , "Shuah Khan" , Jakub Kicinski , Simon Horman , 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: [PATCH v5 03/15] tools: ynl_gen_rst.py: create a top-level reference Date: Tue, 17 Jun 2025 10:02:00 +0200 Message-ID: <4496d88c381b9f7ddce37c5a2d53156c5e8e6a17.1750146719.git.mchehab+huawei@kernel.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" Currently, rt documents are referred with: Documentation/userspace-api/netlink/netlink-raw.rst: :doc:`rt-link<../../ne= tworking/netlink_spec/rt-link>` Documentation/userspace-api/netlink/netlink-raw.rst: :doc:`tc<../../network= ing/netlink_spec/tc>` Documentation/userspace-api/netlink/netlink-raw.rst: :doc:`tc<../../network= ing/netlink_spec/tc>` that's hard to maintain, and may break if we change the way rst files are generated from yaml. Better to use instead a reference for the netlink family. So, add a netlink- reference to all generated docs. Signed-off-by: Mauro Carvalho Chehab --- tools/net/ynl/pyynl/ynl_gen_rst.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/net/ynl/pyynl/ynl_gen_rst.py b/tools/net/ynl/pyynl/ynl_g= en_rst.py index 0cb6348e28d3..7bfb8ceeeefc 100755 --- a/tools/net/ynl/pyynl/ynl_gen_rst.py +++ b/tools/net/ynl/pyynl/ynl_gen_rst.py @@ -314,10 +314,11 @@ def parse_yaml(obj: Dict[str, Any]) -> str: =20 # Main header =20 - lines.append(rst_header()) - family =3D obj['name'] =20 + lines.append(rst_header()) + lines.append(rst_label("netlink-" + family)) + title =3D f"Family ``{family}`` netlink specification" lines.append(rst_title(title)) lines.append(rst_paragraph(".. contents:: :depth: 3\n")) --=20 2.49.0 From nobody Fri Oct 10 09:55:27 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7DE0928DF02; Tue, 17 Jun 2025 08:02:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; cv=none; b=OA7EFKI01QLNxMXYdk8xGqxf3p51JkMNZShHTrvywkVm9ZYsgEc6IxIExZgKuJug7oQPsl44e85FnxWjUBYeTAxu23xxCv0VG0s/MR+MjvfLlCru6oVF8to6/pppv5dD7Hm+eIPbM/aF1o/w/YxyzvqvajijJ6TzcDCi+Y6ZcBY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; c=relaxed/simple; bh=5GdVV6A8bXN64ovkNLx7Xdx5aR1iPXnV/yeu24lgmqI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hSeJsa+vdNL5MIeuUAZ8N5QbOHhl1gAnnzu/7fHw8GqqF43UV/mnksjfu2jZ0nDrt72i9Jh834cSA/Kj0Y2mZC6/luxyue/VbSs4P2EJ6fguaxb2H401cApnjFtlMza9NCoMFik6e+jFJsdflYf3tsd6EwwrhZU7WfEAnHPHdQY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=uOMOPn+m; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="uOMOPn+m" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E1AEFC4CEF4; Tue, 17 Jun 2025 08:02:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750147352; bh=5GdVV6A8bXN64ovkNLx7Xdx5aR1iPXnV/yeu24lgmqI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uOMOPn+m1yfIhvgONplR1Usc4iysrHrJZYnc/Q0rROBjUYdNggtuelIGRJwH9B3d/ 1INd1hXWAJAmucd2fKQ5FiqAhOQJmj18KP4/lO8b3nLgPYY9WST80I7CTFmLD3KSU4 MsE5gG6gg/62uvuI2hf5kcJS0UwwRIpV8EtYW2kZBnOCF16ffTZT+Z0pTfu77qQL5C qN5Wj856IIonXqPWr6l/m8YKzrBYibIF3wodC79JH+nF6cOog21p7dp1j9dEGZKk70 0+T2hSj7Qri0N+ShAb9TopsCDoZqahWNM0EnalAamHpfP117o6unK8xos/K9AulRkh QSvXLVKscyzGA== Received: from mchehab by mail.kernel.org with local (Exim 4.98.2) (envelope-from ) id 1uRRH3-00000001vd2-469f; Tue, 17 Jun 2025 10:02:29 +0200 From: Mauro Carvalho Chehab To: Linux Doc Mailing List , Jonathan Corbet Cc: Mauro Carvalho Chehab , "Akira Yokosawa" , "Breno Leitao" , "David S. Miller" , "Donald Hunter" , "Eric Dumazet" , "Ignacio Encinas Rubio" , "Jan Stancek" , "Marco Elver" , "Mauro Carvalho Chehab" , "Paolo Abeni" , "Ruben Wauters" , "Shuah Khan" , Jakub Kicinski , Simon Horman , 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: [PATCH v5 04/15] docs: netlink: netlink-raw.rst: use :ref: instead of :doc: Date: Tue, 17 Jun 2025 10:02:01 +0200 Message-ID: <2ad71c748e2f6dc3095b6ce67ec4d43f0fcc038c.1750146719.git.mchehab+huawei@kernel.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" Having :doc: references with relative paths doesn't always work, as it may have troubles when O=3D is used. So, replace them by Sphinx cross-reference tag that are now created by ynl_gen_rst.py. Signed-off-by: Mauro Carvalho Chehab --- Documentation/userspace-api/netlink/netlink-raw.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/userspace-api/netlink/netlink-raw.rst b/Document= ation/userspace-api/netlink/netlink-raw.rst index 31fc91020eb3..aae296c170c5 100644 --- a/Documentation/userspace-api/netlink/netlink-raw.rst +++ b/Documentation/userspace-api/netlink/netlink-raw.rst @@ -62,8 +62,8 @@ Sub-messages ------------ =20 Several raw netlink families such as -:doc:`rt-link<../../networking/netlink_spec/rt-link>` and -:doc:`tc<../../networking/netlink_spec/tc>` use attribute nesting as an +:ref:`rt-link` and +:ref:`tc` use attribute nesting as an abstraction to carry module specific information. =20 Conceptually it looks as follows:: @@ -162,7 +162,7 @@ then this is an error. Nested struct definitions ------------------------- =20 -Many raw netlink families such as :doc:`tc<../../networking/netlink_spec/t= c>` +Many raw netlink families such as :ref:`tc` make use of nested struct definitions. The ``netlink-raw`` schema makes it possible to embed a struct within a struct definition using the ``struct`` property. For example, the following struct definition embeds the --=20 2.49.0 From nobody Fri Oct 10 09:55:27 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D07A8528E; Tue, 17 Jun 2025 08:02:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; cv=none; b=VhNbvn3X6Yw2K/I58h+e0LyE7VVBs82w872PvIdB4H9iRdCH2sptpp0W8NNJ5QBGk13BzUH4LPXrBAsS4Act/9+oIluK97NyAlZ7wamWWxegG8+qZNHkBviAkK3sJf9TFvlvcYBR6OzKJFfsKwXWZGuyxIwyy53jIY8/aUAt6ZI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; c=relaxed/simple; bh=zjfj2Tm7h9LKUnhgzAVTuVnT8YUaP6pYYIdRhxmKFAc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VcGYxhPQVcRjb/AX3C2wQeWjHagu927qWb7bYheZNEI45GKboj64FDn5wxz6ULQ2qmqezSjNrnxflpFJ2K6+0cPJa1pMP4QTqVWn+cNog3UG4UqWum2CkbfuNJzH2gu4X7iR57dJ62cIfaaB5HFYTYRVyYaJcCm0T66V0yvU1WA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Tf5PXJHb; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Tf5PXJHb" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DF1C8C4CEE3; Tue, 17 Jun 2025 08:02:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750147351; bh=zjfj2Tm7h9LKUnhgzAVTuVnT8YUaP6pYYIdRhxmKFAc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Tf5PXJHbyqoDMJUjhFzgNd2QGPUruuk54hW8GfaiY4HU/qL1o+lPlFJ4ixNuynI+I LgDzId9V2N2/TBnov9FlC+ewqG+seIJu21fNhZQalb2Z+c38L5lWALHfK40MHkUrkz rjdD5mtoXusfnPP5ksGOkgtAOH8vtnQ7UX34RX34vdPdBjX4ZQXW+MtlLGjq2iUh94 ScnqiaNRn8Kw/zchQ1QNIbu4pnRHYxj6AYirHgpT+InZ9lflxBH1ksL5Xnge+LabWM y0CkkOO+WxmJxLa+mla504XWl2rQtvPJZXMQ7ITvVL3uIEG7xsquNK4YdcDPpqywRV SpN7aT8dbEagg== Received: from mchehab by mail.kernel.org with local (Exim 4.98.2) (envelope-from ) id 1uRRH4-00000001vd6-01hy; Tue, 17 Jun 2025 10:02:30 +0200 From: Mauro Carvalho Chehab To: Linux Doc Mailing List , Jonathan Corbet Cc: Mauro Carvalho Chehab , "Akira Yokosawa" , "Breno Leitao" , "David S. Miller" , "Donald Hunter" , "Eric Dumazet" , "Ignacio Encinas Rubio" , "Jan Stancek" , "Marco Elver" , "Mauro Carvalho Chehab" , "Paolo Abeni" , "Ruben Wauters" , "Shuah Khan" , Jakub Kicinski , Simon Horman , 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: [PATCH v5 05/15] tools: ynl_gen_rst.py: make the index parser more generic Date: Tue, 17 Jun 2025 10:02:02 +0200 Message-ID: <1cd8b28bfe159677b8a8b1228b04ba2919c8aee8.1750146719.git.mchehab+huawei@kernel.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" It is not a good practice to store build-generated files inside $(srctree), as one may be using O=3D and even have the Kernel on a read-only directory. Change the YAML generation for netlink files to allow it to parse data based on the source or on the object tree. Signed-off-by: Mauro Carvalho Chehab --- tools/net/ynl/pyynl/ynl_gen_rst.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tools/net/ynl/pyynl/ynl_gen_rst.py b/tools/net/ynl/pyynl/ynl_g= en_rst.py index 7bfb8ceeeefc..b1e5acafb998 100755 --- a/tools/net/ynl/pyynl/ynl_gen_rst.py +++ b/tools/net/ynl/pyynl/ynl_gen_rst.py @@ -365,6 +365,7 @@ def parse_arguments() -> argparse.Namespace: =20 parser.add_argument("-v", "--verbose", action=3D"store_true") parser.add_argument("-o", "--output", help=3D"Output file name") + parser.add_argument("-d", "--input_dir", help=3D"YAML input directory") =20 # Index and input are mutually exclusive group =3D parser.add_mutually_exclusive_group() @@ -405,11 +406,14 @@ def write_to_rstfile(content: str, filename: str) -> = None: """Write the generated content into an RST file""" logging.debug("Saving RST file to %s", filename) =20 + dir =3D os.path.dirname(filename) + os.makedirs(dir, exist_ok=3DTrue) + with open(filename, "w", encoding=3D"utf-8") as rst_file: rst_file.write(content) =20 =20 -def generate_main_index_rst(output: str) -> None: +def generate_main_index_rst(output: str, index_dir: str) -> None: """Generate the `networking_spec/index` content and write to the file"= "" lines =3D [] =20 @@ -418,12 +422,18 @@ def generate_main_index_rst(output: str) -> None: lines.append(rst_title("Netlink Family Specifications")) lines.append(rst_toctree(1)) =20 - index_dir =3D os.path.dirname(output) - logging.debug("Looking for .rst files in %s", index_dir) + index_fname =3D os.path.basename(output) + base, ext =3D os.path.splitext(index_fname) + + if not index_dir: + index_dir =3D os.path.dirname(output) + + logging.debug(f"Looking for {ext} files in %s", index_dir) for filename in sorted(os.listdir(index_dir)): - if not filename.endswith(".rst") or filename =3D=3D "index.rst": + if not filename.endswith(ext) or filename =3D=3D index_fname: continue - lines.append(f" {filename.replace('.rst', '')}\n") + base, ext =3D os.path.splitext(filename) + lines.append(f" {base}\n") =20 logging.debug("Writing an index file at %s", output) write_to_rstfile("".join(lines), output) @@ -447,7 +457,7 @@ def main() -> None: =20 if args.index: # Generate the index RST file - generate_main_index_rst(args.output) + generate_main_index_rst(args.output, args.input_dir) =20 =20 if __name__ =3D=3D "__main__": --=20 2.49.0 From nobody Fri Oct 10 09:55:27 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AA23828FA9E; Tue, 17 Jun 2025 08:02:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; cv=none; b=dUw8B9n0J0N15x1YxAVysJj/DnsfcvO9jt3gZt9uKSEHa/b8kEqWe1kccWztkAxM/2dCZaGJHvDKfYJvlqB+ZVyd3QuN3QBIZy5nWy0zg7Wy91yYwAuXO/WtRoRWEAQyLkzpfgdn956b9F1a1OSayTH9PawQjlLrAqA8RY7sL4g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; c=relaxed/simple; bh=fvRwGKCbfw6LegMInco3S0uwoQxCeizpIrmQwZztVDA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OK/2Rqbr9/mAo9p9ovdQ7WjmBZagibcFK1MGBNafv4NSbX+Sfffb9Y6Suyls4uSb2WEyetyFS3A/M2U7poaDqeCHHmRPJlzcCE6vIF3jqCgUzivqjf10wXzWjd2FqjCowKICzqqSgPC7TNhIjF4StnlSSnIMhDrGapa01FgeRH4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qokGAN6J; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="qokGAN6J" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D9423C4AF0B; Tue, 17 Jun 2025 08:02:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750147352; bh=fvRwGKCbfw6LegMInco3S0uwoQxCeizpIrmQwZztVDA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qokGAN6JZjyPyBq4mJJmGKX2yosS28XVlCtsdHCWfNvirwr8a2Aw/BpPJEmeiwf0k uQaaouyP7fb/7tp6zdRVC6+OVPQfLOjTghTscOCahUiDbwSABdgTXTDj3AUrEuOFwR 3CYQ6iv5lon/QAIQ+xyUXxCfCKCGh6Tau4SRlbm7IRc4pVml8lRdetU/T2szgFeZHo nzxLhXEa6J/ttHEtjk3hlFQ8BbBKOe/Bc9KXSjHkjD3UZqY3jA2IAHubBiuF7SxyV8 PUFLG4CeZSn4QBpBpvwBu4hWDGPucykADzziO9qgTP3Z/bzS3cv5H0IuWxDHabg97y 6sr2nuTNj8yeQ== Received: from mchehab by mail.kernel.org with local (Exim 4.98.2) (envelope-from ) id 1uRRH4-00000001vdB-09d8; Tue, 17 Jun 2025 10:02:30 +0200 From: Mauro Carvalho Chehab To: Linux Doc Mailing List , Jonathan Corbet Cc: Mauro Carvalho Chehab , "Akira Yokosawa" , "Breno Leitao" , "David S. Miller" , "Donald Hunter" , "Eric Dumazet" , "Ignacio Encinas Rubio" , "Jan Stancek" , "Marco Elver" , "Mauro Carvalho Chehab" , "Paolo Abeni" , "Ruben Wauters" , "Shuah Khan" , Jakub Kicinski , Simon Horman , 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: [PATCH v5 06/15] tools: ynl_gen_rst.py: Split library from command line tool Date: Tue, 17 Jun 2025 10:02:03 +0200 Message-ID: <26f6087563a1b7f6b26b5f38856ea5f06f528fee.1750146719.git.mchehab+huawei@kernel.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" As we'll be using the Netlink specs parser inside a Sphinx extension, move the library part from the command line parser. No functional changes. Signed-off-by: Mauro Carvalho Chehab --- tools/net/ynl/pyynl/netlink_yml_parser.py | 391 ++++++++++++++++++++++ tools/net/ynl/pyynl/ynl_gen_rst.py | 374 +-------------------- 2 files changed, 401 insertions(+), 364 deletions(-) create mode 100755 tools/net/ynl/pyynl/netlink_yml_parser.py diff --git a/tools/net/ynl/pyynl/netlink_yml_parser.py b/tools/net/ynl/pyyn= l/netlink_yml_parser.py new file mode 100755 index 000000000000..3c15b578f947 --- /dev/null +++ b/tools/net/ynl/pyynl/netlink_yml_parser.py @@ -0,0 +1,391 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 +# -*- coding: utf-8; mode: python -*- + +""" + Script to auto generate the documentation for Netlink specifications. + + :copyright: Copyright (C) 2023 Breno Leitao + :license: GPL Version 2, June 1991 see linux/COPYING for details. + + This script performs extensive parsing to the Linux kernel's netlink Y= AML + spec files, in an effort to avoid needing to heavily mark up the origi= nal + YAML file. + + This code is split in three big parts: + 1) RST formatters: Use to convert a string to a RST output + 2) Parser helpers: Functions to parse the YAML data structure + 3) Main function and small helpers +""" + +from typing import Any, Dict, List +import os.path +import logging +import yaml + + +SPACE_PER_LEVEL =3D 4 + + +# RST Formatters +# =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +def headroom(level: int) -> str: + """Return space to format""" + return " " * (level * SPACE_PER_LEVEL) + + +def bold(text: str) -> str: + """Format bold text""" + return f"**{text}**" + + +def inline(text: str) -> str: + """Format inline text""" + return f"``{text}``" + + +def sanitize(text: str) -> str: + """Remove newlines and multiple spaces""" + # This is useful for some fields that are spread across multiple lines + return str(text).replace("\n", " ").strip() + + +def rst_fields(key: str, value: str, level: int =3D 0) -> str: + """Return a RST formatted field""" + return headroom(level) + f":{key}: {value}" + + +def rst_definition(key: str, value: Any, level: int =3D 0) -> str: + """Format a single rst definition""" + return headroom(level) + key + "\n" + headroom(level + 1) + str(value) + + +def rst_paragraph(paragraph: str, level: int =3D 0) -> str: + """Return a formatted paragraph""" + return headroom(level) + paragraph + + +def rst_bullet(item: str, level: int =3D 0) -> str: + """Return a formatted a bullet""" + return headroom(level) + f"- {item}" + + +def rst_subsection(title: str) -> str: + """Add a sub-section to the document""" + return f"{title}\n" + "-" * len(title) + + +def rst_subsubsection(title: str) -> str: + """Add a sub-sub-section to the document""" + return f"{title}\n" + "~" * len(title) + + +def rst_section(namespace: str, prefix: str, title: str) -> str: + """Add a section to the document""" + return f".. _{namespace}-{prefix}-{title}:\n\n{title}\n" + "=3D" * len= (title) + + +def rst_subtitle(title: str) -> str: + """Add a subtitle to the document""" + return "\n" + "-" * len(title) + f"\n{title}\n" + "-" * len(title) + "= \n\n" + + +def rst_title(title: str) -> str: + """Add a title to the document""" + return "=3D" * len(title) + f"\n{title}\n" + "=3D" * len(title) + "\n\= n" + + +def rst_list_inline(list_: List[str], level: int =3D 0) -> str: + """Format a list using inlines""" + return headroom(level) + "[" + ", ".join(inline(i) for i in list_) + "= ]" + + +def rst_ref(namespace: str, prefix: str, name: str) -> str: + """Add a hyperlink to the document""" + mappings =3D {'enum': 'definition', + 'fixed-header': 'definition', + 'nested-attributes': 'attribute-set', + 'struct': 'definition'} + if prefix in mappings: + prefix =3D mappings[prefix] + return f":ref:`{namespace}-{prefix}-{name}`" + + +def rst_header() -> str: + """The headers for all the auto generated RST files""" + lines =3D [] + + lines.append(rst_paragraph(".. SPDX-License-Identifier: GPL-2.0")) + lines.append(rst_paragraph(".. NOTE: This document was auto-generated.= \n\n")) + + return "\n".join(lines) + + +def rst_toctree(maxdepth: int =3D 2) -> str: + """Generate a toctree RST primitive""" + lines =3D [] + + lines.append(".. toctree::") + lines.append(f" :maxdepth: {maxdepth}\n\n") + + return "\n".join(lines) + + +def rst_label(title: str) -> str: + """Return a formatted label""" + return f".. _{title}:\n\n" + + +# Parsers +# =3D=3D=3D=3D=3D=3D=3D + + +def parse_mcast_group(mcast_group: List[Dict[str, Any]]) -> str: + """Parse 'multicast' group list and return a formatted string""" + lines =3D [] + for group in mcast_group: + lines.append(rst_bullet(group["name"])) + + return "\n".join(lines) + + +def parse_do(do_dict: Dict[str, Any], level: int =3D 0) -> str: + """Parse 'do' section and return a formatted string""" + lines =3D [] + for key in do_dict.keys(): + lines.append(rst_paragraph(bold(key), level + 1)) + if key in ['request', 'reply']: + lines.append(parse_do_attributes(do_dict[key], level + 1) + "\= n") + else: + lines.append(headroom(level + 2) + do_dict[key] + "\n") + + return "\n".join(lines) + + +def parse_do_attributes(attrs: Dict[str, Any], level: int =3D 0) -> str: + """Parse 'attributes' section""" + if "attributes" not in attrs: + return "" + lines =3D [rst_fields("attributes", rst_list_inline(attrs["attributes"= ]), level + 1)] + + return "\n".join(lines) + + +def parse_operations(operations: List[Dict[str, Any]], namespace: str) -> = str: + """Parse operations block""" + preprocessed =3D ["name", "doc", "title", "do", "dump", "flags"] + linkable =3D ["fixed-header", "attribute-set"] + lines =3D [] + + for operation in operations: + lines.append(rst_section(namespace, 'operation', operation["name"]= )) + lines.append(rst_paragraph(operation["doc"]) + "\n") + + for key in operation.keys(): + if key in preprocessed: + # Skip the special fields + continue + value =3D operation[key] + if key in linkable: + value =3D rst_ref(namespace, key, value) + lines.append(rst_fields(key, value, 0)) + if 'flags' in operation: + lines.append(rst_fields('flags', rst_list_inline(operation['fl= ags']))) + + if "do" in operation: + lines.append(rst_paragraph(":do:", 0)) + lines.append(parse_do(operation["do"], 0)) + if "dump" in operation: + lines.append(rst_paragraph(":dump:", 0)) + lines.append(parse_do(operation["dump"], 0)) + + # New line after fields + lines.append("\n") + + return "\n".join(lines) + + +def parse_entries(entries: List[Dict[str, Any]], level: int) -> str: + """Parse a list of entries""" + ignored =3D ["pad"] + lines =3D [] + for entry in entries: + if isinstance(entry, dict): + # entries could be a list or a dictionary + field_name =3D entry.get("name", "") + if field_name in ignored: + continue + type_ =3D entry.get("type") + if type_: + field_name +=3D f" ({inline(type_)})" + lines.append( + rst_fields(field_name, sanitize(entry.get("doc", "")), lev= el) + ) + elif isinstance(entry, list): + lines.append(rst_list_inline(entry, level)) + else: + lines.append(rst_bullet(inline(sanitize(entry)), level)) + + lines.append("\n") + return "\n".join(lines) + + +def parse_definitions(defs: Dict[str, Any], namespace: str) -> str: + """Parse definitions section""" + preprocessed =3D ["name", "entries", "members"] + ignored =3D ["render-max"] # This is not printed + lines =3D [] + + for definition in defs: + lines.append(rst_section(namespace, 'definition', definition["name= "])) + for k in definition.keys(): + if k in preprocessed + ignored: + continue + lines.append(rst_fields(k, sanitize(definition[k]), 0)) + + # Field list needs to finish with a new line + lines.append("\n") + if "entries" in definition: + lines.append(rst_paragraph(":entries:", 0)) + lines.append(parse_entries(definition["entries"], 1)) + if "members" in definition: + lines.append(rst_paragraph(":members:", 0)) + lines.append(parse_entries(definition["members"], 1)) + + return "\n".join(lines) + + +def parse_attr_sets(entries: List[Dict[str, Any]], namespace: str) -> str: + """Parse attribute from attribute-set""" + preprocessed =3D ["name", "type"] + linkable =3D ["enum", "nested-attributes", "struct", "sub-message"] + ignored =3D ["checks"] + lines =3D [] + + for entry in entries: + lines.append(rst_section(namespace, 'attribute-set', entry["name"]= )) + for attr in entry["attributes"]: + type_ =3D attr.get("type") + attr_line =3D attr["name"] + if type_: + # Add the attribute type in the same line + attr_line +=3D f" ({inline(type_)})" + + lines.append(rst_subsubsection(attr_line)) + + for k in attr.keys(): + if k in preprocessed + ignored: + continue + if k in linkable: + value =3D rst_ref(namespace, k, attr[k]) + else: + value =3D sanitize(attr[k]) + lines.append(rst_fields(k, value, 0)) + lines.append("\n") + + return "\n".join(lines) + + +def parse_sub_messages(entries: List[Dict[str, Any]], namespace: str) -> s= tr: + """Parse sub-message definitions""" + lines =3D [] + + for entry in entries: + lines.append(rst_section(namespace, 'sub-message', entry["name"])) + for fmt in entry["formats"]: + value =3D fmt["value"] + + lines.append(rst_bullet(bold(value))) + for attr in ['fixed-header', 'attribute-set']: + if attr in fmt: + lines.append(rst_fields(attr, + rst_ref(namespace, attr, fmt[a= ttr]), + 1)) + lines.append("\n") + + return "\n".join(lines) + + +def parse_yaml(obj: Dict[str, Any]) -> str: + """Format the whole YAML into a RST string""" + lines =3D [] + + # Main header + + family =3D obj['name'] + + lines.append(rst_header()) + lines.append(rst_label("netlink-" + family)) + + title =3D f"Family ``{family}`` netlink specification" + lines.append(rst_title(title)) + lines.append(rst_paragraph(".. contents:: :depth: 3\n")) + + if "doc" in obj: + lines.append(rst_subtitle("Summary")) + lines.append(rst_paragraph(obj["doc"], 0)) + + # Operations + if "operations" in obj: + lines.append(rst_subtitle("Operations")) + lines.append(parse_operations(obj["operations"]["list"], family)) + + # Multicast groups + if "mcast-groups" in obj: + lines.append(rst_subtitle("Multicast groups")) + lines.append(parse_mcast_group(obj["mcast-groups"]["list"])) + + # Definitions + if "definitions" in obj: + lines.append(rst_subtitle("Definitions")) + lines.append(parse_definitions(obj["definitions"], family)) + + # Attributes set + if "attribute-sets" in obj: + lines.append(rst_subtitle("Attribute sets")) + lines.append(parse_attr_sets(obj["attribute-sets"], family)) + + # Sub-messages + if "sub-messages" in obj: + lines.append(rst_subtitle("Sub-messages")) + lines.append(parse_sub_messages(obj["sub-messages"], family)) + + return "\n".join(lines) + + +# Main functions +# =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + + +def parse_yaml_file(filename: str) -> str: + """Transform the YAML specified by filename into an RST-formatted stri= ng""" + with open(filename, "r", encoding=3D"utf-8") as spec_file: + yaml_data =3D yaml.safe_load(spec_file) + content =3D parse_yaml(yaml_data) + + return content + + +def generate_main_index_rst(output: str, index_dir: str) -> str: + """Generate the `networking_spec/index` content and write to the file"= "" + lines =3D [] + + lines.append(rst_header()) + lines.append(rst_label("specs")) + lines.append(rst_title("Netlink Family Specifications")) + lines.append(rst_toctree(1)) + + index_fname =3D os.path.basename(output) + base, ext =3D os.path.splitext(index_fname) + + if not index_dir: + index_dir =3D os.path.dirname(output) + + logging.debug(f"Looking for {ext} files in %s", index_dir) + for filename in sorted(os.listdir(index_dir)): + if not filename.endswith(ext) or filename =3D=3D index_fname: + continue + base, ext =3D os.path.splitext(filename) + lines.append(f" {base}\n") + + return "".join(lines), output diff --git a/tools/net/ynl/pyynl/ynl_gen_rst.py b/tools/net/ynl/pyynl/ynl_g= en_rst.py index b1e5acafb998..38dafe3d9179 100755 --- a/tools/net/ynl/pyynl/ynl_gen_rst.py +++ b/tools/net/ynl/pyynl/ynl_gen_rst.py @@ -18,345 +18,17 @@ 3) Main function and small helpers """ =20 -from typing import Any, Dict, List import os.path import sys import argparse import logging -import yaml =20 +LIB_DIR =3D "../../../../scripts/lib" +SRC_DIR =3D os.path.dirname(os.path.realpath(__file__)) =20 -SPACE_PER_LEVEL =3D 4 +sys.path.insert(0, os.path.join(SRC_DIR, LIB_DIR)) =20 - -# RST Formatters -# =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D -def headroom(level: int) -> str: - """Return space to format""" - return " " * (level * SPACE_PER_LEVEL) - - -def bold(text: str) -> str: - """Format bold text""" - return f"**{text}**" - - -def inline(text: str) -> str: - """Format inline text""" - return f"``{text}``" - - -def sanitize(text: str) -> str: - """Remove newlines and multiple spaces""" - # This is useful for some fields that are spread across multiple lines - return str(text).replace("\n", " ").strip() - - -def rst_fields(key: str, value: str, level: int =3D 0) -> str: - """Return a RST formatted field""" - return headroom(level) + f":{key}: {value}" - - -def rst_definition(key: str, value: Any, level: int =3D 0) -> str: - """Format a single rst definition""" - return headroom(level) + key + "\n" + headroom(level + 1) + str(value) - - -def rst_paragraph(paragraph: str, level: int =3D 0) -> str: - """Return a formatted paragraph""" - return headroom(level) + paragraph - - -def rst_bullet(item: str, level: int =3D 0) -> str: - """Return a formatted a bullet""" - return headroom(level) + f"- {item}" - - -def rst_subsection(title: str) -> str: - """Add a sub-section to the document""" - return f"{title}\n" + "-" * len(title) - - -def rst_subsubsection(title: str) -> str: - """Add a sub-sub-section to the document""" - return f"{title}\n" + "~" * len(title) - - -def rst_section(namespace: str, prefix: str, title: str) -> str: - """Add a section to the document""" - return f".. _{namespace}-{prefix}-{title}:\n\n{title}\n" + "=3D" * len= (title) - - -def rst_subtitle(title: str) -> str: - """Add a subtitle to the document""" - return "\n" + "-" * len(title) + f"\n{title}\n" + "-" * len(title) + "= \n\n" - - -def rst_title(title: str) -> str: - """Add a title to the document""" - return "=3D" * len(title) + f"\n{title}\n" + "=3D" * len(title) + "\n\= n" - - -def rst_list_inline(list_: List[str], level: int =3D 0) -> str: - """Format a list using inlines""" - return headroom(level) + "[" + ", ".join(inline(i) for i in list_) + "= ]" - - -def rst_ref(namespace: str, prefix: str, name: str) -> str: - """Add a hyperlink to the document""" - mappings =3D {'enum': 'definition', - 'fixed-header': 'definition', - 'nested-attributes': 'attribute-set', - 'struct': 'definition'} - if prefix in mappings: - prefix =3D mappings[prefix] - return f":ref:`{namespace}-{prefix}-{name}`" - - -def rst_header() -> str: - """The headers for all the auto generated RST files""" - lines =3D [] - - lines.append(rst_paragraph(".. SPDX-License-Identifier: GPL-2.0")) - lines.append(rst_paragraph(".. NOTE: This document was auto-generated.= \n\n")) - - return "\n".join(lines) - - -def rst_toctree(maxdepth: int =3D 2) -> str: - """Generate a toctree RST primitive""" - lines =3D [] - - lines.append(".. toctree::") - lines.append(f" :maxdepth: {maxdepth}\n\n") - - return "\n".join(lines) - - -def rst_label(title: str) -> str: - """Return a formatted label""" - return f".. _{title}:\n\n" - - -# Parsers -# =3D=3D=3D=3D=3D=3D=3D - - -def parse_mcast_group(mcast_group: List[Dict[str, Any]]) -> str: - """Parse 'multicast' group list and return a formatted string""" - lines =3D [] - for group in mcast_group: - lines.append(rst_bullet(group["name"])) - - return "\n".join(lines) - - -def parse_do(do_dict: Dict[str, Any], level: int =3D 0) -> str: - """Parse 'do' section and return a formatted string""" - lines =3D [] - for key in do_dict.keys(): - lines.append(rst_paragraph(bold(key), level + 1)) - if key in ['request', 'reply']: - lines.append(parse_do_attributes(do_dict[key], level + 1) + "\= n") - else: - lines.append(headroom(level + 2) + do_dict[key] + "\n") - - return "\n".join(lines) - - -def parse_do_attributes(attrs: Dict[str, Any], level: int =3D 0) -> str: - """Parse 'attributes' section""" - if "attributes" not in attrs: - return "" - lines =3D [rst_fields("attributes", rst_list_inline(attrs["attributes"= ]), level + 1)] - - return "\n".join(lines) - - -def parse_operations(operations: List[Dict[str, Any]], namespace: str) -> = str: - """Parse operations block""" - preprocessed =3D ["name", "doc", "title", "do", "dump", "flags"] - linkable =3D ["fixed-header", "attribute-set"] - lines =3D [] - - for operation in operations: - lines.append(rst_section(namespace, 'operation', operation["name"]= )) - lines.append(rst_paragraph(operation["doc"]) + "\n") - - for key in operation.keys(): - if key in preprocessed: - # Skip the special fields - continue - value =3D operation[key] - if key in linkable: - value =3D rst_ref(namespace, key, value) - lines.append(rst_fields(key, value, 0)) - if 'flags' in operation: - lines.append(rst_fields('flags', rst_list_inline(operation['fl= ags']))) - - if "do" in operation: - lines.append(rst_paragraph(":do:", 0)) - lines.append(parse_do(operation["do"], 0)) - if "dump" in operation: - lines.append(rst_paragraph(":dump:", 0)) - lines.append(parse_do(operation["dump"], 0)) - - # New line after fields - lines.append("\n") - - return "\n".join(lines) - - -def parse_entries(entries: List[Dict[str, Any]], level: int) -> str: - """Parse a list of entries""" - ignored =3D ["pad"] - lines =3D [] - for entry in entries: - if isinstance(entry, dict): - # entries could be a list or a dictionary - field_name =3D entry.get("name", "") - if field_name in ignored: - continue - type_ =3D entry.get("type") - if type_: - field_name +=3D f" ({inline(type_)})" - lines.append( - rst_fields(field_name, sanitize(entry.get("doc", "")), lev= el) - ) - elif isinstance(entry, list): - lines.append(rst_list_inline(entry, level)) - else: - lines.append(rst_bullet(inline(sanitize(entry)), level)) - - lines.append("\n") - return "\n".join(lines) - - -def parse_definitions(defs: Dict[str, Any], namespace: str) -> str: - """Parse definitions section""" - preprocessed =3D ["name", "entries", "members"] - ignored =3D ["render-max"] # This is not printed - lines =3D [] - - for definition in defs: - lines.append(rst_section(namespace, 'definition', definition["name= "])) - for k in definition.keys(): - if k in preprocessed + ignored: - continue - lines.append(rst_fields(k, sanitize(definition[k]), 0)) - - # Field list needs to finish with a new line - lines.append("\n") - if "entries" in definition: - lines.append(rst_paragraph(":entries:", 0)) - lines.append(parse_entries(definition["entries"], 1)) - if "members" in definition: - lines.append(rst_paragraph(":members:", 0)) - lines.append(parse_entries(definition["members"], 1)) - - return "\n".join(lines) - - -def parse_attr_sets(entries: List[Dict[str, Any]], namespace: str) -> str: - """Parse attribute from attribute-set""" - preprocessed =3D ["name", "type"] - linkable =3D ["enum", "nested-attributes", "struct", "sub-message"] - ignored =3D ["checks"] - lines =3D [] - - for entry in entries: - lines.append(rst_section(namespace, 'attribute-set', entry["name"]= )) - for attr in entry["attributes"]: - type_ =3D attr.get("type") - attr_line =3D attr["name"] - if type_: - # Add the attribute type in the same line - attr_line +=3D f" ({inline(type_)})" - - lines.append(rst_subsubsection(attr_line)) - - for k in attr.keys(): - if k in preprocessed + ignored: - continue - if k in linkable: - value =3D rst_ref(namespace, k, attr[k]) - else: - value =3D sanitize(attr[k]) - lines.append(rst_fields(k, value, 0)) - lines.append("\n") - - return "\n".join(lines) - - -def parse_sub_messages(entries: List[Dict[str, Any]], namespace: str) -> s= tr: - """Parse sub-message definitions""" - lines =3D [] - - for entry in entries: - lines.append(rst_section(namespace, 'sub-message', entry["name"])) - for fmt in entry["formats"]: - value =3D fmt["value"] - - lines.append(rst_bullet(bold(value))) - for attr in ['fixed-header', 'attribute-set']: - if attr in fmt: - lines.append(rst_fields(attr, - rst_ref(namespace, attr, fmt[a= ttr]), - 1)) - lines.append("\n") - - return "\n".join(lines) - - -def parse_yaml(obj: Dict[str, Any]) -> str: - """Format the whole YAML into a RST string""" - lines =3D [] - - # Main header - - family =3D obj['name'] - - lines.append(rst_header()) - lines.append(rst_label("netlink-" + family)) - - title =3D f"Family ``{family}`` netlink specification" - lines.append(rst_title(title)) - lines.append(rst_paragraph(".. contents:: :depth: 3\n")) - - if "doc" in obj: - lines.append(rst_subtitle("Summary")) - lines.append(rst_paragraph(obj["doc"], 0)) - - # Operations - if "operations" in obj: - lines.append(rst_subtitle("Operations")) - lines.append(parse_operations(obj["operations"]["list"], family)) - - # Multicast groups - if "mcast-groups" in obj: - lines.append(rst_subtitle("Multicast groups")) - lines.append(parse_mcast_group(obj["mcast-groups"]["list"])) - - # Definitions - if "definitions" in obj: - lines.append(rst_subtitle("Definitions")) - lines.append(parse_definitions(obj["definitions"], family)) - - # Attributes set - if "attribute-sets" in obj: - lines.append(rst_subtitle("Attribute sets")) - lines.append(parse_attr_sets(obj["attribute-sets"], family)) - - # Sub-messages - if "sub-messages" in obj: - lines.append(rst_subtitle("Sub-messages")) - lines.append(parse_sub_messages(obj["sub-messages"], family)) - - return "\n".join(lines) - - -# Main functions -# =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +from netlink_yml_parser import parse_yaml_file, generate_main_index_rst =20 =20 def parse_arguments() -> argparse.Namespace: @@ -393,50 +65,24 @@ def parse_arguments() -> argparse.Namespace: return args =20 =20 -def parse_yaml_file(filename: str) -> str: - """Transform the YAML specified by filename into an RST-formatted stri= ng""" - with open(filename, "r", encoding=3D"utf-8") as spec_file: - yaml_data =3D yaml.safe_load(spec_file) - content =3D parse_yaml(yaml_data) - - return content - - def write_to_rstfile(content: str, filename: str) -> None: """Write the generated content into an RST file""" logging.debug("Saving RST file to %s", filename) =20 - dir =3D os.path.dirname(filename) - os.makedirs(dir, exist_ok=3DTrue) + directory =3D os.path.dirname(filename) + os.makedirs(directory, exist_ok=3DTrue) =20 with open(filename, "w", encoding=3D"utf-8") as rst_file: rst_file.write(content) =20 =20 -def generate_main_index_rst(output: str, index_dir: str) -> None: +def write_index_rst(output: str, index_dir: str) -> None: """Generate the `networking_spec/index` content and write to the file"= "" - lines =3D [] =20 - lines.append(rst_header()) - lines.append(rst_label("specs")) - lines.append(rst_title("Netlink Family Specifications")) - lines.append(rst_toctree(1)) - - index_fname =3D os.path.basename(output) - base, ext =3D os.path.splitext(index_fname) - - if not index_dir: - index_dir =3D os.path.dirname(output) - - logging.debug(f"Looking for {ext} files in %s", index_dir) - for filename in sorted(os.listdir(index_dir)): - if not filename.endswith(ext) or filename =3D=3D index_fname: - continue - base, ext =3D os.path.splitext(filename) - lines.append(f" {base}\n") + msg =3D generate_main_index_rst(output, index_dir) =20 logging.debug("Writing an index file at %s", output) - write_to_rstfile("".join(lines), output) + write_to_rstfile(msg, output) =20 =20 def main() -> None: @@ -457,7 +103,7 @@ def main() -> None: =20 if args.index: # Generate the index RST file - generate_main_index_rst(args.output, args.input_dir) + write_index_rst(args.output, args.input_dir) =20 =20 if __name__ =3D=3D "__main__": --=20 2.49.0 From nobody Fri Oct 10 09:55:27 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B2B5D28FAAE; Tue, 17 Jun 2025 08:02:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; cv=none; b=nuSNC3oT+q2FjMe1uo19hoCZDL4+9uXWf6tYKY0AyX27Bsrbnh3kbeTeEAIG7SEOrK6F0yl8/88zm/kM60QPftkvDTuoXPDKt4+z/rnE84hArZXtVz1PHacUhJNH7ZjfV9cGmfJZDNK9rDk+mCf84RUBQKHEXjV22aP0DAZqy/4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; c=relaxed/simple; bh=Lbcs43EE24F7v4kZMOpwcJb2G8H6tfac/MUY4SMl3ag=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ehbe8r1MyESZRiWKpkf3JinyiX0jEBxK2Arl8d2rrJH3xX16nZFW+VzOENk/CFT+LZAr5MpEquKZjy1UKsIXnE02PY8sc1lcNfirSzRrAdxUUQIZedZQj7fwYEC+w4LxB+TSIQicHypSsDHgSRPRVIZ+OqglhzyBBkhWpV1W3SM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cC4/kTxi; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="cC4/kTxi" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E9785C4CEF2; Tue, 17 Jun 2025 08:02:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750147352; bh=Lbcs43EE24F7v4kZMOpwcJb2G8H6tfac/MUY4SMl3ag=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cC4/kTxicqF/bIYDWxuiDZdshvwge+dnG7BsB+sX66tCaSnrIgWSpqVqMj8R4SPCQ 7R0UgxYkEjRKUkkICRHMXf9Mi+RQXbyS2NExCkQFkuelD2laCgtjYuRedEHo9w5G27 qdg+86LCpWXrGIuieFeRQLzfmgrWSlw3ef6H/YqYDzdLRBH72Uh3XDaQKmT3Lk0UBI Y/WfGUokWfc42Xr80EvgEzaYf7yf7kTxfj74TDT2TpWvrwHUFJVKvLrgZIHG5iqxua sQcUTqm1/K41akXwpHLFQd0AtlBcDBvxsc9b8lyMu6T8lGWG0MCE3j61GcAsxbxpXm JVRK2lfxHFvhA== Received: from mchehab by mail.kernel.org with local (Exim 4.98.2) (envelope-from ) id 1uRRH4-00000001vdF-0Hkw; Tue, 17 Jun 2025 10:02:30 +0200 From: Mauro Carvalho Chehab To: Linux Doc Mailing List , Jonathan Corbet Cc: Mauro Carvalho Chehab , "Akira Yokosawa" , "Breno Leitao" , "David S. Miller" , "Donald Hunter" , "Eric Dumazet" , "Ignacio Encinas Rubio" , "Jan Stancek" , "Marco Elver" , "Mauro Carvalho Chehab" , "Paolo Abeni" , "Ruben Wauters" , "Shuah Khan" , Jakub Kicinski , Simon Horman , 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: [PATCH v5 07/15] scripts: lib: netlink_yml_parser.py: use classes Date: Tue, 17 Jun 2025 10:02:04 +0200 Message-ID: X-Mailer: git-send-email 2.49.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" As we'll be importing netlink parser into a Sphinx extension, move all functions and global variables inside two classes: - RstFormatters, containing ReST formatter logic, which are YAML independent; - YnlDocGenerator: contains the actual parser classes. That's the only class that needs to be imported by the script or by a Sphinx extension. With that, we won't pollute Sphinx namespace, avoiding any potential clashes. Signed-off-by: Mauro Carvalho Chehab --- tools/net/ynl/pyynl/netlink_yml_parser.py | 594 +++++++++++----------- tools/net/ynl/pyynl/ynl_gen_rst.py | 19 +- 2 files changed, 314 insertions(+), 299 deletions(-) diff --git a/tools/net/ynl/pyynl/netlink_yml_parser.py b/tools/net/ynl/pyyn= l/netlink_yml_parser.py index 3c15b578f947..839e78b39de3 100755 --- a/tools/net/ynl/pyynl/netlink_yml_parser.py +++ b/tools/net/ynl/pyynl/netlink_yml_parser.py @@ -3,389 +3,407 @@ # -*- coding: utf-8; mode: python -*- =20 """ - Script to auto generate the documentation for Netlink specifications. + Class to auto generate the documentation for Netlink specifications. =20 :copyright: Copyright (C) 2023 Breno Leitao :license: GPL Version 2, June 1991 see linux/COPYING for details. =20 - This script performs extensive parsing to the Linux kernel's netlink Y= AML + This class performs extensive parsing to the Linux kernel's netlink YA= ML spec files, in an effort to avoid needing to heavily mark up the origi= nal YAML file. =20 - This code is split in three big parts: + This code is split in two classes: 1) RST formatters: Use to convert a string to a RST output - 2) Parser helpers: Functions to parse the YAML data structure - 3) Main function and small helpers + 2) YAML Netlink (YNL) doc generator: Generate docs from YAML data """ =20 from typing import Any, Dict, List import os.path +import sys +import argparse import logging import yaml =20 =20 -SPACE_PER_LEVEL =3D 4 - - +# =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D # RST Formatters # =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D -def headroom(level: int) -> str: - """Return space to format""" - return " " * (level * SPACE_PER_LEVEL) +class RstFormatters: + SPACE_PER_LEVEL =3D 4 =20 + @staticmethod + def headroom(level: int) -> str: + """Return space to format""" + return " " * (level * RstFormatters.SPACE_PER_LEVEL) =20 -def bold(text: str) -> str: - """Format bold text""" - return f"**{text}**" =20 + @staticmethod + def bold(text: str) -> str: + """Format bold text""" + return f"**{text}**" =20 -def inline(text: str) -> str: - """Format inline text""" - return f"``{text}``" =20 + @staticmethod + def inline(text: str) -> str: + """Format inline text""" + return f"``{text}``" =20 -def sanitize(text: str) -> str: - """Remove newlines and multiple spaces""" - # This is useful for some fields that are spread across multiple lines - return str(text).replace("\n", " ").strip() =20 + @staticmethod + def sanitize(text: str) -> str: + """Remove newlines and multiple spaces""" + # This is useful for some fields that are spread across multiple l= ines + return str(text).replace("\n", " ").strip() =20 -def rst_fields(key: str, value: str, level: int =3D 0) -> str: - """Return a RST formatted field""" - return headroom(level) + f":{key}: {value}" =20 + def rst_fields(self, key: str, value: str, level: int =3D 0) -> str: + """Return a RST formatted field""" + return self.headroom(level) + f":{key}: {value}" =20 -def rst_definition(key: str, value: Any, level: int =3D 0) -> str: - """Format a single rst definition""" - return headroom(level) + key + "\n" + headroom(level + 1) + str(value) =20 + def rst_definition(self, key: str, value: Any, level: int =3D 0) -> st= r: + """Format a single rst definition""" + return self.headroom(level) + key + "\n" + self.headroom(level + 1= ) + str(value) =20 -def rst_paragraph(paragraph: str, level: int =3D 0) -> str: - """Return a formatted paragraph""" - return headroom(level) + paragraph =20 + def rst_paragraph(self, paragraph: str, level: int =3D 0) -> str: + """Return a formatted paragraph""" + return self.headroom(level) + paragraph =20 -def rst_bullet(item: str, level: int =3D 0) -> str: - """Return a formatted a bullet""" - return headroom(level) + f"- {item}" =20 + def rst_bullet(self, item: str, level: int =3D 0) -> str: + """Return a formatted a bullet""" + return self.headroom(level) + f"- {item}" =20 -def rst_subsection(title: str) -> str: - """Add a sub-section to the document""" - return f"{title}\n" + "-" * len(title) =20 + @staticmethod + def rst_subsection(title: str) -> str: + """Add a sub-section to the document""" + return f"{title}\n" + "-" * len(title) =20 -def rst_subsubsection(title: str) -> str: - """Add a sub-sub-section to the document""" - return f"{title}\n" + "~" * len(title) =20 + @staticmethod + def rst_subsubsection(title: str) -> str: + """Add a sub-sub-section to the document""" + return f"{title}\n" + "~" * len(title) =20 -def rst_section(namespace: str, prefix: str, title: str) -> str: - """Add a section to the document""" - return f".. _{namespace}-{prefix}-{title}:\n\n{title}\n" + "=3D" * len= (title) =20 + @staticmethod + def rst_section(namespace: str, prefix: str, title: str) -> str: + """Add a section to the document""" + return f".. _{namespace}-{prefix}-{title}:\n\n{title}\n" + "=3D" *= len(title) =20 -def rst_subtitle(title: str) -> str: - """Add a subtitle to the document""" - return "\n" + "-" * len(title) + f"\n{title}\n" + "-" * len(title) + "= \n\n" =20 + @staticmethod + def rst_subtitle(title: str) -> str: + """Add a subtitle to the document""" + return "\n" + "-" * len(title) + f"\n{title}\n" + "-" * len(title)= + "\n\n" =20 -def rst_title(title: str) -> str: - """Add a title to the document""" - return "=3D" * len(title) + f"\n{title}\n" + "=3D" * len(title) + "\n\= n" =20 + @staticmethod + def rst_title(title: str) -> str: + """Add a title to the document""" + return "=3D" * len(title) + f"\n{title}\n" + "=3D" * len(title) + = "\n\n" =20 -def rst_list_inline(list_: List[str], level: int =3D 0) -> str: - """Format a list using inlines""" - return headroom(level) + "[" + ", ".join(inline(i) for i in list_) + "= ]" =20 + def rst_list_inline(self, list_: List[str], level: int =3D 0) -> str: + """Format a list using inlines""" + return self.headroom(level) + "[" + ", ".join(self.inline(i) for i= in list_) + "]" =20 -def rst_ref(namespace: str, prefix: str, name: str) -> str: - """Add a hyperlink to the document""" - mappings =3D {'enum': 'definition', - 'fixed-header': 'definition', - 'nested-attributes': 'attribute-set', - 'struct': 'definition'} - if prefix in mappings: - prefix =3D mappings[prefix] - return f":ref:`{namespace}-{prefix}-{name}`" =20 + @staticmethod + def rst_ref(namespace: str, prefix: str, name: str) -> str: + """Add a hyperlink to the document""" + mappings =3D {'enum': 'definition', + 'fixed-header': 'definition', + 'nested-attributes': 'attribute-set', + 'struct': 'definition'} + if prefix in mappings: + prefix =3D mappings[prefix] + return f":ref:`{namespace}-{prefix}-{name}`" =20 -def rst_header() -> str: - """The headers for all the auto generated RST files""" - lines =3D [] =20 - lines.append(rst_paragraph(".. SPDX-License-Identifier: GPL-2.0")) - lines.append(rst_paragraph(".. NOTE: This document was auto-generated.= \n\n")) + def rst_header(self) -> str: + """The headers for all the auto generated RST files""" + lines =3D [] =20 - return "\n".join(lines) + lines.append(self.rst_paragraph(".. SPDX-License-Identifier: GPL-2= .0")) + lines.append(self.rst_paragraph(".. NOTE: This document was auto-g= enerated.\n\n")) =20 + return "\n".join(lines) =20 -def rst_toctree(maxdepth: int =3D 2) -> str: - """Generate a toctree RST primitive""" - lines =3D [] =20 - lines.append(".. toctree::") - lines.append(f" :maxdepth: {maxdepth}\n\n") + @staticmethod + def rst_toctree(maxdepth: int =3D 2) -> str: + """Generate a toctree RST primitive""" + lines =3D [] =20 - return "\n".join(lines) + lines.append(".. toctree::") + lines.append(f" :maxdepth: {maxdepth}\n\n") =20 + return "\n".join(lines) =20 -def rst_label(title: str) -> str: - """Return a formatted label""" - return f".. _{title}:\n\n" =20 + @staticmethod + def rst_label(title: str) -> str: + """Return a formatted label""" + return f".. _{title}:\n\n" =20 +# =3D=3D=3D=3D=3D=3D=3D # Parsers # =3D=3D=3D=3D=3D=3D=3D +class YnlDocGenerator: + + fmt =3D RstFormatters() + + def parse_mcast_group(self, mcast_group: List[Dict[str, Any]]) -> str: + """Parse 'multicast' group list and return a formatted string""" + lines =3D [] + for group in mcast_group: + lines.append(self.fmt.rst_bullet(group["name"])) + + return "\n".join(lines) + + + def parse_do(self, do_dict: Dict[str, Any], level: int =3D 0) -> str: + """Parse 'do' section and return a formatted string""" + lines =3D [] + for key in do_dict.keys(): + 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") + else: + lines.append(self.fmt.headroom(level + 2) + do_dict[key] += "\n") + + return "\n".join(lines) + + + def parse_do_attributes(self, attrs: Dict[str, Any], level: int =3D 0)= -> str: + """Parse 'attributes' section""" + if "attributes" not in attrs: + return "" + lines =3D [self.fmt.rst_fields("attributes", self.fmt.rst_list_inl= ine(attrs["attributes"]), level + 1)] + + return "\n".join(lines) + + + def parse_operations(self, operations: List[Dict[str, Any]], namespace= : str) -> str: + """Parse operations block""" + preprocessed =3D ["name", "doc", "title", "do", "dump", "flags"] + linkable =3D ["fixed-header", "attribute-set"] + lines =3D [] + + for operation in operations: + lines.append(self.fmt.rst_section(namespace, 'operation', oper= ation["name"])) + lines.append(self.fmt.rst_paragraph(operation["doc"]) + "\n") + + for key in operation.keys(): + if key in preprocessed: + # Skip the special fields + continue + value =3D operation[key] + if key in linkable: + value =3D self.fmt.rst_ref(namespace, key, value) + lines.append(self.fmt.rst_fields(key, value, 0)) + if 'flags' in operation: + lines.append(self.fmt.rst_fields('flags', self.fmt.rst_lis= t_inline(operation['flags']))) + + if "do" in operation: + lines.append(self.fmt.rst_paragraph(":do:", 0)) + lines.append(self.parse_do(operation["do"], 0)) + if "dump" in operation: + lines.append(self.fmt.rst_paragraph(":dump:", 0)) + lines.append(self.parse_do(operation["dump"], 0)) + + # New line after fields + lines.append("\n") + + return "\n".join(lines) + + + def parse_entries(self, entries: List[Dict[str, Any]], level: int) -> = str: + """Parse a list of entries""" + ignored =3D ["pad"] + lines =3D [] + for entry in entries: + if isinstance(entry, dict): + # entries could be a list or a dictionary + field_name =3D entry.get("name", "") + if field_name in ignored: + continue + type_ =3D entry.get("type") + if type_: + field_name +=3D f" ({self.fmt.inline(type_)})" + lines.append( + self.fmt.rst_fields(field_name, self.fmt.sanitize(entr= y.get("doc", "")), level) + ) + elif isinstance(entry, list): + lines.append(self.fmt.rst_list_inline(entry, level)) + else: + lines.append(self.fmt.rst_bullet(self.fmt.inline(self.fmt.= sanitize(entry)), level)) =20 + lines.append("\n") + return "\n".join(lines) =20 -def parse_mcast_group(mcast_group: List[Dict[str, Any]]) -> str: - """Parse 'multicast' group list and return a formatted string""" - lines =3D [] - for group in mcast_group: - lines.append(rst_bullet(group["name"])) - - return "\n".join(lines) - - -def parse_do(do_dict: Dict[str, Any], level: int =3D 0) -> str: - """Parse 'do' section and return a formatted string""" - lines =3D [] - for key in do_dict.keys(): - lines.append(rst_paragraph(bold(key), level + 1)) - if key in ['request', 'reply']: - lines.append(parse_do_attributes(do_dict[key], level + 1) + "\= n") - else: - lines.append(headroom(level + 2) + do_dict[key] + "\n") - - return "\n".join(lines) - - -def parse_do_attributes(attrs: Dict[str, Any], level: int =3D 0) -> str: - """Parse 'attributes' section""" - if "attributes" not in attrs: - return "" - lines =3D [rst_fields("attributes", rst_list_inline(attrs["attributes"= ]), level + 1)] - - return "\n".join(lines) - - -def parse_operations(operations: List[Dict[str, Any]], namespace: str) -> = str: - """Parse operations block""" - preprocessed =3D ["name", "doc", "title", "do", "dump", "flags"] - linkable =3D ["fixed-header", "attribute-set"] - lines =3D [] - - for operation in operations: - lines.append(rst_section(namespace, 'operation', operation["name"]= )) - lines.append(rst_paragraph(operation["doc"]) + "\n") - - for key in operation.keys(): - if key in preprocessed: - # Skip the special fields - continue - value =3D operation[key] - if key in linkable: - value =3D rst_ref(namespace, key, value) - lines.append(rst_fields(key, value, 0)) - if 'flags' in operation: - lines.append(rst_fields('flags', rst_list_inline(operation['fl= ags']))) - - if "do" in operation: - lines.append(rst_paragraph(":do:", 0)) - lines.append(parse_do(operation["do"], 0)) - if "dump" in operation: - lines.append(rst_paragraph(":dump:", 0)) - lines.append(parse_do(operation["dump"], 0)) =20 - # New line after fields - lines.append("\n") + def parse_definitions(self, defs: Dict[str, Any], namespace: str) -> s= tr: + """Parse definitions section""" + preprocessed =3D ["name", "entries", "members"] + ignored =3D ["render-max"] # This is not printed + lines =3D [] =20 - return "\n".join(lines) - - -def parse_entries(entries: List[Dict[str, Any]], level: int) -> str: - """Parse a list of entries""" - ignored =3D ["pad"] - lines =3D [] - for entry in entries: - if isinstance(entry, dict): - # entries could be a list or a dictionary - field_name =3D entry.get("name", "") - if field_name in ignored: - continue - type_ =3D entry.get("type") - if type_: - field_name +=3D f" ({inline(type_)})" - lines.append( - rst_fields(field_name, sanitize(entry.get("doc", "")), lev= el) - ) - elif isinstance(entry, list): - lines.append(rst_list_inline(entry, level)) - else: - lines.append(rst_bullet(inline(sanitize(entry)), level)) - - lines.append("\n") - return "\n".join(lines) - - -def parse_definitions(defs: Dict[str, Any], namespace: str) -> str: - """Parse definitions section""" - preprocessed =3D ["name", "entries", "members"] - ignored =3D ["render-max"] # This is not printed - lines =3D [] - - for definition in defs: - lines.append(rst_section(namespace, 'definition', definition["name= "])) - for k in definition.keys(): - if k in preprocessed + ignored: - continue - lines.append(rst_fields(k, sanitize(definition[k]), 0)) - - # Field list needs to finish with a new line - lines.append("\n") - if "entries" in definition: - lines.append(rst_paragraph(":entries:", 0)) - lines.append(parse_entries(definition["entries"], 1)) - if "members" in definition: - lines.append(rst_paragraph(":members:", 0)) - lines.append(parse_entries(definition["members"], 1)) - - return "\n".join(lines) - - -def parse_attr_sets(entries: List[Dict[str, Any]], namespace: str) -> str: - """Parse attribute from attribute-set""" - preprocessed =3D ["name", "type"] - linkable =3D ["enum", "nested-attributes", "struct", "sub-message"] - ignored =3D ["checks"] - lines =3D [] - - for entry in entries: - lines.append(rst_section(namespace, 'attribute-set', entry["name"]= )) - for attr in entry["attributes"]: - type_ =3D attr.get("type") - attr_line =3D attr["name"] - if type_: - # Add the attribute type in the same line - attr_line +=3D f" ({inline(type_)})" - - lines.append(rst_subsubsection(attr_line)) - - for k in attr.keys(): + for definition in defs: + lines.append(self.fmt.rst_section(namespace, 'definition', def= inition["name"])) + for k in definition.keys(): if k in preprocessed + ignored: continue - if k in linkable: - value =3D rst_ref(namespace, k, attr[k]) - else: - value =3D sanitize(attr[k]) - lines.append(rst_fields(k, value, 0)) + lines.append(self.fmt.rst_fields(k, self.fmt.sanitize(defi= nition[k]), 0)) + + # Field list needs to finish with a new line lines.append("\n") + if "entries" in definition: + lines.append(self.fmt.rst_paragraph(":entries:", 0)) + lines.append(self.parse_entries(definition["entries"], 1)) + if "members" in definition: + lines.append(self.fmt.rst_paragraph(":members:", 0)) + lines.append(self.parse_entries(definition["members"], 1)) =20 - return "\n".join(lines) + return "\n".join(lines) =20 =20 -def parse_sub_messages(entries: List[Dict[str, Any]], namespace: str) -> s= tr: - """Parse sub-message definitions""" - lines =3D [] + def parse_attr_sets(self, entries: List[Dict[str, Any]], namespace: st= r) -> str: + """Parse attribute from attribute-set""" + preprocessed =3D ["name", "type"] + linkable =3D ["enum", "nested-attributes", "struct", "sub-message"] + ignored =3D ["checks"] + lines =3D [] =20 - for entry in entries: - lines.append(rst_section(namespace, 'sub-message', entry["name"])) - for fmt in entry["formats"]: - value =3D fmt["value"] + for entry in entries: + lines.append(self.fmt.rst_section(namespace, 'attribute-set', = entry["name"])) + for attr in entry["attributes"]: + type_ =3D attr.get("type") + attr_line =3D attr["name"] + if type_: + # Add the attribute type in the same line + attr_line +=3D f" ({self.fmt.inline(type_)})" =20 - lines.append(rst_bullet(bold(value))) - for attr in ['fixed-header', 'attribute-set']: - if attr in fmt: - lines.append(rst_fields(attr, - rst_ref(namespace, attr, fmt[a= ttr]), - 1)) - lines.append("\n") + lines.append(self.fmt.rst_subsubsection(attr_line)) + + for k in attr.keys(): + if k in preprocessed + ignored: + continue + if k in linkable: + value =3D self.fmt.rst_ref(namespace, k, attr[k]) + else: + value =3D self.fmt.sanitize(attr[k]) + lines.append(self.fmt.rst_fields(k, value, 0)) + lines.append("\n") + + return "\n".join(lines) + + + def parse_sub_messages(self, entries: List[Dict[str, Any]], namespace:= str) -> str: + """Parse sub-message definitions""" + lines =3D [] + + for entry in entries: + lines.append(self.fmt.rst_section(namespace, 'sub-message', en= try["name"])) + for fmt in entry["formats"]: + value =3D fmt["value"] + + lines.append(self.fmt.rst_bullet(self.fmt.bold(value))) + for attr in ['fixed-header', 'attribute-set']: + if attr in fmt: + lines.append(self.fmt.rst_fields(attr, + self.fmt.rst_ref(namespace= , attr, fmt[attr]), + 1)) + lines.append("\n") + + return "\n".join(lines) =20 - return "\n".join(lines) =20 + def parse_yaml(self, obj: Dict[str, Any]) -> str: + """Format the whole YAML into a RST string""" + lines =3D [] =20 -def parse_yaml(obj: Dict[str, Any]) -> str: - """Format the whole YAML into a RST string""" - lines =3D [] + # Main header =20 - # Main header + family =3D obj['name'] =20 - family =3D obj['name'] + lines.append(self.fmt.rst_header()) + lines.append(self.fmt.rst_label("netlink-" + family)) =20 - lines.append(rst_header()) - lines.append(rst_label("netlink-" + family)) + title =3D f"Family ``{family}`` netlink specification" + lines.append(self.fmt.rst_title(title)) + lines.append(self.fmt.rst_paragraph(".. contents:: :depth: 3\n")) =20 - title =3D f"Family ``{family}`` netlink specification" - lines.append(rst_title(title)) - lines.append(rst_paragraph(".. contents:: :depth: 3\n")) + if "doc" in obj: + lines.append(self.fmt.rst_subtitle("Summary")) + lines.append(self.fmt.rst_paragraph(obj["doc"], 0)) =20 - if "doc" in obj: - lines.append(rst_subtitle("Summary")) - lines.append(rst_paragraph(obj["doc"], 0)) + # Operations + if "operations" in obj: + lines.append(self.fmt.rst_subtitle("Operations")) + lines.append(self.parse_operations(obj["operations"]["list"], = family)) =20 - # Operations - if "operations" in obj: - lines.append(rst_subtitle("Operations")) - lines.append(parse_operations(obj["operations"]["list"], family)) + # Multicast groups + if "mcast-groups" in obj: + lines.append(self.fmt.rst_subtitle("Multicast groups")) + lines.append(self.parse_mcast_group(obj["mcast-groups"]["list"= ])) =20 - # Multicast groups - if "mcast-groups" in obj: - lines.append(rst_subtitle("Multicast groups")) - lines.append(parse_mcast_group(obj["mcast-groups"]["list"])) + # Definitions + if "definitions" in obj: + lines.append(self.fmt.rst_subtitle("Definitions")) + lines.append(self.parse_definitions(obj["definitions"], family= )) =20 - # Definitions - if "definitions" in obj: - lines.append(rst_subtitle("Definitions")) - lines.append(parse_definitions(obj["definitions"], family)) + # Attributes set + if "attribute-sets" in obj: + lines.append(self.fmt.rst_subtitle("Attribute sets")) + lines.append(self.parse_attr_sets(obj["attribute-sets"], famil= y)) =20 - # Attributes set - if "attribute-sets" in obj: - lines.append(rst_subtitle("Attribute sets")) - lines.append(parse_attr_sets(obj["attribute-sets"], family)) + # Sub-messages + if "sub-messages" in obj: + lines.append(self.fmt.rst_subtitle("Sub-messages")) + lines.append(self.parse_sub_messages(obj["sub-messages"], fami= ly)) =20 - # Sub-messages - if "sub-messages" in obj: - lines.append(rst_subtitle("Sub-messages")) - lines.append(parse_sub_messages(obj["sub-messages"], family)) + return "\n".join(lines) =20 - return "\n".join(lines) =20 + # Main functions + # =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 -# Main functions -# =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 + def parse_yaml_file(self, filename: str) -> str: + """Transform the YAML specified by filename into an RST-formatted = string""" + with open(filename, "r", encoding=3D"utf-8") as spec_file: + yaml_data =3D yaml.safe_load(spec_file) + content =3D self.parse_yaml(yaml_data) =20 -def parse_yaml_file(filename: str) -> str: - """Transform the YAML specified by filename into an RST-formatted stri= ng""" - with open(filename, "r", encoding=3D"utf-8") as spec_file: - yaml_data =3D yaml.safe_load(spec_file) - content =3D parse_yaml(yaml_data) + return content =20 - return content =20 + def generate_main_index_rst(self, output: str, index_dir: str) -> None: + """Generate the `networking_spec/index` content and write to the f= ile""" + lines =3D [] =20 -def generate_main_index_rst(output: str, index_dir: str) -> str: - """Generate the `networking_spec/index` content and write to the file"= "" - lines =3D [] + lines.append(self.fmt.rst_header()) + lines.append(self.fmt.rst_label("specs")) + lines.append(self.fmt.rst_title("Netlink Family Specifications")) + lines.append(self.fmt.rst_toctree(1)) =20 - lines.append(rst_header()) - lines.append(rst_label("specs")) - lines.append(rst_title("Netlink Family Specifications")) - lines.append(rst_toctree(1)) + index_fname =3D os.path.basename(output) + base, ext =3D os.path.splitext(index_fname) =20 - index_fname =3D os.path.basename(output) - base, ext =3D os.path.splitext(index_fname) + if not index_dir: + index_dir =3D os.path.dirname(output) =20 - if not index_dir: - index_dir =3D os.path.dirname(output) + logging.debug(f"Looking for {ext} files in %s", index_dir) + for filename in sorted(os.listdir(index_dir)): + if not filename.endswith(ext) or filename =3D=3D index_fname: + continue + base, ext =3D os.path.splitext(filename) + lines.append(f" {base}\n") =20 - logging.debug(f"Looking for {ext} files in %s", index_dir) - for filename in sorted(os.listdir(index_dir)): - if not filename.endswith(ext) or filename =3D=3D index_fname: - continue - base, ext =3D os.path.splitext(filename) - lines.append(f" {base}\n") + logging.debug("Writing an index file at %s", output) =20 - return "".join(lines), output + return "".join(lines) diff --git a/tools/net/ynl/pyynl/ynl_gen_rst.py b/tools/net/ynl/pyynl/ynl_g= en_rst.py index 38dafe3d9179..624b0960476e 100755 --- a/tools/net/ynl/pyynl/ynl_gen_rst.py +++ b/tools/net/ynl/pyynl/ynl_gen_rst.py @@ -10,12 +10,7 @@ =20 This script performs extensive parsing to the Linux kernel's netlink Y= AML spec files, in an effort to avoid needing to heavily mark up the origi= nal - YAML file. - - This code is split in three big parts: - 1) RST formatters: Use to convert a string to a RST output - 2) Parser helpers: Functions to parse the YAML data structure - 3) Main function and small helpers + YAML file. It uses the library code from scripts/lib. """ =20 import os.path @@ -28,7 +23,7 @@ SRC_DIR =3D os.path.dirname(os.path.realpath(__file__)) =20 sys.path.insert(0, os.path.join(SRC_DIR, LIB_DIR)) =20 -from netlink_yml_parser import parse_yaml_file, generate_main_index_rst +from netlink_yml_parser import YnlDocGenerator =20 =20 def parse_arguments() -> argparse.Namespace: @@ -76,10 +71,10 @@ def write_to_rstfile(content: str, filename: str) -> No= ne: rst_file.write(content) =20 =20 -def write_index_rst(output: str, index_dir: str) -> None: +def write_index_rst(parser: YnlDocGenerator, output: str, index_dir: str) = -> None: """Generate the `networking_spec/index` content and write to the file"= "" =20 - msg =3D generate_main_index_rst(output, index_dir) + msg =3D parser.generate_main_index_rst(output, index_dir) =20 logging.debug("Writing an index file at %s", output) write_to_rstfile(msg, output) @@ -90,10 +85,12 @@ def main() -> None: =20 args =3D parse_arguments() =20 + parser =3D YnlDocGenerator() + if args.input: logging.debug("Parsing %s", args.input) try: - content =3D parse_yaml_file(os.path.join(args.input)) + content =3D parser.parse_yaml_file(os.path.join(args.input)) except Exception as exception: logging.warning("Failed to parse %s.", args.input) logging.warning(exception) @@ -103,7 +100,7 @@ def main() -> None: =20 if args.index: # Generate the index RST file - write_index_rst(args.output, args.input_dir) + write_index_rst(parser, args.output, args.input_dir) =20 =20 if __name__ =3D=3D "__main__": --=20 2.49.0 From nobody Fri Oct 10 09:55:27 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8DFB528F515; Tue, 17 Jun 2025 08:02:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; cv=none; b=IS2LexmFX9vqdr0GVRnl/njieiPcR2YRmoAuA8/dR4WWf5NNWFW8x2DDRuWtBjkW/LwMdf1/K4tIxXtkcAg4uegEVIqrqK2ntxLrbNLHjim/drVgoj7FpRADIausiYlU6/5aITxrZcctqpD1Z7jXqLsxDabuWg/ee4Dpuk4sJ6Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; c=relaxed/simple; bh=X34UFnqM4G4i6Xk/mdPdXBpYZ9AY5zKFdIRSFm6AiUI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oyluKixota0xWT4YcMbpMy6T29W1QMTj/V7JxtyU0B6i3eQwxYOD5isJ3SZ3K0wiVf2ED3U1MVRxgRCsNNTmI9eucLo4chyqt4axhvYD8D8mvQhlWFMlyDho/igSbgJuFOvUtXe0b5y4BamdxS2fhpcXlKTnN0xNtfI2SNhzltU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=a2fhPZq/; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="a2fhPZq/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EEAEEC4CEF7; Tue, 17 Jun 2025 08:02:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750147352; bh=X34UFnqM4G4i6Xk/mdPdXBpYZ9AY5zKFdIRSFm6AiUI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=a2fhPZq/bc7M9i1qhZ/hJFHT5g4IQsbvJPsxhThpAVMqMx9HAzL37UOAzYavJ4eQz RNC9cXETr9u1SwyMjMEYTF4V6SiNGC54QrMBGYoeopVLq9LEvjZ+MYguAHuPks6Pqg MMJTcOCA5IYX8M/vPhQRfuh1G29AsIgBVe7jHKnuvVPV+kyw3e+lO9jcKoH6SNI1wh cE3EsGsWDMx1xgu0t08SuEisedzc42A6OKJjeBFPFsc1umpi8SvEYfBMgkkigY7LzF uEN0TWSrkUXoVEsJfXeDmoaGaZ2FyKH3yvTzMRmVXeoWyW4tVabhr0QhVXWpxM6I1j z7nxx7zcxfdYQ== Received: from mchehab by mail.kernel.org with local (Exim 4.98.2) (envelope-from ) id 1uRRH4-00000001vdI-0PPP; Tue, 17 Jun 2025 10:02:30 +0200 From: Mauro Carvalho Chehab To: Linux Doc Mailing List , Jonathan Corbet Cc: Mauro Carvalho Chehab , "Akira Yokosawa" , "Breno Leitao" , "David S. Miller" , "Donald Hunter" , "Eric Dumazet" , "Ignacio Encinas Rubio" , "Jan Stancek" , "Marco Elver" , "Mauro Carvalho Chehab" , "Paolo Abeni" , "Ruben Wauters" , "Shuah Khan" , Jakub Kicinski , Simon Horman , 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: [PATCH v5 08/15] docs: netlink: index.rst: add a netlink index file Date: Tue, 17 Jun 2025 10:02:05 +0200 Message-ID: <4d8a16864767c1eb660cb905dbc935a3d0df8d9a.1750146719.git.mchehab+huawei@kernel.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" Instead of generating the index file, use glob to automatically include all data from yaml. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Donald Hunter --- Documentation/netlink/specs/index.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 Documentation/netlink/specs/index.rst diff --git a/Documentation/netlink/specs/index.rst b/Documentation/netlink/= specs/index.rst new file mode 100644 index 000000000000..7f7cf4a096f2 --- /dev/null +++ b/Documentation/netlink/specs/index.rst @@ -0,0 +1,13 @@ +.. SPDX-License-Identifier: GPL-2.0 + +.. _specs: + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D +Netlink Family Specifications +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D + +.. toctree:: + :maxdepth: 1 + :glob: + + * --=20 2.49.0 From nobody Fri Oct 10 09:55:27 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C7FB328FFF3; Tue, 17 Jun 2025 08:02:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; cv=none; b=YU1APOlE2/K1FJ7XiKSjZMCwbvQX+fdjZABM53hW0bDz6OyEeznNzY6tHP0qayyeFCjtqRhoSJ/1U2bSRVu9NKSequBP9kFP2vSuPLe9yghcyBbz8mcxXE+/4jynQtX7UujE/p9aIDPlT/HHlp7vy26hMA3Jag6tJCbXPTja0qA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; c=relaxed/simple; bh=iVC0GdftjUz57Jcaq/naOorp34P65m/H+bbrvm2J+Fc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TtB2esjLvdCaan8lwejD66MFbsRBIo5zzzsQOow0t+WhAHdDd7F6D5m5rySResYC6Boe3d0nn0iVxOdroSK9HnbGXUZ6+Wcc/ELAmD9OA8AmbRVLbuCBXOi3cFbda2EPdLg/WmVqxrzyzEjZuFEBD/pWL60SxDMsalsRt85I908= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DSmzQ35B; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DSmzQ35B" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EC52BC4CEF6; Tue, 17 Jun 2025 08:02:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750147352; bh=iVC0GdftjUz57Jcaq/naOorp34P65m/H+bbrvm2J+Fc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DSmzQ35BS+UYLALCVOZIoFHWI8oWmaK3k+xvWA3aTVCQYnqFgZIgTNsokNjFZOqCr tXpOGcApTGWDatdqlpLcn7MFTagWI4TgdGTjUYdNdB1FPR79DYRNsIwfNPi5KBhc41 9MoQSX4mngTCnHCEgX2BTuQ9Vzp/K8gqiGq+RD74xer2xcDlmOoGlLqomgxVANxCVd zOtF5fqIN7OLAQfzF2pCV42/VqtG8U5evo2ltCDOthjXOIe8TGo/6QXqo7J/3aR/eN ppCTf37XxYr73iI3gVKTj1A+DmUbpWyBLJfniMXQFGRI61yK1qfmB6w6JL912jUmFF +KIXrqaXBiksQ== Received: from mchehab by mail.kernel.org with local (Exim 4.98.2) (envelope-from ) id 1uRRH4-00000001vdN-0X8d; Tue, 17 Jun 2025 10:02:30 +0200 From: Mauro Carvalho Chehab To: Linux Doc Mailing List , Jonathan Corbet Cc: Mauro Carvalho Chehab , "Akira Yokosawa" , "Breno Leitao" , "David S. Miller" , "Donald Hunter" , "Eric Dumazet" , "Ignacio Encinas Rubio" , "Jan Stancek" , "Marco Elver" , "Mauro Carvalho Chehab" , "Paolo Abeni" , "Ruben Wauters" , "Shuah Khan" , Jakub Kicinski , Simon Horman , 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: [PATCH v5 09/15] tools: ynl_gen_rst.py: clanup coding style Date: Tue, 17 Jun 2025 10:02:06 +0200 Message-ID: X-Mailer: git-send-email 2.49.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" Cleanup some coding style issues pointed by pylint and flake8. No functional changes. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Breno Leitao --- tools/net/ynl/pyynl/netlink_yml_parser.py | 75 ++++++++--------------- tools/net/ynl/pyynl/ynl_gen_rst.py | 2 +- 2 files changed, 27 insertions(+), 50 deletions(-) diff --git a/tools/net/ynl/pyynl/netlink_yml_parser.py b/tools/net/ynl/pyyn= l/netlink_yml_parser.py index 839e78b39de3..f71360f0ceb7 100755 --- a/tools/net/ynl/pyynl/netlink_yml_parser.py +++ b/tools/net/ynl/pyynl/netlink_yml_parser.py @@ -18,17 +18,12 @@ """ =20 from typing import Any, Dict, List -import os.path -import sys -import argparse -import logging import yaml =20 =20 -# =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D -# RST Formatters -# =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D class RstFormatters: + """RST Formatters""" + SPACE_PER_LEVEL =3D 4 =20 @staticmethod @@ -36,81 +31,67 @@ class RstFormatters: """Return space to format""" return " " * (level * RstFormatters.SPACE_PER_LEVEL) =20 - @staticmethod def bold(text: str) -> str: """Format bold text""" return f"**{text}**" =20 - @staticmethod def inline(text: str) -> str: """Format inline text""" return f"``{text}``" =20 - @staticmethod def sanitize(text: str) -> str: """Remove newlines and multiple spaces""" # This is useful for some fields that are spread across multiple l= ines return str(text).replace("\n", " ").strip() =20 - def rst_fields(self, key: str, value: str, level: int =3D 0) -> str: """Return a RST formatted field""" return self.headroom(level) + f":{key}: {value}" =20 - def rst_definition(self, key: str, value: Any, level: int =3D 0) -> st= r: """Format a single rst definition""" return self.headroom(level) + key + "\n" + self.headroom(level + 1= ) + str(value) =20 - def rst_paragraph(self, paragraph: str, level: int =3D 0) -> str: """Return a formatted paragraph""" return self.headroom(level) + paragraph =20 - def rst_bullet(self, item: str, level: int =3D 0) -> str: """Return a formatted a bullet""" return self.headroom(level) + f"- {item}" =20 - @staticmethod def rst_subsection(title: str) -> str: """Add a sub-section to the document""" return f"{title}\n" + "-" * len(title) =20 - @staticmethod def rst_subsubsection(title: str) -> str: """Add a sub-sub-section to the document""" return f"{title}\n" + "~" * len(title) =20 - @staticmethod def rst_section(namespace: str, prefix: str, title: str) -> str: """Add a section to the document""" return f".. _{namespace}-{prefix}-{title}:\n\n{title}\n" + "=3D" *= len(title) =20 - @staticmethod def rst_subtitle(title: str) -> str: """Add a subtitle to the document""" return "\n" + "-" * len(title) + f"\n{title}\n" + "-" * len(title)= + "\n\n" =20 - @staticmethod def rst_title(title: str) -> str: """Add a title to the document""" return "=3D" * len(title) + f"\n{title}\n" + "=3D" * len(title) + = "\n\n" =20 - def rst_list_inline(self, list_: List[str], level: int =3D 0) -> str: """Format a list using inlines""" return self.headroom(level) + "[" + ", ".join(self.inline(i) for i= in list_) + "]" =20 - @staticmethod def rst_ref(namespace: str, prefix: str, name: str) -> str: """Add a hyperlink to the document""" @@ -119,10 +100,9 @@ class RstFormatters: 'nested-attributes': 'attribute-set', 'struct': 'definition'} if prefix in mappings: - prefix =3D mappings[prefix] + prefix =3D mappings.get(prefix, "") return f":ref:`{namespace}-{prefix}-{name}`" =20 - def rst_header(self) -> str: """The headers for all the auto generated RST files""" lines =3D [] @@ -132,7 +112,6 @@ class RstFormatters: =20 return "\n".join(lines) =20 - @staticmethod def rst_toctree(maxdepth: int =3D 2) -> str: """Generate a toctree RST primitive""" @@ -143,16 +122,13 @@ class RstFormatters: =20 return "\n".join(lines) =20 - @staticmethod def rst_label(title: str) -> str: """Return a formatted label""" return f".. _{title}:\n\n" =20 -# =3D=3D=3D=3D=3D=3D=3D -# Parsers -# =3D=3D=3D=3D=3D=3D=3D class YnlDocGenerator: + """YAML Netlink specs Parser""" =20 fmt =3D RstFormatters() =20 @@ -164,7 +140,6 @@ class YnlDocGenerator: =20 return "\n".join(lines) =20 - def parse_do(self, do_dict: Dict[str, Any], level: int =3D 0) -> str: """Parse 'do' section and return a formatted string""" lines =3D [] @@ -177,16 +152,16 @@ class YnlDocGenerator: =20 return "\n".join(lines) =20 - def parse_do_attributes(self, attrs: Dict[str, Any], level: int =3D 0)= -> str: """Parse 'attributes' section""" if "attributes" not in attrs: return "" - lines =3D [self.fmt.rst_fields("attributes", self.fmt.rst_list_inl= ine(attrs["attributes"]), level + 1)] + lines =3D [self.fmt.rst_fields("attributes", + self.fmt.rst_list_inline(attrs["attri= butes"]), + level + 1)] =20 return "\n".join(lines) =20 - def parse_operations(self, operations: List[Dict[str, Any]], namespace= : str) -> str: """Parse operations block""" preprocessed =3D ["name", "doc", "title", "do", "dump", "flags"] @@ -194,7 +169,8 @@ class YnlDocGenerator: lines =3D [] =20 for operation in operations: - lines.append(self.fmt.rst_section(namespace, 'operation', oper= ation["name"])) + lines.append(self.fmt.rst_section(namespace, 'operation', + operation["name"])) lines.append(self.fmt.rst_paragraph(operation["doc"]) + "\n") =20 for key in operation.keys(): @@ -206,7 +182,8 @@ class YnlDocGenerator: value =3D self.fmt.rst_ref(namespace, key, value) lines.append(self.fmt.rst_fields(key, value, 0)) if 'flags' in operation: - lines.append(self.fmt.rst_fields('flags', self.fmt.rst_lis= t_inline(operation['flags']))) + lines.append(self.fmt.rst_fields('flags', + self.fmt.rst_list_inline(= operation['flags']))) =20 if "do" in operation: lines.append(self.fmt.rst_paragraph(":do:", 0)) @@ -220,7 +197,6 @@ class YnlDocGenerator: =20 return "\n".join(lines) =20 - def parse_entries(self, entries: List[Dict[str, Any]], level: int) -> = str: """Parse a list of entries""" ignored =3D ["pad"] @@ -235,17 +211,19 @@ class YnlDocGenerator: if type_: field_name +=3D f" ({self.fmt.inline(type_)})" lines.append( - self.fmt.rst_fields(field_name, self.fmt.sanitize(entr= y.get("doc", "")), level) + self.fmt.rst_fields(field_name, + self.fmt.sanitize(entry.get("doc",= "")), + level) ) elif isinstance(entry, list): lines.append(self.fmt.rst_list_inline(entry, level)) else: - lines.append(self.fmt.rst_bullet(self.fmt.inline(self.fmt.= sanitize(entry)), level)) + lines.append(self.fmt.rst_bullet(self.fmt.inline(self.fmt.= sanitize(entry)), + level)) =20 lines.append("\n") return "\n".join(lines) =20 - def parse_definitions(self, defs: Dict[str, Any], namespace: str) -> s= tr: """Parse definitions section""" preprocessed =3D ["name", "entries", "members"] @@ -270,7 +248,6 @@ class YnlDocGenerator: =20 return "\n".join(lines) =20 - def parse_attr_sets(self, entries: List[Dict[str, Any]], namespace: st= r) -> str: """Parse attribute from attribute-set""" preprocessed =3D ["name", "type"] @@ -279,7 +256,8 @@ class YnlDocGenerator: lines =3D [] =20 for entry in entries: - lines.append(self.fmt.rst_section(namespace, 'attribute-set', = entry["name"])) + lines.append(self.fmt.rst_section(namespace, 'attribute-set', + entry["name"])) for attr in entry["attributes"]: type_ =3D attr.get("type") attr_line =3D attr["name"] @@ -301,13 +279,13 @@ class YnlDocGenerator: =20 return "\n".join(lines) =20 - def parse_sub_messages(self, entries: List[Dict[str, Any]], namespace:= str) -> str: """Parse sub-message definitions""" lines =3D [] =20 for entry in entries: - lines.append(self.fmt.rst_section(namespace, 'sub-message', en= try["name"])) + lines.append(self.fmt.rst_section(namespace, 'sub-message', + entry["name"])) for fmt in entry["formats"]: value =3D fmt["value"] =20 @@ -315,13 +293,14 @@ class YnlDocGenerator: for attr in ['fixed-header', 'attribute-set']: if attr in fmt: lines.append(self.fmt.rst_fields(attr, - self.fmt.rst_ref(namespace= , attr, fmt[attr]), - 1)) + self.fmt.rst_ref(= namespace, + = attr, + = fmt[attr]), + 1)) lines.append("\n") =20 return "\n".join(lines) =20 - def parse_yaml(self, obj: Dict[str, Any]) -> str: """Format the whole YAML into a RST string""" lines =3D [] @@ -344,7 +323,8 @@ class YnlDocGenerator: # Operations if "operations" in obj: lines.append(self.fmt.rst_subtitle("Operations")) - lines.append(self.parse_operations(obj["operations"]["list"], = family)) + lines.append(self.parse_operations(obj["operations"]["list"], + family)) =20 # Multicast groups if "mcast-groups" in obj: @@ -368,11 +348,9 @@ class YnlDocGenerator: =20 return "\n".join(lines) =20 - # Main functions # =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 - def parse_yaml_file(self, filename: str) -> str: """Transform the YAML specified by filename into an RST-formatted = string""" with open(filename, "r", encoding=3D"utf-8") as spec_file: @@ -381,7 +359,6 @@ class YnlDocGenerator: =20 return content =20 - def generate_main_index_rst(self, output: str, index_dir: str) -> None: """Generate the `networking_spec/index` content and write to the f= ile""" lines =3D [] diff --git a/tools/net/ynl/pyynl/ynl_gen_rst.py b/tools/net/ynl/pyynl/ynl_g= en_rst.py index 624b0960476e..5d29ce01c60c 100755 --- a/tools/net/ynl/pyynl/ynl_gen_rst.py +++ b/tools/net/ynl/pyynl/ynl_gen_rst.py @@ -23,7 +23,7 @@ SRC_DIR =3D os.path.dirname(os.path.realpath(__file__)) =20 sys.path.insert(0, os.path.join(SRC_DIR, LIB_DIR)) =20 -from netlink_yml_parser import YnlDocGenerator +from netlink_yml_parser import YnlDocGenerator # pylint: disable=3D= C0413 =20 =20 def parse_arguments() -> argparse.Namespace: --=20 2.49.0 From nobody Fri Oct 10 09:55:27 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8E11B28F519; Tue, 17 Jun 2025 08:02:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; cv=none; b=AVjtlTiWrX9lhP0xYEPmDYTj2V+Mj8/4IoSp5SX4gba/BDhzQ2YUHJT3/J9n300ppS2pvKtEP1vGmjmJHsXStAXYPr6oDCrpWNAU6S7p38fSStqpwYAXZpUl2rG9xWGTHoVgxmzdaGEHgNS2m9tTuc9j33DefnABge1U460nePA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; c=relaxed/simple; bh=2WQh1GG+XNK0Cdx26utHd/0dTt1jIj+urA1wFYdPe3Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=M0zkdPqWk5NEGPCtBclHE43gRrmv6SjcmFuJs7TJciRAHkocPdDXn8oJsJa5ntxmIAuDjjasFXbLw5u2G6IBxYJ8CxUbOhiRPOmkToGu/It2aPaEXnAAtc+pm1cbtA84bZmYmDd9l3PCJndPwT5/nzfp87ukrGp3khuA5P7OMtM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LTiDICqO; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LTiDICqO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E65ABC4CEF3; Tue, 17 Jun 2025 08:02:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750147352; bh=2WQh1GG+XNK0Cdx26utHd/0dTt1jIj+urA1wFYdPe3Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LTiDICqOpYDUvE5CADJ2LGOtRNcPzKG80RuZ1QmkaFxusoTbJQM5kWX3EclidDS1L oXR7WLhWBxchtBooUtR0Uu3LtLChyClw2s8ImGRxWJXREhtd1yB9xiXcZUsXVYYLbx t/FKLv8ManueGX1Js26Bh14UGsTfkTH+GFEhBQjZYglysvHl+ER/a49DXfsAoVQ6ks erGLLcFpbjrqj4Ya7a2h8Sd3CiO3NT69UH4OHysfzWtIeqdZM3qpOOsIULGQ4lZ3YN vLb+r7y6ATEApOZYgtok00/8yISqGMzQLOcvdztZ3YMBzo+Y2qkylj5fICaNPA9yCW hxSOENK7Yp2MA== Received: from mchehab by mail.kernel.org with local (Exim 4.98.2) (envelope-from ) id 1uRRH4-00000001vdQ-0eUZ; Tue, 17 Jun 2025 10:02:30 +0200 From: Mauro Carvalho Chehab To: Linux Doc Mailing List , Jonathan Corbet Cc: Mauro Carvalho Chehab , "Akira Yokosawa" , "Breno Leitao" , "David S. Miller" , "Donald Hunter" , "Eric Dumazet" , "Ignacio Encinas Rubio" , "Jan Stancek" , "Marco Elver" , "Mauro Carvalho Chehab" , "Paolo Abeni" , "Ruben Wauters" , "Shuah Khan" , 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: [PATCH v5 10/15] docs: sphinx: add a parser for yaml files for Netlink specs Date: Tue, 17 Jun 2025 10:02:07 +0200 Message-ID: X-Mailer: git-send-email 2.49.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" Add a simple sphinx.Parser to handle yaml files and add the the code to handle Netlink specs. All other yaml files are ignored. The code was written in a way that parsing yaml for different subsystems and even for different parts of Netlink are easy. All it takes to have a different parser is to add an import line similar to: from netlink_yml_parser import YnlDocGenerator adding the corresponding parser somewhere at the extension: netlink_parser =3D YnlDocGenerator() And then add a logic inside parse() to handle different doc outputs, depending on the file location, similar to: if "/netlink/specs/" in fname: msg =3D self.netlink_parser.parse_yaml_file(fname) Signed-off-by: Mauro Carvalho Chehab --- Documentation/sphinx/parser_yaml.py | 76 +++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100755 Documentation/sphinx/parser_yaml.py diff --git a/Documentation/sphinx/parser_yaml.py b/Documentation/sphinx/par= ser_yaml.py new file mode 100755 index 000000000000..635945e1c5ba --- /dev/null +++ b/Documentation/sphinx/parser_yaml.py @@ -0,0 +1,76 @@ +""" +Sphinx extension for processing YAML files +""" + +import os +import re +import sys + +from pprint import pformat + +from docutils.parsers.rst import Parser as RSTParser +from docutils.statemachine import ViewList + +from sphinx.util import logging +from sphinx.parsers import Parser + +srctree =3D os.path.abspath(os.environ["srctree"]) +sys.path.insert(0, os.path.join(srctree, "tools/net/ynl/pyynl")) + +from netlink_yml_parser import YnlDocGenerator # pylint: disable=3D= C0413 + +logger =3D logging.getLogger(__name__) + +class YamlParser(Parser): + """Custom parser for YAML files.""" + + # Need at least two elements on this set + supported =3D ('yaml', 'yml') + + netlink_parser =3D YnlDocGenerator() + + def do_parse(self, inputstring, document, msg): + """Parse YAML and generate a document tree.""" + + self.setup_parse(inputstring, document) + + result =3D ViewList() + + try: + # Parse message with RSTParser + for i, line in enumerate(msg.split('\n')): + result.append(line, document.current_source, i) + + rst_parser =3D RSTParser() + rst_parser.parse('\n'.join(result), document) + + except Exception as e: + document.reporter.error("YAML parsing error: %s" % pformat(e)) + + self.finish_parse() + + # Overrides docutils.parsers.Parser. See sphinx.parsers.RSTParser + def parse(self, inputstring, document): + """Check if a YAML is meant to be parsed.""" + + fname =3D document.current_source + + # Handle netlink yaml specs + if "/netlink/specs/" in fname: + msg =3D self.netlink_parser.parse_yaml_file(fname) + self.do_parse(inputstring, document, msg) + + # All other yaml files are ignored + +def setup(app): + """Setup function for the Sphinx extension.""" + + # Add YAML parser + app.add_source_parser(YamlParser) + app.add_source_suffix('.yaml', 'yaml') + + return { + 'version': '1.0', + 'parallel_read_safe': True, + 'parallel_write_safe': True, + } --=20 2.49.0 From nobody Fri Oct 10 09:55:27 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7A4C428DB76; Tue, 17 Jun 2025 08:02:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; cv=none; b=ej9zQdPGae2DdJ/7feiOfspVWtbfdb+ShqnJrNInVgt+6QtqAyTvRFcH2XHUaonXmIpj3PM6wljMCDGYzVyvEGf0R/EO2WRsZqJXA2veEtWWjc86BxU3W1KCAptaFBU9qZ2AcOnhIVj8MgAFDVuCwZH5QSebYK6aIJnP6ZCSHrM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; c=relaxed/simple; bh=kQHlY3bWllau5HvjKpHpFCWRhH0lO7fc0jbc3mDapcU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pqqcQzLltLshKMN8ZR1FaEhY/IlZOOEC/71UeE9Njy1Wj7JLIuZB4uQ7CCpkRX8NfZ4PqvceenYoXvYkPKiIKhnLYI444V9T2wUx/EQ/lqlpbuhVVPPXP2QZ03QGSM2F/NEaJcldT/9rd7l16g8ACazqJpqOvo02dsKlzzb0GLQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=T89YkpEh; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="T89YkpEh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F1369C4AF0C; Tue, 17 Jun 2025 08:02:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750147352; bh=kQHlY3bWllau5HvjKpHpFCWRhH0lO7fc0jbc3mDapcU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=T89YkpEh+yt7E9PInVmtgyC2VDTBKs7zzPkmPoAaZkLz2LrXbXnwfVDE70OlWLtx+ 0jAotLmsVKi6yOsZEyptFffUQ1BcuiT3JB47zpJX7OiVAixDEcAGmse7HKKgi6aU2t uv/nlmr1d1120spfzMgqt/i3mxqcv0jSr62cRcvv6zTm5P6S16Tf13J6BeYV1HU8Tz xOVRVkNdJEUYc7CRgh3H0ug3WO9x+LH1QWW/Ev9H/mJj3b1mU8vHo5woYxJVE9ZMcI TTgWuokyEo1obBsCVkRB2vKs1ErAjDWp/+sQDX/L3AuCSVSa0BFkD8gjMDqedlbcqX Kzm4OUdAYHiDg== Received: from mchehab by mail.kernel.org with local (Exim 4.98.2) (envelope-from ) id 1uRRH4-00000001vdV-0m2s; Tue, 17 Jun 2025 10:02:30 +0200 From: Mauro Carvalho Chehab To: Linux Doc Mailing List , Jonathan Corbet Cc: Mauro Carvalho Chehab , "Akira Yokosawa" , "Breno Leitao" , "David S. Miller" , "Donald Hunter" , "Eric Dumazet" , "Ignacio Encinas Rubio" , "Jan Stancek" , "Marco Elver" , "Mauro Carvalho Chehab" , "Paolo Abeni" , "Ruben Wauters" , "Shuah Khan" , Jakub Kicinski , Simon Horman , 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: [PATCH v5 11/15] docs: use parser_yaml extension to handle Netlink specs Date: Tue, 17 Jun 2025 10:02:08 +0200 Message-ID: X-Mailer: git-send-email 2.49.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" Instead of manually calling ynl_gen_rst.py, use a Sphinx extension. This way, no .rst files would be written to the Kernel source directories. We are using here a toctree with :glob: property. This way, there is no need to touch the netlink/specs/index.rst file every time a new Netlink spec is added/renamed/removed. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Donald Hunter --- Documentation/Makefile | 17 ----------------- Documentation/conf.py | 13 +++++++------ Documentation/networking/index.rst | 2 +- .../networking/netlink_spec/readme.txt | 4 ---- 4 files changed, 8 insertions(+), 28 deletions(-) delete mode 100644 Documentation/networking/netlink_spec/readme.txt diff --git a/Documentation/Makefile b/Documentation/Makefile index b98477df5ddf..820f07e0afe6 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -104,22 +104,6 @@ quiet_cmd_sphinx =3D SPHINX $@ --> file://$(abspath $= (BUILDDIR)/$3/$4) cp $(if $(patsubst /%,,$(DOCS_CSS)),$(abspath $(srctree)/$(DOCS_CSS)),$(= DOCS_CSS)) $(BUILDDIR)/$3/_static/; \ fi =20 -YNL_INDEX:=3D$(srctree)/Documentation/networking/netlink_spec/index.rst -YNL_RST_DIR:=3D$(srctree)/Documentation/networking/netlink_spec -YNL_YAML_DIR:=3D$(srctree)/Documentation/netlink/specs -YNL_TOOL:=3D$(srctree)/tools/net/ynl/pyynl/ynl_gen_rst.py - -YNL_RST_FILES_TMP :=3D $(patsubst %.yaml,%.rst,$(wildcard $(YNL_YAML_DIR)/= *.yaml)) -YNL_RST_FILES :=3D $(patsubst $(YNL_YAML_DIR)%,$(YNL_RST_DIR)%, $(YNL_RST_= FILES_TMP)) - -$(YNL_INDEX): $(YNL_RST_FILES) - $(Q)$(YNL_TOOL) -o $@ -x - -$(YNL_RST_DIR)/%.rst: $(YNL_YAML_DIR)/%.yaml $(YNL_TOOL) - $(Q)$(YNL_TOOL) -i $< -o $@ - -htmldocs texinfodocs latexdocs epubdocs xmldocs: $(YNL_INDEX) - htmldocs: @$(srctree)/scripts/sphinx-pre-install --version-check @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,html,$(var),,$(var))) @@ -186,7 +170,6 @@ refcheckdocs: $(Q)cd $(srctree);scripts/documentation-file-ref-check =20 cleandocs: - $(Q)rm -f $(YNL_INDEX) $(YNL_RST_FILES) $(Q)rm -rf $(BUILDDIR) $(Q)$(MAKE) BUILDDIR=3D$(abspath $(BUILDDIR)) $(build)=3DDocumentation/us= erspace-api/media clean =20 diff --git a/Documentation/conf.py b/Documentation/conf.py index e887c1b786a4..a17940ac730f 100644 --- a/Documentation/conf.py +++ b/Documentation/conf.py @@ -25,7 +25,7 @@ include_patterns =3D ['**.rst'] exclude_patterns =3D [] =20 # List of patterns that contain directory names in glob format. -dyn_include_patterns =3D [] +dyn_include_patterns =3D ['netlink/specs/*.yaml'] dyn_exclude_patterns =3D ['output'] =20 # Properly handle include/exclude patterns @@ -93,7 +93,7 @@ needs_sphinx =3D '3.4.3' extensions =3D ['kerneldoc', 'rstFlatTable', 'kernel_include', 'kfigure', 'sphinx.ext.ifconfig', 'automarkup', 'maintainers_include', 'sphinx.ext.autosectionlabel', - 'kernel_abi', 'kernel_feat', 'translations'] + 'kernel_abi', 'kernel_feat', 'translations', 'parser_yaml'] =20 # Since Sphinx version 3, the C function parser is more pedantic with rega= rds # to type checking. Due to that, having macros at c:function cause problem= s. @@ -191,10 +191,11 @@ else: # Add any paths that contain templates here, relative to this directory. templates_path =3D ['sphinx/templates'] =20 -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# source_suffix =3D ['.rst', '.md'] -source_suffix =3D '.rst' +# The suffixes of source filenames that will be automatically parsed +source_suffix =3D { + '.rst': 'restructuredtext', + '.yaml': 'yaml', +} =20 # The encoding of source files. #source_encoding =3D 'utf-8-sig' diff --git a/Documentation/networking/index.rst b/Documentation/networking/= index.rst index ac90b82f3ce9..b7a4969e9bc9 100644 --- a/Documentation/networking/index.rst +++ b/Documentation/networking/index.rst @@ -57,7 +57,7 @@ Contents: filter generic-hdlc generic_netlink - netlink_spec/index + ../netlink/specs/index gen_stats gtp ila diff --git a/Documentation/networking/netlink_spec/readme.txt b/Documentati= on/networking/netlink_spec/readme.txt deleted file mode 100644 index 030b44aca4e6..000000000000 --- a/Documentation/networking/netlink_spec/readme.txt +++ /dev/null @@ -1,4 +0,0 @@ -SPDX-License-Identifier: GPL-2.0 - -This file is populated during the build of the documentation (htmldocs) by= the -tools/net/ynl/pyynl/ynl_gen_rst.py script. --=20 2.49.0 From nobody Fri Oct 10 09:55:27 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8E4FA28F51B; Tue, 17 Jun 2025 08:02:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; cv=none; b=ZY+c43CbIeFr7goR+b3pdEUUGRQMxKAjZBgJgbmE/g3+BLjrqXF4GSBgGHPmYKb6lEW8apHoCnBmtvvOmbq2xYOUrpchkrIVVOC0kiU3shZUscWjyXswmOEsQ987H/Lb5Xd710YJqPnjTfYBYf+9seLgmWPY8JSE7KU9jmhpaSw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; c=relaxed/simple; bh=00F9KG3FuikbC/77I/aVEWzxRtC/68GGYQsrs3gqu00=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=n28cdbUGChDvhbFlT69pJVrR2gTKH6MK4GheD1avy0gE/Jgjx3myXRhkv7y0eKD9TObmUAdu+eCR+re76WHsgOeSBookCeFCAF3Ih8gLwq870jxuZvZGKGH+Y1NDidrYbrN60dX8ls2qu0AyuvEd6PbEgAbYsTj3ZsSOyoFyhXg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TwuajmCw; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="TwuajmCw" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F2B69C4CEF5; Tue, 17 Jun 2025 08:02:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750147352; bh=00F9KG3FuikbC/77I/aVEWzxRtC/68GGYQsrs3gqu00=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TwuajmCwI0oYrAjWxUXovlNWnhKTzm3MsHRU/cSDm+wvx4aELova1XQHPzzCBgo/U 1R/UVYEOR291s1EwlmG7TOERRgb+XHPnDHi+yrNY7uyL+LlqcNmACTRq3R7ytci+I/ 0bw4kjF5yHg0CsmipHj2lnsfQHkyOllZzEN6w4xBSA4cVmCc/PUKpoIF+xVF5QCVff A2xvY63Ya2RqF69ElOrAO/jbHUXzteiJfw0PK4jKcittts7SzSFnb835GQGbHTtjUO k7uxQslvrUYYEiRd3d1OAqabrZvWwAbjTs5lWmuRS5iVnFX1GfUn3qTpCdxf6F5KR6 OPYqpNxk3J2XA== Received: from mchehab by mail.kernel.org with local (Exim 4.98.2) (envelope-from ) id 1uRRH4-00000001vdY-0tj6; Tue, 17 Jun 2025 10:02:30 +0200 From: Mauro Carvalho Chehab To: Linux Doc Mailing List , Jonathan Corbet Cc: Mauro Carvalho Chehab , "Akira Yokosawa" , "Breno Leitao" , "David S. Miller" , "Donald Hunter" , "Eric Dumazet" , "Ignacio Encinas Rubio" , "Jan Stancek" , "Marco Elver" , "Mauro Carvalho Chehab" , "Paolo Abeni" , "Ruben Wauters" , "Shuah Khan" , Jakub Kicinski , Simon Horman , 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: [PATCH v5 12/15] docs: uapi: netlink: update netlink specs link Date: Tue, 17 Jun 2025 10:02:09 +0200 Message-ID: <33f4626404cc92ee3f3aab481a8d163e9b4a0f6c.1750146719.git.mchehab+huawei@kernel.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" With the recent parser_yaml extension, and the removal of the auto-generated ReST source files, the location of netlink specs changed. Update uAPI accordingly. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Donald Hunter --- Documentation/userspace-api/netlink/index.rst | 2 +- Documentation/userspace-api/netlink/specs.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/userspace-api/netlink/index.rst b/Documentation/= userspace-api/netlink/index.rst index c1b6765cc963..83ae25066591 100644 --- a/Documentation/userspace-api/netlink/index.rst +++ b/Documentation/userspace-api/netlink/index.rst @@ -18,4 +18,4 @@ Netlink documentation for users. =20 See also: - :ref:`Documentation/core-api/netlink.rst ` - - :ref:`Documentation/networking/netlink_spec/index.rst ` + - :ref:`Documentation/netlink/specs/index.rst ` diff --git a/Documentation/userspace-api/netlink/specs.rst b/Documentation/= userspace-api/netlink/specs.rst index 1b50d97d8d7c..debb4bfca5c4 100644 --- a/Documentation/userspace-api/netlink/specs.rst +++ b/Documentation/userspace-api/netlink/specs.rst @@ -15,7 +15,7 @@ kernel headers directly. Internally kernel uses the YAML specs to generate: =20 - the C uAPI header - - documentation of the protocol as a ReST file - see :ref:`Documentation/= networking/netlink_spec/index.rst ` + - documentation of the protocol as a ReST file - see :ref:`Documentation/= netlink/specs/index.rst ` - policy tables for input attribute validation - operation tables =20 --=20 2.49.0 From nobody Fri Oct 10 09:55:27 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8FE5C28F523; Tue, 17 Jun 2025 08:02:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; cv=none; b=LKX9J5rqMmZ17iYuOXPNRfx+YsriOtwki1IaDbq83+k6UOSVKSYid4kvhhmw3LHsn38hMz6ddrqg9GqDyTjRCMHsOJ+uoVn25pdMMRIR2DOoL8PCiv2SuAUm0dbjtI1E6/OVsODIVjINvTnnhHiDNr5daG+tXVetG4fTV51i3q4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; c=relaxed/simple; bh=C7lqrDjzDa02WPrVr/CYc29SDHPtcet6G1AKkNphAuc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FUTtvOgYCeuBi7qZKqmK40t/cvSRzrBNx6uHx/S4V1dWWYLaD5U3OLtkORlfhmFZHSMQ7eT1c8SXF1GzNovdaFBa7iOSiQi7jcOmRTEUNhI8BCx5+lEms/m3mrQExLSMgdlXY861sGsqKJodovKUGgJovWqKX8kmxiWO7kCBvD8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FMBM/Oze; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FMBM/Oze" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 02ED8C4CEF8; Tue, 17 Jun 2025 08:02:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750147352; bh=C7lqrDjzDa02WPrVr/CYc29SDHPtcet6G1AKkNphAuc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FMBM/OzeZpbZ6Um9QokRlMfbRtVUJ16O25+5MicNyI/Nd+r+QW6IDIeFM2CH0BDW5 a7Faw+3aLEDR1Tc8mRQ45U+tasXtppQjzmkxvLeAtcWWRSQDy9K2q+JWXUWiEAV/si ZWz+Tm0EYnZYEVA20taQLW4BotFu1NHR8bc8KHdCIlDhxqRELnK2Mc/5Vdonka9QaB ppFAggD1EnxI1MFrmfed3bxakVgTXaMW42TtaNkCarx3G0X5+Dpqnu2kZ+kLTcGWd2 +iEVI4Z5a+u8GYWy4qs+8J6oK1/EfIpdQHDw9AVlV3i9tQxGPteX7XrPDbvTcSgiYr HyH/uD78Yd2nw== Received: from mchehab by mail.kernel.org with local (Exim 4.98.2) (envelope-from ) id 1uRRH4-00000001vdc-11Nz; Tue, 17 Jun 2025 10:02:30 +0200 From: Mauro Carvalho Chehab To: Linux Doc Mailing List , Jonathan Corbet Cc: Mauro Carvalho Chehab , "Akira Yokosawa" , "Breno Leitao" , "David S. Miller" , "Donald Hunter" , "Eric Dumazet" , "Ignacio Encinas Rubio" , "Jan Stancek" , "Marco Elver" , "Mauro Carvalho Chehab" , "Paolo Abeni" , "Ruben Wauters" , "Shuah Khan" , Jakub Kicinski , Simon Horman , 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: [PATCH v5 13/15] tools: ynl_gen_rst.py: drop support for generating index files Date: Tue, 17 Jun 2025 10:02:10 +0200 Message-ID: <4cf209151b11701a0dbf53aa4da95784d2927b63.1750146719.git.mchehab+huawei@kernel.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" As we're now using an index file with a glob, there's no need to generate index files anymore. Signed-off-by: Mauro Carvalho Chehab --- tools/net/ynl/pyynl/netlink_yml_parser.py | 26 ----------------------- tools/net/ynl/pyynl/ynl_gen_rst.py | 17 --------------- 2 files changed, 43 deletions(-) diff --git a/tools/net/ynl/pyynl/netlink_yml_parser.py b/tools/net/ynl/pyyn= l/netlink_yml_parser.py index f71360f0ceb7..866551726723 100755 --- a/tools/net/ynl/pyynl/netlink_yml_parser.py +++ b/tools/net/ynl/pyynl/netlink_yml_parser.py @@ -358,29 +358,3 @@ class YnlDocGenerator: content =3D self.parse_yaml(yaml_data) =20 return content - - def generate_main_index_rst(self, output: str, index_dir: str) -> None: - """Generate the `networking_spec/index` content and write to the f= ile""" - lines =3D [] - - lines.append(self.fmt.rst_header()) - lines.append(self.fmt.rst_label("specs")) - lines.append(self.fmt.rst_title("Netlink Family Specifications")) - lines.append(self.fmt.rst_toctree(1)) - - index_fname =3D os.path.basename(output) - base, ext =3D os.path.splitext(index_fname) - - if not index_dir: - index_dir =3D os.path.dirname(output) - - logging.debug(f"Looking for {ext} files in %s", index_dir) - for filename in sorted(os.listdir(index_dir)): - if not filename.endswith(ext) or filename =3D=3D index_fname: - continue - base, ext =3D os.path.splitext(filename) - lines.append(f" {base}\n") - - logging.debug("Writing an index file at %s", output) - - return "".join(lines) diff --git a/tools/net/ynl/pyynl/ynl_gen_rst.py b/tools/net/ynl/pyynl/ynl_g= en_rst.py index 5d29ce01c60c..9e756d3c403d 100755 --- a/tools/net/ynl/pyynl/ynl_gen_rst.py +++ b/tools/net/ynl/pyynl/ynl_gen_rst.py @@ -32,13 +32,9 @@ def parse_arguments() -> argparse.Namespace: =20 parser.add_argument("-v", "--verbose", action=3D"store_true") parser.add_argument("-o", "--output", help=3D"Output file name") - parser.add_argument("-d", "--input_dir", help=3D"YAML input directory") =20 # Index and input are mutually exclusive group =3D parser.add_mutually_exclusive_group() - group.add_argument( - "-x", "--index", action=3D"store_true", help=3D"Generate the index= page" - ) group.add_argument("-i", "--input", help=3D"YAML file name") =20 args =3D parser.parse_args() @@ -71,15 +67,6 @@ def write_to_rstfile(content: str, filename: str) -> Non= e: rst_file.write(content) =20 =20 -def write_index_rst(parser: YnlDocGenerator, output: str, index_dir: str) = -> None: - """Generate the `networking_spec/index` content and write to the file"= "" - - msg =3D parser.generate_main_index_rst(output, index_dir) - - logging.debug("Writing an index file at %s", output) - write_to_rstfile(msg, output) - - def main() -> None: """Main function that reads the YAML files and generates the RST files= """ =20 @@ -98,10 +85,6 @@ def main() -> None: =20 write_to_rstfile(content, args.output) =20 - if args.index: - # Generate the index RST file - write_index_rst(parser, args.output, args.input_dir) - =20 if __name__ =3D=3D "__main__": main() --=20 2.49.0 From nobody Fri Oct 10 09:55:27 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A366428FA93; Tue, 17 Jun 2025 08:02:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; cv=none; b=YuLvVYHbDdfDUCuCg1zCsfatdv5YGWkkvzfTkiw1WuRc7e/Xtp8es1D10/Z2kECgs4+mPXm2TuT0U//YYxIMSBYFyAgE7spDjUxa8ByKZRTi6DfVgU0h/UFq0PxqKHALgFRTDU4a0qsOvqAtd0xZGL9Z3wke8ai/ik6x/GJ060A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; c=relaxed/simple; bh=vvV+xmO0j0mWtU1wNfJ75+6hS9+rll7NzjTztVenfl0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IqejmpEKq5xvTL52sDRm3gYZngE6wVdMHsElv4b+wlyfErFUCDqePhcxYxxAH1WZ73EPmVNZgQn4aFO6BsAhcnNZC75/jHI3FxPitSIsqNv4aziQ+XemJDscZvU4cz/JyLLzUBcrD4Q4n5YRyhpcqNqWiSoowNS8tew9LXaeDYM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GN8Pd0ps; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GN8Pd0ps" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0DDA6C4CEFE; Tue, 17 Jun 2025 08:02:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750147352; bh=vvV+xmO0j0mWtU1wNfJ75+6hS9+rll7NzjTztVenfl0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GN8Pd0psWtSir3682S1Fr/Su1JPCZZBYyyEbDq4E1Z25Aqp4fJSFjZiYpLXQ6dkgE PnCze+/MpElqauHOJXCVCrONftL6g3ACk3pZnC1kzDVfJiNc8wLKPuZ4SVfXlSKBdb hifXqbRiF3qN0AZ5/2QWcY73WdDMs3LqxS//MZRHGel7KGZy7aQlekG6c7O6ldJyc6 OJy/QpQKOTy0CoF4tOrsolQ72M8PJlGice+wRPALdq5HEi53RTPVQSJ7ECim9i/1Yp dna1/ShBNL9amKKyw26uFAH+dmHnPffQDmGru6WCa6rIJ0k73aRfUb0RvLY7C5Okok 4CsRkQGzj1PJw== Received: from mchehab by mail.kernel.org with local (Exim 4.98.2) (envelope-from ) id 1uRRH4-00000001vdg-196d; Tue, 17 Jun 2025 10:02:30 +0200 From: Mauro Carvalho Chehab To: Linux Doc Mailing List , Jonathan Corbet Cc: Mauro Carvalho Chehab , "Akira Yokosawa" , "Breno Leitao" , "David S. Miller" , "Donald Hunter" , "Eric Dumazet" , "Ignacio Encinas Rubio" , "Jan Stancek" , "Marco Elver" , "Mauro Carvalho Chehab" , "Paolo Abeni" , "Ruben Wauters" , "Shuah Khan" , Jakub Kicinski , Simon Horman , 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: [PATCH v5 14/15] docs: netlink: remove obsolete .gitignore from unused directory Date: Tue, 17 Jun 2025 10:02:11 +0200 Message-ID: <073835aa035718b120971b7a53e0f270d146fe87.1750146719.git.mchehab+huawei@kernel.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" The previous code was generating source rst files under Documentation/networking/netlink_spec/. With the Sphinx YAML parser, this is now gone. So, stop ignoring *.rst files inside netlink specs directory. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Donald Hunter --- Documentation/networking/netlink_spec/.gitignore | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Documentation/networking/netlink_spec/.gitignore diff --git a/Documentation/networking/netlink_spec/.gitignore b/Documentati= on/networking/netlink_spec/.gitignore deleted file mode 100644 index 30d85567b592..000000000000 --- a/Documentation/networking/netlink_spec/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.rst --=20 2.49.0 From nobody Fri Oct 10 09:55:27 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B47BF28FAB5; Tue, 17 Jun 2025 08:02:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; cv=none; b=lxTep79uFI8QE1qVpvRpHCSAtL6D1HZk09fL5vcNRjMRSDaRuna9iwZLmJScNdpMI1c6L0CEwrI45KABR2eepBphrsLc8nqg+tBd+b8ssyqTe8g71iWGAklZ8Ye3X0YmM2Beil5Sbohix5ihFUtMxSNC4x/sCRdzYC4tW4HWb9A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750147352; c=relaxed/simple; bh=2wpS1pJgr4e8EIQ3/QK7bcd03hAN/nvcFh7aQufz/C8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=V1+LYKK2WqU6zfQNj8FbcuE1ufO7hgm0ltMaFqeIncpprn5ieHmcRRMjkddWmb6Ce89Vcz1Th9RX9sFuFtLCxRCHL2p3ieLQW20cqpTJuSTpf0CX2FQOH4+YLU2X3OX27qcTh7ZpQKOZkwhHsV7hv2TS0i/YUJyepAHxZauholA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NZyIK/Ta; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="NZyIK/Ta" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0A778C4CEFA; Tue, 17 Jun 2025 08:02:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750147352; bh=2wpS1pJgr4e8EIQ3/QK7bcd03hAN/nvcFh7aQufz/C8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NZyIK/TalGBKsKZzFsFFlNCwzfFsIiVf9mLw0FUGE1ZoIyqeTHB3mX1VyAgAmjMWA 3h9pZAadJU6Pq4URI3Ukz9AWepHXnlWCoRcOmespX3Tj9THY+FpUUhcEvHEm/pBcZ+ +FSLWy/qn2FgCJU5l3bR/+WgfJV25zBbtZPW4Ox2VU8aEFEiwaKkxMcet9VqWSZTN6 QVnC4xgeb6nrGArVP/JS41VtGyjUDhOS+KV1zzkltB/Tc3M6UelGzCas5T6fnyJUbu 5p6uLK47lrM6k6EhRJksY50sHw6a8VUsZBtkeQdvUj/KhttLcSjpKzVfQJTY2Pt1LJ IPlOToNcYTimA== Received: from mchehab by mail.kernel.org with local (Exim 4.98.2) (envelope-from ) id 1uRRH4-00000001vdk-1Gaq; Tue, 17 Jun 2025 10:02:30 +0200 From: Mauro Carvalho Chehab To: Linux Doc Mailing List , Jonathan Corbet Cc: Mauro Carvalho Chehab , "Akira Yokosawa" , "Breno Leitao" , "David S. Miller" , "Donald Hunter" , "Eric Dumazet" , "Ignacio Encinas Rubio" , "Jan Stancek" , "Marco Elver" , "Mauro Carvalho Chehab" , "Paolo Abeni" , "Ruben Wauters" , "Shuah Khan" , 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: [PATCH v5 15/15] MAINTAINERS: add netlink_yml_parser.py to linux-doc Date: Tue, 17 Jun 2025 10:02:12 +0200 Message-ID: <0db3a4962bfba8eca4a7e0404331ce1398701f5d.1750146719.git.mchehab+huawei@kernel.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" The documentation build depends on the parsing code at ynl_gen_rst.py. Ensure that changes to it will be c/c to linux-doc ML and maintainers by adding an entry for it. This way, if a change there would affect the build, or the minimal version required for Python, doc developers may know in advance. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Breno Leitao --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index a92290fffa16..caa3425e5755 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7202,6 +7202,7 @@ F: scripts/get_abi.py F: scripts/kernel-doc* F: scripts/lib/abi/* F: scripts/lib/kdoc/* +F: tools/net/ynl/pyynl/netlink_yml_parser.py F: scripts/sphinx-pre-install X: Documentation/ABI/ X: Documentation/admin-guide/media/ --=20 2.49.0