Skip to content

Commit 5f117b2

Browse files
authored
Increase test coverage of the python_format checker (#1176)
1 parent 363ad75 commit 5f117b2

File tree

2 files changed

+64
-4
lines changed

2 files changed

+64
-4
lines changed

babel/messages/checkers.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,6 @@ def _validate_format(format: str, alternative: str) -> None:
6565
arguments are not interchangeable as `alternative` may contain less
6666
placeholders if `format` uses named placeholders.
6767
68-
The behavior of this function is undefined if the string does not use
69-
string formatting.
70-
7168
If the string formatting of `alternative` is compatible to `format` the
7269
function returns `None`, otherwise a `TranslationError` is raised.
7370
@@ -121,6 +118,9 @@ def _check_positional(results: list[tuple[str, str]]) -> bool:
121118

122119
a, b = map(_parse, (format, alternative))
123120

121+
if not a:
122+
return
123+
124124
# now check if both strings are positional or named
125125
a_positional, b_positional = map(_check_positional, (a, b))
126126
if a_positional and not b_positional and not b:

tests/messages/test_checkers.py

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@
1414
from datetime import datetime
1515
from io import BytesIO
1616

17+
import pytest
18+
1719
from babel import __version__ as VERSION
1820
from babel.core import Locale, UnknownLocaleError
1921
from babel.dates import format_datetime
20-
from babel.messages import checkers
22+
from babel.messages import Message, checkers
23+
from babel.messages.catalog import TranslationError
24+
from babel.messages.checkers import _validate_format, python_format
2125
from babel.messages.plurals import PLURALS
2226
from babel.messages.pofile import read_po
2327
from babel.util import LOCALTZ
@@ -325,3 +329,59 @@ def test_6_num_plurals_checkers(self):
325329
catalog = read_po(BytesIO(po_file), _locale)
326330
message = catalog['foobar']
327331
checkers.num_plurals(catalog, message)
332+
333+
334+
class TestPythonFormat:
335+
@pytest.mark.parametrize(('msgid', 'msgstr'), [
336+
('foo %s', 'foo'),
337+
(('foo %s', 'bar'), ('foo', 'bar')),
338+
(('foo', 'bar %s'), ('foo', 'bar')),
339+
(('foo %s', 'bar'), ('foo')),
340+
])
341+
def test_python_format_invalid(self, msgid, msgstr):
342+
msg = Message(msgid, msgstr)
343+
with pytest.raises(TranslationError):
344+
python_format(None, msg)
345+
346+
@pytest.mark.parametrize(('msgid', 'msgstr'), [
347+
('foo', 'foo'),
348+
('foo', 'foo %s'),
349+
(('foo %s', 'bar %d'), ('foo %s', 'bar %d')),
350+
(('foo %s', 'bar %d'), ('foo %s', 'bar %d', 'baz')),
351+
(('foo', 'bar %s'), ('foo')),
352+
])
353+
def test_python_format_valid(self, msgid, msgstr):
354+
msg = Message(msgid, msgstr)
355+
python_format(None, msg)
356+
357+
@pytest.mark.parametrize(('msgid', 'msgstr', 'error'), [
358+
('%s %(foo)s', '%s %(foo)s', 'format string mixes positional and named placeholders'),
359+
('foo %s', 'foo', 'placeholders are incompatible'),
360+
('%s', '%(foo)s', 'the format strings are of different kinds'),
361+
('%s', '%s %d', 'positional format placeholders are unbalanced'),
362+
('%s', '%d', "incompatible format for placeholder 1: 's' and 'd' are not compatible"),
363+
('%s %s %d', '%s %s %s', "incompatible format for placeholder 3: 'd' and 's' are not compatible"),
364+
('%(foo)s', '%(bar)s', "unknown named placeholder 'bar'"),
365+
('%(foo)s', '%(bar)d', "unknown named placeholder 'bar'"),
366+
('%(foo)s', '%(foo)d', "incompatible format for placeholder 'foo': 'd' and 's' are not compatible"),
367+
])
368+
def test__validate_format_invalid(self, msgid, msgstr, error):
369+
with pytest.raises(TranslationError, match=error):
370+
_validate_format(msgid, msgstr)
371+
372+
@pytest.mark.parametrize(('msgid', 'msgstr'), [
373+
('foo', 'foo'),
374+
('foo', 'foo %s'),
375+
('%s foo', 'foo %s'),
376+
('%i', '%d'),
377+
('%d', '%u'),
378+
('%x', '%X'),
379+
('%f', '%F'),
380+
('%F', '%g'),
381+
('%g', '%G'),
382+
('%(foo)s', 'foo'),
383+
('%(foo)s', '%(foo)s %(foo)s'),
384+
('%(bar)s foo %(n)d', '%(n)d foo %(bar)s'),
385+
])
386+
def test__validate_format_valid(self, msgid, msgstr):
387+
_validate_format(msgid, msgstr)

0 commit comments

Comments
 (0)