2022-02-19 21:05:56 -06:00
|
|
|
"""Test the build process with gettext builder with the test root."""
|
2010-06-07 07:04:16 -05:00
|
|
|
|
2018-02-19 07:39:14 -06:00
|
|
|
import gettext
|
2010-06-08 23:46:30 -05:00
|
|
|
import os
|
2013-01-05 08:38:21 -06:00
|
|
|
import re
|
2019-01-12 05:14:26 -06:00
|
|
|
import subprocess
|
2023-08-10 04:20:48 -05:00
|
|
|
import sys
|
2022-10-17 09:54:59 -05:00
|
|
|
from subprocess import CalledProcessError
|
2010-06-08 23:46:30 -05:00
|
|
|
|
2017-01-05 10:14:47 -06:00
|
|
|
import pytest
|
|
|
|
|
2022-05-22 10:37:45 -05:00
|
|
|
from sphinx.builders.gettext import Catalog, MsgOrigin
|
2023-03-05 09:25:47 -06:00
|
|
|
|
2023-08-10 04:20:48 -05:00
|
|
|
if sys.version_info[:2] >= (3, 11):
|
2023-03-05 09:25:47 -06:00
|
|
|
from contextlib import chdir
|
2023-08-10 04:20:48 -05:00
|
|
|
else:
|
2023-03-05 09:25:47 -06:00
|
|
|
from sphinx.util.osutil import _chdir as chdir
|
2010-06-07 07:04:16 -05:00
|
|
|
|
2023-08-10 04:20:48 -05:00
|
|
|
_MSGID_PATTERN = re.compile(r'msgid "(.*)"')
|
|
|
|
|
|
|
|
|
|
|
|
def msgid_getter(msgid):
|
|
|
|
if m := _MSGID_PATTERN.search(msgid):
|
|
|
|
return m[1]
|
|
|
|
return None
|
|
|
|
|
2014-09-21 11:36:27 -05:00
|
|
|
|
2022-05-22 10:37:45 -05:00
|
|
|
def test_Catalog_duplicated_message():
|
|
|
|
catalog = Catalog()
|
|
|
|
catalog.add('hello', MsgOrigin('/path/to/filename', 1))
|
|
|
|
catalog.add('hello', MsgOrigin('/path/to/filename', 1))
|
|
|
|
catalog.add('hello', MsgOrigin('/path/to/filename', 2))
|
|
|
|
catalog.add('hello', MsgOrigin('/path/to/yetanother', 1))
|
|
|
|
catalog.add('world', MsgOrigin('/path/to/filename', 1))
|
|
|
|
|
|
|
|
assert len(list(catalog)) == 2
|
|
|
|
|
|
|
|
msg1, msg2 = list(catalog)
|
|
|
|
assert msg1.text == 'hello'
|
|
|
|
assert msg1.locations == [('/path/to/filename', 1),
|
|
|
|
('/path/to/filename', 2),
|
|
|
|
('/path/to/yetanother', 1)]
|
|
|
|
assert msg2.text == 'world'
|
|
|
|
assert msg2.locations == [('/path/to/filename', 1)]
|
|
|
|
|
|
|
|
|
2017-01-06 09:46:26 -06:00
|
|
|
@pytest.mark.sphinx('gettext', srcdir='root-gettext')
|
|
|
|
def test_build_gettext(app):
|
2010-11-14 12:42:50 -06:00
|
|
|
# Generic build; should fail only when the builder is horribly broken.
|
2024-01-16 20:38:46 -06:00
|
|
|
app.build(force_all=True)
|
2010-06-07 07:04:16 -05:00
|
|
|
|
2010-11-14 12:42:50 -06:00
|
|
|
# Do messages end up in the correct location?
|
|
|
|
# top-level documents end up in a message catalog
|
2023-07-27 18:39:12 -05:00
|
|
|
assert (app.outdir / 'extapi.pot').is_file()
|
2010-11-14 12:42:50 -06:00
|
|
|
# directory items are grouped into sections
|
2023-07-27 18:39:12 -05:00
|
|
|
assert (app.outdir / 'subdir.pot').is_file()
|
2010-06-08 23:46:30 -05:00
|
|
|
|
2012-12-16 14:21:37 -06:00
|
|
|
# regression test for issue #960
|
2022-04-26 21:04:19 -05:00
|
|
|
catalog = (app.outdir / 'markup.pot').read_text(encoding='utf8')
|
2017-01-06 09:46:26 -06:00
|
|
|
assert 'msgid "something, something else, something more"' in catalog
|
2010-06-17 04:46:49 -05:00
|
|
|
|
2017-01-06 09:46:26 -06:00
|
|
|
|
|
|
|
@pytest.mark.sphinx('gettext', srcdir='root-gettext')
|
|
|
|
def test_msgfmt(app):
|
2024-01-16 20:38:46 -06:00
|
|
|
app.build(force_all=True)
|
2023-08-10 04:20:48 -05:00
|
|
|
|
2023-07-27 18:39:12 -05:00
|
|
|
(app.outdir / 'en' / 'LC_MESSAGES').mkdir(parents=True, exist_ok=True)
|
2023-03-05 09:25:47 -06:00
|
|
|
with chdir(app.outdir):
|
2010-06-08 23:46:30 -05:00
|
|
|
try:
|
2019-01-12 05:14:26 -06:00
|
|
|
args = ['msginit', '--no-translator', '-i', 'markup.pot', '--locale', 'en_US']
|
2022-10-17 09:54:59 -05:00
|
|
|
subprocess.run(args, capture_output=True, check=True)
|
2010-06-08 23:46:30 -05:00
|
|
|
except OSError:
|
2017-01-06 09:46:26 -06:00
|
|
|
pytest.skip() # most likely msginit was not found
|
2019-01-12 05:14:26 -06:00
|
|
|
except CalledProcessError as exc:
|
|
|
|
print(exc.stdout)
|
|
|
|
print(exc.stderr)
|
2023-08-13 14:07:28 -05:00
|
|
|
msg = f'msginit exited with return code {exc.returncode}'
|
|
|
|
raise AssertionError(msg) from exc
|
2019-01-12 05:14:26 -06:00
|
|
|
|
2023-07-27 18:39:12 -05:00
|
|
|
assert (app.outdir / 'en_US.po').is_file(), 'msginit failed'
|
2010-06-08 23:54:59 -05:00
|
|
|
try:
|
2019-06-30 00:55:22 -05:00
|
|
|
args = ['msgfmt', 'en_US.po',
|
|
|
|
'-o', os.path.join('en', 'LC_MESSAGES', 'test_root.mo')]
|
2022-10-17 09:54:59 -05:00
|
|
|
subprocess.run(args, capture_output=True, check=True)
|
2010-06-08 23:54:59 -05:00
|
|
|
except OSError:
|
2017-01-06 09:46:26 -06:00
|
|
|
pytest.skip() # most likely msgfmt was not found
|
2019-01-12 05:14:26 -06:00
|
|
|
except CalledProcessError as exc:
|
|
|
|
print(exc.stdout)
|
|
|
|
print(exc.stderr)
|
2023-08-13 14:07:28 -05:00
|
|
|
msg = f'msgfmt exited with return code {exc.returncode}'
|
|
|
|
raise AssertionError(msg) from exc
|
2019-01-12 05:14:26 -06:00
|
|
|
|
2017-01-06 09:46:26 -06:00
|
|
|
mo = app.outdir / 'en' / 'LC_MESSAGES' / 'test_root.mo'
|
2023-07-27 18:39:12 -05:00
|
|
|
assert mo.is_file(), 'msgfmt failed'
|
2010-06-22 23:18:47 -05:00
|
|
|
|
2010-08-15 05:30:13 -05:00
|
|
|
_ = gettext.translation('test_root', app.outdir, languages=['en']).gettext
|
2018-12-15 08:02:28 -06:00
|
|
|
assert _("Testing various markup") == "Testing various markup"
|
2013-01-05 08:38:21 -06:00
|
|
|
|
|
|
|
|
2017-01-05 10:14:47 -06:00
|
|
|
@pytest.mark.sphinx(
|
|
|
|
'gettext', testroot='intl', srcdir='gettext',
|
|
|
|
confoverrides={'gettext_compact': False})
|
2017-01-06 09:46:26 -06:00
|
|
|
def test_gettext_index_entries(app):
|
2013-01-05 08:38:21 -06:00
|
|
|
# regression test for #976
|
2024-01-16 20:38:46 -06:00
|
|
|
app.build(filenames=[app.srcdir / 'index_entries.txt'])
|
2013-01-05 08:38:21 -06:00
|
|
|
|
2022-04-26 21:04:19 -05:00
|
|
|
pot = (app.outdir / 'index_entries.pot').read_text(encoding='utf8')
|
2023-08-10 04:20:48 -05:00
|
|
|
msg_ids = list(filter(None, map(msgid_getter, pot.splitlines())))
|
2013-01-05 08:38:21 -06:00
|
|
|
|
2023-08-10 04:20:48 -05:00
|
|
|
assert msg_ids == [
|
2013-01-05 08:38:21 -06:00
|
|
|
"i18n with index entries",
|
|
|
|
"index target section",
|
|
|
|
"this is :index:`Newsletter` target paragraph.",
|
|
|
|
"various index entries",
|
|
|
|
"That's all.",
|
|
|
|
"Mailing List",
|
|
|
|
"Newsletter",
|
|
|
|
"Recipients List",
|
|
|
|
"First",
|
|
|
|
"Second",
|
|
|
|
"Third",
|
|
|
|
"Entry",
|
|
|
|
"See",
|
2016-06-11 10:00:52 -05:00
|
|
|
]
|
2014-09-28 07:19:54 -05:00
|
|
|
|
|
|
|
|
2017-01-05 10:14:47 -06:00
|
|
|
@pytest.mark.sphinx(
|
|
|
|
'gettext', testroot='intl', srcdir='gettext',
|
2017-01-06 09:46:26 -06:00
|
|
|
confoverrides={'gettext_compact': False,
|
|
|
|
'gettext_additional_targets': []})
|
|
|
|
def test_gettext_disable_index_entries(app):
|
2014-09-28 07:19:54 -05:00
|
|
|
# regression test for #976
|
2023-01-03 22:22:20 -06:00
|
|
|
app.env._pickled_doctree_cache.clear() # clear cache
|
2024-01-16 20:38:46 -06:00
|
|
|
app.build(filenames=[app.srcdir / 'index_entries.txt'])
|
2014-09-28 07:19:54 -05:00
|
|
|
|
2022-04-26 21:04:19 -05:00
|
|
|
pot = (app.outdir / 'index_entries.pot').read_text(encoding='utf8')
|
2023-08-10 04:20:48 -05:00
|
|
|
msg_ids = list(filter(None, map(msgid_getter, pot.splitlines())))
|
2014-09-28 07:19:54 -05:00
|
|
|
|
2023-08-10 04:20:48 -05:00
|
|
|
assert msg_ids == [
|
2014-09-28 07:19:54 -05:00
|
|
|
"i18n with index entries",
|
|
|
|
"index target section",
|
|
|
|
"this is :index:`Newsletter` target paragraph.",
|
|
|
|
"various index entries",
|
|
|
|
"That's all.",
|
2013-01-05 08:38:21 -06:00
|
|
|
]
|
2013-03-10 08:07:31 -05:00
|
|
|
|
|
|
|
|
2017-01-05 10:14:47 -06:00
|
|
|
@pytest.mark.sphinx('gettext', testroot='intl', srcdir='gettext')
|
2017-01-06 09:46:26 -06:00
|
|
|
def test_gettext_template(app):
|
2024-01-16 20:38:46 -06:00
|
|
|
app.build(force_all=True)
|
2023-08-10 04:20:48 -05:00
|
|
|
|
2023-07-27 18:39:12 -05:00
|
|
|
assert (app.outdir / 'sphinx.pot').is_file()
|
2013-03-10 08:07:31 -05:00
|
|
|
|
2022-04-26 21:04:19 -05:00
|
|
|
result = (app.outdir / 'sphinx.pot').read_text(encoding='utf8')
|
2013-03-10 08:07:31 -05:00
|
|
|
assert "Welcome" in result
|
|
|
|
assert "Sphinx %(version)s" in result
|
2018-02-17 18:05:32 -06:00
|
|
|
|
|
|
|
|
2018-02-18 18:51:30 -06:00
|
|
|
@pytest.mark.sphinx('gettext', testroot='gettext-template')
|
2018-02-17 18:05:32 -06:00
|
|
|
def test_gettext_template_msgid_order_in_sphinxpot(app):
|
2024-01-16 20:38:46 -06:00
|
|
|
app.build(force_all=True)
|
2023-07-27 18:39:12 -05:00
|
|
|
assert (app.outdir / 'sphinx.pot').is_file()
|
2018-02-17 18:05:32 -06:00
|
|
|
|
2022-04-26 21:04:19 -05:00
|
|
|
result = (app.outdir / 'sphinx.pot').read_text(encoding='utf8')
|
2018-02-17 18:05:32 -06:00
|
|
|
assert re.search(
|
|
|
|
('msgid "Template 1".*'
|
2018-07-28 06:19:30 -05:00
|
|
|
'msgid "This is Template 1\\.".*'
|
2018-02-17 18:05:32 -06:00
|
|
|
'msgid "Template 2".*'
|
2018-07-28 06:19:30 -05:00
|
|
|
'msgid "This is Template 2\\.".*'),
|
2018-02-17 18:05:32 -06:00
|
|
|
result,
|
2023-08-10 04:20:48 -05:00
|
|
|
flags=re.DOTALL)
|
2020-08-06 02:18:36 -05:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.sphinx(
|
|
|
|
'gettext', srcdir='root-gettext',
|
|
|
|
confoverrides={'gettext_compact': 'documentation'})
|
|
|
|
def test_build_single_pot(app):
|
2024-01-16 20:38:46 -06:00
|
|
|
app.build(force_all=True)
|
2020-08-06 02:18:36 -05:00
|
|
|
|
2023-07-27 18:39:12 -05:00
|
|
|
assert (app.outdir / 'documentation.pot').is_file()
|
2020-08-06 02:18:36 -05:00
|
|
|
|
2022-04-26 21:04:19 -05:00
|
|
|
result = (app.outdir / 'documentation.pot').read_text(encoding='utf8')
|
2020-08-06 02:18:36 -05:00
|
|
|
assert re.search(
|
|
|
|
('msgid "Todo".*'
|
|
|
|
'msgid "Like footnotes.".*'
|
|
|
|
'msgid "The minute.".*'
|
|
|
|
'msgid "Generated section".*'),
|
|
|
|
result,
|
2023-08-10 04:20:48 -05:00
|
|
|
flags=re.DOTALL)
|
2023-08-10 04:01:25 -05:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.sphinx(
|
|
|
|
'gettext',
|
|
|
|
testroot='intl_substitution_definitions',
|
|
|
|
srcdir='gettext-subst',
|
|
|
|
confoverrides={'gettext_compact': False,
|
|
|
|
'gettext_additional_targets': ['image']})
|
|
|
|
def test_gettext_prolog_epilog_substitution(app):
|
2024-01-16 20:38:46 -06:00
|
|
|
app.build(force_all=True)
|
2023-08-10 04:01:25 -05:00
|
|
|
|
|
|
|
assert (app.outdir / 'prolog_epilog_substitution.pot').is_file()
|
|
|
|
pot = (app.outdir / 'prolog_epilog_substitution.pot').read_text(encoding='utf8')
|
|
|
|
msg_ids = list(filter(None, map(msgid_getter, pot.splitlines())))
|
2023-08-10 04:20:48 -05:00
|
|
|
|
2023-08-10 04:01:25 -05:00
|
|
|
assert msg_ids == [
|
|
|
|
"i18n with prologue and epilogue substitutions",
|
|
|
|
"This is content that contains |subst_prolog_1|.",
|
|
|
|
"Substituted image |subst_prolog_2| here.",
|
|
|
|
"subst_prolog_2",
|
|
|
|
".. image:: /img.png",
|
|
|
|
"This is content that contains |subst_epilog_1|.",
|
|
|
|
"Substituted image |subst_epilog_2| here.",
|
|
|
|
"subst_epilog_2",
|
|
|
|
".. image:: /i18n.png",
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.sphinx(
|
|
|
|
'gettext',
|
|
|
|
testroot='intl_substitution_definitions',
|
|
|
|
srcdir='gettext-subst',
|
|
|
|
confoverrides={'gettext_compact': False,
|
|
|
|
'gettext_additional_targets': ['image']})
|
|
|
|
def test_gettext_prolog_epilog_substitution_excluded(app):
|
|
|
|
# regression test for #9428
|
2024-01-16 20:38:46 -06:00
|
|
|
app.build(force_all=True)
|
2023-08-10 04:01:25 -05:00
|
|
|
|
|
|
|
assert (app.outdir / 'prolog_epilog_substitution_excluded.pot').is_file()
|
|
|
|
pot = (app.outdir / 'prolog_epilog_substitution_excluded.pot').read_text(encoding='utf8')
|
2023-08-10 04:20:48 -05:00
|
|
|
msg_ids = list(filter(None, map(msgid_getter, pot.splitlines())))
|
2023-08-10 04:01:25 -05:00
|
|
|
|
2023-08-10 04:20:48 -05:00
|
|
|
assert msg_ids == [
|
2023-08-10 04:01:25 -05:00
|
|
|
"i18n without prologue and epilogue substitutions",
|
|
|
|
"This is content that does not include prologue and epilogue substitutions.",
|
|
|
|
]
|