Skip to content

Fix Markdown reporter max_length handling - #858

Open
PeterDaveHello wants to merge 1 commit into
thp:masterfrom
PeterDaveHello:fix-markdown-max-length
Open

Fix Markdown reporter max_length handling#858
PeterDaveHello wants to merge 1 commit into
thp:masterfrom
PeterDaveHello:fix-markdown-max-length

Conversation

@PeterDaveHello

@PeterDaveHello PeterDaveHello commented Dec 10, 2025

Copy link
Copy Markdown
Contributor

Fix Markdown reporter handling of unlimited and size-limited output.

max_length=None no longer raises a TypeError. Trimming is now handled in _render(), so exact-fit reports remain unchanged while oversized reports preserve as much content as possible with a compact [...] marker. For size-limited reporters such as Matrix and Gotify, oversized details are measured before formatting, avoiding unnecessary memory use for very large diffs.

Tests cover unlimited output, exact and tiny limits, trimmed details, footers, and oversized diffs.

Comment thread lib/urlwatch/tests/test_reporters.py Outdated
job_state = _DummyJobState(diff="line1\nline2\nline3")
reporter = MarkdownReporter(report, report.config["report"]["markdown"], [job_state], datetime.timedelta())

output = list(reporter.submit(max_length=10))

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't max_length in the function become negative?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It only goes negative if a very small max_length is passed. This is because submit() first does max_length -= len(trimmed_msg) and the trimmed_msg string is about 58 chars, so max_length=10 becomes -48. Even then it just trims and does not crash. If you want to avoid that impression, I can change the test to use a value >= 60.

@thp thp left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In which situation would max_length actually become None?

@PeterDaveHello

Copy link
Copy Markdown
Contributor Author

Agreed that a plain CLI run won't hit this. The crash only happens when the Markdown reporter output is actually consumed (Python/hook/extension usage): with default max_length=None, submit() subtracts from None. This is a minimal guard and does not change behavior when a length is provided.

@thp thp left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The more I think about it, the more I think that max_length -= len(trimmed_msg) should be done later (only when trimmed is truthy). If it isn't trimmed, we still want to have the full max_length, and if it is trimmed, something like [...] or [trimmed] might be better to allow for more "payload" and less "boilerplate". In particular, if max_length < len(trimmed_msg), then technically we wouldn't be able to show anything, not even the summary or the details. And if the "trimmed message" is quite small (e.g. "[...]" - 5 characters).

Then again, it's probably the _render() method that should do all deciding and value adding (possibly with an additional return value before the footer), so that it knows what the "real" max length is, and either fit the message in there, or trim it.

In other words:

The message "Hello world" (11 characters) and trimmed_msg = "[...]" (5 characters)

with max_length == 11 should still be:

"Hello world"

but with max_length == 10, should be:

"Hello[...]"

Right now, with max_length == 11, it would be:

"Hello [...]"

@PeterDaveHello
PeterDaveHello force-pushed the fix-markdown-max-length branch from 4f5f740 to ce8e240 Compare December 28, 2025 19:08
@PeterDaveHello
PeterDaveHello requested a review from thp December 28, 2025 19:08
Comment thread lib/urlwatch/reporters.py Outdated
trimmed_marker = "[...]\n"
if len(trimmed_marker) > max_length:
trimmed_marker = ""
reserved_length = max_length - len(trimmed_marker) if trimmed_marker else max_length

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If trimmed_marker is the empty string (the only way if trimmed_marker should evaluate to falsy), then len(trimmed_marker) == 0, so the result is the same.

Suggested change
reserved_length = max_length - len(trimmed_marker) if trimmed_marker else max_length
reserved_length = max_length - len(trimmed_marker)

Comment thread lib/urlwatch/reporters.py Outdated
if len(trimmed_marker) > max_length:
trimmed_marker = ""
reserved_length = max_length - len(trimmed_marker) if trimmed_marker else max_length
trimmed, summary, details, footer = MarkdownReporter._render(

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unfortunate that we have to call MarkdownReporter._render() twice here. Can't MarkdownReporter._render() contain all that trimming logic?

@thp thp left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comments. Ideally call MarkdownReporter._render() only once and let it figure out trimming (since MarkdownReporter._render() already returns the trimmed status, might as well return trimmed_msg instead (being the empty string if not trimmed or not enough space).

@thp

thp commented Jul 10, 2026

Copy link
Copy Markdown
Owner

@PeterDaveHello Any updates here?

@PeterDaveHello

Copy link
Copy Markdown
Contributor Author

Sorry, I forgot this PR, will take a look at it.

@PeterDaveHello
PeterDaveHello force-pushed the fix-markdown-max-length branch from ce8e240 to e2d8dfc Compare August 12, 2026 18:55
@PeterDaveHello PeterDaveHello changed the title Prevent Markdown reporter crash when max_length is None Fix Markdown reporter max_length handling Aug 12, 2026
@PeterDaveHello
PeterDaveHello requested a review from thp August 12, 2026 19:18
Let _render() measure the complete layout before deciding whether to
trim, reserving marker space only when necessary. For finite limits,
bound summary joining and measure detail bodies before formatting so
oversized reports do not materialize the full message.

This keeps exact-length output intact, preserves payload with a compact
trim marker, separates it cleanly from Markdown footers, avoids None
arithmetic and negative slicing, and bounds temporary output for Matrix
and Gotify.

Tests cover unlimited and bounded output, exact limits, trimming,
oversized details, summaries, and footers.
@PeterDaveHello
PeterDaveHello force-pushed the fix-markdown-max-length branch from e2d8dfc to 59a1f03 Compare August 13, 2026 14:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants