Node.py

Summary

Lines:

48 of 48 covered (100.0%)

Coverage:

100.0%

Directory:

Sphinx

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
47COVERAGE_STATES = {
48	"covered":   "covered",
49	"partial":   "partial",
50	"uncovered": "uncovered",
51	"excluded":  "excluded",
52	"":          "not executable",
53}
54"""
55The coverage states of a listing's lines, as the listing's legend names them, by state; ``""`` for a line, which
56isn't executable.
57"""
58
59DOCUMENTATION_STATES = {
60	"documented":   "documented",
61	"undocumented": "undocumented",
62	"ignored":      "ignored",
63	"excluded":     "excluded",
64	"":             "not counted",
65}
66"""
67The documentation states of a condensed listing's lines, as the listing's legend names them, by state; ``""`` for a
68line, whose documentation isn't counted.
69"""
70
71type visitFunc =  Callable[[Any, Any], Any]
72"""A function writing the start of a node: called with the translator and the node."""
73
74type departFunc = Callable[[Any, Any], Any]
75"""A function writing the end of a node: called with the translator and the node."""
76
77
78@export
79class RegisteredNode(TypedDict):
80	"""An entry of :data:`~pyTooling.Sphinx.NODES`: a node class, and its visitors per output format."""
81
82	name:  str                                        #: Name of the node.
83	node:  type[nodes.Element]                        #: The node class to register.
84	html:  tuple[visitFunc, departFunc]               #: Visit and depart function writing the node in HTML.
85	latex: NotRequired[tuple[visitFunc, departFunc]]  #: Visit and depart function writing the node in LaTeX, if any.
86
87
88@export
89class TreeItem(nodes.list_item):
90	"""
91	An entry of a tree: a list item, which HTML draws around a ``<details>`` element if the entry has children.
92
93	Attribute ``expanded`` states whether the entry is expanded initially, and is ``None`` if it has no children.
94	Attribute ``columnWidth`` holds the width of the column of the entries' texts as a CSS length, measured from the
95	tree's left edge, if the entry is a root of a tree with descriptions; else ``None``.
96	"""
97
98
99@export
100class TreeLabel(nodes.paragraph):
101	"""
102	An entry's text: a paragraph, which HTML draws as the ``<summary>`` of the entry's ``<details>`` element.
103
104	Attribute ``icon`` holds the icon of the entry's kind, ``expandedIcon`` and ``collapsedIcon`` the icons showing
105	whether the entry is expanded. Both are ``None`` if the entry has no children. Attribute ``level`` holds the entry's
106	level, ``0`` for a root, and ``descriptionColumn`` whether the tree has descriptions: then HTML draws the entry as
107	a row of two columns, whether this entry has a description or not.
108
109	An entry's description follows its text, as a :class:`TreeSeparator` and a :class:`TreeDescription`.
110	"""
111
112
113@export
114class TreeSeparator(nodes.inline):
115	"""
116	The separator between an entry's text and its description: an en dash, which HTML skips.
117
118	HTML draws the description in a column of its own. Every other format - e.g. LaTeX - writes its base-class, so the
119	description follows the text in the same line: ``text – description``.
120	"""
121
122
123@export
124class TreeDescription(nodes.inline):
125	"""
126	An entry's description, which HTML draws in a column of its own: all descriptions of a tree start at the same
127	horizontal position, whatever the entry's level.
128	"""
129
130
131@export
132class TreeLegend(nodes.paragraph):
133	"""
134	A tree's legend: a paragraph of :class:`TreeLegendItem` nodes, which HTML draws as one line above or below the tree.
135
136	Formats drawing no icons in a tree don't get it: :class:`~pyTooling.Sphinx.Tree.RemoveTreeLegends` removes it.
137	"""
138
139
140@export
141class TreeLegendItem(nodes.inline):
142	"""
143	An item of a tree's legend: the text explaining an icon. Attribute ``icon`` holds the icon.
144	"""
145
146
147@export
148class CopyButton(nodes.inline):
149	"""
150	A button copying a text into the clipboard, which HTML draws as a ``<button>``; every other format writes nothing.
151
152	Attribute ``copy`` holds the text to copy, and ``label`` what the button does, for a screen reader and as a tooltip.
153	The node has no children, so a format writing its base-class - an inline element - writes nothing.
154
155	The script :file:`pyTooling.js` gives the button its function.
156	"""
157
158
159@export
160class Abbreviation(nodes.abbreviation):
161	"""
162	A reference to an abbreviation in its short form, which HTML draws with a box explaining it on hover.
163
164	Attributes ``short`` and ``long`` hold the abbreviation's forms, even if the node's text is a title the role was
165	written with; ``summary`` holds the summary of its description the box shows, or an empty string. The attribute
166	``explanation`` of the base-class is left unset: LaTeX and text would append it in parentheses, and an abbreviation
167	is written in the form its role asks for.
168	"""
169
170
171@export
172class Landscape(nodes.container):
173	"""
174	A container whose content LaTeX puts on landscape pages; HTML writes the content only.
175
176	A wide table is such content.
177
178	LaTeX's ``landscape`` environment needs package ``pdflscape``, which :func:`~pyTooling.Sphinx.setup` requests. The
179	report tables of domain ``report`` are what this node holds.
180	"""
181
182
183@export
184class CoverageListing(nodes.literal_block):
185	"""
186	A source file's code coverage: its lines, syntax highlighted, each marked by its coverage state.
187
188	Attribute ``lines`` holds a tuple per line: the line number, the state (``covered``, ``partial``, ``uncovered``,
189	``excluded``, or ``""`` for a line, which isn't executable), the hits or ``None``, the number of branches and of
190	taken branches, and the line's tokens as ``(CSS class, text)`` pairs - the short classes of Pygments' token types,
191	which Sphinx' Pygments stylesheet colors. Attribute ``anchors`` states whether a line gets the ID ``L<number>``.
192	Attribute ``path`` holds the file's path in the report, which the listing's header shows beside the legend of the
193	coverage states.
194
195	The node's text is the plain source, so a builder without visitors for this node writes it as a literal block.
196	"""
197
198
199@export
200class DocCoverageListing(nodes.literal_block):
201	"""
202	A Python module's documentation coverage: its condensed source, syntax highlighted, each line marked by its
203	documentation state.
204
205	The source is condensed to what is documented: a function's or class' decorators, its header and its doc-string,
206	fields and variables; a body is elided to one ``...`` line.
207
208	Attribute ``lines`` holds a tuple per line: the line number - ``None`` for an elided body's ``...`` -, the state
209	(``documented``, ``undocumented``, ``ignored``, ``excluded``, or ``""`` for a line, whose documentation isn't
210	counted), and the line's tokens as ``(CSS class, text)`` pairs - the short classes of Pygments' token types, which
211	Sphinx' Pygments stylesheet colors. Attribute ``path`` holds the module's path, which the listing's header shows
212	beside the legend of the documentation states.
213
214	The node's text is the condensed source, so a builder without visitors for this node writes it as a literal block.
215	"""
216
217
218@export
219class Emoji(nodes.inline):
220	"""
221	An emoji: its characters, which HTML draws with its shortcode as tooltip.
222
223	Attribute ``shortcode`` holds the emoji's GitHub shortcode without colons, e.g. ``tada``. LaTeX writes its base-class,
224	so the characters as they are - LuaLaTeX draws them with a Unicode emoji font, which e.g. :file:`pytooling.sty` of
225	the MiKTeX image maps them to.
226	"""
227
228
229@export
230class TaskListCheckbox(nodes.inline):
231	"""
232	The checkbox opening a task list item, which HTML draws as a disabled checkbox.
233
234	Attribute ``checked`` states whether the task is done. The node's text is a ballot box, with check if the task is
235	done, so a format writing its base-class - an inline element - writes that character. LaTeX writes a box symbol.
236	"""
237
238
239@export
240class ReportIndentation(nodes.inline):
241	"""
242	The name of an entry in a report table, indented by the entry's depth: HTML as a padding, LaTeX by a macro.
243
244	Attribute ``level`` holds the number of indentation steps, e.g. ``2`` for a testcase in a testsuite. A wrapped name
245	stays at its indentation. A format writing its base-class - an inline element - writes the name without indentation.
246	"""
247
248
249@export
250class LineBreak(nodes.inline):
251	"""
252	A line break inside a paragraph, which HTML writes as ``<br />`` and LaTeX as ``\\newline``.
253
254	The node's text is a newline, so a format writing its base-class - an inline element - writes a space.
255	"""
256
257
258@export
259class FoldedDependencies(nodes.container):
260	"""
261	The folded dependencies of a duplicate in a dependency table: a :class:`FoldedSummary` and the bullet
262	list of the dependencies, which HTML draws as a ``<details>`` element, unfolded by a click on its summary.
263
264	Formats that can't unfold anything - LaTeX, text, manual pages and Texinfo - get the summary alone:
265	:class:`~pyTooling.Sphinx.DependencyTable.ReplaceFoldedDependencies` replaces the node.
266	"""
267
268
269@export
270class FoldedSummary(nodes.paragraph):
271	"""
272	The summary of a duplicate's folded dependencies: how many there are, and a link to the line showing them; HTML
273	draws it as the ``<summary>`` of the :class:`FoldedDependencies`'s ``<details>`` element.
274	"""