5. Docstring format¶
5.1. Definitions¶
This section is normative.
Normativity Keyword
A Normativity Keyword is a typographically distinct word from the following set:
{must, must not, Must, Must not, should, should not, Should, Should not, may, May}.
In the Waterloo docstring format these keywords are realized as the plain word enclosed by “|” (ASCII 124).
Whenever we talk about Normativity Keywords (with capitals), we always mean the tokenized form with delimiters “|”.
Identifier
An Identifier is a string value that matches the regular expression [a-zA-Z_][a-zA-Z0-9_]*.
Qualified Identifier
A Qualified Identifier is a string formed by concatenating Identifiers (at least one) with a dot as separator.
5.2. Terminology¶
This section is informative.
Documentation Coverage
Documentation Coverage is the property of a documented code base
that all objects explicitly declared as public are accompanied by valid
Waterloo docstrings.
An object is considered explicitly declared as public if it is listed in
a section of the form Public_* in the enclosing documentation
scope (module or class).
Documentation coverage is evaluated solely based on the presence, structure, and validity of docstrings, and is independent of the semantic correctness or completeness of their contents.
Lint rule
A lint rule is a normative requirement that can be checked unambiguously by a tool against the docstring text
and the available program context (e.g. signatures, importability, symbol tables).
Normative guidance that is not intended to be tool-enforced does not require a rule ID.
Liskov-compatible
A method is Liskov-compatible if it satisfies the Liskov Substitution Principle (LSP)
in relation to the method it overrides. Tools may check type-level compatibility (e.g. contravariance of arguments and covariance of return types)
if sufficient type information is available. Behavioral consistency (pre-/post-conditions and exception behavior)
is generally not statically verifiable and is therefore out of scope for mandatory validation.
Scope Monotonicity Rule
A rule defined in chapter Scopes and visibility, which states that each object
(depending on the circumstances) should have a scope that is no more restrictive than any
of its dependent objects. For example, a class with the scope core
cannot have nested classes or methods with the scope public – If this were allowed,
a public user would have to deal with objects that are explicitly restricted
to the smaller group of core users, which does not make sense.
5.3. Specification conventions¶
This section is informative.
The specification of rule-based normative topics throughout this document follows a common structural pattern. The purpose of this pattern is to ensure consistency, readability, and long-term maintainability of the specification text.
A specification block may consist of the following components, in the order listed below:
Normative rules
One or more rules identified by rule IDs. These define the formal semantics and validation requirements.
Obsolete rules (optional)
A list of previously defined rules that have been superseded. Each obsolete rule should indicate the version in which it became obsolete and, if applicable, the rule that replaces it.
Rationale (informative, optional)
Explanatory text describing the intent, design considerations, or background of the preceding rules. The rationale does not introduce additional normative requirements.
Last review (editorial, optional)
A date indicating the most recent editorial review of the section. This item has no normative effect.
Not all components are mandatory. Their presence depends on the complexity, maturity, and historical evolution of the topic under consideration. This structural pattern serves as a guideline for authors and editors of this specification. It is intended to promote uniformity without constraining future refinement.
5.4. Meta¶
This section is normative.
In this section, we specify that all normative rules and error codes for defining the Waterloo project are given IDs, and how we construct these IDs. We do this by the following set of rules.
[META-000] – Each normative rule that is intended to be enforced by tools (a “lint rule”)
mustbe assigned a unique, unchangeable ASCII-string-valued rule ID.[META-001] – A rule ID
mustconsist of one or more uppercase ASCII letters[A-Z]+, followed by a hyphenation character (ASCII 45), followed by three digits[0-9]{3}. (Informative note: The set of possible rule IDs is countably infinite.)[META-002] – Rule IDs
must notbe re-used if a rule becomes obsolete. A new rulemustalways be assigned an ID that did not exist before.[META-003] – Rule IDs
mustbe treated as stable external references for tooling, configuration, automated validation reports, and documentation. Toolsshouldinclude the rule ID in every diagnostic message derived from a normative rule.[META-004] – Rules, as free-form text in documentation,
muststart with the Rule ID delimited by square brackets, followed by a whitespace character which allows simple, unique and robust parsing of the Rule ID. Informative: In this document which is written in reST, we insert a space (ASCII 32), a double-hyphen (en-dash), and another space (ASCII 32) between the braced Rule ID and the rule free-form text. When a rule is merely mentioned but not introduced, square bracketsshould notbe used.[META-005] – Obsolete rule IDs, when mentioned in prose,
must notbe introduced with square brackets; square bracketsmustbe reserved for the point where a rule is defined.
5.5. Rule taxonomy¶
This section is informative.
The prefixes of rule IDs have a mnemonic function. The following list explains the mnemonic prefixes and their semantics.
Meta
META: Meta: rules defining the concept of rules
Parsing and validation
DOC: Docstrings in general
PNB: Partial Normativity Bugs
PRSR: Parser
TKN: Tokenizer
Helper ruleset
LQID: List of [Qualified] Identifiers
Sections and subsections
CON: All profiles: Section
ContractCCLO: Profile
class: SectionClass_overviewCMTO: Profile
class: SectionMethod_overviewCPCL: Profile
class: SectionPublic_classesCPMT: Profile
class: SectionPublic_methodsCPTYP: Profile
classSectionPublic_typesCPVAR: Profile
class: SectionPublic_variablesCPCON: Profile
class: SectionPublic_constantsDEF: All profiles: Section
DefinitionsDER: Profile
class: SectionDerived_fromDESC: All profiles: Section
DescriptionFAC: Profile
class: SectionFactoryMCLO: Profile
module: SectionClass_overviewMFNO: Profile
module: SectionFunction_overviewMPCL: Profile
module: SectionPublic_classesMPFN: Profile
module: SectionPublic_functionsMPTYP: Profile
moduleSectionPublic_typesMPVAR: Profile
module: SectionPublic_variablesMPCON: Profile
module: SectionPublic_constantsNOTE: All profiles: Section
NotesPAR: Profiles
function,method: SectionParametersPRE: All profiles: Section
PreambleRAI: Profiles
function,method: SectionRaisesRET: Profiles
function,method: SectionReturnsSCP: All profiles: Subsection
scopeSEE: All profiles: Section
See_alsoSTA: All profiles: Subsection
statusTERM: All profiles: Section
Terminology
Tools and extensions
TOOL: Error messages from
waterlint(or other tools)JPTR: Error messages related to JSON Pointer references in tool-generated JSON
JSCH: Error messages related to JSON and JSON Schema
AXMPL: Error messages related to example mapping (e.g. for
waterlint add-example-json)CARVE: Error messages related to carving walk input into JSON objects
RHTM: Error messages related to rendering HTML (e.g. for
waterlint render-html5)XTNSN: Error messages related to extensions (e.g. for IDEs)
MCPS: Error messages returned by an MCP server
DCKR: Error messages related to rendering Docker builder output (e.g. for
waterlint render-docker)XPLN: Error messages related to explain commands (e.g. for
waterlint explain-sectionandwaterlint explain-subsection)
Miscellaneous
VLII: Warning for a section or subsection that violates the LoII principle. The warning will remain in place until the section or subsection is generally accepted and recognized as having practical benefits that outweigh the LoII principle.
Obsolete
PTY: Profiles
module,class: SectionPublic_typesPVAR: Profiles
module,class: SectionPublic_variablesPCON: Profiles
module,class: SectionPublic_constants
5.6. The structure of Waterloo docstrings¶
This section is informative.
This section defines the structure of Waterloo docstrings. It does so in human-readable form. The structure is presented as lists for the various sections with embedded lists for subsections. The following patterns occur in any order:
<Section>:
<Subsection>:
<Free-Form-Content>
...
<Subsection>:
<Itemized-Content>
...
<Subsection>:
<List-Of-Identifiers>
...
<Subsection>:
<List-Of-Qualified-Identifiers>
...
and also, in any order
<Section>:
<Free-Form-Content>
...
<Section>:
<Itemized-Content>
...
<Section>:
<List-Of-Identifiers>
...
<Section>:
<List-Of-Qualified-Identifiers>
In the patterns above, <Free-Form-Content> denotes paragraph-capable
text. It may contain ordinary prose as well as explicitly marked bullet lists
or enumerations. This form is typically used where explanation, descriptive
structure, or more flexible text layout is required.
<Itemized-Content> denotes line-oriented content that is interpreted as
a sequence of individual items. In practice, this form is often used for
contract-like statements such as obligations, preconditions, postconditions, or
other entries that are naturally read item by item rather than as connected
prose.
On the docstring level, both forms are represented as indented text blocks. They differ primarily in their intended interpretation and in the way tools and output layers are expected to present them. For systematic examples and test cases that illustrate this distinction, see Test: Flow control in freeform sections.
The label string is defined as the substring between the first non-indentation character of the line and the last colon in the line. Since a label line must not contain any non-whitespace characters after that last colon, this rule is unambiguous. Tools must reject a label line that contains any non-whitespace characters after the last colon.
A section label is always an identifier followed by a colon. Subsection labels may be identifiers, qualified identifiers or plain non-empty human-readable string followed by a colon. The precise form of the subsection label depends on the subsection type and purpose. In either case it matches a string parsed greedily and closed by colon.
The indentation in the patterns above reflects the (relative) indentation for sections, subsections, and content in the docstring.
5.7. Conventions¶
This section is informative.
We shall use a simple dot notation in order to refer to subsections in the docstring format, like Preamble.normative_sections or Definitions.<DefItem>.
5.8. Building the AST¶
This section is normative.
The Abstract Syntax Tree (AST) is created in two steps. In the first step (“tokenization”) the docstring is transformed into an intermediate tree representation as defined in this section. In the second step (“parsing”), the intermediate representation is transformed into the AST.
We allow two indentation schemes named TAB
(using tab, ASCII 0x09, as indentation unit)
and SPC4
(using four spaces, ASCII 0x20, as indentation unit).
The indentation scheme must not be mixed within a single docstring.
The grammar of the tokenizer in Pseudo-EBNF is:
(* Possible ways to indent *)
spc = "\x20" ;
tab = "\x09" ;
newline = "\n" | "\r\n" ;
backslash = "\x5c" ;
ws_char = spc | tab ;
non_ws_char = ? all characters but spc and tab ? ;
non_nl_char = ? all characters but newline ? ;
(* either *)
indent_unit = tab ;
(* or *)
indent_unit = spc, spc, spc, spc ;
(* chosen by analyzing leading whitespace of the first indented non-empty line *)
(* A docstring consists of a set of sections *)
wldocstring = { section } ;
(* A section is one logical line plus an optional nested block *)
section = indent_token, logical_line, [ block ] ;
block = indent_increase, { section }, indent_decrease ;
(* A logical line is one or more physical lines joined by trailing backslash.
Constraint: all physical lines of one logical line have the same indentation level. *)
logical_line = physical_line, { continuation } ;
(* A physical line has non-whitespace content *)
physical_line = content, newline ;
(* Continuation: previous content ends with backslash (ignoring trailing whitespace).
The following physical line is joined; one ASCII space is inserted at the join point. *)
continuation = indent_nochange, content_cont, newline ;
(* Content of the first physical line: must not start with ws *)
content = non_ws_char, { non_nl_char } ;
(* Content of a continued physical line: same constraint *)
content_cont = non_ws_char, { non_nl_char } ;
(* Abstraction of indentation *)
indent_increase = ? indentation increases by one indent_unit ? ;
indent_decrease = ? indentation decreases by one indent_unit ? ;
indent_nochange = ? indentation remains unchanged ? ;
indent_token = ? current indentation string, a multiple of indent_unit ? ;
The tokenizer operates on logical lines.
A logical line is the result of joining one or more physical lines
according to the rule logical_line defined above.
Physical lines serve only as input units and have no independent
semantic meaning once logical lines have been formed.
Empty lines and whitespace-only lines do not form logical lines.
They must be ignored for indentation analysis and must not affect
the tokenizer state.
The normative rules derived from this grammar are:
[TKN-001] – The indentation scheme
mustbe consistent within a docstring.[TKN-002] – In indentation scheme SPC4, indentation
mustbe a multiple of 4.[TKN-003] – The indentation scheme
mustbe either TAB or SPC4.[TKN-004] – Indentation from one logical line to the next
must notincrease by more than one unit.[TKN-005] – A physical content line
maybe continued on the next physical line by placing a backslash (ASCII 92) as the last non-whitespace character.[TKN-006] – Line continuation according to TKN-005
mustonly join lines at the same indentation level.[TKN-007] – A physical content line that ends with a backslash according to TKN-005
should notbe the last physical line within an indentation block.[TKN-008] – Tools
mustjoin continued lines by removing the backslash and newline and inserting a single ASCII space character at the join position.
- [TKN-009] – Tools
mustemit a warning if
either a trailing backslash used for line continuation is not escaped,
or the enclosing Python string literal is not declared as a raw string.
[TKN-999] – The tokenizer implementation
mustnot produce undefined behavior. Informative: This rule serves as a catch-all for unspecified tokenizer errors.
In order to describe the tokenizer state, we define the following type (in Python for practical reasons):
DocstringTree = List[ Union[ str, "DocstringTree"]]
A DocstringTree is a value of this type.
The tokenizer maintains the following state:
A DocstringTree (initial state:
[]), represented by a variable such astarget.A stack whose elements reference
targetor any subtree thereof (see recursive definition ofDocstringTree). The initial state is[target]. The stack is represented by a variablestack.An integer variable
cur_indentrepresenting the current indentation level. The initial value is computed as the greatest common indentation over all non-empty physical lines of the docstring, measured in indent units (TAB or SPC4).
For each logical line, processed sequentially, the tokenizer performs the following:
If the indentation level remains unchanged, the logical line is appended as a string to the subtree referenced by the top element of
stack.If the indentation level increases by one indent unit, an empty DocstringTree is appended to the subtree referenced by the top element of
stack, and a reference to this new subtree is pushed ontostack.If the indentation level decreases by
nindent units, an element is popped fromstackfor each of thenindentation levels.
The resulting DocstringTree contains only two kinds of elements: strings and lists.
The tokenizer must produce a DocstringTree in which each nested list
corresponds to exactly one indentation increase relative to its parent.
The parser then transforms the DocstringTree into an Abstract Syntax Tree (AST).
The parser must treat the top-level DocstringTree as a sequence of candidate
sections and interpret strings and nested lists according to the section and
subsection rules defined below.
In particular, the tokenizer does not decide whether a given logical line is a valid section label, subsection label, or content line. These classifications are determined only during parsing, based on the rule-based section and subsection specifications in section Common sections for all profiles ff.
Parsing is successful if and only if the structure of the DocstringTree is compatible with those section and subsection requirements.
5.9. Inline markup in free-form content¶
This subsection is normative.
Waterloo docstrings are primarily plain text. However, a small set of inline markup tokens is defined to allow machine-verifiable references and consistent rendering in target formats (e.g. reST/Sphinx).
Inline markup tokens may occur in free-form content lines.
Inline markup tokens must not occur in:
section labels,
subsection labels,
list entries in sections that are defined as “List-Of-Identifiers” or “List-Of-Qualified-Identifiers”.
5.9.1. Tokens¶
This subsection is normative.
The set of tokens currently available is:
- Token
|Must|,|must|, … as listed in Normativity Keyword.
Usage:
|Must|,|must_not|, …
- Token
|term|
Usage:
|term|`my_term`The argument (inside the tick delimiters)
mustmatch the pattern of an Identifier.The argument
mustrefer to an existing definition itemDefinitions.<DefItem>.[DEF-007] – If token
|term|is used at least once, sectionDefinitionsmustexist and be listed as normative.[DEF-008] – Each token
|term|mustreference a defined or inherited term in sectionDefinitions.Tools
mustreport an error if the referenced definition item does not exist.Renderers
shouldtranslate this markup to a suitable construct in the target format (e.g. a term/definition role in reST).If the target format does not support such a construct, tools
mustfall back to rendering only the argument text.
- Token
|None|
Usage:
|None|The token denotes the Python value
None.Renderers
shouldtranslate this token to a suitable representation in the target format.Tools
mustpreserve the token text if no translation is available.
- Token
|Self|
Usage:
|Self|The token denotes the implicit receiver of a method or fluent API, i.e. Python
selfor typingSelf.Renderers
shouldtranslate this token to a suitable representation in the target format.Tools
mustpreserve the token text if no translation is available.
- Token
|True|
Usage:
|True|The token denotes the Python value
True.Renderers
shouldtranslate this token to a suitable representation in the target format.Tools
mustpreserve the token text if no translation is available.
- Token
|False|
Usage:
|False|The token denotes the Python value
False.Renderers
shouldtranslate this token to a suitable representation in the target format.Tools
mustpreserve the token text if no translation is available.
- Tokens
|attr|,|cmd|,|dfn|,|file|,|func|,|label|,|key|,|lit|,|mod|,|op|,|opt|,|ref|,|tag|,|type|,|value|,|var|,|var_type|
Usage: Tools
mustaccept the form|role|`content`, whereroleis one of the above tokens andcontentis a non-empty string that does not contain backticks.These tokens
mustonly be used inside Waterloo docstrings. Using them in accompanying reST documentsmaytrigger warnings or errors from the Sphinx builder.These tokens represent semantic roles. When building the Abstract Syntax Tree, tools
mustpreserve them without modification.Tools translating to a target format (e.g.
reST)mustmap these roles to well-defined constructs in the target format.Informative: These tokens improve semantic clarity for human readers and may assist automated tools or AI agents. Tools that are not tied to a specific rendering target may ignore them.
As mentioned above, the tokenized form using the pipe character “|”
is defined only within Waterloo docstrings.
The Waterloo Sphinx extension additionally defines equivalent roles
in native reST form, e.g. :wtrl_file:`path/to/file`.
5.9.2. Textflow tokens¶
This subsection is informative. It describes the current interpretation used by output layers, but the description is not yet intended as a complete normative definition.
Textflow tokens are interpreted at the rendering stage and influence the visual structure of the output without affecting the logical structure of the docstring.
Paragraph token
A line starting with a single pipe character |,
optionally followed only by whitespace, denotes a paragraph boundary.
This token is used to visually separate blocks of text into distinct
paragraphs in the rendered output.
List tokens
The following characters at the beginning of a line are interpreted as list markers:
*+-#
A list marker is recognized only if it is immediately followed by a space character (ASCII 32).
Consecutive lines starting with a list marker form a list block.
List nesting is determined by the order of occurrence of distinct list
markers within such a block. Each distinct marker introduces
a new nesting level within the block.
Indentation of lines within a list block must not be used to express
nesting. Nesting must be determined solely by the choice of list marker.
The marker # denotes an ordered list. In the current
implementation, ordered lists are rendered using Arabic numerals
followed by a period.
5.9.3. Semantic role |ref|¶
This subsection is normative.
Semantic role |ref| is used to create references.
The following forms are supported:
|ref|`Name <DocutilsLabel>`– A reference to adocutilslabel, equivalent to:ref:`Name <DocutilsLabel>`.
|ref|`Name <https://some.url>`– A reference to an external HTTP or HTTPS target.
|ref|`Name <wtrl://Module.Class.Object>`– A reference to the documentation of a Waterloo object. The object pathmustbe resolvable by the Waterloo name resolution mechanism. Partial qualification is permitted if the reference can be resolved unambiguously in the current resolution context.
In HTML rendering, the visible label is preserved even when the target cannot be turned into a link. The target part is still parsed so that it can be resolved when possible, but the displayed text remains the label.
Current implementation limitation:
An object defined in a different document is reachable via
|ref|only if the target document is built before the document containing the reference.
5.9.4. Examples¶
This subsection is informative.
|Must| return |None| if no result is available.
|Must| return |Self| to support fluent APIs.
|Must| accept a |term|`Qualified_Identifier` as input.
5.10. Rules not bound to a particular section¶
This section is normative.
[DOC-001] – Each module, class, function, or method object subject to validation
musthave a docstring.[DOC-007] – The docstring
must notbe empty after whitespace-stripping.[DOC-002] – Validation
mustonly be applied to modules, classes, functions, or methods; other object typesmust notbe validated.[PRSR-001] – Sections and subsections
muststart with a label line, as specified below.[PRSR-002] – The line containing the section or subsection label
muststart with a non-empty label string after stripping indentation.[PRSR-003] – The label string
mustbe followed by a colon (ASCII 58).[PRSR-004] – No characters other than optional whitespace
mayfollow the colon on a label line.[PRSR-005] – The label of a section
mustmatch the pattern of an Identifier followed by a colon.[PRSR-006] – The label of a subsection
maybe any non-empty human-readable string followed by a colon.[PRSR-007] – Any section label
must notoccur more than once on a docstring.[PRSR-008] – Any subsection label
must notoccur more than once inside its parent section.
The following set of rules applies to both lists of Identifiers and lists of
Qualified Identifiers.
Whenever rule LQID-001 is referenced, the surrounding context must explicitly
state whether it applies to Identifiers or to Qualified Identifiers.
[Rules last reviewed on 2026-03-03]
[LQID-001] – Lists of [Qualified] Identifiers
mustobey rules LQID-002 through LQID-005.[LQID-002] – Each logical line
maycontain zero or more [Qualified] Identifiers, separated by commas.[LQID-003] – Whitespace surrounding each [Qualified] Identifier
mustbe stripped by tools.[LQID-004] – Each [Qualified] Identifier
mustoccur at most once in the resulting list.[LQID-005] – Tools
musttreat the result as a flat list of [Qualified] Identifiers, without preserving line structure or grouping.[LQID-006] – If a CSV list is wrapped across multiple physical lines, every non-final physical line
mustend with a comma.
The following warning rule applies when a section appears in a docstring but violates the LoII principle. This happens, for example, when definitions are imported from a module docstring into a class, function, or method docstring. Since definitions are normative, that import introduces non-locality.
[VLII-001] – A warning with this rule ID
maybe issued if a section appears in a docstring that violates the LoII principle. Informative: The section that triggers this warning is not deprecated unless explicitly stated.
5.11. Normativity keyword handling¶
This section is normative.
The following rules apply to free-form textual content within normative sections. They ensure that normativity keywords are used in a machine-detectable and unambiguous way. In the following rules “WS” stands for one or more whitespace characters.
[PNB-001] – Tools
mustdetect the token sequences|must|/|Must|+ WS +not/NOT,|should|/|Should|+ WS +not/NOT, and|may|/|May|+ WS +not/NOTwhen they occur within a single logical content line.[PNB-002] – If
|must|/|Must|+ WS +not/NOTor|should|/|Should|+ WS +not/NOTis detected, toolsmustemit at least a warning. Informative: Use|must_not|/|Must_not|or|should_not|/|Should_not|instead.[PNB-003] – If the token sequence
|may|/|May|+ WS +not/NOTis detected, toolsmustemit at least a warning. Informative: The phrase “may not” is ambiguous in English andshouldbe avoided in normative text.
5.12. Sections and subsections¶
This section is normative.
5.12.1. Section property overview¶
This subsection is informative.
The following table gives an overview of common structural properties of sections and subsections. In particular, it summarizes:
the expected content kind,
the typical normativity status, and
the main rationale for using that form.
The table is intended as an orientation aid and as a preview of the more detailed rule-based specifications below. The rules in the following subsections remain the single source of truth.
In the Normativity column, Not applicable means that the specification does not assign a normativity status because the corresponding subsection belongs to the preamble and serves as metadata.
Section or subsection |
Content kind |
Normativity |
Rationale |
|---|---|---|---|
|
identifier |
Not applicable |
Implied by content kind |
|
list of identifiers |
Not applicable |
Implied by content kind |
|
identifier |
Not applicable |
Implied by content kind |
|
list of identifiers |
Not applicable |
Implied by content kind |
|
free-form text |
Normative |
Needs paragraph-capable text |
|
list of identifiers |
Normative |
Implied by content kind |
|
free-form text |
Non-normative |
Needs paragraph-capable text |
|
itemized text |
Normative |
Line-by-line contract |
|
itemized text |
Normative |
Line-by-line contract |
|
qualified identifier |
Normative |
Implied by content kind |
|
list of identifiers |
Normative |
Implied by content kind |
|
itemized text |
Normative |
Line-by-line contract |
|
itemized text |
Normative |
Line-by-line contract |
|
itemized text |
Normative |
Line-by-line contract |
|
free-form text |
Can be both |
Needs paragraph-capable text |
|
list of qualified identifiers |
Normative |
Implied by content kind |
|
itemized text |
Normative |
Line-by-line contract |
|
list of qualified identifiers |
Normative |
Implied by content kind |
|
list of qualified identifiers |
Normative |
Implied by content kind |
|
list of qualified identifiers |
Normative |
Implied by content kind |
|
free-form text |
Non-normative |
Descriptive text preferred |
|
free-form text |
Non-normative |
Descriptive text preferred |
|
free-form text |
Non-normative |
Descriptive text preferred |
|
free-form text |
Normative |
Needs paragraph-capable text |
|
free-form text |
Normative |
Needs paragraph-capable text |
|
free-form text |
Normative |
Needs paragraph-capable text |
|
free-form text |
Normative |
Needs paragraph-capable text |
|
free-form text |
Normative |
Needs paragraph-capable text |
|
itemized text |
Normative |
Line-by-line contract |
|
free-form text |
Non-normative |
Needs paragraph-capable text |
|
list of qualified identifiers |
Can be both |
Implied by content kind |
5.12.2. Common sections for all profiles¶
Preamble:[PRE-001] – The section
mustexist and itmustbe the first of all sections.[PRE-002] – The section
must notlist itself innormative_sections.[PRE-015] –
Must nothave subsections other than {profile,normative_sections,status,scope}.profile:[PRE-003] – The subsection
mustexist.[PRE-004] – The subsection
musthave exactly one entry.[PRE-014] – The entry
mustmatch the pattern of an Identifier.[PRE-005] – The entry
mustbe one of {module,class,function,method,inherited_method}.
normative_sections:[PRE-006] – The subsection
mustexist.[PRE-021] – The content
mustbe a list of Identifiers according to rule LQID-001. In this context, “Identifier” (not “Qualified Identifier”) applies.[PRE-011] – The subsection
mustlist the normative sections of the documentation block.[PRE-012] – Each section listed in this subsection
mustexist.[PRE-013] – Each section or subsection in the docstring that contains a Normativity Keyword must be listed in this subsection.
status:[PRE-016] – The subsection
must notexist unless specified explicitly for a given profile.
scope:[SCP-001] – The subsection
mayexist.[SCP-002] – The content
mustbe a list of Identifiers according to LQID-001.[SCP-003] – Entries in
Preamble.scopemustbe valid scope identifiers as defined in Scope values.[SCP-010] – A missing or empty subsection
mustbe interpreted aspublic.[SCP-004] – Scope assignments and internal references
mustobey theScope Monotonicity Ruleas defined in Scopes and visibility.[SCP-005] – For every internal reference introduced by sections
Public_classes,Public_functions, orPublic_methods, the source objectmustbe the documented module or class and the target objectmustbe the referenced public class/function/method. The source objectmustbe at least as public as the target object. Validatorsmustapply the scope compatibility test defined in Scope Monotonicity Rule. Any violation of the scope compatibility test in this casemustbe reported as an error.[SCP-006] – If section
See_alsois listed inPreamble.normative_sections, then for every internal reference inSee_alsothat resolves to a Waterloo-documented object, the source objectmustbe the referenced object and the target objectmustbe the documented module or class. The source objectmustbe at least as public as the target object. Validatorsmustapply the scope compatibility test defined in Scope Monotonicity Rule. Any violation of the scope compatibility test in this casemustbe reported as an error.[SCP-007] – If section
See_alsois not listed inPreamble.normative_sections, then for every internal reference inSee_alsothat resolves to a Waterloo-documented object, the source objectmustbe the referenced object and the target objectmustbe the documented module or class. The source objectmustbe at least as public as the target object. Validatorsmustapply the scope compatibility test defined in Scope Monotonicity Rule. Any violation of the scope compatibility test in this casemustbe reported as a warning.[SCP-008] – For profile
inherited_method, subsectionContract.baseintroduces an internal reference from the derived method to the referenced base method. The source objectmustbe the referenced base method and the target objectmustbe the derived method. The source objectmustbe at least as public as the target object. Validatorsmustapply the scope compatibility test defined in Scope Monotonicity Rule to this reference. Any violation of the scope compatibility test in this casemustbe reported as an error.[SCP-009] – Section
Derived_fromintroduces internal references from the documented class to the referenced base classes. The source objectmustbe any of its referenced base classes and the target objectmustbe the documented class. The source objectmustbe at least as public as the target object. Validatorsmustapply the scope compatibility test defined in Scope Monotonicity Rule to each such reference that resolves to a Waterloo-documented object. Any scope-compatibility violation in this casemustbe reported as an error.
- Obsolete rules
PRE-007 – Obsolete since 0.5.5; superseded by PRE-021 and PRE-022.
PRE-008 – Obsolete since 0.5.5; superseded by PRE-021 and PRE-022.
PRE-009 – Obsolete since 0.5.5; superseded by PRE-021 and PRE-022.
PRE-010 – Obsolete since 0.5.5; superseded by PRE-021 and PRE-022.
PRE-022 – Obsolete since 0.5.5; Implied by other rules.
For the following section, we define:
- Current Object
The object in which the docstring resides. This can be a class or a callable, but not a module.
- Direct Module
The module that contains the
Current Object.- Term
The first identifier in a
Definitions.<DefItem>header.- Variation
Any identifier after the first one in a
Definitions.<DefItem>header.
Definitions:[DEF-001] – The section
mayexist.[DEF-002] – If it exists, it
mustbe listed as normative inPreamble.normative_sections.[DEF-003] – Each entry in the section
musthave the form of a subsection matching one of the following patterns:<DefItem>:[DEF-020] – Any number of subsections
mayexist.[DEF-004] –
<DefItem>mustmatch <Identifier> ( “,” <Identifier> )* with optional whitespace around commas.[DEF-005] – In
<DefItem>, the first identifier denotes theTerm; each following identifier denotes aVariationof that term.[DEF-006] – The subsection content
mustbe free-form text.[DEF-009] – The subsection content
shouldnot be empty.[DEF-010] –
<DefItem>must notbe_inherit.
_inherit:[DEF-011] – The subsection
_inheritmust notappear in profilemodule.[DEF-012] – The subsection
_inheritmayappear in profilesclass,function,method, andinherited_method.[DEF-014] – If the subsection
_inheritexists, theDirect Modulemusthave a valid docstring.[DEF-015] – If the subsection
_inheritexists, the docstring of theDirect Modulemustcontain aDefinitionssection.[DEF-016] – The content of
_inheritmustbe a list of identifiers according to LQID-001.[DEF-017] – Each entry in
_inheritmust notoccur as aTermorVariationin theDefinitionssection of theCurrent Object.[DEF-018] – Each entry in
_inheritmustoccur as aTermin theDirect Moduledocstring’sDefinitionssection.[DEF-019] – The use of the subsection
_inheritmustresult in a warning with rule IDVLII-001at validation time.[DEF-022] – Implicitly, all
Variationsof an inheritedTermare inherited as well.
- Obsolete rules
DEF-013 – Obsolete since 0.5.2; superseded by PRSR-008.
Rationale (informative)
TermsandVariationsare restricted to Identifiers for the following reasons:They can be referenced in a machine-verifiable way via the semantic role
|term|`...`.They are robust with respect to formatting changes such as line wrapping.
They behave similarly to symbolic constants or macros in a programming language: the identifier provides a stable symbolic anchor, while the definition body provides the human-readable explanation.
Last review: 2026-03-25
Terminology:[TERM-001] – The section
mayexist.[TERM-002] – It
must notbe listed as normative inPreamble.normative_sections.[TERM-003] – It
must notcontain Normativity Keywords.[TERM-004] – Each entry in the section
musthave the form of a subsection matching the following pattern:<Term>:[TERM-009] – Any number of subsections
mayexist[TERM-005] –
<Term>mustbe a non-empty human-readable string.[TERM-006] –
<Term>stands for the term to be explained informatively.[TERM-007] – The subsection content
mustbe free-form text.[TERM-008] – The subsection content
shouldnot be empty.
Rationale (informative)
In contrast to the
Definitionssection, theTerminologysection allows arbitrary human-readable labels and is intended solely for explanatory purposes.Last review: 2026-02-23
Description:[DESC-001] – The section
mayexist.[DESC-002] – The section
maybe listed as normative inPreamble.normative_sections.[DESC-004] – The content
mayconsist of any number of free-form lines.- Obsolete rules:
DESC-003 – Obsolete since 0.5.1; superseded by PRE-013.
DESC-005 – Obsolete since 0.5.5 (pipe operator as separator); more general approach required.
Notes:[NOTE-001] – The section
mayexist.[NOTE-002] – It
must notbe listed as normative inPreamble.normative_sections.[NOTE-003] – It
must notcontain Normativity Keywords.[NOTE-004] – Tools
musttreat the content of sectionNotesas informative and must not derive normative requirements from it.[NOTE-005] – Each entry in the section
musthave the form of a subsection matching the following pattern:<Note>:[NOTE-008] – Any number of subsections
mayexist[NOTE-006] –
<Note>mustbe a non-empty human-readable string.[NOTE-007] – The subsection content
mustbe free-form text.[NOTE-009] – The subsection content
shouldnot be empty.
Last review: 2026-02-23
See_also:[SEE-001] – The section
mayexist.[SEE-011] – The section
maybe listed as normative inPreamble.normative_sections.[SEE-002] – Each entry in the section
mustbe an Identifier or a Qualified Identifier.[SEE-003] – If the section is not listed as normative each entry
shouldrefer to an existing public object.[SEE-004] – If the section is listed as normative each entry
mustrefer to an existing public object.[SEE-005] – An entry in
See_alsomust notrefer to the documented object itself.[SEE-006] – An entry in
See_alsoshouldrefer to an object that has a docstring, if the object is documentable (module, class, or callable).[SEE-007] – If the section is not listed as normative the object (module, class, function, or method) referred to by entry
shouldhave a valid Waterloo docstring.[SEE-008] – If the section is listed as normative the object (module, class, function, or method) referred to by entry
musthave a valid Waterloo docstring.[SEE-009] – Tools
musttreat unresolved references as errors whenSee_alsois normative, andmusttreat them as warnings whenSee_alsois informative.[SEE-010] – Rules SEE-007 and SEE-008
must notbe tested for built-ins. The criteriamustbeinspect.ismodule,inspect.isclass, andinspect.isfunction.Informative: Listing
See_alsoas normative increases strictness and allows tools to rely on resolvable references.Informative: Resolution may be limited across module boundaries, since object resolution typically follows the import hierarchy.
Last review: 2026-01-31
5.12.3. Sections for module docstrings¶
In addition to the sections described in Common sections for all profiles
a module docstring must have the following structure:
[DOC-003] – Module docstrings
must notcontain sections other than {Preamble,Definitions,Terminology,Description,Notes,See_also,Contract,Public_classes,Class_overview,Public_functions,Function_overview,Public_types,Public_variables,Public_constants}.Preamble:profile:[PRE-017] – The profile
mustbemodule.
Contract:[CON-001] – The section
mustexist.[CON-002] – The section
mustbe listed as normative inPreamble.normative_sections.[CON-028] –
Must nothave subsections other than {general}.general:[CON-022] – The subsection
mustexist.[CON-003] –
Mustcontain an explanation of the purpose of the module sufficient to decide whether the module is applicable to a given use case.
- Obsolete rules:
CON-029
CON-030
CON-031
Public_classes:[MPCL-001] – The section
mayexist.[MPCL-002] – If it exists, it
mustbe listed as normative inPreamble.normative_sections.[MPCL-003] – The content
mustbe a list of Qualified Identifiers according to LQID-001.[MPCL-004] – Each entry listed
mustbe resolvable relative to the documented module.[MPCL-005] – Each entry listed
mustrefer to a class.[MPCL-006] – Each class with a valid docstring
shouldbe listed inPublic_classes.[MPCL-007] – Each class listed in
Public_classesshouldhave a valid docstring.[MPCL-008] – A class not listed in
Public_classesmayhave an invalid or missing docstring.
Class_overview:[MCLO-001] – The section
mayexist.[MCLO-002] –
Must notbe listed as normative inPreamble.normative_sections.[MCLO-003] –
Must notexist if there is no sectionPublic_classes:[MCLO-004] – Each entry in the section
musthave the form of a subsection matching the following pattern:<Class>:[MCLO-005] –
<Class>mustmatch the pattern of an Identifier.[MCLO-006] – The subsection content
mustbe free-form text.[MCLO-007] – The subsection content is informative and
must notcontain any Normativity Keyword.[MCLO-008] –
<Class>mustbe resolvable relative to the documented module.[MCLO-009] –
<Class>mustrefer to a class object.[MCLO-011] –
<Class>mustappear in sectionPublic_classes.
[MCLO-010] – Any number of subsections
mayexist.Last review: 2026-02-25
Public_functions:[MPFN-001] – The section
mayexist.[MPFN-002] – If it exists, it
mustbe listed as normative inPreamble.normative_sections.[MPFN-003] – The content
mustbe a list of Qualified Identifiers according to LQID-001.[MPFN-004] – Each entry listed
mustbe resolvable relative to the documented module.[MPFN-005] – Each entry listed
mustrefer to a function.[MPFN-006] – Each function with a valid docstring
shouldbe listed inPublic_functions.[MPFN-007] – Each function listed in
Public_functionsshouldhave a valid docstring.[MPFN-008] – A function not listed in
Public_functionsmayhave an invalid or missing docstring.
Function_overview:[MFNO-001] – The section
mayexist.[MFNO-002] –
Must notbe listed as normative inPreamble.normative_sections.[MFNO-003] –
Must notexist if there is no sectionPublic_functions:[MFNO-004] – Each entry in the section
musthave the form of a subsection matching the following pattern:<Function>:[MFNO-005] –
<Function>mustmatch the pattern of an Identifier.[MFNO-006] – The subsection content
mustbe free-form text.[MFNO-007] – The content is informative and
must notcontain any Normativity Keyword.[MFNO-008] –
<Function>mustbe resolvable relative to the documented module.[MFNO-009] –
<Function>mustrefer to a function object.[MFNO-011] –
<Function>mustappear in sectionPublic_functions.
[MFNO-010] – Any number of subsections
mayexist.Last review: 2026-02-25
Public_types:[MPTYP-001] – The section
mayexist.[MPTYP-002] – If it exists, it
mustbe listed as normative inPreamble.normative_sections.[MPTYP-003] – Each entry in the section
musthave the form of a subsection matching the following pattern:<Type>:[MPTYP-004] –
<Type>mustmatch the pattern of an Identifier.[MPTYP-006] – The subsection content
mustbe free-form text.[MPTYP-005] –
<Type>mustbe resolvable relative to the documented module.[MPTYP-008] –
<Type>mustrefer to a TypeAlias or NewType.
- Obsolete rules
MPTYP-007 – Obsolete in version 0.5.3; duplicate of MPTYP-005.
Last review: 2026-06-29
Public_variables:[MPVAR-001] – The section
mayexist.[MPVAR-002] – If it exists, it
mustbe listed as normative inPreamble.normative_sections.[MPVAR-003] – Each entry in the section
musthave the form of a subsection matching the following pattern:<Assignable>:[MPVAR-004] –
<Assignable>mustmatch the pattern of an Identifier.[MPVAR-006] – The subsection content
mustbe free-form text.[MPVAR-005] –
<Assignable>mustbe resolvable relative to the documented module, either as a runtime attribute or as an annotated variable.[MPVAR-008] –
<Assignable>mustrefer to a Named Value.[MPVAR-009] – If the object referenced by
<Assignable>is annotated, the annotationmust notbe wtrl_type:Final.
- Obsolete rules
MPVAR-007 – Obsolete in version 0.5.3; duplicate of MPVAR-005.
Last review: 2026-06-29
Public_constants:[MPCON-001] – The section
mayexist.[MPCON-002] – If it exists, it
mustbe listed as normative inPreamble.normative_sections.[MPCON-003] – Each entry in the section
musthave the form of a subsection matching the following pattern:<Assignable>:[MPCON-004] –
<Assignable>mustmatch the pattern of an Identifier.[MPCON-007] – The subsection content
mustbe free-form text.[MPCON-005] –
<Assignable>mustbe resolvable relative to the documented module.[MPCON-009] –
<Assignable>mustrefer to a Named Value.[MPCON-006] – If the object referenced by
<Assignable>is annotated, the annotationmustbeFinal.
- Obsolete rules
MPCON-008 – Obsolete in version 0.5.3; duplicate of MPCON-005.
Last review: 2026-06-29
5.12.4. Sections for class docstrings¶
In addition to the sections described in Common sections for all profiles
a class docstring must have the following structure:
[DOC-004] – Class docstrings
must notcontain sections other than {Preamble,Definitions,Terminology,Description,Notes,See_also,Contract,Derived_from,Public_classes,Class_overview,Public_methods,Method_overview,Public_types,Public_variables,Public_constants,Factory}.Preamble:profile:[PRE-018] – The profile
mustbeclass.
Contract:[CON-032] –
Must nothave subsections other than {general,constructor,api,traits}.general:[CON-023] – The subsection
mustexist.[CON-006] –
Mustcontain an explanation of the purpose of the class sufficient to decide whether the class is applicable to a given use case.
constructor:[CON-007] – The subsection
mustexist.[CON-008] –
Shouldcontain a brief explanation of the constructor or point to special method__init__with a valid docstring.
traits:[CON-012] – The subsection
mayexist.[CON-053] – If it exists, the content
mustbe a list of Identifiers according to rule LQID-001. In this context, “Identifier” (not “Qualified Identifier”) applies.- [CON-017] – Each trait identifier
mustbe one of the following final– A class markedfinalmust notbe derived from.abstract– A class markedabstractmust notbe instantiated directly.
- [CON-017] – Each trait identifier
- Obsolete rules
CON-004 – Obsolete in version 0.5.5; Superseded by CON-001
CON-005 – Obsolete in version 0.5.5; Superseded by CON-002
CON-009 – Obsolete in version 0.5.5; Obsolete subsection
api.CON-010 – Obsolete in version 0.5.5; Obsolete subsection
api.CON-011 – Obsolete in version 0.5.5; Obsolete subsection
api.CON-018 – Obsolete in version 0.5.5; Now covered by CON-017
CON-013 – Obsolete in version 0.5.5; Superseded by CON-053
CON-014 – Obsolete in version 0.5.5; Superseded by CON-053
CON-015 – Obsolete in version 0.5.5; Superseded by CON-053
CON-016 – Obsolete in version 0.5.5; Superseded by CON-053
Derived_from:[DER-001] – The section
mayexist.[DER-004] – If it exists, it
mustbe listed as normative inPreamble.normative_sections.[DER-009] – If it exists, the content
mustbe a list of [Qualified] Identifiers according to rule LQID-001.[DER-002] –
Mustlist the base classes that contribute public functions, types, constants, attributes, or semantic guarantees.[DER-003] – Each entry
mustrefer to a direct base class of the documented class.[DER-010] – Each entry
mustname one of the direct base classes either as a direct Identifier or as a Qualified Identifier.[DER-011] – A direct Identifier entry
mustresolve unambiguously to exactly one direct base class.[DER-012] – A Qualified Identifier entry
mustresolve to a direct base class by fully qualifying the name of that base class.[DER-013] – If a direct Identifier would match more than one direct base class, the entry
mustbe qualified enough to resolve the ambiguity.- Obsolete rules
DER-005 – Obsolete in version 0.5.5; superseded by DER-009.
DER-006 – Obsolete in version 0.5.5; superseded by DER-009.
DER-007 – Obsolete in version 0.5.5; superseded by DER-009.
DER-008 – Obsolete in version 0.5.5; superseded by DER-009.
Public_classes:[CPCL-001] – The section
mayexist.[CPCL-002] – If it exists, it
mustbe listed as normative inPreamble.normative_sections.[CPCL-003] – The content
mustbe a list of Qualified Identifiers according to LQID-001.[CPCL-004] – Each entry listed
mustbe resolvable relative to the documented class.[CPCL-005] – Each entry listed
mustrefer to a class.[CPCL-006] – Each class with a valid docstring
shouldbe listed inPublic_classes.[CPCL-007] – Each class listed in
Public_classesshouldhave a valid docstring.[CPCL-008] – A class not listed in
Public_classesmayhave an invalid or missing docstring.
Class_overview:(nested/inner classes)[CCLO-001] – The section
mayexist.[CCLO-002] –
Must notbe listed as normative inPreamble.normative_sections.[CCLO-003] –
Must notexist if there is no sectionPublic_classes:[CCLO-004] – Each entry in the section
musthave the form of a subsection matching the following pattern:<Class>:[CCLO-005] –
<Class>mustmatch the pattern of an Identifier.[CCLO-006] – The subsection content
mustbe free-form text.[CCLO-007] – The subsection content is informative and
must notcontain any Normativity Keyword.[CCLO-008] –
<Class>mustbe resolvable relative to the documented class.[CCLO-009] –
<Class>mustrefer to a class object.[CCLO-011] –
<Class>mustappear in sectionPublic_classes.
[CCLO-010] – Any number of subsections
mayexist.Last review: 2026-02-25
Public_methods:[CPMT-001] – The section
mayexist.[CPMT-002] – If it exists, it
mustbe listed as normative inPreamble.normative_sections.[CPMT-003] – The content
mustbe a list of Qualified Identifiers according to LQID-001.[CPMT-004] – Each entry listed
mustbe resolvable relative to the documented class.[CPMT-005] – Each entry listed
mustrefer to a method.[CPMT-006] – Each method with a valid docstring
shouldbe listed in sectionPublic_methods.[CPMT-007] – Each method listed in section
Public_methodsshouldhave a valid docstring.[CPMT-008] – A method not listed in
Public_methodsmayhave an invalid or missing docstring.
Method_overview:[CMTO-001] – The section
mayexist.[CMTO-002] –
Must notbe listed as normative inPreamble.normative_sections.[CMTO-003] –
Must notexist if there is no sectionPublic_methods:[CMTO-004] – Each entry in the section
musthave the form of a subsection matching the following pattern:<Method>:[CMTO-005] –
<Method>mustmatch the pattern of an Identifier.[CMTO-006] – The subsection content
mustbe free-form text.[CMTO-007] – The subsection content is informative and
must notcontain any Normativity Keyword.[CMTO-008] –
<Method>mustbe resolvable relative to the documented class.[CMTO-009] –
<Method>mustrefer to a method.[CMTO-011] –
<Method>mustappear in sectionPublic_methods.
[CMTO-010] – Any number of subsections
mayexist.Last review: 2026-02-25
Public_types:[CPTYP-001] – The section
mayexist.[CPTYP-002] – If it exists, it
mustbe listed as normative inPreamble.normative_sections.[CPTYP-003] – Each entry in the section
musthave the form of a subsection matching the following pattern:<Type>:[CPTYP-004] –
<Type>mustmatch the pattern of an Identifier.[CPTYP-006] – The subsection content
mustbe free-form text.[CPTYP-005] –
<Type>mustbe resolvable relative to the documented class.[CPTYP-008] –
<Type>mustrefer to a TypeAlias or NewType.
- Obsolete rules
CPTYP-007 – Obsolete in version 0.5.3; duplicate of CPTYP-005.
Last review: 2026-06-29
Public_variables:[CPVAR-001] – The section
mayexist.[CPVAR-002] – If it exists, it
mustbe listed as normative inPreamble.normative_sections.[CPVAR-003] – Each entry in the section
musthave the form of a subsection matching the following pattern:<Assignable>:[CPVAR-004] –
<Assignable>mustmatch the pattern of an Identifier.[CPVAR-006] – The subsection content
mustbe free-form text.[CPVAR-005] –
<Assignable>mustbe resolvable relative to the documented class, either as a runtime attribute or as an annotated field.[CPVAR-008] –
<Assignable>mustrefer to a Named Value.[CPVAR-009] – If the object referenced by
<Assignable>is annotated, the annotationmust notbe wtrl_type:Final.
- Obsolete rules
CPVAR-007 – Obsolete in version 0.5.3; duplicate of CPVAR-005.
Last review: 2026-06-29
Public_constants:[CPCON-001] – The section
mayexist.[CPCON-002] – If it exists, it
mustbe listed as normative inPreamble.normative_sections.[CPCON-003] – Each entry in the section
musthave the form of a subsection matching the following pattern:<Assignable>:[CPCON-004] –
<Assignable>mustmatch the pattern of an Identifier.[CPCON-007] – The subsection content
mustbe free-form text.[CPCON-005] –
<Assignable>mustbe resolvable relative to the documented class.[CPCON-009] –
<Assignable>mustrefer to a Named Value.[CPCON-006] – If the object referenced by
<Assignable>is annotated, the annotationmustbeFinal.
- Obsolete rules
CPCON-008 – Obsolete in version 0.5.3; duplicate of CPCON-005.
Last review: 2026-02-24
Factory:[FAC-001] – The section
mayexist.[FAC-009] – The section
mustbe listed as normative inPreamble.normative_sections.[FAC-004] – Each entry in the section
musthave the form of a subsection matching the following pattern:<Function>:[FAC-005] –
<Function>mustmatch the pattern of a Qualified Identifier.[FAC-008] – Each
<Function>mustoccur at most once within its enclosingFactorysection.[FAC-006] –
<Function>mustresolve to an existing function.[FAC-007] – The content of
<Function>mustbe interpreted as free-form text.
- Obsolete rules:
FAC-002 – Obsolete since version 0.5.1; superseded by PRE-013.
FAC-003 – Obsolete since version 0.5.0.
Last review: 2026-02-23
5.12.5. Sections for function/method docstrings¶
In addition to the sections described in Common sections for all profiles
a function or method docstring must have the following structure:
Preamble:profile:[PRE-019] – The profile
mustbefunctionormethod.
status:[STA-001] – The subsection
mayexist.[STA-002] – The subsection
mustcontain exactly one entry.[STA-003] – The entry
mustbe an Identifier.- [STA-004] – The following trait identifiers are defined by this specification:
experimental– The object is under active development and its behavior or signature may change without notice.stable– The object is intended for normal use and its behavior and signature are expected to remain compatible across releases.frozen– The object is considered feature-complete and should not receive behavioral changes except for critical bug fixes.deprecated– The object should no longer be used for new code and may be removed in a future version.draft– The object is incomplete and primarily intended for internal use or discussion; its contract is not yet finalized.
[STA-005] – If subsection
Statusis absent, toolsshouldtreat the status asstable.
[DOC-005] – Function or method docstrings
must notcontain sections other than {Preamble,Definitions,Terminology,Description,Notes,See_also,Contract,Parameters,Returns,Raises}.Contract:[CON-027] –
Must nothave subsections other than {general,invariants,requires,ensures}.- For subsections {
general,invariants,requires,ensures} the following rules apply: [CON-051] – Tools
musttreat the free-form content as an ordered sequence of logical lines.[CON-052] – Tools
muststore exactly one string item per logical line andmustpreserve the original order.
- For subsections {
general:[CON-024] – The subsection
mustexist.[CON-021] –
Mustcontain an explanation of the purpose of the function sufficient to decide whether the function is applicable to a given use case.
invariants:[CON-025] – The subsection
mayexist.[CON-026] – The subsection content
mustbe free-form text.
requires:[CON-047] – The subsection
mayexist.[CON-048] – The subsection content
mustbe free-form text.
ensures:[CON-049] – The subsection
mayexist.[CON-050] – The subsection content
mustbe free-form text.
- Obsolete rules
CON-019 – Obsolete in version 0.5.5; Superseded by CON-001
CON-020 – Obsolete in version 0.5.5; Superseded by CON-002
Last review: 2026-03-03
Parameters:[PAR-001] – The section
mustexist.[PAR-002] – The section
mustbe listed as normative inPreamble.normative_sections.[PAR-003] – The section
mustlist all parameters and provide an explanation for each parameter.[PAR-008] – Each entry in the section
musthave the form of a subsection matching the following pattern:<Par>:[PAR-006] –
<Par>mustbe an Identifier.[PAR-007] – The subsection content
mustbe free-form text.[PAR-004] – Each parameter in the function’s signature
mustbe documented by a corresponding<Par>entry.[PAR-005] – Each
<Par>entrymustcorrespond to a parameter in the function’s signature.
Last review: 2026-02-25
Returns:[RET-001] – The section
mustexist.[RET-002] – The section
mustbe listed as normative inPreamble.normative_sections.[RET-005] – The section
must notcontain subsections.[RET-003] – The section
mustexplain the return value of the documented function or method.[RET-004] – If the documented function or method is annotated with return type
bool, sectionReturnsshouldmention at least one of the tokens|True|or|False|.[RET-006] – If the documented function or method is annotated to return
None, sectionReturnsshouldmention the token|None|.[RET-007] – If the documented function or method is annotated to return
Self, sectionReturnsshouldmention the token|Self|.[RET-008] – Validators
shouldapply rule RET-006 only if the function or method is annotated to returnNoneand the section containsNonein non-tokenised form.[RET-009] – Validators
shouldapply rule RET-007 only if the function or method is annotated to returnSelfand the section containsselforSelfin non-tokenised form.[RET-010] – Violations of rules RET-004, RET-006, and RET-007
mustbe reported as warnings andmust notbe reported as errors.Last review: 2026-02-25
Raises:[RAI-001] – The section
mustexist.[RAI-002] – The section
mustbe listed as normative inPreamble.normative_sections.[RAI-003] – The section
mustlist all exception classes that may be raised under correct and contract-compliant usage.[RAI-011] – Each entry in the section
musthave the form of a subsection matching the following pattern:<Exception>:[RAI-008] –
<Exception>mustbe a Qualified Identifier.[RAI-004] –
<Exception>mustresolve to an existing (exception) class.[RAI-005] – The subsection content
mustbe free-form text.[RAI-006] – The content
mustexplain the circumstances which must or may lead to raising the exception addressed by<Exception>.[RAI-007] – Each entry listed
mustrepresent a subclass ofBaseException.
- Obsolete rules
RAI-009 – Obsolete since 0.5.2; superseded by RAI-004.
RAI-010 – Obsolete since 0.5.3;
5.12.6. Sections for inherited method docstrings¶
In addition to the sections described in Common sections for all profiles
an inherited method docstring must have the following structure:
[DOC-006] – Inherited method docstrings
must notcontain sections other than {Preamble,Definitions,Terminology,Description,Notes,See_also,Contract}.Preamble:profile:[PRE-020] – The profile
mustbeinherited_method.
Contract:[CON-035] – The section
must nothave subsections other than {general,base}.general:[CON-036] – The subsection
mustexist.[CON-037] –
Mustcontain an explanation of the purpose of the method sufficient to decide whether the method is applicable to a given use case.[CON-038] –
Shouldpoint out in how far the method differs from the base method referenced inContract.base.
base:[CON-039] – The subsection
mustexist.[CON-040] – The subsection
mustcontain exactly one entry.[CON-041] – The entry
mustbe a Qualified Identifier.[CON-042] – The entry
mustbe resolvable to a function or method object.[CON-043] – The resolved object
mustbe a method of a base class of the documented class.[CON-044] – The name of the resolved object
mustequal the name of the documented method.[CON-045] – The referenced base method
musthave a valid docstring.[CON-046] – Tools
shouldcheck type-level Liskov compatibility against the referenced base method if sufficient type information is available.
- Obsolete rules:
CON-033 – Obsolete in version 0.5.5; Superseded by CON-001
CON-034 – Obsolete in version 0.5.5; Superseded by CON-002
Last review: 2026-02-23
5.13. Rules for exceptions not supposed to occur¶
This section is normative.
The rule declarations in this section describe error conditions that correspond to logically unreachable branches in the implementation. Under correct implementation of both the specification and the analyzed code, these cases should never occur.
However, since the documentation is regularly validated against the codebase, formal rule identifiers must exist so that such situations can be reported consistently if they are encountered.
If any of the rules listed below is triggered during validation, this indicates an internal inconsistency or an implementation defect.
[DOC-999] –
Should notoccur.[MCLO-999] –
Should notoccur.[MPTYP-999] –
Should notoccur.[MPVAR-999] –
Should notoccur.
5.14. Coverage rules and intended workflow¶
This section is informative.
The Waterloo specification contains a set of rules that connect docstring validity and public API listings
in sections such as Public_classes, Public_functions, and Public_methods.
Taken together, these rules define an intended workflow and an interpretation of documentation “coverage”.
In short, Waterloo treats the Public_* sections as an explicit declaration of public API surface
(for a given scope). Listing an object in a Public_* section is a commitment:
the specification requires the object to exist, and requires the object to have a valid docstring.
Conversely, the existence of a valid docstring does not automatically make an object part of the public API.
The specification recommends listing documented objects in Public_* sections, but does not require it.
This supports incremental documentation work, experimentation, and internal documentation without forcing immediate API exposure.
5.14.1. Module-level coverage¶
At module level, the specification expresses the following principles:
The specification recommends that each class with a valid docstring is listed in
Public_classes(MPCL-006).The specification recommends that each class listed in
Public_classeshas a valid docstring (MPCL-007).The specification recommends that each function with a valid docstring is listed in
Public_functions(MPFN-006).The specification recommends that each function listed in
Public_functionshas a valid docstring (MPFN-007).The specification requires that each type listed in
Public_typesexists in the module (MPTYP-005).The specification requires that each variable listed in
Public_variablesexists in the module, either as a runtime attribute or as an annotated variable (MPVAR-005).The specification requires that each constant listed in
Public_constantsexists in the module (MPCON-005).
5.14.2. Class-level coverage¶
At class level, the specification expresses the following principles:
The specification requires that each class listed in
Public_classesexists as an attribute on the documented class (CPCL-004).The specification recommends that each embedded class with a valid docstring is listed in section
Public_classes(CPCL-006).The specification recommends that each method with a valid docstring is listed in section
Public_methods(CPMT-006).The specification requires that each method listed in section
Public_methodsexists and is a method/function (CPMT-005).The specification requires that each variable listed in
Public_variablesexists on the documented class, either as a runtime attribute or as an annotated field (CPVAR-005).The specification requires that each constant listed in
Public_constantsexists on the documented class (CPCON-005).
5.14.3. Practical consequence¶
These rules allow authors to write many valid docstrings without immediately declaring the documented objects as public.
Only objects explicitly listed in Public_* sections are treated as part of the public API surface
(for the given scope) and are therefore subject to strict coverage expectations.
5.15. Scopes and visibility¶
This section is normative.
This section defines the semantics of the scope attribute and the
rules governing visibility, rendering, and validation across different scopes.
The purpose of scopes is to allow a single codebase and documentation set to be rendered consistently for different audiences, such as public users, extension developers, or core developers.
More formally, the purpose is to ensure that any rendered documentation artifact forms a reference-closed subgraph of the complete documentation graph.
5.15.1. Conceptual model¶
Each documented object (module, class, function, or method) is assigned one or
more scope values via the Preamble.scope subsection.
Scopes do not represent access control. Instead, they describe the intended audience and contractual visibility of an object. Scopes are interpreted uniformly by validators, renderers, and coverage tools.
5.15.2. Scope values¶
This section is normative.
Any tool must recognize and dispatch the following scope identifiers:
publicextensioncore
with the following semantics:
public– stable API intended for general external users.extension– API intended for extension, plugin, or application developers.core– internal API intended for core developers of the project.
The specification defines a partial order over scope values such that:
s(public) <=s(extension)s(extension) <=s(core)
This order expresses increasing internality and decreasing audience size.
5.15.3. Scope sets¶
This section is informative. Rules SCP-002 and SCP-010 describe the properties listed here in a normative way.
The scope subsection may list zero or more scope identifiers.
The scope of an object is therefore a set of scope values.
If the scope subsection is absent or empty, the default scope set is
{ public }.
5.15.4. Visibility¶
An object is considered visible for a given rendering or validation context if at least one of its scope values is visible in that context.
Let S be a set of scope values selected by a tool (for example, for rendering or
coverage analysis). An object is visible under a scope set S if and only if there exists
a scope value s_obj assigned to the object and a scope value s_query in S
such that:
s_obj <= s_query
In other words, an object is visible if at least one of its declared scopes is less than or equal to at least one selected scope.
5.15.5. Scope Monotonicity Rule¶
Documented objects form a directed reference graph.
Reference edges arise exclusively from the constructs listed below. For each reference edge, the source and target objects are defined according to the semantics of the corresponding construct. The following sections constitute the only means by which reference edges are introduced into the documentation graph.
Public classes, functions, and methods
Entries in
Public_classesinduce reference edges from the containing module/class to the listed classes.Entries in
Public_functionsinduce reference edges from the containing module to the listed functions.Entries in
Public_methodsinduce reference edges from the containing class to the listed methods.
Rationale (informative)
This reflects the intuitive notion that the containing object “contains” the listed objects as part of its public API surface. The reference edge represents a contractual relationship: the containing object is responsible for providing access to the contained objects, and users of the containing object are expected to interact with the contained objects as part of their usage of the containing object. The containing object must be at least as public as the contained objects, since otherwise it would block access to visible such objects.
Inheritance
Subsection
Contract.basein profileinherited_methodinduces a reference edge from the referenced(!) base method to the referencing(!) method.Entries in
Derived_frominduce reference edges from the base(!) class to the derived(!) class.
Rationale (informative)
This reflects the intuitive notion that a derived class or method “refers to” its base class or method as part of its contract. The reference edge represents a contractual relationship: the derived object is obliged to uphold the contract of the base object, and users of the derived object are expected to rely on the guarantees provided by the base object as part of their usage of the derived object.
Cross-referencing
Entries in
See_alsoinduce reference edges from the referenced(!) objects to the referencing(!) object.
Rationale (informative)
A section See_also represents an explicit warrant that the referenced objects
are accessible and relevant to users of the referencing object. Information flows from the referenced objects
to the referencing object, and users of the referencing object are expected to consult the referenced objects,
therefore the referenced objects must be at least as public as the referencing object.
If we define A as the source of information and B as the target of information, in terms of the numeric scope order, this means:
For containment-style references, there exist s_A in scopes(A) and s_B in scopes(B) such that s_A <= s_B, (“A is at least as public as B”) where A represents the containing object and B represents the contained object.
For
Derived_fromandContract.base, there exist s_A in scopes(A) and s_B in scopes(B) such that s_A <= s_B, (“A is at least as public as B”) where A represents the referenced object and B represents the referencing object containing theDerived_fromorContract.basesection.For
See_also, there exist s_A in scopes(A) and s_B in scopes(B) such that s_A <= s_B, (“A is at least as public as B”) where A represents the referenced object and B represents the referencing object containing theSee_alsosection.
This rule set is referred to as the Scope Monotonicity Rule.
5.15.6. Non-referential relationships¶
Certain structural relationships do not introduce reference edges
for the purposes of scope validation.
In particular, entries in the Factory section do not
constitute reference edges.
The Factory section describes callable entry points
for object construction. The direction of instantiation does not
imply contractual visibility in either direction.
For example:
A factory function may have scope
corewhile the constructed class has scopepublic.Conversely, a class may have scope
corewhile a factory function providing controlled access to instances is visible underpublic.
Both situations are valid and do not violate scope monotonicity. Therefore, factory declarations do not participate in the reference graph.
5.15.7. Rendering and validation¶
When rendering documentation for a selected scope set S, tools must:
render only objects that are visible under S, and
emit only references to visible objects.
Validators must enforce the scope monotonicity rule and report violations as
errors.
This guarantees that documentation rendered for any scope set is internally consistent and closed under references.
5.16. Rationale: SSoT for Normative Statements¶
This section is informative.
This rationale provides the motivation for rules MCLO-007, MFNO-007, CCLO-007, and CMTO-007. Waterloo follows the principle of Single Source of Truth (SSoT) for normative requirements. Every normative statement is defined exactly once and at exactly one semantic location.
In particular, normative requirements describing the behavior, guarantees, or obligations of an object are defined exclusively in the docstring of that object itself, in accordance with the principles of Locality of Information (LoII) and Single Source of Truth (SSoT).
Sections such as Public_classes, Public_functions,
and Public_methods declare which objects belong to the documented
public API surface. Sections such as Class_overview,
Function_overview, and Method_overview may provide
informative summaries for those objects. Neither kind of section is intended to
redefine or qualify the behavior of the objects they mention.
Allowing normativity keywords in API listing sections or overview sections would introduce multiple independent locations for normative statements about the same object. This would make it impossible to ensure consistency and would undermine automated validation, tooling, and long-term maintainability.
Therefore, once an object is equipped with its own valid docstring, all normative statements concerning that object are required to appear there and nowhere else. API listing sections may declare membership in the public API surface, and overview sections may provide descriptive or summarizing text, but neither may introduce additional normative requirements.
This design ensures that tools, validators, and human readers can rely on a single authoritative specification for each documented object, and that normative changes are localized, explicit, and unambiguous.
5.17. Distinction Description vs Notes¶
This section is informative.
The Description and Notes sections overlap thematically. We would like
to suggest the following semantics: Description describes the object to be documented for normal use,
whereas Notes are intended more for edge cases, caveats, race conditions, restrictions, and todos.
We have deliberately implemented Notes as non-normative in order to prevent runaway growth
of self-defined normative sections. Notes of a normative nature should be added to the Contract section instead.
5.18. Distinction general vs invariants¶
This section is informative.
The Contract.general and Contract.invariants subsections overlap thematically.
We would like to suggest the following semantics: Contract.general describes the object to be documented
for normal use, focusing on its purpose and applicability, whereas Contract.invariants is intended for
non-trivial properties that are expected to hold for all valid inputs and states.
Invariants are typically statements about closure properties, idempotence, determinism, round-trip behaviour,
and other guarantees that are especially useful for targeted automated tests.
Invariants of a normative nature should be placed in Contract.invariants rather than being scattered
throughout free-form prose.
Invariants may be more technical in nature and may refer to internal representations such as an AST or a DocstringTree.
5.19. Distinction ensures vs invariants¶
This section is informative.
The subsections ensures and invariants overlap thematically, but serve different purposes.
ensures describes postconditions that hold after a successful call of the documented function.
invariants describes properties that remain true across repeated calls and are typically suited
for automated testing, such as idempotence, non-mutation of inputs, or round-trip properties.