Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions babel/messages/checkers.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ def _parse(string: str) -> list[tuple[str, str]]:
name, format, typechar = match.groups()
if typechar == '%' and name is None:
continue
if name is None:
# A star width or precision consumes an integer argument first.
result.extend((None, 'd') for _ in range(format.count('*')))
result.append((name, str(typechar)))
return result

Expand Down
53 changes: 52 additions & 1 deletion tests/messages/test_checkers.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from babel.core import Locale, UnknownLocaleError
from babel.dates import format_datetime
from babel.messages import Message, checkers
from babel.messages.catalog import TranslationError
from babel.messages.catalog import Catalog, TranslationError
from babel.messages.checkers import _validate_format, python_format
from babel.messages.plurals import PLURALS
from babel.messages.pofile import read_po
Expand Down Expand Up @@ -370,6 +370,57 @@ def test_python_format_valid(msgid, msgstr):
python_format(None, msg)


@pytest.mark.parametrize(
('msgid', 'msgstr', 'arguments'),
[
('%*s', '%s', (4, 'word')),
('%s', '%*s', ('word',)),
('%.*f', '%.2f', (2, 1.234)),
('%.2f', '%.*f', (1.234,)),
('%*.*f', '%.*f', (8, 2, 1.234)),
('%.*f', '%*.*f', (2, 1.234)),
('%*.*f', '%*f', (8, 2, 1.234)),
('%*f', '%*.*f', (8, 1.234)),
('%s %*s', '%*s %s', ('label', 5, 'value')),
('%*s %s', '%s %*s', (5, 'value', 'label')),
],
)
def test_python_format_star_arguments_invalid(msgid, msgstr, arguments):
assert isinstance(msgid % arguments, str)
with pytest.raises(TypeError):
msgstr % arguments
with pytest.raises(TranslationError):
python_format(None, Message(msgid, msgstr))


@pytest.mark.parametrize(
('msgid', 'msgstr', 'arguments'),
[
('%*s', '[%*s]', (-6, 'word')),
('%.*f', '%.*G', (2, 1.234)),
('%*.*f', '%*.*F', (8, 2, 1.234)),
('%10.2f', '%12.3f', (1.234,)),
('%s %%*s', '%% %s', ('word',)),
('%(name)10s', '%(name)s', {'name': 'word'}),
('%*s', '%.*s', (4, 'example')),
],
)
def test_python_format_star_arguments_valid(msgid, msgstr, arguments):
assert isinstance(msgid % arguments, str)
assert isinstance(msgstr % arguments, str)
python_format(None, Message(msgid, msgstr))


def test_python_format_star_plural_catalog_check():
catalog = Catalog(locale='en')
message = catalog.add(('%*s', '%*s'), ('%*s', '%s'))
errors = list(catalog.check())
assert len(errors) == 1
assert errors[0][0] is message
assert len(errors[0][1]) == 1
assert isinstance(errors[0][1][0], TranslationError)


@pytest.mark.parametrize(
('msgid', 'msgstr', 'error'),
[
Expand Down