Skip to content

Commit b3c105e

Browse files
jpmckinneyakx
andauthored
fix(extract): use the first matching method and options (#1121)
... instead of the first matching method and last matching options. Co-authored-by: Aarni Koskela <[email protected]>
1 parent cfdbc63 commit b3c105e

File tree

3 files changed

+52
-8
lines changed

3 files changed

+52
-8
lines changed

babel/messages/extract.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ def check_and_call_extract_file(
276276
for opattern, odict in options_map.items():
277277
if pathmatch(opattern, filename):
278278
options = odict
279+
break
279280
if callback:
280281
callback(filename, method, options)
281282
for message_tuple in extract_from_file(

tests/messages/test_frontend.py

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
project_dir,
4646
this_dir,
4747
)
48+
from tests.messages.utils import CUSTOM_EXTRACTOR_COOKIE
4849

4950

5051
def _po_file(locale):
@@ -1392,7 +1393,11 @@ def test_update_init_missing(self):
13921393

13931394
mapping_cfg = """
13941395
[extractors]
1395-
custom = mypackage.module:myfunc
1396+
custom = tests.messages.utils:custom_extractor
1397+
1398+
# Special extractor for a given Python file
1399+
[custom: special.py]
1400+
treat = delicious
13961401
13971402
# Python source files
13981403
[python: **.py]
@@ -1411,7 +1416,13 @@ def test_update_init_missing(self):
14111416

14121417
mapping_toml = """
14131418
[extractors]
1414-
custom = "mypackage.module:myfunc"
1419+
custom = "tests.messages.utils:custom_extractor"
1420+
1421+
# Special extractor for a given Python file
1422+
[[mappings]]
1423+
method = "custom"
1424+
pattern = "special.py"
1425+
treat = "delightful"
14151426
14161427
# Python source files
14171428
[[mappings]]
@@ -1470,18 +1481,17 @@ def test_parse_mapping(data: str, parser, preprocess, is_toml):
14701481
buf = StringIO(data)
14711482

14721483
method_map, options_map = parser(buf)
1473-
assert len(method_map) == 4
1484+
assert len(method_map) == 5
14741485

1475-
assert method_map[0] == ('**.py', 'python')
1486+
assert method_map[1] == ('**.py', 'python')
14761487
assert options_map['**.py'] == {}
1477-
assert method_map[1] == ('**/templates/**.html', 'genshi')
1488+
assert method_map[2] == ('**/templates/**.html', 'genshi')
14781489
assert options_map['**/templates/**.html']['include_attrs'] == ''
1479-
assert method_map[2] == ('**/templates/**.txt', 'genshi')
1490+
assert method_map[3] == ('**/templates/**.txt', 'genshi')
14801491
assert (options_map['**/templates/**.txt']['template_class']
14811492
== 'genshi.template:TextTemplate')
14821493
assert options_map['**/templates/**.txt']['encoding'] == 'latin-1'
1483-
1484-
assert method_map[3] == ('**/custom/*.*', 'mypackage.module:myfunc')
1494+
assert method_map[4] == ('**/custom/*.*', 'tests.messages.utils:custom_extractor')
14851495
assert options_map['**/custom/*.*'] == {}
14861496

14871497

@@ -1663,3 +1673,29 @@ def test_extract_header_comment(monkeypatch, tmp_path):
16631673
cmdinst.run()
16641674
pot_content = pot_file.read_text()
16651675
assert 'Boing' in pot_content
1676+
1677+
1678+
@pytest.mark.parametrize("mapping_format", ("toml", "cfg"))
1679+
def test_pr_1121(tmp_path, monkeypatch, caplog, mapping_format):
1680+
"""
1681+
Test that extraction uses the first matching method and options,
1682+
instead of the first matching method and last matching options.
1683+
1684+
Without the fix in PR #1121, this test would fail,
1685+
since the `custom_extractor` isn't passed a delicious treat via
1686+
the configuration.
1687+
"""
1688+
if mapping_format == "cfg":
1689+
mapping_file = (tmp_path / "mapping.cfg")
1690+
mapping_file.write_text(mapping_cfg)
1691+
else:
1692+
mapping_file = (tmp_path / "mapping.toml")
1693+
mapping_file.write_text(mapping_toml)
1694+
(tmp_path / "special.py").write_text("# this file is special")
1695+
pot_path = (tmp_path / "output.pot")
1696+
monkeypatch.chdir(tmp_path)
1697+
cmdinst = configure_cli_command(f"extract . -o {shlex.quote(str(pot_path))} --mapping {shlex.quote(mapping_file.name)}")
1698+
assert isinstance(cmdinst, ExtractMessages)
1699+
cmdinst.run()
1700+
# If the custom extractor didn't run, we wouldn't see the cookie in there.
1701+
assert CUSTOM_EXTRACTOR_COOKIE in pot_path.read_text()

tests/messages/utils.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CUSTOM_EXTRACTOR_COOKIE = "custom extractor was here"
2+
3+
4+
def custom_extractor(fileobj, keywords, comment_tags, options):
5+
if "treat" not in options:
6+
raise RuntimeError(f"The custom extractor refuses to run without a delicious treat; got {options!r}")
7+
return [(1, next(iter(keywords)), (CUSTOM_EXTRACTOR_COOKIE,), [])]

0 commit comments

Comments
 (0)