From a31afebf3d76274a260dfb8967475c2e6595efc4 Mon Sep 17 00:00:00 2001 From: Anton Petnitsky <168552591+Mukller@users.noreply.github.com> Date: Wed, 29 Jul 2026 19:17:07 +0300 Subject: [PATCH 1/2] fix(extract): skip bytes literals in _parse_python_string (#1190) _parse_python_string() is typed -> str | None but was returning bytes for literals like b'foo'. The caller appended the bytes value to `buf` and the subsequent ''.join(buf) raised: TypeError: sequence item 0: expected str instance, bytes found Guard the return with isinstance(body.value, str) so that byte-string literals are treated the same as other non-extractable expressions (i.e. silently ignored). bytes cannot be used as gettext messages anyway. --- babel/messages/extract.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/babel/messages/extract.py b/babel/messages/extract.py index 6fad84304..b4f2792d3 100644 --- a/babel/messages/extract.py +++ b/babel/messages/extract.py @@ -710,7 +710,8 @@ def _parse_python_string(value: str, encoding: str, future_flags: int) -> str | if isinstance(code, ast.Expression): body = code.body if isinstance(body, ast.Constant): - return body.value + if isinstance(body.value, str): + return body.value if isinstance(body, ast.JoinedStr): # f-string if all(isinstance(node, ast.Constant) for node in body.values): return ''.join(node.value for node in body.values) From 5fd2fa4b41fe9e887a12b89c4437de6a6f494489 Mon Sep 17 00:00:00 2001 From: Anton Petnitsky <168552591+Mukller@users.noreply.github.com> Date: Thu, 30 Jul 2026 22:09:19 +0300 Subject: [PATCH 2/2] fix(extract): warn when a bytes literal is passed to a gettext function Instead of silently returning None, emit a SyntaxWarning so users know their _(b"...") call is being skipped during extraction. Addresses review feedback from @akx on PR #1298. --- babel/messages/extract.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/babel/messages/extract.py b/babel/messages/extract.py index b4f2792d3..9fad70ab4 100644 --- a/babel/messages/extract.py +++ b/babel/messages/extract.py @@ -712,6 +712,14 @@ def _parse_python_string(value: str, encoding: str, future_flags: int) -> str | if isinstance(body, ast.Constant): if isinstance(body.value, str): return body.value + if isinstance(body.value, bytes): + warnings.warn( + f"Bytes literal {value!r} passed to a gettext function; " + "it will be skipped during message extraction. " + "Use a str literal instead.", + SyntaxWarning, + stacklevel=2, + ) if isinstance(body, ast.JoinedStr): # f-string if all(isinstance(node, ast.Constant) for node in body.values): return ''.join(node.value for node in body.values)