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
20 changes: 16 additions & 4 deletions babel/messages/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,18 @@ def _has_python_brace_format(string: str) -> bool:
return field_name_seen


def _parse_datetime_header(value: str) -> datetime.datetime:
def _parse_datetime_header(value: str) -> datetime.datetime | None:
match = re.match(r'^(?P<datetime>.*?)(?P<tzoffset>[+-]\d{4})?$', value)

dt = datetime.datetime.strptime(match.group('datetime'), '%Y-%m-%d %H:%M')
dt_str = match.group('datetime').strip()
if not dt_str:
# Some tools (e.g. Poedit) leave the PO-Revision-Date/POT-Creation-Date
# header value blank instead of using the conventional
# 'YEAR-MO-DA HO:MI+ZONE' placeholder or omitting the header
# altogether. There's nothing meaningful to parse in that case.
return None

dt = datetime.datetime.strptime(dt_str, '%Y-%m-%d %H:%M')

# Separate the offset into a sign component, hours, and # minutes
tzoffset = match.group('tzoffset')
Expand Down Expand Up @@ -591,11 +599,15 @@ def _set_mime_headers(self, headers: Iterable[tuple[str, str]]) -> None:
self._num_plurals = int(params.get('nplurals', 2))
self._plural_expr = params.get('plural', '(n != 1)')
elif name == 'pot-creation-date':
self.creation_date = _parse_datetime_header(value)
parsed = _parse_datetime_header(value)
if parsed is not None:
self.creation_date = parsed
elif name == 'po-revision-date':
# Keep the value if it's not the default one
if 'YEAR' not in value:
self.revision_date = _parse_datetime_header(value)
parsed = _parse_datetime_header(value)
if parsed is not None:
self.revision_date = parsed

@property
def mime_headers(self) -> list[tuple[str, str]]:
Expand Down
23 changes: 23 additions & 0 deletions tests/messages/test_catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,29 @@ def test_datetime_parsing():
assert val2.tzinfo is None


def test_datetime_parsing_blank_value():
# Some tools (e.g. Poedit) leave the PO-Revision-Date/POT-Creation-Date
# header value blank instead of using the conventional
# 'YEAR-MO-DA HO:MI+ZONE' placeholder or omitting the header
# altogether; this used to raise a ValueError. See GH issue #1219.
assert catalog._parse_datetime_header('') is None
assert catalog._parse_datetime_header(' ') is None


def test_set_mime_headers_ignores_blank_dates():
cat = catalog.Catalog()
default_creation_date = cat.creation_date
default_revision_date = cat.revision_date

cat._set_mime_headers([
('POT-Creation-Date', ''),
('PO-Revision-Date', ''),
])

assert cat.creation_date == default_creation_date
assert cat.revision_date == default_revision_date


def test_update_catalog_comments():
# Based on https://web.archive.org/web/20100710131029/http://babel.edgewall.org/attachment/ticket/163/cat-update-comments.py

Expand Down