pyTooling.Sphinx
Summary
- Doc-string:
documented
File |
Expected |
Covered |
Uncovered |
Coverage |
|---|---|---|---|---|
__init__.py |
74 |
74 |
0 |
100.0% |
Overall (25 files) |
920 |
917 |
3 |
99.7% |
Packages
Package |
Expected |
Covered |
Uncovered |
Coverage |
|---|---|---|---|---|
1 |
1 |
0 |
100.0% |
Modules
Module |
Expected |
Covered |
Uncovered |
Coverage |
|---|---|---|---|---|
41 |
41 |
0 |
100.0% |
|
70 |
70 |
0 |
100.0% |
|
22 |
22 |
0 |
100.0% |
|
28 |
27 |
1 |
96.4% |
|
28 |
28 |
0 |
100.0% |
|
103 |
101 |
2 |
98.1% |
|
76 |
76 |
0 |
100.0% |
|
61 |
61 |
0 |
100.0% |
|
30 |
30 |
0 |
100.0% |
|
50 |
50 |
0 |
100.0% |
|
24 |
24 |
0 |
100.0% |
|
44 |
44 |
0 |
100.0% |
|
25 |
25 |
0 |
100.0% |
|
34 |
34 |
0 |
100.0% |
|
7 |
7 |
0 |
100.0% |
|
13 |
13 |
0 |
100.0% |
|
32 |
32 |
0 |
100.0% |
|
31 |
31 |
0 |
100.0% |
|
48 |
48 |
0 |
100.0% |
|
51 |
51 |
0 |
100.0% |
|
14 |
14 |
0 |
100.0% |
|
6 |
6 |
0 |
100.0% |
|
7 |
7 |
0 |
100.0% |
Source
pyTooling.Sphinx/__init__.pydocumentedundocumentedignoredexcludednot counted
31"""
32A Sphinx extension providing the roles, nodes and directives shared by pyTooling and its sibling projects.
33
34Every project in the family used to carry its own :file:`doc/prolog.inc` - eighteen hand-copied files, 36 to 67
35lines each, already drifted apart - declaring the same roles as **ReST source** that is re-parsed into every
36document of every project. This extension declares them once:
37
38.. code-block:: Python
39
40 # doc/conf.py
41 extensions = [
42 ...,
43 "pyTooling.Sphinx",
44 ]
45
46.. rubric:: What it registers
47
48* the **style roles**, together with the stylesheet they need - so the styling is a CSS file instead of a
49 ``raw:: html`` block smuggled into every page - and the LaTeX package :file:`pyTooling.Sphinx.sty`, which strikes
50 through and underlines in LaTeX:
51
52 * ``:bolditalic:``, ``:underline:``, ``:strike:`` and ``:xlarge:`` - weight, decoration and size;
53 * ``:red:``, ``:green:``, ``:blue:`` and ``:purple:`` - colour, each from a CSS custom property a project can
54 redefine;
55 * ``:deletion:`` and ``:addition:`` - the two a diff needs.
56
57* the **code role**:
58
59 * ``:pycode:`` - highlights inline Python.
60
61* the **abbreviation roles**, named as in LaTeX' ``acro`` package:
62
63 * ``:acs:``, ``:acl:`` and ``:acf:`` - an abbreviation, its long form, or both;
64 * ``:acsp:``, ``:aclp:`` and ``:acfp:`` - their plurals.
65
66* the **directives**:
67
68 * :rst:dir:`condensed-class` - renders a class' public interface from its source;
69 * :rst:dir:`dependency-table` - renders a project's dependencies from its requirements files, which
70 :file:`conf.py` declares under ``pyTooling_Dependency_Requirements``;
71 * :rst:dir:`xmlschema-graph` - draws an XML schema as a Graphviz graph. It sets up :mod:`sphinx.ext.graphviz`
72 itself, and needs :mod:`xmlschema` only in a project that uses it.
73 * :rst:dir:`shields` - renders a project's badges from shields.io, in rows, from the coordinates its options
74 state: the GitHub repository, the PyPI package, the licenses, the workflow and the documentation's URL.
75 * :rst:dir:`tree` - draws a hierarchy written as an indented list as a tree, each node foldable in HTML.
76 * :rst:dir:`unicode-table` - lists icons with their Unicode names and code points, which HTML copies into the
77 clipboard on a click; the script doing so is linked like the stylesheet.
78 * :rst:dir:`abbreviations` - lists abbreviations, which the abbreviation roles refer to.
79
80* the domain ``report`` - unit test, code coverage and documentation coverage reports as tables -, with the
81 configuration values ``pyTooling_Unittest_Testsuites``, ``pyTooling_CodeCoverage_Packages`` and
82 ``pyTooling_DocCoverage_Packages`` declaring the reports. Reading a report needs the extra ``reports``
83 (pyEDAA.Reports), which is imported only then:
84
85 * :rst:dir:`report:unittest-summary` - a unit test report, per testsuite and testcase; a report declared with
86 ``pages`` gets a page per testsuite and testcase (:mod:`~pyTooling.Sphinx.UnittestPages`), which the roles
87 ``:ts:`` and ``:tc:`` - also ``:report:ts:`` and ``:report:tc:`` - refer to;
88 * :rst:dir:`report:code-coverage` and :rst:dir:`report:code-coverage-legend` - a code coverage report and its
89 coverage levels;
90 * :rst:dir:`report:doc-coverage` and :rst:dir:`report:doc-coverage-legend` - a package's documentation coverage
91 and its coverage levels; a package declared with ``pages`` gets a page per package and module
92 (:class:`~pyTooling.Sphinx.DocCoverage.DocCoverageReportPages`), which the role ``:doccov:`` refers to.
93
94* the **nodes** the directives emit, listed in :data:`NODES` with their visitors per output format.
95
96* the **external link icons** - in HTML, an icon behind each external link, chosen by its target, and the size behind
97 each download -, with the configuration values ``pyTooling_ExternalLink_Icons``, ``pyTooling_ExternalLink_NewTab``,
98 ``pyTooling_ExternalLink_Hosts``, ``pyTooling_ExternalLink_DownloadSizes``, ``pyTooling_ExternalLink_RemoteSizes``
99 and ``pyTooling_ExternalLink_RemoteSizeTimeout`` (:mod:`~pyTooling.Sphinx.ExternalLink`).
100
101Two classes aren't registered, because they are base-classes for a project's own directives:
102:class:`~pyTooling.Sphinx.BaseDirective` offers typed option access and table construction
103over the untyped mapping and the hand-assembled node trees docutils presents, and
104:class:`~pyTooling.Sphinx.SchemaGraph.SchemaGraph` draws a schema file named as a directive's
105argument, leaving only the reading of that schema to a derived class.
106
107.. attention::
108
109 This package requires **Python 3.12 or newer**, because it requires Sphinx 9.1 and Sphinx 9.1 does.
110
111.. seealso::
112
113 :mod:`pyTooling.Documentation`
114 |rarr| The doc-string helpers, which need no Sphinx.
115"""
116__author__ = "Patrick Lehmann"
117__email__ = "Paebbels@gmail.com"
118__copyright__ = "2026-2026, Patrick Lehmann"
119__license__ = "Apache License, Version 2.0"
120__version__ = "0.1.0rc4"
121__keywords__ = ["Sphinx", "Sphinx Extension", "Documentation", "Directive", "Role", "Domain", "docutils"]
122__project_url__ = "https://github.com/pyTooling/pyTooling.Sphinx"
123__documentation_url__ = "https://pyTooling.github.io/pyTooling.Sphinx"
124__issue_tracker_url__ = "https://GitHub.com/pyTooling/pyTooling.Sphinx/issues"
125
...
168
170__all__ = [
171 "STYLESHEET", "SCRIPT", "LATEX_PACKAGE", "SUBSTITUTIONS", "NODES", "LINE_ANCHOR", "REPORT_ROLES"
172]
173
174#: Name of the stylesheet, in :mod:`pyTooling.Sphinx.Resources`.
175STYLESHEET = "pyTooling.css"
176
177#: Name of the script, in :mod:`pyTooling.Sphinx.Resources`: it gives the copy buttons of the ``unicode-table``
178#: directive their function.
179SCRIPT = "pyTooling.js"
180
181#: Name of the LaTeX package, whose file :file:`pyTooling.Sphinx.sty` is in :mod:`pyTooling.Sphinx.Resources`: it
182#: defines the commands LaTeX writes for the style roles ``:strike:`` and ``:underline:``.
183LATEX_PACKAGE = "pyTooling.Sphinx"
184
185#: Substitutions that have to stay substitutions, because ``|br|`` is written as one in every project.
186#:
187#: ``|br|`` and ``|hr|`` delegate to the ``:br:`` and ``:hr:`` roles rather than writing HTML themselves, so they
188#: reach every output format instead of only HTML - see :func:`~pyTooling.Sphinx.Roles.breakRole`.
189SUBSTITUTIONS = """
190.. |degree| unicode:: U+00B0
191 :trim:
192
193.. |br| replace:: :br:`.`
194
195.. |hr| replace:: :hr:`.`
196"""
197
198#: The nodes the extension registers, each with its visitors per output format.
199#:
200#: A format without visitors of its own - e.g. LaTeX for the tree's nodes - writes a node with the visitors of its
201#: base-class.
202NODES: tuple[RegisteredNode, ...] = (
203 {"name": "TreeItem", "node": TreeItem, "html": translateTreeItem},
204 {"name": "TreeLabel", "node": TreeLabel, "html": translateTreeLabel},
205 {"name": "TreeSeparator", "node": TreeSeparator, "html": translateTreeSeparator},
206 {"name": "TreeDescription", "node": TreeDescription, "html": translateTreeDescription},
207 {"name": "TreeLegend", "node": TreeLegend, "html": translateTreeLegend},
208 {"name": "TreeLegendItem", "node": TreeLegendItem, "html": translateTreeLegendItem},
209 {"name": "CopyButton", "node": CopyButton, "html": translateCopyButton},
210 {"name": "Abbreviation", "node": Abbreviation, "html": translateAbbreviation},
211 {"name": "Landscape", "node": Landscape, "html": translateLandscapeAsHTML,
212 "latex": translateLandscapeAsLaTeX},
213 {"name": "CoverageListing", "node": CoverageListing, "html": translateCoverageListingAsHTML,
214 "latex": translateCoverageListingAsLaTeX},
215 {"name": "DocCoverageListing", "node": DocCoverageListing, "html": translateDocCoverageListingAsHTML,
216 "latex": translateDocCoverageListingAsLaTeX},
217 {"name": "Emoji", "node": Emoji, "html": translateEmoji},
218 {"name": "TaskListCheckbox", "node": TaskListCheckbox, "html": translateTaskListCheckboxAsHTML,
219 "latex": translateTaskListCheckboxAsLaTeX},
220 {"name": "LineBreak", "node": LineBreak, "html": translateLineBreakAsHTML,
221 "latex": translateLineBreakAsLaTeX},
222 {"name": "ReportIndentation", "node": ReportIndentation, "html": translateReportIndentationAsHTML,
223 "latex": translateReportIndentationAsLaTeX},
224)
225
227_EnumType = TypeVar("_EnumType", bound=Enum)
228"""Type of an enumeration read from a directive's options."""
229
231@export
232class SphinxExtensionError(ExtensionError, DocumentationError):
233 """
234 Base-exception of all exceptions raised by :mod:`pyTooling.Sphinx`.
235
236 It derives from **both** hierarchies on purpose: :exc:`~sphinx.errors.ExtensionError` is what Sphinx catches and
237 reports with the position of the directive, and :exc:`~pyTooling.Documentation.DocumentationError` is what a
238 caller of pyTooling catches. Neither would be enough alone.
239 """
240
242@export
243class ReportExtensionError(SphinxExtensionError):
244 """
245 The exception raised by the ``report`` domain.
246
247 It is raised e.g. for a mistake in the domain's configuration values or options.
248 """
249
251@export
252class ReportsPackageMissingError(ReportExtensionError):
253 """
254 The exception raised when a report is read, but the optional packages of the extra ``reports`` aren't installed.
255
256 The message names what was attempted and the packages it needs; a note says how to install them.
257 """
258
259 def __init__(self, task: str, packages: str = "'pyEDAA.Reports'") -> None:
260 """
261 Initialize the exception with what was attempted and the packages it needs.
262
263 :param task: What needs the packages, e.g. ``Reading a unit test report``.
264 :param packages: Optional, the packages needed, quoted. Default: ``'pyEDAA.Reports'``.
265 """
...
268
270@export
271class LegendStyle(Flag):
272 """
273 How a legend directive of domain ``report`` lays out the coverage levels; a document writes the names with dashes.
274 """
275
276 Default = 0 #: No style.
277 Table = 1 #: A table.
278
279 Horizontal = 1024 #: A column per level.
280 Vertical = 2048 #: A row per level.
281
282 horizontal_table = Table | Horizontal #: A table with a column per level, written ``horizontal-table``.
283 vertical_table = Table | Vertical #: A table with a row per level, written ``vertical-table``.
284
286@export
287def strip(option: str) -> str:
288 """
289 Option converter removing surrounding whitespace.
290
291 :param option: The option's value as it was written.
292 :returns: The value without surrounding whitespace.
293 """
...
295
297@export
298def stripAndNormalize(option: str) -> str:
299 """
300 Option converter removing surrounding whitespace and lowering the case.
301
302 :param option: The option's value as it was written.
303 :returns: The value without surrounding whitespace, in lower case.
304 """
...
306
308@export
309class BaseDirective(ObjectDescription[str]):
310 """
311 Base-class for a directive, offering typed option access and table construction.
312
313 A derived class sets :attr:`directiveName` - which is what the error messages name - and declares
314 ``option_spec`` as any directive does. What it gets in return is a ``_Parse***Option`` per type instead of
315 reaching into :attr:`options` and validating by hand, and a ``_Create***TableHeader`` per table shape instead of
316 assembling :class:`~docutils.nodes.tgroup`, :class:`~docutils.nodes.colspec`, :class:`~docutils.nodes.thead`
317 and :class:`~docutils.nodes.row` in the right order.
318 """
319
320 has_content = False #: A boolean; ``True`` if content is allowed.
321 required_arguments = 0 #: Number of required directive arguments.
322 optional_arguments = 0 #: Number of optional arguments after the required ones.
323 final_argument_whitespace = False #: A boolean; ``True`` if the last argument may contain spaces.
324 option_spec = {} #: Mapping of option names to validator functions.
325
326 directiveName: str #: Name the directive is invoked by, used in every error message.
327
328 def _ParseBooleanOption(self, optionName: str, default: Nullable[bool] = None) -> bool:
329 """
330 Read an option written as ``yes``/``true`` or ``no``/``false``.
331
332 :param optionName: Name of the option to read.
333 :param default: Optional, the value to return when the option wasn't given.
334 :returns: The option's value.
335 :raises SphinxExtensionError: If the option wasn't given and has no default.
336 :raises SphinxExtensionError: If the option's value is neither of the two accepted spellings.
337 """
...
356
357 def _ParseStringOption(self, optionName: str, default: Nullable[str] = None, regexp: str = "\\w+") -> str:
358 """
359 Read an option that has to match a regular expression.
360
361 The pattern defaults to one or more word characters.
362
363 :param optionName: Name of the option to read.
364 :param default: Optional, the value to return when the option wasn't given.
365 :param regexp: Optional, the pattern the value has to match.
366 :returns: The option's value.
367 :raises SphinxExtensionError: If the option wasn't given and has no default.
368 :raises SphinxExtensionError: If the option's value doesn't match the pattern.
369 """
...
386
387 def _ParseEnumOption(
388 self,
389 optionName: str,
390 enumType: type[_EnumType],
391 default: Nullable[_EnumType] = None
392 ) -> _EnumType:
393 """
394 Read an option naming a member of an enumeration.
395
396 The written value is lowered and its dashes become underscores, so ``horizontal-table`` in a document selects
397 the ``horizontal_table`` member - a document reads in the spelling documents use, and the enumeration keeps
398 the spelling Python uses.
399
400 :param optionName: Name of the option to read.
401 :param enumType: The enumeration whose members the value is looked up in.
402 :param default: Optional, the member to return when the option wasn't given.
403 :returns: The named member of the enumeration.
404 :raises SphinxExtensionError: If the option wasn't given and has no default.
405 :raises SphinxExtensionError: If the value names no member of the enumeration.
406 """
...
426
427 def _CreateSingleRowTableHeader(
428 self,
429 columns: list[tuple[str, Nullable[int]]],
430 identifier: str,
431 classes: list[str]
432 ) -> nodes.tgroup:
433 """
434 Create a table with a single header row.
435
436 :param columns: One ``(title, width)`` pair per column; a width of ``None`` leaves it to the writer.
437 :param identifier: Identifier of the table.
438 :param classes: CSS classes to put on the table.
439 :returns: The table's column group, with the header row already in it.
440 """
...
456
457 def _CreateDoubleRowTableHeader(
458 self,
459 columns: list[tuple[str, Nullable[list[tuple[str, int]]], Nullable[int]]],
460 identifier: str,
461 classes: list[str]
462 ) -> nodes.tgroup:
463 """
464 Create a table whose header spans two rows, so a column can group sub-columns.
465
466 A column's ``subColumns`` is ``None`` when it spans both header rows, and otherwise holds the
467 ``(title, width)`` pairs below it.
468
469 :param columns: One ``(title, subColumns, width)`` triple per column.
470 :param identifier: Identifier of the table.
471 :param classes: CSS classes to put on the table.
472 :returns: The table's column group, with both header rows already in it.
473 """
...
510
511 def _CreateRotatedTableHeader(
512 self,
513 columns: list[tuple[str, Nullable[list[str]]]],
514 identifier: str,
515 classes: list[str]
516 ) -> nodes.tgroup:
517 """
518 Create a table whose header titles are rotated, for many narrow columns.
519
520 :param columns: One ``(title, classes)`` pair per column; the classes are put on the header cell.
521 :param identifier: Identifier of the table.
522 :param classes: CSS classes to put on the table.
523 :returns: The table's column group, with the header row already in it.
524 """
...
542
543 def _internalError(
544 self,
545 container: nodes.container,
546 location: str,
547 message: str,
548 exception: Exception
549 ) -> list[nodes.Node]:
550 """
551 Report an exception a directive couldn't recover from, in the log **and** on the page.
552
553 A directive that fails silently leaves a hole in the documentation that nobody notices. This puts the message
554 where a reader sees it and the traceback where a maintainer does. The exception's notes - e.g. how to install a
555 missing package - are logged below it.
556
557 :param container: The container the message is put into.
558 :param location: Name of the logger, which is what the log line is attributed to.
559 :param message: What went wrong, in one sentence.
560 :param exception: The exception that was caught.
561 :returns: The container, as the list a directive's ``run`` returns.
562 """
...
576
578@export
579def installStaticFiles(sphinx: Sphinx) -> None:
580 """
581 Call-back for Sphinx' ``builder-inited`` event, writing the stylesheet and the script into the build and linking
582 them.
583
584 A file is named by the hash of its content, so a browser re-reads it when it changes and re-uses it when it doesn't.
585 Older copies are removed when the content changed.
586
587 :param sphinx: The Sphinx application.
588 """
...
607
609@export
610def installLaTeXPackage(sphinx: Sphinx) -> None:
611 """
612 Call-back for Sphinx' ``builder-inited`` event, writing the LaTeX package :data:`LATEX_PACKAGE` into the build of a
613 LaTeX builder, where the document's ``\\usepackage`` finds it.
614
615 :param sphinx: The Sphinx application.
616 """
...
623
625@export
626def extendProlog(sphinx: Sphinx, config: Any) -> None:
627 """
628 Call-back for Sphinx' ``config-inited`` event, appending the shared substitutions to ``rst_prolog``.
629
630 A role can be registered; a **substitution** cannot - ``|br|`` is substitution syntax, and every project writes
631 it that way already. Appending them here is what lets a project delete them from its own prolog without changing
632 a single document.
633
634 :param sphinx: The Sphinx application.
635 :param config: The configuration, after :file:`conf.py` was read.
636 """
...
638
640@export
641def setLaTeXDefaults(sphinx: Sphinx, config: Config) -> None:
642 """
643 Call-back for Sphinx' ``config-inited`` event, setting LaTeX defaults, unless :file:`conf.py` sets them.
644
645 * ``latex_table_style``: ``["booktabs"]``, without Sphinx' default ``colorrows``.
646 * ``latex_elements["maxlistdepth"]``: ``"10"`` nested lists, e.g. a :rst:dir:`tree` with more than 4 levels.
647
648 :param sphinx: The Sphinx application.
649 :param config: The configuration, after :file:`conf.py` was read.
650 """
...
655
657@export
658class ReportEntry(NamedTuple):
659 """
660 An object of a report, which has a page of its own - a testcase, a source file, ...: where it is, and its names.
661 """
662
663 docName: str #: Name of the generated document showing the object.
664 reportID: str #: Identifier of the report in its configuration value.
665 path: tuple[str, ...] #: Names of the objects from the report's root down to this object's own name.
666 separator: str #: Separator of the names in a qualified name, e.g. ``.`` or ``/``.
667 title: Nullable[str] #: Title of the object written for a reader, if the report has one.
668
669 @readonly
670 def Name(self) -> str:
671 """
672 Read-only property to return the object's own name, the last element of :attr:`path`.
673
674 :returns: The name.
675 """
...
677
678 @readonly
679 def QualifiedName(self) -> str:
680 """
681 Read-only property to return the qualified name: the names of :attr:`path` joined by :attr:`separator`.
682
683 :returns: The qualified name, e.g. ``pytest.tests.unit.Arithmetic.Addition.test_Positive``.
684 """
...
686
687 def Matches(self, name: str) -> bool:
688 """
689 Check whether a name is the qualified name or a suffix of it, which starts at an element of :attr:`path`.
690
691 :param name: The name as written in a reference, without a report ID.
692 :returns: ``True`` if the name is the qualified name or one of its suffixes.
693 """
...
695
697@export
698class ReportRoleDefinition(NamedTuple):
699 """
700 What a role of domain ``report`` refers to: a kind of object of the reports declared in a configuration value.
701 """
702
703 objectType: str #: The object type, as listed by the domain, e.g. ``testcase``.
704 configValue: str #: The configuration value declaring the reports; its first report is the default one.
705 reports: str #: The reports, as a warning names them, e.g. ``unit test reports``.
706 lineAnchors: bool = False #: Whether a target may end in ``#<line number>``, linking to the line on the page.
707
709#: The line number a target of a role with line anchors may end in, e.g. ``#12`` of ``src/Counter.vhdl#12``.
710LINE_ANCHOR = re_compile(r"#(\d+)$")
711
712#: The roles referring to the objects of reports with pages, by role name.
713REPORT_ROLES = {
714 "tc": ReportRoleDefinition("testcase", "pyTooling_Unittest_Testsuites", "unit test reports"),
715 "ts": ReportRoleDefinition("testsuite", "pyTooling_Unittest_Testsuites", "unit test reports"),
716 "cov": ReportRoleDefinition("source", "pyTooling_CodeCoverage_Packages", "code coverage reports", True),
717 "doccov": ReportRoleDefinition("module", "pyTooling_DocCoverage_Packages", "documentation coverage reports"),
718}
719
721@export
722class ReportRole(XRefRole):
723 """
724 A role of domain ``report`` referring to an object of a report with pages.
725
726 Role ``tc`` refers to a testcase, ``ts`` to a testsuite.
727
728 Sphinx registers a role outside a domain without one, so the reference would be resolved by nobody; this role puts
729 domain ``report`` on the reference, and uses its name as the reference's type. So it works as ``:report:tc:`` and
730 as the global ``:tc:``.
731 """
732
733 def run(self) -> tuple[list[nodes.Node], list[nodes.system_message]]:
734 """
735 Create the reference, or only the text if the role is written with ``!``.
736
737 :returns: The nodes and messages a role returns.
738 """
...
747
749@export
750class ReportDomain(Domain):
751 """
752 The Sphinx domain ``report``, integrating unit test, code coverage and documentation coverage reports.
753
754 Its directives are registered by :func:`setup`, and read their reports from the files declared in :file:`conf.py`.
755
756 A report with generated pages contributes an object per page - e.g. a unit test report its testsuites and
757 testcases -, which the roles of :data:`REPORT_ROLES` refer to, e.g. ``:report:tc:``, also registered as ``:tc:``. A
758 reference names an object by its qualified name, or by a suffix of it, optionally preceded by the report's
759 identifier and a colon; without one, the first report of the role's configuration value is meant.
760 """
761
762 name = "report" #: Name of the domain, the prefix of its directives.
763 label = "rpt" #: Name of the domain, as displayed.
764 data_version = 2 #: Version of the domain data's layout; a pickled environment of another version is dropped.
765
766 object_types = {
767 definition.objectType: ObjType(definition.objectType, roleName) for roleName, definition in REPORT_ROLES.items()
768 } #: The objects: per role, the objects of the reports with generated pages.
769 initial_data: dict[str, Any] = {
770 roleName: {} for roleName in REPORT_ROLES
771 } #: The data of an empty documentation: per role, no object.
772 roles = {
773 roleName: ReportRole(innernodeclass=nodes.inline, warn_dangling=True) for roleName in REPORT_ROLES
774 } #: The roles, also registered without the domain's prefix.
775 dangling_warnings = {
776 roleName: f"{definition.objectType} '%(target)s' not found in the {definition.reports}"
777 for roleName, definition in REPORT_ROLES.items()
778 } #: The warning for a reference to an unknown object, per role.
779
780 def AddEntry(self, roleName: str, entry: ReportEntry) -> None:
781 """
782 Register an object, which has a generated page.
783
784 :param roleName: The role referring to the object, e.g. ``tc`` for a testcase.
785 :param entry: The object.
786 """
...
788
789 def FindEntries(self, roleName: str, target: str) -> list[ReportEntry]:
790 """
791 Find the objects a reference's target names.
792
793 A target is ``[<report ID>:]<name>``. If the part before the first colon isn't the identifier of a report, the
794 whole target is the name in the default report - the first one of the role's configuration value -, as e.g. a
795 parametrized testcase's name may contain a colon. A name is a qualified name or a suffix of one (see
796 :meth:`ReportEntry.Matches`); an exact qualified name wins over suffixes.
797
798 :param roleName: The role referring to the object, e.g. ``tc`` for a testcase.
799 :param target: The reference's target.
800 :returns: The matching entries: none, one, or several if the name is ambiguous.
801 """
...
817
818 def clear_doc(self, docname: str) -> None:
819 """
820 Forget the objects of a document, before it is generated again.
821
822 :param docname: Name of the document.
823 """
...
828
829 def merge_domaindata(self, docnames: Iterable[str], otherdata: dict[str, Any]) -> None:
830 """
831 Take over the objects a parallel reader collected for its documents.
832
833 :param docnames: Names of the documents the other reader read.
834 :param otherdata: The other reader's domain data.
835 """
...
843
844 def resolve_xref(
845 self,
846 env: BuildEnvironment,
847 fromdocname: str,
848 builder: Builder,
849 typ: str,
850 target: str,
851 node: pending_xref,
852 contnode: nodes.Element
853 ) -> Nullable[nodes.Element]:
854 """
855 Resolve a reference to an object of a report into a link to its page.
856
857 The link shows the object's name, or the title written in the role; in HTML, its title written for a reader - if
858 the report has one - is shown on hover. An ambiguous name is warned about and shown as text.
859
860 :param env: The build environment.
861 :param fromdocname: Name of the document holding the reference.
862 :param builder: The builder writing the documents.
863 :param typ: The role's name, e.g. ``tc``.
864 :param target: The object referred to.
865 :param node: The reference.
866 :param contnode: The reference's text.
867 :returns: The link, the text if the name is ambiguous or the builder doesn't write the page, or
868 ``None`` if nothing matches.
869 """
...
901
902 def resolve_any_xref(
903 self,
904 env: BuildEnvironment,
905 fromdocname: str,
906 builder: Builder,
907 target: str,
908 node: pending_xref,
909 contnode: nodes.Element
910 ) -> list[tuple[str, nodes.reference]]:
911 """
912 Resolve a reference of role ``:any:`` to an object of a report with an unambiguous name.
913
914 :param env: The build environment.
915 :param fromdocname: Name of the document holding the reference.
916 :param builder: The builder writing the documents.
917 :param target: The text referred to.
918 :param node: The reference.
919 :param contnode: The reference's text.
920 :returns: A role and link per kind of object the text names unambiguously.
921 """
...
931
932 def get_objects(self) -> Iterator[tuple[str, str, str, str, str, int]]:
933 """
934 Name the objects of the reports, for the search and for other documentations referring to them.
935
936 An object's name is ``<report ID>:<qualified name>``. A testcase gets a lower search priority than a testsuite,
937 as a report may have thousands of them.
938
939 :returns: A tuple per object: name, display name, type, document, anchor and search priority.
940 """
...
946
948@export
949def checkReportConfiguration(sphinx: Sphinx, config: Config) -> None:
950 """
951 Call-back for Sphinx' ``config-inited`` event, checking the reports' configuration values and loading their settings.
952
953 A mistake is logged as an error rather than stopping the build; a directive naming that report fails on its own.
954
955 :param sphinx: The Sphinx application.
956 :param config: The configuration, after :file:`conf.py` was read.
957 """
...
973
975@export
976def readReports(sphinx: Sphinx) -> None:
977 """
978 Call-back for Sphinx' ``builder-inited`` event, reading the report files, analyzing the documented packages, and
979 registering the reports' pages.
980
981 :param sphinx: The Sphinx application.
982 """
...
995
997@export
998def setup(sphinx: Sphinx) -> dict[str, Any]:
999 """
1000 Register the roles, the nodes, the directives and the domain ``report`` with Sphinx.
1001
1002 The modules are imported here rather than with the package, and none of them imports an optional dependency at
1003 module level - e.g. pyEDAA.Reports is imported only when a report is read - so the extension works without them.
1004
1005 :param sphinx: The Sphinx application to register with.
1006 :returns: The extension's metadata.
1007 """
...