Node.py
Summary
- Lines:
42 of 42 covered (100.0%)
- Coverage:
100.0%
- Directory:
Source
pyTooling/Sphinx/Node.pycoveredpartialuncoveredexcludednot executable
1# ==================================================================================================================== #
2# _____ _ _ ____ _ _ #
3# _ __ _ |_ _|__ ___ | (_)_ __ __ _ / ___| _ __ | |__ (_)_ __ __ __ #
4# | '_ \| | | || |/ _ \ / _ \| | | '_ \ / _` | \___ \| '_ \| '_ \| | '_ \\ \/ / #
5# | |_) | |_| || | (_) | (_) | | | | | | (_| |_ ___) | |_) | | | | | | | |> < #
6# | .__/ \__, ||_|\___/ \___/|_|_|_| |_|\__, (_)____/| .__/|_| |_|_|_| |_/_/\_\ #
7# |_| |___/ |___/ |_| #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2026-2026 Patrick Lehmann - Bötzingen, Germany #
15# #
16# Licensed under the Apache License, Version 2.0 (the "License"); #
17# you may not use this file except in compliance with the License. #
18# You may obtain a copy of the License at #
19# #
20# http://www.apache.org/licenses/LICENSE-2.0 #
21# #
22# Unless required by applicable law or agreed to in writing, software #
23# distributed under the License is distributed on an "AS IS" BASIS, #
24# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
25# See the License for the specific language governing permissions and #
26# limitations under the License. #
27# #
28# SPDX-License-Identifier: Apache-2.0 #
29# ==================================================================================================================== #
30#
31"""
32The docutils nodes pyTooling.Sphinx adds, and what registering one with Sphinx takes.
33
34A node is a class here; the functions writing it are in a module per output format - :mod:`~pyTooling.Sphinx.HTML`
35and :mod:`~pyTooling.Sphinx.LaTeX` - and :data:`~pyTooling.Sphinx.NODES` pairs both for :func:`~pyTooling.Sphinx.setup`.
36A node without visitors for a format is written by the visitors of its base-class there.
37"""
38from typing import Any, Callable, NotRequired, TypedDict
39
40from docutils import nodes
41
42from pyTooling.Decorators import export
43
44
45__all__ = ["visitFunc", "departFunc", "COVERAGE_STATES", "DOCUMENTATION_STATES"]
46
47#: The coverage states of a listing's lines, as the listing's legend names them, by state; ``""`` for a line, which
48#: isn't executable.
49COVERAGE_STATES = {
50 "covered": "covered",
51 "partial": "partial",
52 "uncovered": "uncovered",
53 "excluded": "excluded",
54 "": "not executable",
55}
56
57#: The documentation states of a condensed listing's lines, as the listing's legend names them, by state; ``""`` for a
58#: line, whose documentation isn't counted.
59DOCUMENTATION_STATES = {
60 "documented": "documented",
61 "undocumented": "undocumented",
62 "ignored": "ignored",
63 "excluded": "excluded",
64 "": "not counted",
65}
66
67type visitFunc = Callable[[Any, Any], Any]
68"""A function writing the start of a node: called with the translator and the node."""
69
70type departFunc = Callable[[Any, Any], Any]
71"""A function writing the end of a node: called with the translator and the node."""
72
73
74@export
75class RegisteredNode(TypedDict):
76 """An entry of :data:`~pyTooling.Sphinx.NODES`: a node class, and its visitors per output format."""
77
78 name: str #: Name of the node.
79 node: type[nodes.Element] #: The node class to register.
80 html: tuple[visitFunc, departFunc] #: Visit and depart function writing the node in HTML.
81 latex: NotRequired[tuple[visitFunc, departFunc]] #: Visit and depart function writing the node in LaTeX, if any.
82
83
84@export
85class TreeItem(nodes.list_item):
86 """
87 An entry of a tree: a list item, which HTML draws around a ``<details>`` element if the entry has children.
88
89 Attribute ``expanded`` states whether the entry is expanded initially, and is ``None`` if it has no children.
90 Attribute ``columnWidth`` holds the width of the column of the entries' texts as a CSS length, measured from the
91 tree's left edge, if the entry is a root of a tree with descriptions; else ``None``.
92 """
93
94
95@export
96class TreeLabel(nodes.paragraph):
97 """
98 An entry's text: a paragraph, which HTML draws as the ``<summary>`` of the entry's ``<details>`` element.
99
100 Attribute ``icon`` holds the icon of the entry's kind, ``expandedIcon`` and ``collapsedIcon`` the icons showing
101 whether the entry is expanded. Both are ``None`` if the entry has no children. Attribute ``level`` holds the entry's
102 level, ``0`` for a root, and ``descriptionColumn`` whether the tree has descriptions: then HTML draws the entry as
103 a row of two columns, whether this entry has a description or not.
104
105 An entry's description follows its text, as a :class:`TreeSeparator` and a :class:`TreeDescription`.
106 """
107
108
109@export
110class TreeSeparator(nodes.inline):
111 """
112 The separator between an entry's text and its description: an en dash, which HTML skips.
113
114 HTML draws the description in a column of its own. Every other format - e.g. LaTeX - writes its base-class, so the
115 description follows the text in the same line: ``text – description``.
116 """
117
118
119@export
120class TreeDescription(nodes.inline):
121 """
122 An entry's description, which HTML draws in a column of its own: all descriptions of a tree start at the same
123 horizontal position, whatever the entry's level.
124 """
125
126
127@export
128class TreeLegend(nodes.paragraph):
129 """
130 A tree's legend: a paragraph of :class:`TreeLegendItem` nodes, which HTML draws as one line above or below the tree.
131
132 Formats drawing no icons in a tree don't get it: :class:`~pyTooling.Sphinx.Tree.RemoveTreeLegends` removes it.
133 """
134
135
136@export
137class TreeLegendItem(nodes.inline):
138 """
139 An item of a tree's legend: the text explaining an icon. Attribute ``icon`` holds the icon.
140 """
141
142
143@export
144class CopyButton(nodes.inline):
145 """
146 A button copying a text into the clipboard, which HTML draws as a ``<button>``; every other format writes nothing.
147
148 Attribute ``copy`` holds the text to copy, and ``label`` what the button does, for a screen reader and as a tooltip.
149 The node has no children, so a format writing its base-class - an inline element - writes nothing.
150
151 The script :file:`pyTooling.js` gives the button its function.
152 """
153
154
155@export
156class Abbreviation(nodes.abbreviation):
157 """
158 A reference to an abbreviation in its short form, which HTML draws with a box explaining it on hover.
159
160 Attributes ``short`` and ``long`` hold the abbreviation's forms, even if the node's text is a title the role was
161 written with; ``summary`` holds the summary of its description the box shows, or an empty string. The attribute
162 ``explanation`` of the base-class is left unset: LaTeX and text would append it in parentheses, and an abbreviation
163 is written in the form its role asks for.
164 """
165
166
167@export
168class Landscape(nodes.container):
169 """
170 A container whose content LaTeX puts on landscape pages; HTML writes the content only.
171
172 A wide table is such content.
173
174 LaTeX's ``landscape`` environment needs package ``pdflscape``, which :func:`~pyTooling.Sphinx.setup` requests. The
175 report tables of domain ``report`` are what this node holds.
176 """
177
178
179@export
180class CoverageListing(nodes.literal_block):
181 """
182 A source file's code coverage: its lines, syntax highlighted, each marked by its coverage state.
183
184 Attribute ``lines`` holds a tuple per line: the line number, the state (``covered``, ``partial``, ``uncovered``,
185 ``excluded``, or ``""`` for a line, which isn't executable), the hits or ``None``, the number of branches and of
186 taken branches, and the line's tokens as ``(CSS class, text)`` pairs - the short classes of Pygments' token types,
187 which Sphinx' Pygments stylesheet colors. Attribute ``anchors`` states whether a line gets the ID ``L<number>``.
188 Attribute ``path`` holds the file's path in the report, which the listing's header shows beside the legend of the
189 coverage states.
190
191 The node's text is the plain source, so a builder without visitors for this node writes it as a literal block.
192 """
193
194
195@export
196class DocCoverageListing(nodes.literal_block):
197 """
198 A Python module's documentation coverage: its condensed source, syntax highlighted, each line marked by its
199 documentation state.
200
201 The source is condensed to what is documented: a function's or class' decorators, its header and its doc-string,
202 fields and variables; a body is elided to one ``...`` line.
203
204 Attribute ``lines`` holds a tuple per line: the line number - ``None`` for an elided body's ``...`` -, the state
205 (``documented``, ``undocumented``, ``ignored``, ``excluded``, or ``""`` for a line, whose documentation isn't
206 counted), and the line's tokens as ``(CSS class, text)`` pairs - the short classes of Pygments' token types, which
207 Sphinx' Pygments stylesheet colors. Attribute ``path`` holds the module's path, which the listing's header shows
208 beside the legend of the documentation states.
209
210 The node's text is the condensed source, so a builder without visitors for this node writes it as a literal block.
211 """
212
213
214@export
215class Emoji(nodes.inline):
216 """
217 An emoji: its characters, which HTML draws with its shortcode as tooltip.
218
219 Attribute ``shortcode`` holds the emoji's GitHub shortcode without colons, e.g. ``tada``. LaTeX writes its base-class,
220 so the characters as they are - LuaLaTeX draws them with a Unicode emoji font, which e.g. :file:`pytooling.sty` of
221 the MiKTeX image maps them to.
222 """
223
224
225@export
226class TaskListCheckbox(nodes.inline):
227 """
228 The checkbox opening a task list item, which HTML draws as a disabled checkbox.
229
230 Attribute ``checked`` states whether the task is done. The node's text is a ballot box, with check if the task is
231 done, so a format writing its base-class - an inline element - writes that character. LaTeX writes a box symbol.
232 """
233
234
235@export
236class ReportIndentation(nodes.inline):
237 """
238 The name of an entry in a report table, indented by the entry's depth: HTML as a padding, LaTeX by a macro.
239
240 Attribute ``level`` holds the number of indentation steps, e.g. ``2`` for a testcase in a testsuite. A wrapped name
241 stays at its indentation. A format writing its base-class - an inline element - writes the name without indentation.
242 """
243
244
245@export
246class LineBreak(nodes.inline):
247 """
248 A line break inside a paragraph, which HTML writes as ``<br />`` and LaTeX as ``\\newline``.
249
250 The node's text is a newline, so a format writing its base-class - an inline element - writes a space.
251 """