app.domain.errata

Erratum content: value types and the Markdown body parser.

An erratum is a separate Markdown file whose frontmatter names the corrected decision in erratum-for (see docs/developer/domain/schema.rst). Its body is split on ATX H2 headings into three sections:

  • ## Original text – the text as written in the decision (optional, e.g. for pure additions);

  • ## Corrected text – the replacement text (required);

  • ## Notes – optional rationale.

Headings match case-insensitively and tolerate trailing whitespace or a trailing colon. Headings inside fenced code blocks are content. Text before the first heading and sections under any other H2 heading are kept as notes and reported as erratum_unknown_section_heading warnings. A repeated section heading appends to that section and is reported as an erratum_duplicate_section warning naming the heading. Line endings are normalised (CRLF and lone CR become LF) before splitting, so no section text keeps a trailing carriage return.

Known limits (by design, documented for authors):

  • Only ATX H2 headings (## Notes) split sections; a setext H2 (a Notes line underlined with ---) is not recognised and stays content of the current section.

  • An unclosed code fence runs to the end of the body: every heading after it is content, so later sections are swallowed (typically reported as a missing Corrected text).

The frontmatter part (ErratumHeader) is validated by app.domain.validation; build_erratum() joins it with the parsed body into an ErratumContent.

Public API: ErratumType, ErratumHeader, ErratumContent, parse_erratum_body(), build_erratum().

class app.domain.errata.ErratumType(*values)

Bases: StrEnum

Kind of correction an erratum reports.

TECHNICAL = 'technical'
EDITORIAL = 'editorial'
class app.domain.errata.ErratumHeader(type, section=None, reported_by=None, reported_date=None)

Bases: object

Validated erratum frontmatter (everything except the target link).

Parameters:
  • type (ErratumType | None) – Erratum type, None if missing or invalid.

  • section (str | None) – Where in the decision the error is, if given.

  • reported_by (str | None) – Free-text reporter; informational only, never an identity.

  • reported_date (date | None) – Authored report date, if valid.

type: ErratumType | None
section: str | None
reported_by: str | None
reported_date: date | None
class app.domain.errata.ErratumContent(type, section, reported_by, reported_date, original, corrected, notes)

Bases: object

The full content of one erratum, safe to persist.

Parameters:
  • type (ErratumType | None) – Erratum type, None if missing or invalid (reported as bad_erratum_type).

  • section (str | None) – Where in the decision the error is, if given.

  • reported_by (str | None) – Free-text reporter; informational only.

  • reported_date (date | None) – Authored report date, if valid.

  • original (str | None) – Markdown of the “Original text” section, if any.

  • corrected (str) – Markdown of the “Corrected text” section; empty when missing (reported as erratum_missing_corrected_text).

  • notes (str | None) – Markdown of the notes, including unrecognised content.

type: ErratumType | None
section: str | None
reported_by: str | None
reported_date: date | None
original: str | None
corrected: str
notes: str | None
to_dict()

Convert to a JSON-serialisable mapping.

Return type:

dict[str, str | None]

Returns:

All fields by name; the type as its value and the date as YYYY-MM-DD.

classmethod from_dict(data)

Rebuild content from to_dict() output.

Parameters:

data (Mapping[str, object]) – Stored mapping; missing optional keys mean None.

Return type:

ErratumContent

Returns:

The content.

Raises:

ValueError – If the type or date is malformed, or a text value is not a string.

app.domain.errata.parse_erratum_body(body)

Split an erratum body into its sections. Never raises.

Parameters:

body (str) – Markdown body without frontmatter.

Return type:

tuple[str | None, str, str | None, tuple[Issue, ...]]

Returns:

The original text (or None), the corrected text (empty when missing), the notes (or None) and the issues.

app.domain.errata.build_erratum(header, body)

Combine validated frontmatter with the parsed body.

Parameters:
  • header (ErratumHeader) – Validated erratum frontmatter.

  • body (str) – Markdown body without frontmatter.

Return type:

tuple[ErratumContent, tuple[Issue, ...]]

Returns:

The erratum content and the body issues.