WriteDocs() and write_bintool_docs() strip four characters from the start of every docstring line but the first, to undo the indentation the source file gives them. Since Python 3.13 the compiler already removes the common indentation from docstrings [1], so this removes four characters of actual text from every line of every entry and bintool description:
$ binman entry-docs | head ... that an image node whose only content is an optional entry which was is an example showing ATF, TEE and a device tree all combined:: Use inspect.cleandoc() instead, which produces the same result on both older and newer interpreters. The existing tests only checked that some output was produced, so they missed this entirely; make them also confirm that a known line of a known description survives intact. Link: https://github.com/python/cpython/issues/81283 [1] Signed-off-by: Alexey Charkov <[email protected]> --- tools/binman/bintool.py | 6 ++++-- tools/binman/entry.py | 9 +++++++-- tools/binman/ftest.py | 19 +++++++++++++++++-- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/tools/binman/bintool.py b/tools/binman/bintool.py index 9c76c8881a46..4cf8d5b165bf 100644 --- a/tools/binman/bintool.py +++ b/tools/binman/bintool.py @@ -12,6 +12,7 @@ the tool, checking its version and fetching it if needed. import collections import glob import importlib +import inspect import multiprocessing import os import shutil @@ -463,9 +464,10 @@ binaries. It is fairly easy to create new bintools. Just add a new file to the if test_missing == name: docs = None if docs: - lines = docs.splitlines() + # See the note in Entry.WriteDocs() about cleandoc() + lines = inspect.cleandoc(docs).splitlines() first_line = lines[0] - rest = [line[4:] for line in lines[1:]] + rest = lines[1:] hdr = 'Bintool: %s: %s' % (name, first_line) print(hdr) print('-' * len(hdr)) diff --git a/tools/binman/entry.py b/tools/binman/entry.py index ce7ef28e94b1..9b39c7118892 100644 --- a/tools/binman/entry.py +++ b/tools/binman/entry.py @@ -6,6 +6,7 @@ from collections import namedtuple import importlib +import inspect import os import pathlib import sys @@ -858,9 +859,13 @@ features to produce new behaviours. if test_missing == name: docs = None if docs: - lines = docs.splitlines() + # Use cleandoc() rather than removing a fixed four characters + # of indent: since Python 3.13 the compiler already strips the + # common indent from docstrings, so doing it again here would + # eat the first four characters of every line + lines = inspect.cleandoc(docs).splitlines() first_line = lines[0] - rest = [line[4:] for line in lines[1:]] + rest = lines[1:] hdr = 'Entry: %s: %s' % (name.replace('_', '-'), first_line) # Create a reference for use by rST docs diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 9553eb6b7366..c5c67c7e68b1 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -1805,7 +1805,15 @@ class TestFunctional(unittest.TestCase): """Test for creation of entry documentation""" with terminal.capture() as (stdout, stderr): control.WriteEntryDocs(control.GetEntryModules()) - self.assertTrue(len(stdout.getvalue()) > 0) + out = stdout.getvalue() + self.assertTrue(len(out) > 0) + + # The body of each docstring must come out dedented but otherwise + # intact. Check a heading which several etypes use, since truncating + # the indent by too much would silently eat the start of every line. + self.assertIn('\nProperties / Entry arguments:\n', out) + self.assertIn('\nEntry: atf-bl31: ARM Trusted Firmware (ATF) BL31 blob\n', + out) def testEntryDocsMissing(self): """Test handling of missing entry documentation""" @@ -5491,7 +5499,14 @@ fdt fdtmap Extract the devicetree blob from the fdtmap """Test for creation of bintool documentation""" with terminal.capture() as (stdout, stderr): control.write_bintool_docs(control.bintool.Bintool.get_tool_list()) - self.assertTrue(len(stdout.getvalue()) > 0) + out = stdout.getvalue() + self.assertTrue(len(out) > 0) + + # As in testEntryDocs(), check that the body is dedented but intact + self.assertIn('\nBintool: mkimage: Image generation for U-Boot\n', out) + self.assertIn( + '\nThis bintool supports running `mkimage` with some basic parameters as\n', + out) def testBintoolDocsMissing(self): """Test handling of missing bintool documentation""" --- base-commit: 44f0dcf476140c1077ee3dbe16a80fdb6f8265c4 change-id: 20260730-b4-binman-docstring-dedent-84cc7a1007cd Best regards, -- Alexey Charkov <[email protected]>
