Skip to content

Accept empty message in retry_if_exception_message#651

Merged
mergify[bot] merged 1 commit into
jd:mainfrom
gaoflow:fix-exception-message-empty-string
Jul 13, 2026
Merged

Accept empty message in retry_if_exception_message#651
mergify[bot] merged 1 commit into
jd:mainfrom
gaoflow:fix-exception-message-empty-string

Conversation

@gaoflow

@gaoflow gaoflow commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Problem

retry_if_exception_message validates its two mutually-exclusive arguments
with truthiness checks:

if message and match:            # both given
    raise TypeError(...)
if not message and not match:    # neither given
    raise TypeError(...)
...
self.match = re.compile(match) if match else None
...
def _check(self, exception):
    if self.message:             # skips message == ""
        return self.message == str(exception)

An empty string is a valid message target — it matches exceptions whose
str() is empty, e.g. a bare raise RuntimeError() (str(RuntimeError()) == "").
But not message is True for "", so:

retry_if_exception_message(message="")
# TypeError: retry_if_exception_message() missing 1 required argument 'message' or 'match'

The result is an asymmetry: you can match every exception message except
the empty one. _check's if self.message: would drop the empty-message branch
as well, falling through to assert self.match is not None.

Fix

Replace the truthiness guards with is None checks, so an empty message is
accepted and matched like any other. retry_if_not_exception_message inherits
the same constructor and is fixed by the same change.

Tests

Added test_retry_if_exception_message_empty_message and
test_retry_if_not_exception_message_empty_message: construct with message=""
and drive the predicate against a bare RuntimeError() (matches) and a
RuntimeError("boom") (does not), plus the inverse for the not-variant. Both
fail before the change (TypeError at construction) and pass after. The
existing test_..._negative_no_inputs (passing no arguments must raise) still
passes.

Full suite: 167 passed, 1 skipped, 12 subtests. ruff check / ruff format --check clean.

retry_if_exception_message validated its message/match arguments with
truthiness checks (if message and match, if not message and not match).
An empty string is a valid message target — it matches exceptions whose
str() is empty, e.g. a bare RuntimeError() — but 'not message' is True
for '', so retry_if_exception_message(message='') wrongly raised
TypeError('missing 1 required argument'). _check had the same problem:
'if self.message:' skipped the empty-message branch.

Replace the truthiness guards with 'is None' checks so an empty message
is accepted and matched. This makes every message matchable, not every
message except the empty one.
@mergify

mergify Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

This pull request spent 18 seconds in the queue, including 2 seconds running CI.

Required conditions to merge

mergify Bot added a commit that referenced this pull request Jul 13, 2026
@mergify mergify Bot merged commit 40fad18 into jd:main Jul 13, 2026
9 checks passed
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