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.
ResidualMarkupErrornames the source.rstfile 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()atutil/changelog_md.py:388numbers the markdown it was handed:and
render()atutil/changelog_md.py:418hands it the converted entry body, not the file:while the error raised at
util/changelog_md.py:420names the source path. So the reader is told to look at a line ofdocs/source/changelog/1.5.0.rstusing 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):docs/source/changelog/1.5.0.rst, which the message namesAll 9 residual hits were reported as
line 46. Body line 46 is the rule-6-joined bullet:whose source spans
.rstlines 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:163already notes that joining moves "every reported line number". Two honest options: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 driftfailure; the underlying role-conversion behaviour is correct and is not what this issue is about.