Skip to content

Commit ef259ff

Browse files
authored
Support no obsolete option (#65)
* tests: Sanity check line-width option Provide a unit test to validate the usage of the `--line-width` option. Signed-off-by: James Knight <[email protected]> * Adjust catalog commands to support forwarding options to babel The following tweaks the catalog wrapper commands used to call babel's `pofile`/`mofile` functions to support forwarding any keyword argument. This can provide flexibility to callers which may wish to utilize additional options provided by babel, without needing to add an explicit option in the catalog wrapper calls. A compatibility adjustment was added to `dump_po` to help map an original argument `line_width` to babel's `width` argument. This is to ensure callers which still use the `line_width` argument can appropriately configure the babel call to impose the provided width. Signed-off-by: James Knight <[email protected]> * Correct docstring spelling Signed-off-by: James Knight <[email protected]> * Provide no-obsolete option Adds support for a `--no-obsolete` option to allow the automatic exclusion of obsolete messages (`#~ `) from updated sources. This utilizes babel's `ignore_obsolete` option to not produce obsolete in a final pot file. The `--no-obsolete` argument was chosen to mimic the same argument naming as seen in `msgattrib` [1]. [1]: https://www.gnu.org/software/gettext/manual/html_node/msgattrib-Invocation.html Signed-off-by: James Knight <[email protected]> * tests: Validate newly added no-obsolete option Signed-off-by: James Knight <[email protected]> --------- Signed-off-by: James Knight <[email protected]>
1 parent a1aa801 commit ef259ff

File tree

4 files changed

+113
-13
lines changed

4 files changed

+113
-13
lines changed

sphinx_intl/basic.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ def get_lang_dirs(path):
2222
# ==================================
2323
# commands
2424

25-
def update(locale_dir, pot_dir, languages, line_width=76):
25+
def update(locale_dir, pot_dir, languages, line_width=76, ignore_obsolete=False):
2626
"""
2727
Update specified language's po files from pot.
2828
2929
:param unicode locale_dir: path for locale directory
3030
:param unicode pot_dir: path for pot directory
3131
:param tuple languages: languages to update po files
32-
:param number line_width: maximum line wdith of po files
32+
:param number line_width: maximum line width of po files
33+
:param bool ignore_obsolete: ignore obsolete entries in po files
3334
:return: {'create': 0, 'update': 0, 'notchanged': 0}
3435
:rtype: dict
3536
"""
@@ -61,15 +62,17 @@ def update(locale_dir, pot_dir, languages, line_width=76):
6162
status['update'] += 1
6263
click.echo('Update: {0} +{1}, -{2}'.format(
6364
po_file, len(added), len(deleted)))
64-
c.dump_po(po_file, cat, line_width)
65+
c.dump_po(po_file, cat, width=line_width,
66+
ignore_obsolete=ignore_obsolete)
6567
else:
6668
status['notchanged'] += 1
6769
click.echo('Not Changed: {0}'.format(po_file))
6870
else: # new po file
6971
status['create'] += 1
7072
click.echo('Create: {0}'.format(po_file))
7173
cat_pot.locale = lang
72-
c.dump_po(po_file, cat_pot, line_width)
74+
c.dump_po(po_file, cat_pot, width=line_width,
75+
ignore_obsolete=ignore_obsolete)
7376

7477
return status
7578

sphinx_intl/catalog.py

+17-7
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
from babel.messages import pofile, mofile
77

88

9-
def load_po(filename):
9+
def load_po(filename, **kwargs):
1010
"""read po/pot file and return catalog object
1111
1212
:param unicode filename: path to po/pot file
13+
:param kwargs: keyword arguments to forward to babel's read_po call
1314
:return: catalog object
1415
"""
1516
# pre-read to get charset
@@ -20,27 +21,36 @@ def load_po(filename):
2021
# To decode lines by babel, read po file as binary mode and specify charset for
2122
# read_po function.
2223
with io.open(filename, 'rb') as f: # FIXME: encoding VS charset
23-
return pofile.read_po(f, charset=charset)
24+
return pofile.read_po(f, charset=charset, **kwargs)
2425

2526

26-
def dump_po(filename, catalog, line_width=76):
27+
def dump_po(filename, catalog, **kwargs):
2728
"""write po/pot file from catalog object
2829
2930
:param unicode filename: path to po file
3031
:param catalog: catalog object
31-
:param line_width: maximum line wdith of po files
32+
:param kwargs: keyword arguments to forward to babel's write_po call; also
33+
accepts a deprecated `line_width` option to forward to
34+
write_po's `width` option
3235
:return: None
3336
"""
3437
dirname = os.path.dirname(filename)
3538
if not os.path.exists(dirname):
3639
os.makedirs(dirname)
3740

41+
# (compatibility) line_width was the original argument used to forward
42+
# line width hints into write_po's `width` argument; if provided,
43+
# set/override the width value
44+
if 'line_width' in kwargs:
45+
kwargs['width'] = kwargs['line_width']
46+
del kwargs['line_width']
47+
3848
# Because babel automatically encode strings, file should be open as binary mode.
3949
with io.open(filename, 'wb') as f:
40-
pofile.write_po(f, catalog, line_width)
50+
pofile.write_po(f, catalog, **kwargs)
4151

4252

43-
def write_mo(filename, catalog):
53+
def write_mo(filename, catalog, **kwargs):
4454
"""write mo file from catalog object
4555
4656
:param unicode filename: path to mo file
@@ -51,7 +61,7 @@ def write_mo(filename, catalog):
5161
if not os.path.exists(dirname):
5262
os.makedirs(dirname)
5363
with io.open(filename, 'wb') as f:
54-
mofile.write_mo(f, catalog)
64+
mofile.write_mo(f, catalog, **kwargs)
5565

5666

5767
def translated_entries(catalog):

sphinx_intl/commands.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ def convert(self, value, param, ctx):
131131
help='The maximum line width for the po files, 0 or a negative number '
132132
'disable line wrapping')
133133

134+
option_no_obsolete = click.option(
135+
'--no-obsolete',
136+
envvar=ENVVAR_PREFIX + '_NO_OBSOLETE',
137+
is_flag=True, default=False,
138+
help='Remove obsolete #~ messages.')
139+
134140
option_transifex_token = click.option(
135141
'--transifex-token',
136142
envvar=ENVVAR_PREFIX + '_TRANSIFEX_TOKEN',
@@ -221,7 +227,8 @@ def main(ctx, config, tag):
221227
@option_pot_dir
222228
@option_language
223229
@option_line_width
224-
def update(locale_dir, pot_dir, language, line_width):
230+
@option_no_obsolete
231+
def update(locale_dir, pot_dir, language, line_width, no_obsolete):
225232
"""
226233
Update specified language's po files from pot.
227234
@@ -247,7 +254,7 @@ def update(locale_dir, pot_dir, language, line_width):
247254
% locals())
248255
raise click.BadParameter(msg, param_hint='language')
249256

250-
basic.update(locale_dir, pot_dir, languages, line_width)
257+
basic.update(locale_dir, pot_dir, languages, line_width, ignore_obsolete=no_obsolete)
251258

252259

253260
@main.command()

tests/test_cmd_pot.py

+80
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
:copyright: Copyright 2019 by Takayuki SHIMIZUKAWA.
99
:license: BSD, see LICENSE for details.
1010
"""
11+
12+
import os
13+
1114
from click.testing import CliRunner
1215

1316
from sphinx_intl import commands
@@ -67,6 +70,83 @@ def test_update_difference_detect(temp):
6770
assert r4.output.count('Not Changed:') == 1
6871

6972

73+
def test_update_line_width(temp):
74+
with open('_build/locale/README.pot', 'r') as f:
75+
template = f.read()
76+
77+
with open('_build/locale/README.pot', 'w') as f:
78+
f.write(template)
79+
f.write('\nmsgid "foorbar identifier1"\nmsgstr ""\n')
80+
81+
po_dir = os.path.join('locale', 'ja', 'LC_MESSAGES')
82+
po_file = os.path.join(po_dir, 'README.po')
83+
84+
r1 = runner.invoke(commands.update, ['-d', 'locale', '-p', '_build/locale', '-l', 'ja'])
85+
assert r1.exit_code == 0
86+
87+
with open(po_file, 'r') as f:
88+
contents = f.read()
89+
assert '"foorbar identifier1"\n' in contents
90+
91+
# change the identifier to trigger an update and impose a lower line-width count
92+
with open('_build/locale/README.pot', 'w') as f:
93+
f.write(template)
94+
f.write('\nmsgid "foorbar identifier2"\nmsgstr ""\n')
95+
96+
r2 = runner.invoke(commands.update, ['-d', 'locale', '-p', '_build/locale', '-w', '1'])
97+
assert r2.exit_code == 0
98+
99+
with open(po_file, 'r') as f:
100+
contents = f.read()
101+
assert '"foorbar"\n' in contents
102+
assert '"identifier2"\n' in contents
103+
104+
105+
def test_update_no_obsolete(temp):
106+
with open('_build/locale/README.pot', 'r') as f:
107+
template = f.read()
108+
109+
with open('_build/locale/README.pot', 'w') as f:
110+
f.write(template)
111+
f.write('\nmsgid "foorbar1"\nmsgstr ""\n')
112+
f.write('\nmsgid "foorbar2"\nmsgstr ""\n')
113+
114+
po_dir = os.path.join('locale', 'ja', 'LC_MESSAGES')
115+
po_file = os.path.join(po_dir, 'README.po')
116+
117+
r1 = runner.invoke(commands.update, ['-d', 'locale', '-p', '_build/locale', '-l', 'ja'])
118+
assert r1.exit_code == 0
119+
120+
with open(po_file, 'r') as f:
121+
contents = f.read()
122+
assert '\nmsgid "foorbar1"\n' in contents
123+
assert '\nmsgid "foorbar2"\n' in contents
124+
125+
# remove the foorbar2 and verify we can see the obsolete entry
126+
with open('_build/locale/README.pot', 'w') as f:
127+
f.write(template)
128+
f.write('\nmsgid "foorbar1"\nmsgstr ""\n')
129+
130+
r2 = runner.invoke(commands.update, ['-d', 'locale', '-p', '_build/locale'])
131+
assert r2.exit_code == 0
132+
133+
with open(po_file, 'r') as f:
134+
contents = f.read()
135+
assert '\n#~ msgid "foorbar2"\n' in contents
136+
137+
# remove the foorbar1 and verify we can no longer see any obsolete entry
138+
with open('_build/locale/README.pot', 'w') as f:
139+
f.write(template)
140+
141+
r3 = runner.invoke(commands.update, ['-d', 'locale', '-p', '_build/locale', '--no-obsolete'])
142+
assert r3.exit_code == 0
143+
144+
with open(po_file, 'r') as f:
145+
contents = f.read()
146+
assert 'msgid "foorbar1"' not in contents
147+
assert 'msgid "foorbar2"' not in contents
148+
149+
70150
def test_stat(temp):
71151
r1 = runner.invoke(commands.update, ['-d', 'locale', '-p', '_build/locale', '-l', 'ja'])
72152
assert r1.exit_code == 0

0 commit comments

Comments
 (0)