Repository: terrapower/armi
Pull request #1576 (2024-01-11 19:00:07)

Adding list-table powers to the docs
## What is the change?

Adding list-table powers to the docs.

## Why is the change being made?

We wanted to improve the PDF version of our docs.

---

Here is an example of the function working correctly in the PDF docs;

![image](https://github.com/terrapower/armi/assets/1831479/fcd40439-f33a-4376-b3aa-9230d0644465)

---

## Checklist

- [x] This PR has only [one purpose or idea](https://terrapower.github.io/armi/developer/tooling.html#one-idea-one-pr).
- [x] [Tests](https://terrapower.github.io/armi/developer/tooling.html#test-it) have been added/updated to verify that the new/changed code works.

<!-- Check the code quality -->

- [x] The code style follows [good practices](https://terrapower.github.io/armi/developer/standards_and_practices.html).
- [x] The commit message(s) follow [good practices](https://terrapower.github.io/armi/developer/tooling.html).

<!-- Check the project-level cruft -->

- [x] The [release notes](https://terrapower.github.io/armi/release/index.html) (location `doc/release/0.X.rst`) are up-to-date with any important changes.
- [x] The [documentation](https://terrapower.github.io/armi/developer/tooling.html#document-it) is still up-to-date in the `doc` folder.
- [x] If any [requirements](https://terrapower.github.io/armi/developer/tooling.html#watch-for-requirements) were affected, mention it in the [release notes](https://terrapower.github.io/armi/release/index.html).
- [x] The dependencies are still up-to-date in `pyproject.toml`.



Patch:
diff --git a/armi/utils/dochelpers.py b/armi/utils/dochelpers.py
index f0cc57d6..9c23c5ae 100644
--- a/armi/utils/dochelpers.py
+++ b/armi/utils/dochelpers.py
@@ -68,6 +68,56 @@ def create_table(rst_table, caption=None, align=None, widths=None, width=None):
     return "\n".join(rst)
 
 
+def createListTable(
+    rows, caption=None, align=None, widths=None, width=None, klass=None
+):
+    """Take a list of data, and produce an RST-type string for a list-table.
+
+    Parameters
+    ----------
+    rows: list
+        List of input data (first row is the header).
+    align: str
+        "left", "center", or "right"
+    widths: str
+        "auto", "grid", or a list of integers
+    width: str
+        `length`_ or `percentage`_ of the current line width
+    klass: str
+        Should be "class", but that is a reserved keyword.
+        "longtable", "special", or something custom
+
+    Returns
+    -------
+        str: RST list-table string
+    """
+    # we need valid input data
+    assert len(rows) > 1, "Not enough input data."
+    len0 = len(rows[0])
+    for row in rows[1:]:
+        assert len(row) == len0, "Rows aren't all the same length."
+
+    # build the list-table header block
+    rst = [".. list-table:: {}".format(caption or "")]
+    rst += ["    :header-rows: 1"]
+    if klass:
+        rst += ["    :class: {}".format(klass)]
+    if align:
+        rst += ["    :align: {}".format(align)]
+    if width:
+        rst += ["    :width: {}".format(width)]
+    if widths:
+        rst += ["    :widths: " + " ".join([str(w) for w in widths])]
+    rst += [""]
+
+    # build the list-table data
+    for row in rows:
+        rst += [f"    * - {row[0]}"]
+        rst += [f"      - {word}" for word in row[1:]]
+
+    return "\n".join(rst)
+
+
 class ExecDirective(Directive):
     """
     Execute the specified python code and insert the output into the document.
diff --git a/doc/user/inputs.rst b/doc/user/inputs.rst
index e2ee8ceb..ee62f200 100644
--- a/doc/user/inputs.rst
+++ b/doc/user/inputs.rst
@@ -586,12 +586,14 @@ in cm.  The following is a list of included component shapes and their dimension
 additional/custom components with arbitrary dimensions may be provided by the user via plugins.
 
 .. exec::
-    from tabulate import tabulate
     from armi.reactor.components import ComponentType
+    from armi.utils.dochelpers import createListTable
 
-    return create_table(tabulate(headers=('Component Name', 'Dimensions'),
-                   tabular_data=[(c.__name__, ', '.join(c.DIMENSION_NAMES)) for c in ComponentType.TYPES.values()],
-                   tablefmt='rst'), caption="Component list")
+    rows = [['Component Name', 'Dimensions']]
+    for c in ComponentType.TYPES.values():
+        rows.append([c.__name__, ', '.join(c.DIMENSION_NAMES)])
+
+    return createListTable(rows, widths=[25, 65], klass="longtable")
 
 When a ``DerivedShape`` is specified as the final component in a block, its area is inferred from
 the difference between the area of the block and the sum of the areas


Test patch:
diff --git a/armi/utils/tests/test_dochelpers.py b/armi/utils/tests/test_dochelpers.py
index 160513a5..5042fabd 100644
--- a/armi/utils/tests/test_dochelpers.py
+++ b/armi/utils/tests/test_dochelpers.py
@@ -19,6 +19,7 @@ from armi.reactor import reactorParameters
 from armi.utils.dochelpers import (
     create_figure,
     create_table,
+    createListTable,
     generateParamTable,
     generatePluginSettingsTable,
 )
@@ -73,3 +74,30 @@ class TestDocHelpers(unittest.TestCase):
         self.assertIn("width: 250", table)
         self.assertIn("widths: [200, 300]", table)
         self.assertIn("thing", table)
+
+    def test_createListTable(self):
+        rows = [["h1", "h2"], ["a1", "a2"], ["b1", "b2"]]
+        table = createListTable(
+            rows,
+            caption="awesomeTable",
+            align="left",
+            widths=[10, 30],
+            width=100,
+            klass="longtable",
+        )
+
+        self.assertEqual(len(table), 189)
+        self.assertIn("awesomeTable", table)
+        self.assertIn("list-table", table)
+        self.assertIn("longtable", table)
+        self.assertIn("width: 100", table)
+        self.assertIn("widths: 10 30", table)
+
+        with self.assertRaises(AssertionError):
+            createListTable([])
+
+        with self.assertRaises(AssertionError):
+            createListTable([["h1", "h2"]])
+
+        with self.assertRaises(AssertionError):
+            createListTable([["h1", "h2"], ["a1", "b2", "c3"]])