如何使用 docutils 创建 2 行表头

问题描述 投票:0回答:1

我为 Sphinx 编写了一个扩展来读取代码覆盖率文件,并将它们以表格形式呈现在 Sphinx 生成的 HTML 文档中。

目前该表只有一个标题行,例如3 列用于语句相关值,4 列用于分支相关数据。我想创建一个 2 行表标题,以便对多列进行分组。

在纯 HTML 中,可以通过添加

colspan=3
来完成。但是如何用 docutils 解决这个问题呢?

完整来源可以在这里找到:https://github.com/pyTooling/sphinx-reports/blob/main/sphinx_reports/CodeCoverage.py#L169

有趣的代码是这样的:

    def _PrepareTable(self, columns: Dict[str, int], identifier: str, classes: List[str]) -> Tuple[nodes.table, nodes.tgroup]:
        table = nodes.table("", identifier=identifier, classes=classes)

        tableGroup = nodes.tgroup(cols=(len(columns)))
        table += tableGroup

        tableRow = nodes.row()
        for columnTitle, width in columns.items():
            tableGroup += nodes.colspec(colwidth=width)
            tableRow += nodes.entry("", nodes.paragraph(text=columnTitle))

        tableGroup += nodes.thead("", tableRow)

        return table, tableGroup

    def _GenerateCoverageTable(self) -> nodes.table:
        # Create a table and table header with 5 columns
        table, tableGroup = self._PrepareTable(
            identifier=self._packageID,
            columns={
                "Module": 500,
                "Total Statements": 100,
                "Excluded Statements": 100,
                "Covered Statements": 100,
                "Missing Statements": 100,
                "Total Branches": 100,
                "Covered Branches": 100,
                "Partial Branches": 100,
                "Missing Branches": 100,
                "Coverage in %": 100
            },
            classes=["report-doccov-table"]
        )
        tableBody = nodes.tbody()
        tableGroup += tableBody

python html-table code-coverage python-sphinx docutils
1个回答
0
投票

不熟悉 docutils API,但您是否考虑过使用具有层序遍历的树?比如:

from collections import deque


class _Column:
    def __init__(self, title: str, width: Optional[int] = None, children: Optional[List['_Column']] = None):
        # Only leaf nodes can have widths
        assert width is None or children is None
        self.width = width
        self.children = children
        self._width_computed = None

    def getWidth(self) -> int:
        if self._width_computed is None:
            self._width_computed = self.width or sum([c.getWidth() for c in self.children or []])
        return self._width_computed
        
    def countLeaves(self) -> int:
        if self.children is None:
            return 1
        return sum([c.countLeaves() for c in self.children or []])
  
...

    def _PrepareTable(self, columns: List[_Column], identifier: str, classes: List[str]) -> Tuple[nodes.table, nodes.tgroup]:
        table = nodes.table("", identifier=identifier, classes=classes)

        tableGroup = nodes.tgroup(cols=(sum([col.countLeaves() for col in columns])))
        table += tableGroup

        tableRow = nodes.row()
        
        # level-order traversal to get widths.
        current_level = 0
        queue = deque([c, 0 for c in columns])
        for col, level in queue:
            if current_level != level:
                current_level = level
                tableGroup += nodes.thead("", tableRow)
                tableRow = nodes.row()
            # You can use level how you like.
            tableGroup += nodes.colspec(colwidth=col.getWidth())
            tableRow += nodes.entry("", nodes.paragraph(text=col.title))
            for child_col in col.children or []:
                queue.appendleft((child_col, level + 1))

        # Add the last level.
        tableGroup += nodes.thead("", tableRow)

        return table, tableGroup

    def _GenerateCoverageTable(self) -> nodes.table:
        # Create a table and table header with 5 columns
        table, tableGroup = self._PrepareTable(
            identifier=self._packageID,
            columns=[
                _Column(
                    title="Module",
                    width=500,
                ),
                _Column(
                    title="Statements",
                    children=[
                        _Column(
                            title="Total Statements",
                            width=100,
                        ),
                        _Column(
                            title="Excluded Statements",
                            width=100,
                        ),
                        _Column(
                            title="Covered Statements",
                            width=100,
                        ),
                        _Column(
                            title="Missing Statements",
                            width=100,
                        ),
                    ]
                ),
                _Column(
                    title="Branches",
                    children=[
                        _Column(
                            title="Total Branches",
                            width=100,
                        ),
                        _Column(
                            title="Covered Branches",
                            width=100,
                        ),
                        _Column(
                            title="Partial Branches",
                            width=100,
                        ),
                        _Column(
                            title="Missing Branches",
                            width=100,
                        ),
                    ]
                ),
                _Column(
                    title="Coverage in %",
                    width=100,
                ),
            ],
            classes=["report-doccov-table"]
        )
        tableGroup += nodes.tbody()
© www.soinside.com 2019 - 2024. All rights reserved.