Skip to content

ResidualMarkupError cites the source .rst but numbers lines against the converted body, so the line number is always wrong #588

Description

@JarryShaw

ResidualMarkupError names the source .rst file but numbers its lines against the converted entry body, so the line number it prints does not exist in the file it points at.

Mechanism

residual() at util/changelog_md.py:388 numbers the markdown it was handed:

for number, line in enumerate(markdown.split('\n'), 1):

and render() at util/changelog_md.py:418 hands it the converted entry body, not the file:

problems = residual(body)

while the error raised at util/changelog_md.py:420 names the source path. So the reader is told to look at a line of docs/source/changelog/1.5.0.rst using a number that was counted in a different, much shorter string.

Measured

Against the changelog entry that failed CI on #586 (its pre-fix head 524d24616):

lines
converted entry body, which the numbers count 49
docs/source/changelog/1.5.0.rst, which the message names 459

All 9 residual hits were reported as line 46. Body line 46 is the rule-6-joined bullet:

- **Changed** -- `ModuleDescriptor.klass` reads an already-imported module out of
  :data:`sys.modules` rather than re-entering :func:`importlib.import_module...

whose source spans .rst lines 424-433. So the nine distinct offences on nine different source lines all collapse onto one reported number, and that number — 46 — is not where any of them lives.

The bound makes it plain: a reported number can never exceed 49 while the named file has 459 lines, so for any entry past the top of the file the citation is guaranteed wrong.

Why it matters

This is the message on a gate that blocks merges. On #586 it sent the first reader — me — to fix a single :data: role, because that was the only hit the CI log surfaced and the line reference gave no way to see there were nine across four role types. The cross-review found the rest by grepping the file instead of trusting the message.

Notes on fixing it

Recovering an exact source line is not trivial, because rule 6 deliberately joins lines and the module docstring at util/changelog_md.py:163 already notes that joining moves "every reported line number". Two honest options:

  • say what the number means — "line 46 of the converted entry" — and name the entry rather than the file; or
  • carry a source-line map through convert() so the original line can be cited.

Either beats the current form, which is confidently wrong. Reporting all distinct hits rather than collapsing them onto the joined line would help independently of which is chosen.

Found while running down #586's Changelog drift failure; the underlying role-conversion behaviour is correct and is not what this issue is about.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions