Skip to content

Commit c092a7d

Browse files
committed
Use pathlib.Path() in catalog frontend; improve test coverage
1 parent 2e56a2a commit c092a7d

File tree

2 files changed

+116
-52
lines changed

2 files changed

+116
-52
lines changed

babel/messages/frontend.py

Lines changed: 38 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import logging
1616
import optparse
1717
import os
18+
import pathlib
1819
import re
1920
import shutil
2021
import sys
@@ -201,44 +202,34 @@ def run(self):
201202
self.log.error('%d errors encountered.', n_errors)
202203
return (1 if n_errors else 0)
203204

204-
def _run_domain(self, domain):
205-
po_files = []
206-
mo_files = []
207-
205+
def _get_po_mo_triples(self, domain: str):
208206
if not self.input_file:
207+
dir_path = pathlib.Path(self.directory)
209208
if self.locale:
210-
po_files.append((self.locale,
211-
os.path.join(self.directory, self.locale,
212-
'LC_MESSAGES',
213-
f"{domain}.po")))
214-
mo_files.append(os.path.join(self.directory, self.locale,
215-
'LC_MESSAGES',
216-
f"{domain}.mo"))
209+
lc_messages_path = dir_path / self.locale / "LC_MESSAGES"
210+
po_file = lc_messages_path / f"{domain}.po"
211+
yield self.locale, po_file, po_file.with_suffix(".mo")
217212
else:
218-
for locale in os.listdir(self.directory):
219-
po_file = os.path.join(self.directory, locale,
220-
'LC_MESSAGES', f"{domain}.po")
221-
if os.path.exists(po_file):
222-
po_files.append((locale, po_file))
223-
mo_files.append(os.path.join(self.directory, locale,
224-
'LC_MESSAGES',
225-
f"{domain}.mo"))
213+
for locale_path in dir_path.iterdir():
214+
po_file = locale_path / "LC_MESSAGES"/ f"{domain}.po"
215+
if po_file.exists():
216+
yield locale_path.name, po_file, po_file.with_suffix(".mo")
226217
else:
227-
po_files.append((self.locale, self.input_file))
218+
po_file = pathlib.Path(self.input_file)
228219
if self.output_file:
229-
mo_files.append(self.output_file)
220+
mo_file = pathlib.Path(self.output_file)
230221
else:
231-
mo_files.append(os.path.join(self.directory, self.locale,
232-
'LC_MESSAGES',
233-
f"{domain}.mo"))
222+
mo_file = pathlib.Path(self.directory) / self.locale / "LC_MESSAGES" / f"{domain}.mo"
223+
yield self.locale, po_file, mo_file
234224

235-
if not po_files:
236-
raise OptionError('no message catalogs found')
225+
def _run_domain(self, domain):
226+
locale_po_mo_triples = list(self._get_po_mo_triples(domain))
227+
if not locale_po_mo_triples:
228+
raise OptionError(f'no message catalogs found for domain {domain!r}')
237229

238230
catalogs_and_errors = {}
239231

240-
for idx, (locale, po_file) in enumerate(po_files):
241-
mo_file = mo_files[idx]
232+
for locale, po_file, mo_file in locale_po_mo_triples:
242233
with open(po_file, 'rb') as infile:
243234
catalog = read_po(infile, locale)
244235

@@ -622,8 +613,8 @@ def finalize_options(self):
622613
if not self.output_file and not self.output_dir:
623614
raise OptionError('you must specify the output directory')
624615
if not self.output_file:
625-
self.output_file = os.path.join(self.output_dir, self.locale,
626-
'LC_MESSAGES', f"{self.domain}.po")
616+
lc_messages_path = pathlib.Path(self.output_dir) / self.locale / "LC_MESSAGES"
617+
self.output_file = str(lc_messages_path / f"{self.domain}.po")
627618

628619
if not os.path.exists(os.path.dirname(self.output_file)):
629620
os.makedirs(os.path.dirname(self.output_file))
@@ -744,36 +735,35 @@ def finalize_options(self):
744735
if self.no_fuzzy_matching and self.previous:
745736
self.previous = False
746737

747-
def run(self):
748-
check_status = {}
749-
po_files = []
738+
def _get_locale_po_file_tuples(self):
750739
if not self.output_file:
740+
output_path = pathlib.Path(self.output_dir)
751741
if self.locale:
752-
po_files.append((self.locale,
753-
os.path.join(self.output_dir, self.locale,
754-
'LC_MESSAGES',
755-
f"{self.domain}.po")))
742+
lc_messages_path = output_path / self.locale / "LC_MESSAGES"
743+
yield self.locale, str(lc_messages_path / f"{self.domain}.po")
756744
else:
757-
for locale in os.listdir(self.output_dir):
758-
po_file = os.path.join(self.output_dir, locale,
759-
'LC_MESSAGES',
760-
f"{self.domain}.po")
761-
if os.path.exists(po_file):
762-
po_files.append((locale, po_file))
745+
for locale_path in output_path.iterdir():
746+
po_file = locale_path / "LC_MESSAGES" / f"{self.domain}.po"
747+
if po_file.exists():
748+
yield locale_path.stem, po_file
763749
else:
764-
po_files.append((self.locale, self.output_file))
765-
766-
if not po_files:
767-
raise OptionError('no message catalogs found')
750+
yield self.locale, self.output_file
768751

752+
def run(self):
769753
domain = self.domain
770754
if not domain:
771755
domain = os.path.splitext(os.path.basename(self.input_file))[0]
772756

