diff --git a/tests/messages/consts.py b/tests/messages/consts.py index f9e796531..98c9cc05a 100644 --- a/tests/messages/consts.py +++ b/tests/messages/consts.py @@ -9,7 +9,6 @@ data_dir = os.path.join(this_dir, 'data') project_dir = os.path.join(data_dir, 'project') i18n_dir = os.path.join(project_dir, 'i18n') -pot_file = os.path.join(i18n_dir, 'temp.pot') def get_po_file_path(locale): diff --git a/tests/messages/frontend/conftest.py b/tests/messages/frontend/conftest.py new file mode 100644 index 000000000..d309255c0 --- /dev/null +++ b/tests/messages/frontend/conftest.py @@ -0,0 +1,9 @@ +import pathlib +import time + +import pytest + + +@pytest.fixture +def pot_file(tmp_path) -> pathlib.Path: + return tmp_path / f'po-{time.time()}.pot' diff --git a/tests/messages/frontend/test_cli.py b/tests/messages/frontend/test_cli.py index 4fea01b22..9eb2c4cd0 100644 --- a/tests/messages/frontend/test_cli.py +++ b/tests/messages/frontend/test_cli.py @@ -17,7 +17,6 @@ import shutil import sys import time -import unittest from datetime import datetime, timedelta from io import StringIO @@ -30,119 +29,105 @@ from babel.messages.frontend import BaseError from babel.messages.pofile import read_po, write_po from babel.util import LOCALTZ -from tests.messages.consts import data_dir, get_po_file_path, i18n_dir, pot_file, this_dir - - -class CommandLineInterfaceTestCase(unittest.TestCase): - - def setUp(self): - data_dir = os.path.join(this_dir, 'data') - self.orig_working_dir = os.getcwd() - self.orig_argv = sys.argv - self.orig_stdout = sys.stdout - self.orig_stderr = sys.stderr - sys.argv = ['pybabel'] - sys.stdout = StringIO() - sys.stderr = StringIO() - os.chdir(data_dir) - - self._remove_log_handlers() - self.cli = frontend.CommandLineInterface() - - def tearDown(self): - os.chdir(self.orig_working_dir) - sys.argv = self.orig_argv - sys.stdout = self.orig_stdout - sys.stderr = self.orig_stderr - for dirname in ['lv_LV', 'ja_JP']: - locale_dir = os.path.join(i18n_dir, dirname) - if os.path.isdir(locale_dir): - shutil.rmtree(locale_dir) - self._remove_log_handlers() - - def _remove_log_handlers(self): - # Logging handlers will be reused if possible (#227). This breaks the - # implicit assumption that our newly created StringIO for sys.stderr - # contains the console output. Removing the old handler ensures that a - # new handler with our new StringIO instance will be used. - log = logging.getLogger('babel') - for handler in log.handlers: - log.removeHandler(handler) - - def test_usage(self): - try: - self.cli.run(sys.argv) - self.fail('Expected SystemExit') - except SystemExit as e: - assert e.code == 2 - assert sys.stderr.getvalue().lower() == """\ +from tests.messages.consts import data_dir, get_po_file_path, i18n_dir + + +@pytest.fixture +def cli(monkeypatch, capsys): + monkeypatch.chdir(data_dir) + monkeypatch.setattr(sys, 'argv', ['pybabel']) + _remove_log_handlers() + yield frontend.CommandLineInterface() + for dirname in ['lv_LV', 'ja_JP']: + locale_dir = os.path.join(i18n_dir, dirname) + if os.path.isdir(locale_dir): + shutil.rmtree(locale_dir) + _remove_log_handlers() + + +def _remove_log_handlers(): + # Logging handlers will be reused if possible (#227). This breaks the + # implicit assumption that our newly created StringIO for sys.stderr + # contains the console output. Removing the old handler ensures that a + # new handler with our new StringIO instance will be used. + log = logging.getLogger('babel') + for handler in log.handlers: + log.removeHandler(handler) + + +def test_usage(cli): + with pytest.raises(SystemExit) as ei: + cli.run(["pybabel"]) + assert ei.value.code == 2 + assert sys.stderr.getvalue().lower() == """\ usage: pybabel command [options] [args] pybabel: error: no valid command or option passed. try the -h/--help option for more information. """ - def test_list_locales(self): - """ - Test the command with the --list-locales arg. - """ - result = self.cli.run(sys.argv + ['--list-locales']) - assert not result - output = sys.stdout.getvalue() - assert 'fr_CH' in output - assert 'French (Switzerland)' in output - assert "\nb'" not in output # No bytes repr markers in output - - def _run_init_catalog(self): - i18n_dir = os.path.join(data_dir, 'project', 'i18n') - pot_path = os.path.join(data_dir, 'project', 'i18n', 'messages.pot') - init_argv = sys.argv + ['init', '--locale', 'en_US', '-d', i18n_dir, - '-i', pot_path] - self.cli.run(init_argv) - - def test_no_duplicated_output_for_multiple_runs(self): - self._run_init_catalog() - first_output = sys.stderr.getvalue() - self._run_init_catalog() - second_output = sys.stderr.getvalue()[len(first_output):] - - # in case the log message is not duplicated we should get the same - # output as before - assert first_output == second_output - - def test_frontend_can_log_to_predefined_handler(self): - custom_stream = StringIO() - log = logging.getLogger('babel') - log.addHandler(logging.StreamHandler(custom_stream)) - - self._run_init_catalog() - assert id(sys.stderr) != id(custom_stream) - assert not sys.stderr.getvalue() - assert custom_stream.getvalue() - - def test_help(self): - try: - self.cli.run(sys.argv + ['--help']) - self.fail('Expected SystemExit') - except SystemExit as e: - assert not e.code - content = sys.stdout.getvalue().lower() - assert 'options:' in content - assert all(command in content for command in ('init', 'update', 'compile', 'extract')) - - def assert_pot_file_exists(self): - assert os.path.isfile(pot_file) - - @freeze_time("1994-11-11") - def test_extract_with_default_mapping(self): - self.cli.run(sys.argv + ['extract', - '--copyright-holder', 'FooBar, Inc.', - '--project', 'TestProject', '--version', '0.1', - '--msgid-bugs-address', 'bugs.address@email.tld', - '-c', 'TRANSLATOR', '-c', 'TRANSLATORS:', - '-o', pot_file, 'project']) - self.assert_pot_file_exists() - date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') - expected_content = fr"""# Translations template for TestProject. + +def test_list_locales(cli): + """ + Test the command with the --list-locales arg. + """ + result = cli.run(['pybabel', '--list-locales']) + assert not result + output = sys.stdout.getvalue() + assert 'fr_CH' in output + assert 'French (Switzerland)' in output + assert "\nb'" not in output # No bytes repr markers in output + + +def _run_init_catalog(cli): + i18n_dir = os.path.join(data_dir, 'project', 'i18n') + pot_path = os.path.join(data_dir, 'project', 'i18n', 'messages.pot') + cli.run(['pybabel', 'init', '--locale', 'en_US', '-d', i18n_dir, '-i', pot_path]) + + +def test_no_duplicated_output_for_multiple_runs(cli): + _run_init_catalog(cli) + first_output = sys.stderr.getvalue() + _run_init_catalog(cli) + second_output = sys.stderr.getvalue()[len(first_output):] + + # in case the log message is not duplicated we should get the same + # output as before + assert first_output == second_output + + +def test_frontend_can_log_to_predefined_handler(cli): + custom_stream = StringIO() + log = logging.getLogger('babel') + log.addHandler(logging.StreamHandler(custom_stream)) + + _run_init_catalog(cli) + assert id(sys.stderr) != id(custom_stream) + assert not sys.stderr.getvalue() + assert custom_stream.getvalue() + + +def test_help(cli): + with pytest.raises(SystemExit) as ei: + cli.run(['pybabel', '--help']) + assert not ei.value.code + content = sys.stdout.getvalue().lower() + assert 'options:' in content + assert all(command in content for command in ('init', 'update', 'compile', 'extract')) + + +@freeze_time("1994-11-11") +def test_extract_with_default_mapping(cli, pot_file): + cli.run([ + 'pybabel', + 'extract', + '--copyright-holder', 'FooBar, Inc.', + '--project', 'TestProject', '--version', '0.1', + '--msgid-bugs-address', 'bugs.address@email.tld', + '-c', 'TRANSLATOR', '-c', 'TRANSLATORS:', + '-o', pot_file, 'project', + ]) + date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') + expected_content = fr"""# Translations template for TestProject. # Copyright (C) {time.strftime('%Y')} FooBar, Inc. # This file is distributed under the same license as the TestProject # project. @@ -181,22 +166,23 @@ def test_extract_with_default_mapping(self): msgstr[1] "" """ - with open(pot_file) as f: - actual_content = f.read() - assert expected_content == actual_content - - @freeze_time("1994-11-11") - def test_extract_with_mapping_file(self): - self.cli.run(sys.argv + ['extract', - '--copyright-holder', 'FooBar, Inc.', - '--project', 'TestProject', '--version', '0.1', - '--msgid-bugs-address', 'bugs.address@email.tld', - '--mapping', os.path.join(data_dir, 'mapping.cfg'), - '-c', 'TRANSLATOR', '-c', 'TRANSLATORS:', - '-o', pot_file, 'project']) - self.assert_pot_file_exists() - date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') - expected_content = fr"""# Translations template for TestProject. + assert expected_content == pot_file.read_text() + + +@freeze_time("1994-11-11") +def test_extract_with_mapping_file(cli, pot_file): + cli.run([ + 'pybabel', + 'extract', + '--copyright-holder', 'FooBar, Inc.', + '--project', 'TestProject', '--version', '0.1', + '--msgid-bugs-address', 'bugs.address@email.tld', + '--mapping', os.path.join(data_dir, 'mapping.cfg'), + '-c', 'TRANSLATOR', '-c', 'TRANSLATORS:', + '-o', pot_file, 'project', + ]) + date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') + expected_content = fr"""# Translations template for TestProject. # Copyright (C) {time.strftime('%Y')} FooBar, Inc. # This file is distributed under the same license as the TestProject # project. @@ -229,26 +215,27 @@ def test_extract_with_mapping_file(self): msgstr[1] "" """ - with open(pot_file) as f: - actual_content = f.read() - assert expected_content == actual_content - - @freeze_time("1994-11-11") - def test_extract_with_exact_file(self): - """Tests that we can call extract with a particular file and only - strings from that file get extracted. (Note the absence of strings from file1.py) - """ - file_to_extract = os.path.join(data_dir, 'project', 'file2.py') - self.cli.run(sys.argv + ['extract', - '--copyright-holder', 'FooBar, Inc.', - '--project', 'TestProject', '--version', '0.1', - '--msgid-bugs-address', 'bugs.address@email.tld', - '--mapping', os.path.join(data_dir, 'mapping.cfg'), - '-c', 'TRANSLATOR', '-c', 'TRANSLATORS:', - '-o', pot_file, file_to_extract]) - self.assert_pot_file_exists() - date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') - expected_content = fr"""# Translations template for TestProject. + assert expected_content == pot_file.read_text() + + +@freeze_time("1994-11-11") +def test_extract_with_exact_file(cli, pot_file): + """Tests that we can call extract with a particular file and only + strings from that file get extracted. (Note the absence of strings from file1.py) + """ + file_to_extract = os.path.join(data_dir, 'project', 'file2.py') + cli.run([ + 'pybabel', + 'extract', + '--copyright-holder', 'FooBar, Inc.', + '--project', 'TestProject', '--version', '0.1', + '--msgid-bugs-address', 'bugs.address@email.tld', + '--mapping', os.path.join(data_dir, 'mapping.cfg'), + '-c', 'TRANSLATOR', '-c', 'TRANSLATORS:', + '-o', pot_file, file_to_extract, + ]) + date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') + expected_content = fr"""# Translations template for TestProject. # Copyright (C) {time.strftime('%Y')} FooBar, Inc. # This file is distributed under the same license as the TestProject # project. @@ -275,20 +262,21 @@ def test_extract_with_exact_file(self): msgstr[1] "" """ - with open(pot_file) as f: - actual_content = f.read() - assert expected_content == actual_content - - @freeze_time("1994-11-11") - def test_init_with_output_dir(self): - po_file = get_po_file_path('en_US') - self.cli.run(sys.argv + ['init', - '--locale', 'en_US', - '-d', os.path.join(i18n_dir), - '-i', os.path.join(i18n_dir, 'messages.pot')]) - assert os.path.isfile(po_file) - date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') - expected_content = fr"""# English (United States) translations for TestProject. + assert expected_content == pot_file.read_text() + + +@freeze_time("1994-11-11") +def test_init_with_output_dir(cli): + po_file = get_po_file_path('en_US') + cli.run([ + 'pybabel', + 'init', + '--locale', 'en_US', + '-d', os.path.join(i18n_dir), + '-i', os.path.join(i18n_dir, 'messages.pot'), + ]) + date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') + expected_content = fr"""# English (United States) translations for TestProject. # Copyright (C) 2007 FooBar, Inc. # This file is distributed under the same license as the TestProject # project. @@ -322,20 +310,23 @@ def test_init_with_output_dir(self): msgstr[1] "" """ - with open(po_file) as f: - actual_content = f.read() - assert expected_content == actual_content - - @freeze_time("1994-11-11") - def test_init_singular_plural_forms(self): - po_file = get_po_file_path('ja_JP') - self.cli.run(sys.argv + ['init', - '--locale', 'ja_JP', - '-d', os.path.join(i18n_dir), - '-i', os.path.join(i18n_dir, 'messages.pot')]) - assert os.path.isfile(po_file) - date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') - expected_content = fr"""# Japanese (Japan) translations for TestProject. + with open(po_file) as f: + actual_content = f.read() + assert expected_content == actual_content + + +@freeze_time("1994-11-11") +def test_init_singular_plural_forms(cli): + po_file = get_po_file_path('ja_JP') + cli.run([ + 'pybabel', + 'init', + '--locale', 'ja_JP', + '-d', os.path.join(i18n_dir), + '-i', os.path.join(i18n_dir, 'messages.pot'), + ]) + date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') + expected_content = fr"""# Japanese (Japan) translations for TestProject. # Copyright (C) 2007 FooBar, Inc. # This file is distributed under the same license as the TestProject # project. @@ -368,20 +359,23 @@ def test_init_singular_plural_forms(self): msgstr[0] "" """ - with open(po_file) as f: - actual_content = f.read() - assert expected_content == actual_content - - @freeze_time("1994-11-11") - def test_init_more_than_2_plural_forms(self): - po_file = get_po_file_path('lv_LV') - self.cli.run(sys.argv + ['init', - '--locale', 'lv_LV', - '-d', i18n_dir, - '-i', os.path.join(i18n_dir, 'messages.pot')]) - assert os.path.isfile(po_file) - date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') - expected_content = fr"""# Latvian (Latvia) translations for TestProject. + with open(po_file) as f: + actual_content = f.read() + assert expected_content == actual_content + + +@freeze_time("1994-11-11") +def test_init_more_than_2_plural_forms(cli): + po_file = get_po_file_path('lv_LV') + cli.run([ + 'pybabel', + 'init', + '--locale', 'lv_LV', + '-d', i18n_dir, + '-i', os.path.join(i18n_dir, 'messages.pot'), + ]) + date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') + expected_content = fr"""# Latvian (Latvia) translations for TestProject. # Copyright (C) 2007 FooBar, Inc. # This file is distributed under the same license as the TestProject # project. @@ -417,293 +411,239 @@ def test_init_more_than_2_plural_forms(self): msgstr[2] "" """ - with open(po_file) as f: - actual_content = f.read() - assert expected_content == actual_content - - def test_compile_catalog(self): - po_file = get_po_file_path('de_DE') - mo_file = po_file.replace('.po', '.mo') - self.cli.run(sys.argv + ['compile', - '--locale', 'de_DE', - '-d', i18n_dir]) - assert not os.path.isfile(mo_file), f'Expected no file at {mo_file!r}' - assert sys.stderr.getvalue() == f'catalog {po_file} is marked as fuzzy, skipping\n' - - def test_compile_fuzzy_catalog(self): - po_file = get_po_file_path('de_DE') - mo_file = po_file.replace('.po', '.mo') - try: - self.cli.run(sys.argv + ['compile', - '--locale', 'de_DE', '--use-fuzzy', - '-d', i18n_dir]) + with open(po_file) as f: + actual_content = f.read() + assert expected_content == actual_content + + +def test_compile_catalog(cli): + po_file = get_po_file_path('de_DE') + mo_file = po_file.replace('.po', '.mo') + cli.run(['pybabel', 'compile', '--locale', 'de_DE', '-d', i18n_dir]) + assert not os.path.isfile(mo_file), f'Expected no file at {mo_file!r}' + assert sys.stderr.getvalue() == f'catalog {po_file} is marked as fuzzy, skipping\n' + + +def test_compile_fuzzy_catalog(cli): + po_file = get_po_file_path('de_DE') + mo_file = po_file.replace('.po', '.mo') + try: + cli.run(['pybabel', 'compile', '--locale', 'de_DE', '--use-fuzzy', '-d', i18n_dir]) + assert os.path.isfile(mo_file) + assert sys.stderr.getvalue() == f'compiling catalog {po_file} to {mo_file}\n' + finally: + if os.path.isfile(mo_file): + os.unlink(mo_file) + + +def test_compile_catalog_with_more_than_2_plural_forms(cli): + po_file = get_po_file_path('ru_RU') + mo_file = po_file.replace('.po', '.mo') + try: + cli.run(['pybabel', 'compile', '--locale', 'ru_RU', '--use-fuzzy', '-d', i18n_dir]) + assert os.path.isfile(mo_file) + assert sys.stderr.getvalue() == f'compiling catalog {po_file} to {mo_file}\n' + finally: + if os.path.isfile(mo_file): + os.unlink(mo_file) + + +def test_compile_catalog_multidomain(cli): + po_foo = os.path.join(i18n_dir, 'de_DE', 'LC_MESSAGES', 'foo.po') + po_bar = os.path.join(i18n_dir, 'de_DE', 'LC_MESSAGES', 'bar.po') + mo_foo = po_foo.replace('.po', '.mo') + mo_bar = po_bar.replace('.po', '.mo') + try: + cli.run([ + 'pybabel', 'compile', + '--locale', 'de_DE', + '--domain', 'foo bar', + '--use-fuzzy', + '-d', i18n_dir, + ]) + for mo_file in [mo_foo, mo_bar]: assert os.path.isfile(mo_file) - assert sys.stderr.getvalue() == f'compiling catalog {po_file} to {mo_file}\n' - finally: - if os.path.isfile(mo_file): - os.unlink(mo_file) + assert sys.stderr.getvalue() == ( + f'compiling catalog {po_foo} to {mo_foo}\n' + f'compiling catalog {po_bar} to {mo_bar}\n' + ) - def test_compile_catalog_with_more_than_2_plural_forms(self): - po_file = get_po_file_path('ru_RU') - mo_file = po_file.replace('.po', '.mo') - try: - self.cli.run(sys.argv + ['compile', - '--locale', 'ru_RU', '--use-fuzzy', - '-d', i18n_dir]) - assert os.path.isfile(mo_file) - assert sys.stderr.getvalue() == f'compiling catalog {po_file} to {mo_file}\n' - finally: + finally: + for mo_file in [mo_foo, mo_bar]: if os.path.isfile(mo_file): os.unlink(mo_file) - def test_compile_catalog_multidomain(self): - po_foo = os.path.join(i18n_dir, 'de_DE', 'LC_MESSAGES', 'foo.po') - po_bar = os.path.join(i18n_dir, 'de_DE', 'LC_MESSAGES', 'bar.po') - mo_foo = po_foo.replace('.po', '.mo') - mo_bar = po_bar.replace('.po', '.mo') - try: - self.cli.run(sys.argv + ['compile', - '--locale', 'de_DE', '--domain', 'foo bar', '--use-fuzzy', - '-d', i18n_dir]) - for mo_file in [mo_foo, mo_bar]: - assert os.path.isfile(mo_file) - assert sys.stderr.getvalue() == ( - f'compiling catalog {po_foo} to {mo_foo}\n' - f'compiling catalog {po_bar} to {mo_bar}\n' - ) - - finally: - for mo_file in [mo_foo, mo_bar]: - if os.path.isfile(mo_file): - os.unlink(mo_file) - - def test_update(self): - template = Catalog() - template.add("1") - template.add("2") - template.add("3") - tmpl_file = os.path.join(i18n_dir, 'temp-template.pot') - with open(tmpl_file, "wb") as outfp: - write_po(outfp, template) - po_file = os.path.join(i18n_dir, 'temp1.po') - self.cli.run(sys.argv + ['init', - '-l', 'fi', - '-o', po_file, - '-i', tmpl_file, - ]) - with open(po_file) as infp: - catalog = read_po(infp) - assert len(catalog) == 3 - - # Add another entry to the template - - template.add("4") - - with open(tmpl_file, "wb") as outfp: - write_po(outfp, template) - - self.cli.run(sys.argv + ['update', - '-l', 'fi_FI', - '-o', po_file, - '-i', tmpl_file]) - - with open(po_file) as infp: - catalog = read_po(infp) - assert len(catalog) == 4 # Catalog was updated - - def test_update_pot_creation_date(self): - template = Catalog() - template.add("1") - template.add("2") - template.add("3") - tmpl_file = os.path.join(i18n_dir, 'temp-template.pot') - with open(tmpl_file, "wb") as outfp: - write_po(outfp, template) - po_file = os.path.join(i18n_dir, 'temp1.po') - self.cli.run(sys.argv + ['init', - '-l', 'fi', - '-o', po_file, - '-i', tmpl_file, - ]) - with open(po_file) as infp: - catalog = read_po(infp) - assert len(catalog) == 3 - original_catalog_creation_date = catalog.creation_date - - # Update the template creation date - template.creation_date -= timedelta(minutes=3) - with open(tmpl_file, "wb") as outfp: - write_po(outfp, template) - - self.cli.run(sys.argv + ['update', - '-l', 'fi_FI', - '-o', po_file, - '-i', tmpl_file]) - - with open(po_file) as infp: - catalog = read_po(infp) - # We didn't ignore the creation date, so expect a diff - assert catalog.creation_date != original_catalog_creation_date - - # Reset the "original" - original_catalog_creation_date = catalog.creation_date - - # Update the template creation date again - # This time, pass the ignore flag and expect the times are different - template.creation_date -= timedelta(minutes=5) - with open(tmpl_file, "wb") as outfp: - write_po(outfp, template) - - self.cli.run(sys.argv + ['update', - '-l', 'fi_FI', - '-o', po_file, - '-i', tmpl_file, - '--ignore-pot-creation-date']) - - with open(po_file) as infp: - catalog = read_po(infp) - # We ignored creation date, so it should not have changed - assert catalog.creation_date == original_catalog_creation_date - - def test_check(self): - template = Catalog() - template.add("1") - template.add("2") - template.add("3") - tmpl_file = os.path.join(i18n_dir, 'temp-template.pot') - with open(tmpl_file, "wb") as outfp: - write_po(outfp, template) - po_file = os.path.join(i18n_dir, 'temp1.po') - self.cli.run(sys.argv + ['init', - '-l', 'fi_FI', - '-o', po_file, - '-i', tmpl_file, - ]) - - # Update the catalog file - self.cli.run(sys.argv + ['update', - '-l', 'fi_FI', - '-o', po_file, - '-i', tmpl_file]) - - # Run a check without introducing any changes to the template - self.cli.run(sys.argv + ['update', - '--check', - '-l', 'fi_FI', - '-o', po_file, - '-i', tmpl_file]) - - # Add a new entry and expect the check to fail - template.add("4") - with open(tmpl_file, "wb") as outfp: - write_po(outfp, template) - - with pytest.raises(BaseError): - self.cli.run(sys.argv + ['update', - '--check', - '-l', 'fi_FI', - '-o', po_file, - '-i', tmpl_file]) - - # Write the latest changes to the po-file - self.cli.run(sys.argv + ['update', - '-l', 'fi_FI', - '-o', po_file, - '-i', tmpl_file]) - - # Update an entry and expect the check to fail - template.add("4", locations=[("foo.py", 1)]) - with open(tmpl_file, "wb") as outfp: - write_po(outfp, template) - - with pytest.raises(BaseError): - self.cli.run(sys.argv + ['update', - '--check', - '-l', 'fi_FI', - '-o', po_file, - '-i', tmpl_file]) - - def test_check_pot_creation_date(self): - template = Catalog() - template.add("1") - template.add("2") - template.add("3") - tmpl_file = os.path.join(i18n_dir, 'temp-template.pot') - with open(tmpl_file, "wb") as outfp: - write_po(outfp, template) - po_file = os.path.join(i18n_dir, 'temp1.po') - self.cli.run(sys.argv + ['init', - '-l', 'fi_FI', - '-o', po_file, - '-i', tmpl_file, - ]) - - # Update the catalog file - self.cli.run(sys.argv + ['update', - '-l', 'fi_FI', - '-o', po_file, - '-i', tmpl_file]) - - # Run a check without introducing any changes to the template - self.cli.run(sys.argv + ['update', - '--check', - '-l', 'fi_FI', - '-o', po_file, - '-i', tmpl_file]) - - # Run a check after changing the template creation date - template.creation_date = datetime.now() - timedelta(minutes=5) - with open(tmpl_file, "wb") as outfp: - write_po(outfp, template) - - # Should fail without --ignore-pot-creation-date flag - with pytest.raises(BaseError): - self.cli.run(sys.argv + ['update', - '--check', - '-l', 'fi_FI', - '-o', po_file, - '-i', tmpl_file]) - # Should pass with --ignore-pot-creation-date flag - self.cli.run(sys.argv + ['update', - '--check', - '-l', 'fi_FI', - '-o', po_file, - '-i', tmpl_file, - '--ignore-pot-creation-date']) - - def test_update_init_missing(self): - template = Catalog() - template.add("1") - template.add("2") - template.add("3") - tmpl_file = os.path.join(i18n_dir, 'temp2-template.pot') - with open(tmpl_file, "wb") as outfp: - write_po(outfp, template) - po_file = os.path.join(i18n_dir, 'temp2.po') - - self.cli.run(sys.argv + ['update', - '--init-missing', - '-l', 'fi', - '-o', po_file, - '-i', tmpl_file]) - - with open(po_file) as infp: - catalog = read_po(infp) - assert len(catalog) == 3 - - # Add another entry to the template - - template.add("4") - - with open(tmpl_file, "wb") as outfp: - write_po(outfp, template) - - self.cli.run(sys.argv + ['update', - '--init-missing', - '-l', 'fi_FI', - '-o', po_file, - '-i', tmpl_file]) - - with open(po_file) as infp: - catalog = read_po(infp) - assert len(catalog) == 4 # Catalog was updated + +def test_update(cli): + template = Catalog() + template.add("1") + template.add("2") + template.add("3") + tmpl_file = os.path.join(i18n_dir, 'temp-template.pot') + with open(tmpl_file, "wb") as outfp: + write_po(outfp, template) + po_file = os.path.join(i18n_dir, 'temp1.po') + cli.run(['pybabel', 'init', '-l', 'fi', '-o', po_file, '-i', tmpl_file]) + with open(po_file) as infp: + catalog = read_po(infp) + assert len(catalog) == 3 + + # Add another entry to the template + + template.add("4") + + with open(tmpl_file, "wb") as outfp: + write_po(outfp, template) + + cli.run(['pybabel', 'update', '-l', 'fi_FI', '-o', po_file, '-i', tmpl_file]) + + with open(po_file) as infp: + catalog = read_po(infp) + assert len(catalog) == 4 # Catalog was updated + + +def test_update_pot_creation_date(cli): + template = Catalog() + template.add("1") + template.add("2") + template.add("3") + tmpl_file = os.path.join(i18n_dir, 'temp-template.pot') + with open(tmpl_file, "wb") as outfp: + write_po(outfp, template) + po_file = os.path.join(i18n_dir, 'temp1.po') + cli.run(['pybabel', 'init', '-l', 'fi', '-o', po_file, '-i', tmpl_file]) + with open(po_file) as infp: + catalog = read_po(infp) + assert len(catalog) == 3 + original_catalog_creation_date = catalog.creation_date + + # Update the template creation date + template.creation_date -= timedelta(minutes=3) + with open(tmpl_file, "wb") as outfp: + write_po(outfp, template) + + cli.run(['pybabel', 'update', '-l', 'fi_FI', '-o', po_file, '-i', tmpl_file]) + + with open(po_file) as infp: + catalog = read_po(infp) + # We didn't ignore the creation date, so expect a diff + assert catalog.creation_date != original_catalog_creation_date + + # Reset the "original" + original_catalog_creation_date = catalog.creation_date + + # Update the template creation date again + # This time, pass the ignore flag and expect the times are different + template.creation_date -= timedelta(minutes=5) + with open(tmpl_file, "wb") as outfp: + write_po(outfp, template) + + cli.run(['pybabel', 'update', '-l', 'fi_FI', '-o', po_file, '-i', tmpl_file, '--ignore-pot-creation-date']) + + with open(po_file) as infp: + catalog = read_po(infp) + # We ignored creation date, so it should not have changed + assert catalog.creation_date == original_catalog_creation_date + + +def test_check(cli): + template = Catalog() + template.add("1") + template.add("2") + template.add("3") + tmpl_file = os.path.join(i18n_dir, 'temp-template.pot') + with open(tmpl_file, "wb") as outfp: + write_po(outfp, template) + po_file = os.path.join(i18n_dir, 'temp1.po') + cli.run(['pybabel', 'init', '-l', 'fi_FI', '-o', po_file, '-i', tmpl_file]) + + # Update the catalog file + cli.run(['pybabel', 'update', '-l', 'fi_FI', '-o', po_file, '-i', tmpl_file]) + + # Run a check without introducing any changes to the template + cli.run(['pybabel', 'update', '--check', '-l', 'fi_FI', '-o', po_file, '-i', tmpl_file]) + + # Add a new entry and expect the check to fail + template.add("4") + with open(tmpl_file, "wb") as outfp: + write_po(outfp, template) + + with pytest.raises(BaseError): + cli.run(['pybabel', 'update', '--check', '-l', 'fi_FI', '-o', po_file, '-i', tmpl_file]) + + # Write the latest changes to the po-file + cli.run(['pybabel', 'update', '-l', 'fi_FI', '-o', po_file, '-i', tmpl_file]) + + # Update an entry and expect the check to fail + template.add("4", locations=[("foo.py", 1)]) + with open(tmpl_file, "wb") as outfp: + write_po(outfp, template) + + with pytest.raises(BaseError): + cli.run(['pybabel', 'update', '--check', '-l', 'fi_FI', '-o', po_file, '-i', tmpl_file]) + + +def test_check_pot_creation_date(cli): + template = Catalog() + template.add("1") + template.add("2") + template.add("3") + tmpl_file = os.path.join(i18n_dir, 'temp-template.pot') + with open(tmpl_file, "wb") as outfp: + write_po(outfp, template) + po_file = os.path.join(i18n_dir, 'temp1.po') + cli.run(['pybabel', 'init', '-l', 'fi_FI', '-o', po_file, '-i', tmpl_file]) + + # Update the catalog file + cli.run(['pybabel', 'update', '-l', 'fi_FI', '-o', po_file, '-i', tmpl_file]) + + # Run a check without introducing any changes to the template + cli.run(['pybabel', 'update', '--check', '-l', 'fi_FI', '-o', po_file, '-i', tmpl_file]) + + # Run a check after changing the template creation date + template.creation_date = datetime.now() - timedelta(minutes=5) + with open(tmpl_file, "wb") as outfp: + write_po(outfp, template) + + # Should fail without --ignore-pot-creation-date flag + with pytest.raises(BaseError): + cli.run(['pybabel', 'update', '--check', '-l', 'fi_FI', '-o', po_file, '-i', tmpl_file]) + # Should pass with --ignore-pot-creation-date flag + cli.run([ + 'pybabel', 'update', + '--check', + '-l', 'fi_FI', + '-o', po_file, + '-i', tmpl_file, + '--ignore-pot-creation-date', + ]) + + +def test_update_init_missing(cli): + template = Catalog() + template.add("1") + template.add("2") + template.add("3") + tmpl_file = os.path.join(i18n_dir, 'temp2-template.pot') + with open(tmpl_file, "wb") as outfp: + write_po(outfp, template) + po_file = os.path.join(i18n_dir, 'temp2.po') + + cli.run(['pybabel', 'update', '--init-missing', '-l', 'fi', '-o', po_file, '-i', tmpl_file]) + + with open(po_file) as infp: + catalog = read_po(infp) + assert len(catalog) == 3 + + # Add another entry to the template + + template.add("4") + + with open(tmpl_file, "wb") as outfp: + write_po(outfp, template) + + cli.run(['pybabel', 'update', '--init-missing', '-l', 'fi_FI', '-o', po_file, '-i', tmpl_file]) + + with open(po_file) as infp: + catalog = read_po(infp) + assert len(catalog) == 4 # Catalog was updated diff --git a/tests/messages/frontend/test_compile.py b/tests/messages/frontend/test_compile.py index 644254134..3db413dac 100644 --- a/tests/messages/frontend/test_compile.py +++ b/tests/messages/frontend/test_compile.py @@ -12,9 +12,6 @@ from __future__ import annotations -import os -import unittest - import pytest from babel.messages import frontend @@ -23,27 +20,24 @@ from tests.messages.utils import Distribution -class CompileCatalogTestCase(unittest.TestCase): - - def setUp(self): - self.olddir = os.getcwd() - os.chdir(data_dir) +@pytest.fixture +def compile_catalog_cmd(monkeypatch): + monkeypatch.chdir(data_dir) + dist = Distribution(TEST_PROJECT_DISTRIBUTION_DATA) + cmd = frontend.CompileCatalog(dist) + cmd.initialize_options() + return cmd - self.dist = Distribution(TEST_PROJECT_DISTRIBUTION_DATA) - self.cmd = frontend.CompileCatalog(self.dist) - self.cmd.initialize_options() - def tearDown(self): - os.chdir(self.olddir) +def test_no_directory_or_output_file_specified(compile_catalog_cmd): + compile_catalog_cmd.locale = 'en_US' + compile_catalog_cmd.input_file = 'dummy' + with pytest.raises(OptionError): + compile_catalog_cmd.finalize_options() - def test_no_directory_or_output_file_specified(self): - self.cmd.locale = 'en_US' - self.cmd.input_file = 'dummy' - with pytest.raises(OptionError): - self.cmd.finalize_options() - def test_no_directory_or_input_file_specified(self): - self.cmd.locale = 'en_US' - self.cmd.output_file = 'dummy' - with pytest.raises(OptionError): - self.cmd.finalize_options() +def test_no_directory_or_input_file_specified(compile_catalog_cmd): + compile_catalog_cmd.locale = 'en_US' + compile_catalog_cmd.output_file = 'dummy' + with pytest.raises(OptionError): + compile_catalog_cmd.finalize_options() diff --git a/tests/messages/frontend/test_extract.py b/tests/messages/frontend/test_extract.py index ff06ea748..7980eddad 100644 --- a/tests/messages/frontend/test_extract.py +++ b/tests/messages/frontend/test_extract.py @@ -12,9 +12,7 @@ from __future__ import annotations -import os import time -import unittest from datetime import datetime import pytest @@ -26,98 +24,94 @@ from babel.messages.frontend import OptionError from babel.messages.pofile import read_po from babel.util import LOCALTZ -from tests.messages.consts import TEST_PROJECT_DISTRIBUTION_DATA, data_dir, pot_file, this_dir +from tests.messages.consts import TEST_PROJECT_DISTRIBUTION_DATA, data_dir, this_dir from tests.messages.utils import Distribution -class ExtractMessagesTestCase(unittest.TestCase): - - def setUp(self): - self.olddir = os.getcwd() - os.chdir(data_dir) - - self.dist = Distribution(TEST_PROJECT_DISTRIBUTION_DATA) - self.cmd = frontend.ExtractMessages(self.dist) - self.cmd.initialize_options() - - def tearDown(self): - if os.path.isfile(pot_file): - os.unlink(pot_file) - - os.chdir(self.olddir) - - def assert_pot_file_exists(self): - assert os.path.isfile(pot_file) - - def test_neither_default_nor_custom_keywords(self): - self.cmd.output_file = 'dummy' - self.cmd.no_default_keywords = True - with pytest.raises(OptionError): - self.cmd.finalize_options() - - def test_no_output_file_specified(self): - with pytest.raises(OptionError): - self.cmd.finalize_options() - - def test_both_sort_output_and_sort_by_file(self): - self.cmd.output_file = 'dummy' - self.cmd.sort_output = True - self.cmd.sort_by_file = True - with pytest.raises(OptionError): - self.cmd.finalize_options() - - def test_invalid_file_or_dir_input_path(self): - self.cmd.input_paths = 'nonexistent_path' - self.cmd.output_file = 'dummy' - with pytest.raises(OptionError): - self.cmd.finalize_options() - - def test_input_paths_is_treated_as_list(self): - self.cmd.input_paths = data_dir - self.cmd.output_file = pot_file - self.cmd.finalize_options() - self.cmd.run() - - with open(pot_file) as f: - catalog = read_po(f) - msg = catalog.get('bar') - assert len(msg.locations) == 1 - assert ('file1.py' in msg.locations[0][0]) - - def test_input_paths_handle_spaces_after_comma(self): - self.cmd.input_paths = f"{this_dir}, {data_dir}" - self.cmd.output_file = pot_file - self.cmd.finalize_options() - assert self.cmd.input_paths == [this_dir, data_dir] - - def test_input_dirs_is_alias_for_input_paths(self): - self.cmd.input_dirs = this_dir - self.cmd.output_file = pot_file - self.cmd.finalize_options() - # Gets listified in `finalize_options`: - assert self.cmd.input_paths == [self.cmd.input_dirs] - - def test_input_dirs_is_mutually_exclusive_with_input_paths(self): - self.cmd.input_dirs = this_dir - self.cmd.input_paths = this_dir - self.cmd.output_file = pot_file - with pytest.raises(OptionError): - self.cmd.finalize_options() - - @freeze_time("1994-11-11") - def test_extraction_with_default_mapping(self): - self.cmd.copyright_holder = 'FooBar, Inc.' - self.cmd.msgid_bugs_address = 'bugs.address@email.tld' - self.cmd.output_file = 'project/i18n/temp.pot' - self.cmd.add_comments = 'TRANSLATOR:,TRANSLATORS:' - - self.cmd.finalize_options() - self.cmd.run() - - self.assert_pot_file_exists() - - date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') - expected_content = fr"""# Translations template for TestProject. +@pytest.fixture() +def extract_cmd(monkeypatch): + monkeypatch.chdir(data_dir) + dist = Distribution(TEST_PROJECT_DISTRIBUTION_DATA) + extract_cmd = frontend.ExtractMessages(dist) + extract_cmd.initialize_options() + return extract_cmd + + +def test_neither_default_nor_custom_keywords(extract_cmd): + extract_cmd.output_file = 'dummy' + extract_cmd.no_default_keywords = True + with pytest.raises(OptionError): + extract_cmd.finalize_options() + + +def test_no_output_file_specified(extract_cmd): + with pytest.raises(OptionError): + extract_cmd.finalize_options() + + +def test_both_sort_output_and_sort_by_file(extract_cmd): + extract_cmd.output_file = 'dummy' + extract_cmd.sort_output = True + extract_cmd.sort_by_file = True + with pytest.raises(OptionError): + extract_cmd.finalize_options() + + +def test_invalid_file_or_dir_input_path(extract_cmd): + extract_cmd.input_paths = 'nonexistent_path' + extract_cmd.output_file = 'dummy' + with pytest.raises(OptionError): + extract_cmd.finalize_options() + + +def test_input_paths_is_treated_as_list(extract_cmd, pot_file): + extract_cmd.input_paths = data_dir + extract_cmd.output_file = pot_file + extract_cmd.finalize_options() + extract_cmd.run() + + with pot_file.open() as f: + catalog = read_po(f) + msg = catalog.get('bar') + assert len(msg.locations) == 1 + assert 'file1.py' in msg.locations[0][0] + + +def test_input_paths_handle_spaces_after_comma(extract_cmd, pot_file): + extract_cmd.input_paths = f"{this_dir}, {data_dir}" + extract_cmd.output_file = pot_file + extract_cmd.finalize_options() + assert extract_cmd.input_paths == [this_dir, data_dir] + + +def test_input_dirs_is_alias_for_input_paths(extract_cmd, pot_file): + extract_cmd.input_dirs = this_dir + extract_cmd.output_file = pot_file + extract_cmd.finalize_options() + # Gets listified in `finalize_options`: + assert extract_cmd.input_paths == [extract_cmd.input_dirs] + + +def test_input_dirs_is_mutually_exclusive_with_input_paths(extract_cmd, pot_file): + extract_cmd.input_dirs = this_dir + extract_cmd.input_paths = this_dir + extract_cmd.output_file = pot_file + with pytest.raises(OptionError): + extract_cmd.finalize_options() + + +@freeze_time("1994-11-11") +def test_extraction_with_default_mapping(extract_cmd, pot_file): + extract_cmd.copyright_holder = 'FooBar, Inc.' + extract_cmd.msgid_bugs_address = 'bugs.address@email.tld' + extract_cmd.output_file = pot_file + extract_cmd.add_comments = 'TRANSLATOR:,TRANSLATORS:' + + extract_cmd.finalize_options() + extract_cmd.run() + + date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') + expected_content = fr"""# Translations template for TestProject. # Copyright (C) {time.strftime('%Y')} FooBar, Inc. # This file is distributed under the same license as the TestProject # project. @@ -156,25 +150,22 @@ def test_extraction_with_default_mapping(self): msgstr[1] "" """ - with open(pot_file) as f: - actual_content = f.read() - assert expected_content == actual_content + assert expected_content == pot_file.read_text() - @freeze_time("1994-11-11") - def test_extraction_with_mapping_file(self): - self.cmd.copyright_holder = 'FooBar, Inc.' - self.cmd.msgid_bugs_address = 'bugs.address@email.tld' - self.cmd.mapping_file = 'mapping.cfg' - self.cmd.output_file = 'project/i18n/temp.pot' - self.cmd.add_comments = 'TRANSLATOR:,TRANSLATORS:' - self.cmd.finalize_options() - self.cmd.run() +@freeze_time("1994-11-11") +def test_extraction_with_mapping_file(extract_cmd, pot_file): + extract_cmd.copyright_holder = 'FooBar, Inc.' + extract_cmd.msgid_bugs_address = 'bugs.address@email.tld' + extract_cmd.mapping_file = 'mapping.cfg' + extract_cmd.output_file = pot_file + extract_cmd.add_comments = 'TRANSLATOR:,TRANSLATORS:' - self.assert_pot_file_exists() + extract_cmd.finalize_options() + extract_cmd.run() - date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') - expected_content = fr"""# Translations template for TestProject. + date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') + expected_content = fr"""# Translations template for TestProject. # Copyright (C) {time.strftime('%Y')} FooBar, Inc. # This file is distributed under the same license as the TestProject # project. @@ -207,30 +198,27 @@ def test_extraction_with_mapping_file(self): msgstr[1] "" """ - with open(pot_file) as f: - actual_content = f.read() - assert expected_content == actual_content - - @freeze_time("1994-11-11") - def test_extraction_with_mapping_dict(self): - self.dist.message_extractors = { - 'project': [ - ('**/ignored/**.*', 'ignore', None), - ('**.py', 'python', None), - ], - } - self.cmd.copyright_holder = 'FooBar, Inc.' - self.cmd.msgid_bugs_address = 'bugs.address@email.tld' - self.cmd.output_file = 'project/i18n/temp.pot' - self.cmd.add_comments = 'TRANSLATOR:,TRANSLATORS:' - - self.cmd.finalize_options() - self.cmd.run() - - self.assert_pot_file_exists() - - date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') - expected_content = fr"""# Translations template for TestProject. + assert expected_content == pot_file.read_text() + + +@freeze_time("1994-11-11") +def test_extraction_with_mapping_dict(extract_cmd, pot_file): + extract_cmd.distribution.message_extractors = { + 'project': [ + ('**/ignored/**.*', 'ignore', None), + ('**.py', 'python', None), + ], + } + extract_cmd.copyright_holder = 'FooBar, Inc.' + extract_cmd.msgid_bugs_address = 'bugs.address@email.tld' + extract_cmd.output_file = pot_file + extract_cmd.add_comments = 'TRANSLATOR:,TRANSLATORS:' + + extract_cmd.finalize_options() + extract_cmd.run() + + date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') + expected_content = fr"""# Translations template for TestProject. # Copyright (C) {time.strftime('%Y')} FooBar, Inc. # This file is distributed under the same license as the TestProject # project. @@ -263,27 +251,24 @@ def test_extraction_with_mapping_dict(self): msgstr[1] "" """ - with open(pot_file) as f: - actual_content = f.read() - assert expected_content == actual_content - - def test_extraction_add_location_file(self): - self.dist.message_extractors = { - 'project': [ - ('**/ignored/**.*', 'ignore', None), - ('**.py', 'python', None), - ], - } - self.cmd.output_file = 'project/i18n/temp.pot' - self.cmd.add_location = 'file' - self.cmd.omit_header = True - - self.cmd.finalize_options() - self.cmd.run() - - self.assert_pot_file_exists() - - expected_content = r"""#: project/file1.py + assert expected_content == pot_file.read_text() + + +def test_extraction_add_location_file(extract_cmd, pot_file): + extract_cmd.distribution.message_extractors = { + 'project': [ + ('**/ignored/**.*', 'ignore', None), + ('**.py', 'python', None), + ], + } + extract_cmd.output_file = pot_file + extract_cmd.add_location = 'file' + extract_cmd.omit_header = True + + extract_cmd.finalize_options() + extract_cmd.run() + + expected_content = r"""#: project/file1.py msgid "bar" msgstr "" @@ -294,6 +279,4 @@ def test_extraction_add_location_file(self): msgstr[1] "" """ - with open(pot_file) as f: - actual_content = f.read() - assert expected_content == actual_content + assert expected_content == pot_file.read_text() diff --git a/tests/messages/frontend/test_frontend.py b/tests/messages/frontend/test_frontend.py index bb196e1e7..a77d5d679 100644 --- a/tests/messages/frontend/test_frontend.py +++ b/tests/messages/frontend/test_frontend.py @@ -134,8 +134,7 @@ def test_parse_mapping(data: str, parser, preprocess, is_toml): def test_parse_keywords(): - kw = frontend.parse_keywords(['_', 'dgettext:2', - 'dngettext:2,3', 'pgettext:1c,2']) + kw = frontend.parse_keywords(['_', 'dgettext:2', 'dngettext:2,3', 'pgettext:1c,2']) assert kw == { '_': None, 'dgettext': (2,), @@ -239,7 +238,6 @@ def test_update_catalog_boolean_args(): assert cmdinst.previous is False # Mutually exclusive with no_fuzzy_matching - def test_compile_catalog_dir(tmp_path): """ Test that `compile` can compile all locales in a directory. @@ -280,7 +278,6 @@ def test_compile_catalog_explicit(tmp_path): assert mo_file.exists() - @pytest.mark.parametrize("explicit_locale", (None, 'fi_FI'), ids=("implicit", "explicit")) def test_update_dir(tmp_path, explicit_locale: bool): """ @@ -290,7 +287,7 @@ def test_update_dir(tmp_path, explicit_locale: bool): template.add("1") template.add("2") template.add("3") - tmpl_file = (tmp_path / 'temp-template.pot') + tmpl_file = tmp_path / 'temp-template.pot' with tmpl_file.open("wb") as outfp: write_po(outfp, template) locales = ("fi_FI", "sv_SE") diff --git a/tests/messages/frontend/test_init.py b/tests/messages/frontend/test_init.py index 9e10c2a58..e69e5cce3 100644 --- a/tests/messages/frontend/test_init.py +++ b/tests/messages/frontend/test_init.py @@ -14,7 +14,6 @@ import os import shutil -import unittest from datetime import datetime import pytest @@ -33,50 +32,44 @@ from tests.messages.utils import Distribution -class InitCatalogTestCase(unittest.TestCase): +@pytest.fixture +def init_cmd(monkeypatch): + monkeypatch.chdir(data_dir) + dist = Distribution(TEST_PROJECT_DISTRIBUTION_DATA) + init_cmd = frontend.InitCatalog(dist) + init_cmd.initialize_options() + yield init_cmd + for dirname in ['en_US', 'ja_JP', 'lv_LV']: + locale_dir = os.path.join(i18n_dir, dirname) + if os.path.isdir(locale_dir): + shutil.rmtree(locale_dir) - def setUp(self): - self.olddir = os.getcwd() - os.chdir(data_dir) - self.dist = Distribution(TEST_PROJECT_DISTRIBUTION_DATA) - self.cmd = frontend.InitCatalog(self.dist) - self.cmd.initialize_options() +def test_no_input_file(init_cmd): + init_cmd.locale = 'en_US' + init_cmd.output_file = 'dummy' + with pytest.raises(frontend.OptionError): + init_cmd.finalize_options() - def tearDown(self): - for dirname in ['en_US', 'ja_JP', 'lv_LV']: - locale_dir = os.path.join(i18n_dir, dirname) - if os.path.isdir(locale_dir): - shutil.rmtree(locale_dir) - os.chdir(self.olddir) +def test_no_locale(init_cmd): + init_cmd.input_file = 'dummy' + init_cmd.output_file = 'dummy' + with pytest.raises(frontend.OptionError): + init_cmd.finalize_options() - def test_no_input_file(self): - self.cmd.locale = 'en_US' - self.cmd.output_file = 'dummy' - with pytest.raises(frontend.OptionError): - self.cmd.finalize_options() - def test_no_locale(self): - self.cmd.input_file = 'dummy' - self.cmd.output_file = 'dummy' - with pytest.raises(frontend.OptionError): - self.cmd.finalize_options() +@freeze_time("1994-11-11") +def test_with_output_dir(init_cmd): + init_cmd.input_file = 'project/i18n/messages.pot' + init_cmd.locale = 'en_US' + init_cmd.output_dir = 'project/i18n' - @freeze_time("1994-11-11") - def test_with_output_dir(self): - self.cmd.input_file = 'project/i18n/messages.pot' - self.cmd.locale = 'en_US' - self.cmd.output_dir = 'project/i18n' + init_cmd.finalize_options() + init_cmd.run() - self.cmd.finalize_options() - self.cmd.run() - - po_file = get_po_file_path('en_US') - assert os.path.isfile(po_file) - - date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') - expected_content = fr"""# English (United States) translations for TestProject. + date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') + expected_content = fr"""# English (United States) translations for TestProject. # Copyright (C) 2007 FooBar, Inc. # This file is distributed under the same license as the TestProject # project. @@ -110,24 +103,22 @@ def test_with_output_dir(self): msgstr[1] "" """ - with open(po_file) as f: - actual_content = f.read() - assert expected_content == actual_content + with open(get_po_file_path('en_US')) as f: + actual_content = f.read() + assert expected_content == actual_content - @freeze_time("1994-11-11") - def test_keeps_catalog_non_fuzzy(self): - self.cmd.input_file = 'project/i18n/messages_non_fuzzy.pot' - self.cmd.locale = 'en_US' - self.cmd.output_dir = 'project/i18n' - self.cmd.finalize_options() - self.cmd.run() +@freeze_time("1994-11-11") +def test_keeps_catalog_non_fuzzy(init_cmd): + init_cmd.input_file = 'project/i18n/messages_non_fuzzy.pot' + init_cmd.locale = 'en_US' + init_cmd.output_dir = 'project/i18n' - po_file = get_po_file_path('en_US') - assert os.path.isfile(po_file) + init_cmd.finalize_options() + init_cmd.run() - date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') - expected_content = fr"""# English (United States) translations for TestProject. + date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') + expected_content = fr"""# English (United States) translations for TestProject. # Copyright (C) 2007 FooBar, Inc. # This file is distributed under the same license as the TestProject # project. @@ -161,24 +152,22 @@ def test_keeps_catalog_non_fuzzy(self): msgstr[1] "" """ - with open(po_file) as f: - actual_content = f.read() - assert expected_content == actual_content + with open(get_po_file_path('en_US')) as f: + actual_content = f.read() + assert expected_content == actual_content - @freeze_time("1994-11-11") - def test_correct_init_more_than_2_plurals(self): - self.cmd.input_file = 'project/i18n/messages.pot' - self.cmd.locale = 'lv_LV' - self.cmd.output_dir = 'project/i18n' - self.cmd.finalize_options() - self.cmd.run() +@freeze_time("1994-11-11") +def test_correct_init_more_than_2_plurals(init_cmd): + init_cmd.input_file = 'project/i18n/messages.pot' + init_cmd.locale = 'lv_LV' + init_cmd.output_dir = 'project/i18n' - po_file = get_po_file_path('lv_LV') - assert os.path.isfile(po_file) + init_cmd.finalize_options() + init_cmd.run() - date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') - expected_content = fr"""# Latvian (Latvia) translations for TestProject. + date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en') + expected_content = fr"""# Latvian (Latvia) translations for TestProject. # Copyright (C) 2007 FooBar, Inc. # This file is distributed under the same license as the TestProject # project. @@ -214,24 +203,22 @@ def test_correct_init_more_than_2_plurals(self): msgstr[2] "" """ - with open(po_file) as f: - actual_content = f.read() - assert expected_content == actual_content + with open(get_po_file_path('lv_LV')) as f: + actual_content = f.read() + assert expected_content == actual_content - @freeze_time("1994-11-11") - def test_correct_init_singular_plural_forms(self): - self.cmd.input_file = 'project/i18n/messages.pot' - self.cmd.locale = 'ja_JP' - self.cmd.output_dir = 'project/i18n' - self.cmd.finalize_options() - self.cmd.run() +@freeze_time("1994-11-11") +def test_correct_init_singular_plural_forms(init_cmd): + init_cmd.input_file = 'project/i18n/messages.pot' + init_cmd.locale = 'ja_JP' + init_cmd.output_dir = 'project/i18n' - po_file = get_po_file_path('ja_JP') - assert os.path.isfile(po_file) + init_cmd.finalize_options() + init_cmd.run() - date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='ja_JP') - expected_content = fr"""# Japanese (Japan) translations for TestProject. + date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='ja_JP') + expected_content = fr"""# Japanese (Japan) translations for TestProject. # Copyright (C) 2007 FooBar, Inc. # This file is distributed under the same license as the TestProject # project. @@ -264,32 +251,31 @@ def test_correct_init_singular_plural_forms(self): msgstr[0] "" """ - with open(po_file) as f: - actual_content = f.read() - assert expected_content == actual_content - - @freeze_time("1994-11-11") - def test_supports_no_wrap(self): - self.cmd.input_file = 'project/i18n/long_messages.pot' - self.cmd.locale = 'en_US' - self.cmd.output_dir = 'project/i18n' - - long_message = '"' + 'xxxxx ' * 15 + '"' - - with open('project/i18n/messages.pot', 'rb') as f: - pot_contents = f.read().decode('latin-1') - pot_with_very_long_line = pot_contents.replace('"bar"', long_message) - with open(self.cmd.input_file, 'wb') as f: - f.write(pot_with_very_long_line.encode('latin-1')) - self.cmd.no_wrap = True - - self.cmd.finalize_options() - self.cmd.run() - - po_file = get_po_file_path('en_US') - assert os.path.isfile(po_file) - date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en_US') - expected_content = fr"""# English (United States) translations for TestProject. + with open(get_po_file_path('ja_JP')) as f: + actual_content = f.read() + assert expected_content == actual_content + + +@freeze_time("1994-11-11") +def test_supports_no_wrap(init_cmd): + init_cmd.input_file = 'project/i18n/long_messages.pot' + init_cmd.locale = 'en_US' + init_cmd.output_dir = 'project/i18n' + + long_message = '"' + 'xxxxx ' * 15 + '"' + + with open('project/i18n/messages.pot', 'rb') as f: + pot_contents = f.read().decode('latin-1') + pot_with_very_long_line = pot_contents.replace('"bar"', long_message) + with open(init_cmd.input_file, 'wb') as f: + f.write(pot_with_very_long_line.encode('latin-1')) + init_cmd.no_wrap = True + + init_cmd.finalize_options() + init_cmd.run() + + date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en_US') + expected_content = fr"""# English (United States) translations for TestProject. # Copyright (C) 2007 FooBar, Inc. # This file is distributed under the same license as the TestProject # project. @@ -323,31 +309,30 @@ def test_supports_no_wrap(self): msgstr[1] "" """ - with open(po_file) as f: - actual_content = f.read() - assert expected_content == actual_content - - @freeze_time("1994-11-11") - def test_supports_width(self): - self.cmd.input_file = 'project/i18n/long_messages.pot' - self.cmd.locale = 'en_US' - self.cmd.output_dir = 'project/i18n' - - long_message = '"' + 'xxxxx ' * 15 + '"' - - with open('project/i18n/messages.pot', 'rb') as f: - pot_contents = f.read().decode('latin-1') - pot_with_very_long_line = pot_contents.replace('"bar"', long_message) - with open(self.cmd.input_file, 'wb') as f: - f.write(pot_with_very_long_line.encode('latin-1')) - self.cmd.width = 120 - self.cmd.finalize_options() - self.cmd.run() - - po_file = get_po_file_path('en_US') - assert os.path.isfile(po_file) - date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en_US') - expected_content = fr"""# English (United States) translations for TestProject. + with open(get_po_file_path('en_US')) as f: + actual_content = f.read() + assert expected_content == actual_content + + +@freeze_time("1994-11-11") +def test_supports_width(init_cmd): + init_cmd.input_file = 'project/i18n/long_messages.pot' + init_cmd.locale = 'en_US' + init_cmd.output_dir = 'project/i18n' + + long_message = '"' + 'xxxxx ' * 15 + '"' + + with open('project/i18n/messages.pot', 'rb') as f: + pot_contents = f.read().decode('latin-1') + pot_with_very_long_line = pot_contents.replace('"bar"', long_message) + with open(init_cmd.input_file, 'wb') as f: + f.write(pot_with_very_long_line.encode('latin-1')) + init_cmd.width = 120 + init_cmd.finalize_options() + init_cmd.run() + + date = format_datetime(datetime(1994, 11, 11, 00, 00), 'yyyy-MM-dd HH:mmZ', tzinfo=LOCALTZ, locale='en_US') + expected_content = fr"""# English (United States) translations for TestProject. # Copyright (C) 2007 FooBar, Inc. # This file is distributed under the same license as the TestProject # project. @@ -381,6 +366,6 @@ def test_supports_width(self): msgstr[1] "" """ - with open(po_file) as f: - actual_content = f.read() - assert expected_content == actual_content + with open(get_po_file_path('en_US')) as f: + actual_content = f.read() + assert expected_content == actual_content