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

Resources

1

1

0

100.0%

Modules

Module

Expected

Covered

Uncovered

Coverage

Abbreviation

41

41

0

100.0%

CodeCoverage

70

70

0

100.0%

CodeCoveragePages

22

22

0

100.0%

CondensedClass

28

27

1

96.4%

CondensedSource

28

28

0

100.0%

DependencyTable

103

101

2

98.1%

DocCoverage

76

76

0

100.0%

ExternalLink

61

61

0

100.0%

GitHubMarkdown

30

30

0

100.0%

HTML

50

50

0

100.0%

LaTeX

24

24

0

100.0%

Markdown

44

44

0

100.0%

Node

25

25

0

100.0%

Pages

34

34

0

100.0%

Roles

7

7

0

100.0%

SchemaGraph

13

13

0

100.0%

Shields

32

32

0

100.0%

Tree

31

31

0

100.0%

UnicodeTable

48

48

0

100.0%

Unittest

51

51

0

100.0%

UnittestPages

14

14

0

100.0%

Workaround

6

6

0

100.0%

XMLSchemaGraph

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	"""
	...