report:doc-coverage
The report:doc-coverage directive renders the documentation coverage of a Python package as a table: a row
per package and module, with the number of items expected to be documented - e.g. classes, functions and
fields -, the documented and the undocumented ones. The package hierarchy is shown by indentation and 📦, a
module by ⚙️, and each row is coloured by its coverage level. report:doc-coverage-legend renders the coverage
levels.
There is no report file: the package’s source directory is analyzed by the
Python reader of pyEDAA.Reports once per build. Packages are declared in
conf.py, each with an identifier the directives name in their report:doc-coverage:reportid
option.
A package can get a page per package and module: a module’s page shows its source
condensed to signatures, doc-strings, fields and variables, each marked by its documentation state. The table
links to the pages, and the role doccov refers to them.
The directives are part of pyTooling.Sphinx; they need the
extra reports.
.. grid:: 2
.. grid-item::
:columns: 8
.. report:doc-coverage::
:reportid: example
.. grid-item::
:columns: 4
.. report:doc-coverage-legend::
:reportid: example
:style: vertical-table
This is how the example renders, for a package with one sub-package. The package is declared with pages, so every package and module links to its page:
| Filename | Total | Covered | Missing | Coverage in % |
|---|---|---|---|---|
| 📦myPackage | 1 | 1 | 0 | 100.0% |
| 📦Units | 1 | 0 | 1 | 0.0% |
| ⚙️Length | 4 | 3 | 1 | 75.0% |
| ⚙️Shapes | 14 | 9 | 5 | 64.3% |
| Overall (4 files): | 20 | 13 | 7 | 65.0% |
| Documentation Coverage | Coverage Level |
|---|---|
| ≤10 % | almost undocumented |
| ≤20 % | almost undocumented |
| ≤30 % | almost undocumented |
| ≤40 % | poorly documented |
| ≤50 % | poorly documented |
| ≤60 % | roughly documented |
| ≤70 % | roughly documented |
| ≤80 % | roughly documented |
| ≤85 % | well documented |
| ≤90 % | well documented |
| ≤95 % | well documented |
| ≤100 % | excellent documented |
The documentation’s own documentation coverage report is rendered by these directives too.
Configuration
The packages are declared in conf.py as a dictionary, keyed by the identifier a directive names in
report:doc-coverage:reportid. A path is relative to the documentation’s source directory.
pyTooling_DocCoverage_Packages→ The analyzed packages, by identifier. An entry has these fields:
name→ The name of the Python package, shown in the first row.
directory→ The package’s source directory.
pages→ The document name the pages per package and module are generated below, e.g.
doccoverage/src. Optional; without it, the package gets no pages.fail_below→ An integer in range 0..100: the coverage in percent below which the package fails.
levels→ The name of a palette in
pyTooling_DocCoverage_Levels, e.g."default", or a palette of its own, written as there.
pyTooling_DocCoverage_Levels→ The palettes of coverage levels, by name. A palette maps an upper limit in percent to a CSS class and a description, and needs a level
100and a level"error". Default: the palettedefault, of 12 levels from ≤10 % to ≤100 %, coloured from blue via red, orange and yellow to green.
# doc/conf.py
pyTooling_DocCoverage_Packages = {
"src": {
"name": "myPackage",
"directory": "../myPackage",
"pages": "doccoverage/src",
"fail_below": 80,
"levels": "default"
}
}
The first entry is the default package of the role doccov.
The configuration is checked when the build starts. A directory that doesn’t exist is logged as an error, and the entries after it aren’t read. The packages are analyzed once per build, before any document is read.
Analysis
A package is read from its source files - every *.py file below its directory, each in its declared encoding -
into the language-neutral documentation coverage model of pyEDAA.Reports, by its
Python reader. Every
documentable item is counted - also fields, variables, and items of a protected (_x) or private (__x) name. The
reader’s default selection (CountedItems.Default) isn’t configurable yet.
Packages, modules, classes, functions, methods and properties are documented by a non-empty doc-string. A comment of docstr_coverage directly above a declaration -
# docstr-coverage: inheritedor# docstr-coverage: excused `reason`- excuses a missing doc-string.A class’ fields and a module’s variables are documented where Sphinx’ autodoc finds their documentation: a
#:comment behind the statement or in the lines above it, or a doc-string literal following it.A field or variable assigned in an
ifortrystatement of a class or module is counted too, e.g. inif TYPE_CHECKING:.Ignored - not expected to be documented - are, e.g., a property’s setter, an
@overloadstub, and a name like__all__.A package without
__init__.py- a namespace package - has nothing to document.
A row of the table counts the items declared in its file: a module’s, or a package’s __init__.py. The summary
row counts all items of the package.
A source file, which can’t be read or parsed, is logged as a warning; its module is excluded from the analysis, and
the analysis continues. Its row - in the table and on the pages - has the coverage level error and says
can’t be read.
Pages per package and module
A package declared with the key pages gets a page per package and per module. They are generated when the
documentation is built - no source file is written - below the document name the key states, named by the package’s
and module’s names, e.g. doccoverage/src/myPackage/Units/Length.
A package’s page shows its parent package, the state of its __init__.py’s doc-string, and its counters: those
of its __init__.py, and overall - with all its packages and modules -, each colored by its coverage level. Then a
table of its packages and a table of its modules, each linked to its page and colored by its coverage level; a
package’s row counts it with all its packages and modules. Last, the condensed listing of its __init__.py. A
namespace package - without __init__.py - shows only its overall counters and has no listing.
A module’s page shows its parent package, the state of its doc-string, its counters, and its condensed listing.
The condensed listing shows a module’s source as far as documentation coverage is about it: the code of a function is of no interest, its signature and its doc-string are. The source is syntax highlighted with Pygments, in the colors of Sphinx’ Pygments style, as every code block. A line is shown as written, with its line number, or elided:
The module’s doc-string is shown. Imports and other statements are elided.
A class or function is shown with its decorators, its header - a signature spanning several lines too - and its doc-string. Its body follows: a class’ fields and methods, a function’s nested functions and classes. Anything else is elided.
A module’s variables and a class’ fields are shown with their
#:comments - behind them or in the lines above - and a doc-string literal following them.A statement holding classes or functions - e.g. an
ifchoosing between two definitions -, and anifortryassigning a variable or field, is shown with the headers of its clauses -if ...:,else:,except ...:-; each clause’s block is shown like a body.A definition written in one line -
def f(): pass- is shown as written.Comments between statements are left out; consecutive blank lines become one.
Consecutive elided statements become a single ... line without a line number, at the statements’ indentation, so
a function’s body becomes .... Each line of a class or function - its decorators, header and doc-string - and of a
field or variable is marked by the documentation state of its item in the analysis:
State |
Line |
|---|---|
|
The item is documented: a class or function by a doc-string - or an excuse comment, e.g.
|
|
The item has no documentation. |
|
The item isn’t expected to be documented, e.g. a property’s setter or |
|
The item is excluded from the analysis. |
(none) |
The line isn’t counted: a blank line, a clause’s header, a repeated assignment of a variable. |
The module’s doc-string is marked by the module’s state, which the page’s summary states too.
A header above the listing shows the module’s path and a legend of these states.
The report:doc-coverage directive lists the package’s page in a hidden table of contents, and a package’s
page lists its packages and modules, so the pages are in the navigation below the table’s document. LaTeX writes the
pages too, below the table’s section; a listing’s line numbers are colored by the documentation state, followed by a
marker: + documented, - undocumented, o ignored, x excluded; a line above the listing shows the
module’s path and the markers’ legend.
Sphinx regards a module’s file - a package’s __init__.py - as the source of its page.
Hint
A module is as many levels below the table’s document as it is nested in packages. A theme limits how deep its
navigation goes, e.g. the option navigation_depth of the Read the Docs theme (default 4; -1 =
unlimited).
Role
- :doccov:
Refers to a package’s or module’s page, showing its name, or the role’s title:
:doccov:`<target>`or:doccov:`title <<target>>`. It is registered in domainreport- as:report:doccov:- and without the domain’s prefix.The target is
[<report ID>:]<dotted name>, e.g.myPackage.Units.Length. A suffix of it starting at a name -Units.LengthorLength- is accepted, if it’s unique. The configured name of the analyzed package is one name, also if it’s dotted, e.g.pyTooling.Sphinx. Without a report ID, the first package ofpyTooling_DocCoverage_Packagesis meant.A target matching nothing or several packages and modules is warned about.
* :doccov:`example:Shapes`
* :doccov:`example:myPackage.Units`
* :doccov:`the length module <example:Length>`
The packages and modules are objects of domain report of type module, named <report ID>:<dotted name> in
the documentation’s inventory (objects.inv), so another documentation refers to them with intersphinx.
Options
- .. report:doc-coverage::
Renders the documentation coverage of a package as a table.
- :reportid: <identifier>
The package, as declared in
pyTooling_DocCoverage_Packages. Required.
- :class: <CSS classes>
Additional CSS classes on the table.
- .. report:doc-coverage-legend::
Renders the coverage levels of a package as a table.
- :reportid: <identifier>
The package, as declared in
pyTooling_DocCoverage_Packages, whose palette is shown. Required.
- :style: horizontal-table | vertical-table
A column per level, or a row per level. Default:
horizontal-table.
- :class: <CSS classes>
Additional CSS classes. Accepted, but not yet put on the table.
Styling
The table carries the classes report-doccov-table and report-doccov-<identifier>, a legend
report-doccov-legend. A row carries its kind - report-package, report-module or report-summary - and the
CSS class of its coverage level, e.g. report-cov-below80. The rules of the stylesheet and the indentation of the
names are those of the code coverage tables. A page’s tables carry
report-doccov-table too, and report-doccov-summary or report-doccov-children.
A condensed listing is styled like a code coverage listing: a line carries
report-line-documented, report-line-undocumented, report-line-ignored or report-line-excluded, which
share the colors of covered, uncovered and excluded; an elided ... carries report-line-elided.