Skip to content

Commit a022a27

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

File tree

2 files changed

+113
-50
lines changed

2 files changed

+113
-50
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: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,14 +1536,14 @@ def test_extract_messages_with_t():
15361536
assert result == expected
15371537

15381538

1539-
def configure_cli_command(cmdline):
1539+
def configure_cli_command(cmdline: str | list[str]):
15401540
"""
15411541
Helper to configure a command class, but not run it just yet.
15421542
15431543
:param cmdline: The command line (sans the executable name)
15441544
:return: Command instance
15451545
"""
1546-
args = shlex.split(cmdline)
1546+
args = shlex.split(cmdline) if isinstance(cmdline, str) else list(cmdline)
15471547
cli = CommandLineInterface()
15481548
cmdinst = cli._configure_command(cmdname=args[0], argv=args[1:])
15491549
return cmdinst
@@ -1601,6 +1601,79 @@ def test_update_catalog_boolean_args():
16011601
assert cmdinst.previous is False # Mutually exclusive with no_fuzzy_matching
16021602

16031603

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

0 commit comments

Comments
 (0)