757+
check_status = {}
758+
locale_po_file_tuples = list(self._get_locale_po_file_tuples())
759+
760+
if not locale_po_file_tuples:
761+
raise OptionError(f'no message catalogs found for domain {domain!r}')
762+
773763
with open(self.input_file, 'rb') as infile:
774764
template = read_po(infile)
775765

776-
for locale, filename in po_files:
766+
for locale, filename in locale_po_file_tuples:
777767
if self.init_missing and not os.path.exists(filename):
778768
if self.check:
779769
check_status[filename] = False

tests/messages/test_frontend.py

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
# This software consists of voluntary contributions made by many
1010
# individuals. For the exact contribution history, see the revision
1111
# history and logs, available at https://github.com/python-babel/babel/commits/master/.
12+
from __future__ import annotations
13+
1214
import logging
1315
import os
1416
import re
@@ -20,7 +22,6 @@
2022
from datetime import datetime, timedelta
2123
from functools import partial
2224
from io import BytesIO, StringIO
23-
from typing import List
2425

2526
import pytest
2627
from freezegun import freeze_time
@@ -63,7 +64,7 @@ def get_version(self) -> str:
6364
return self.attrs['version']
6465

6566
@property
66-
def packages(self) -> List[str]:
67+
def packages(self) -> list[str]:
6768
return self.attrs['packages']
6869

6970

@@ -1536,14 +1537,14 @@ def test_extract_messages_with_t():
15361537
assert result == expected
15371538

15381539

1539-
def configure_cli_command(cmdline):
1540+
def configure_cli_command(cmdline: str | list[str]):
15401541
"""
15411542
Helper to configure a command class, but not run it just yet.
15421543
15431544
:param cmdline: The command line (sans the executable name)
15441545
:return: Command instance
15451546
"""
1546-
args = shlex.split(cmdline)
1547+
args = shlex.split(cmdline) if isinstance(cmdline, str) else list(cmdline)
15471548
cli = CommandLineInterface()
15481549
cmdinst = cli._configure_command(cmdname=args[0], argv=args[1:])
15491550
return cmdinst
@@ -1601,6 +1602,79 @@ def test_update_catalog_boolean_args():
16011602
assert cmdinst.previous is False # Mutually exclusive with no_fuzzy_matching
16021603

16031604

1605+
1606+
def test_compile_catalog_dir(tmp_path):
1607+
"""
1608+
Test that `compile` can compile all locales in a directory.
1609+
"""
1610+
locales = ("fi_FI", "sv_SE")
1611+
for locale in locales:
1612+
l_dir = tmp_path / locale / "LC_MESSAGES"
1613+
l_dir.mkdir(parents=True)
1614+
po_file = l_dir / 'messages.po'
1615+
po_file.write_text('msgid "foo"\nmsgstr "bar"\n')
1616+
cmdinst = configure_cli_command([ # fmt: skip
1617+
'compile',
1618+
'--statistics',
1619+
'--use-fuzzy',
1620+
'-d', str(tmp_path),
1621+
])
1622+
assert not cmdinst.run()
1623+
for locale in locales:
1624+
assert (tmp_path / locale / "LC_MESSAGES" / "messages.mo").exists()
1625+
1626+
1627+
def test_compile_catalog_explicit(tmp_path):
1628+
"""
1629+
Test that `compile` can explicitly compile a single catalog.
1630+
"""
1631+
po_file = tmp_path / 'temp.po'
1632+
po_file.write_text('msgid "foo"\nmsgstr "bar"\n')
1633+
mo_file = tmp_path / 'temp.mo'
1634+
cmdinst = configure_cli_command([ # fmt: skip
1635+
'compile',
1636+
'--statistics',
1637+
'--use-fuzzy',
1638+
'-i', str(po_file),
1639+
'-o', str(mo_file),
1640+
'-l', 'fi_FI',
1641+
])
1642+
assert not cmdinst.run()
1643+
assert mo_file.exists()
1644+
1645+
1646+
1647+
@pytest.mark.parametrize("explicit_locale", (None, 'fi_FI'), ids=("implicit", "explicit"))
1648+
def test_update_dir(tmp_path, explicit_locale: bool):
1649+
"""
1650+
Test that `update` can deal with directories too.
1651+
"""
1652+
template = Catalog()
1653+
template.add("1")
1654+
template.add("2")
1655+
template.add("3")
1656+
tmpl_file = (tmp_path / 'temp-template.pot')
1657+
with tmpl_file.open("wb") as outfp:
1658+
write_po(outfp, template)
1659+
locales = ("fi_FI", "sv_SE")
1660+
for locale in locales:
1661+
l_dir = tmp_path / locale / "LC_MESSAGES"
1662+
l_dir.mkdir(parents=True)
1663+
po_file = l_dir / 'messages.po'
1664+
po_file.touch()
1665+
cmdinst = configure_cli_command([ # fmt: skip
1666+
'update',
1667+
'-i', str(tmpl_file),
1668+
'-d', str(tmp_path),
1669+
*(['-l', explicit_locale] if explicit_locale else []),
1670+
])
1671+
assert not cmdinst.run()
1672+
for locale in locales:
1673+
if explicit_locale and locale != explicit_locale:
1674+
continue
1675+
assert (tmp_path / locale / "LC_MESSAGES" / "messages.po").stat().st_size > 0
1676+
1677+
16041678
def test_extract_cli_knows_dash_s():
16051679
# This is a regression test for https://github.com/python-babel/babel/issues/390
16061680
cmdinst = configure_cli_command("extract -s -o foo babel")

0 commit comments

Comments
 (0)