Refs #26677 -- Simplified i18n test cleanups.
The fact that we aren't dealing with the Django source tree anymore allows us to drop several tearDown()/addCleanup() calls that were concerned with removing apiece files/dirs/symlinks created by test cases, as we are covered by the removal of the parent temporary tree anyways. Thanks Tim Graham for advice and review.
This commit is contained in:
parent
0451dcc2eb
commit
bb7bb379e8
|
@ -3,9 +3,7 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
import gettext as gettext_module
|
import gettext as gettext_module
|
||||||
import os
|
import os
|
||||||
import shutil
|
|
||||||
import stat
|
import stat
|
||||||
import tempfile
|
|
||||||
import unittest
|
import unittest
|
||||||
from subprocess import Popen
|
from subprocess import Popen
|
||||||
|
|
||||||
|
@ -18,43 +16,20 @@ from django.core.management.utils import find_command
|
||||||
from django.test import SimpleTestCase, mock, override_settings
|
from django.test import SimpleTestCase, mock, override_settings
|
||||||
from django.test.utils import captured_stderr, captured_stdout
|
from django.test.utils import captured_stderr, captured_stdout
|
||||||
from django.utils import six, translation
|
from django.utils import six, translation
|
||||||
from django.utils._os import upath
|
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.six import StringIO
|
from django.utils.six import StringIO
|
||||||
from django.utils.translation import ugettext
|
from django.utils.translation import ugettext
|
||||||
|
|
||||||
|
from .utils import RunInTmpDirMixin, copytree
|
||||||
|
|
||||||
has_msgfmt = find_command('msgfmt')
|
has_msgfmt = find_command('msgfmt')
|
||||||
source_code_dir = os.path.dirname(upath(__file__))
|
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipUnless(has_msgfmt, 'msgfmt is mandatory for compilation tests')
|
@unittest.skipUnless(has_msgfmt, 'msgfmt is mandatory for compilation tests')
|
||||||
class MessageCompilationTests(SimpleTestCase):
|
class MessageCompilationTests(RunInTmpDirMixin, SimpleTestCase):
|
||||||
|
|
||||||
work_subdir = 'commands'
|
work_subdir = 'commands'
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self._cwd = os.getcwd()
|
|
||||||
self.work_dir = tempfile.mkdtemp(prefix='i18n_')
|
|
||||||
self.test_dir = os.path.abspath(os.path.join(self.work_dir, self.work_subdir))
|
|
||||||
shutil.copytree(os.path.join(source_code_dir, self.work_subdir), self.test_dir)
|
|
||||||
# Make sure we step out of the temporary working tree before we
|
|
||||||
# remove it as we might be pulling the rug from under our own feet
|
|
||||||
# othewise. Rhis is especially true on Windows.
|
|
||||||
# Remember cleanup actions registered with addCleanup() are called in
|
|
||||||
# reverse so this ordering is important:
|
|
||||||
self.addCleanup(self._rmrf, self.test_dir)
|
|
||||||
self.addCleanup(os.chdir, self._cwd)
|
|
||||||
os.chdir(self.test_dir)
|
|
||||||
|
|
||||||
def _rmrf(self, dname):
|
|
||||||
if os.path.commonprefix([self.test_dir, os.path.abspath(dname)]) != self.test_dir:
|
|
||||||
return
|
|
||||||
shutil.rmtree(dname)
|
|
||||||
|
|
||||||
def rmfile(self, filepath):
|
|
||||||
if os.path.exists(filepath):
|
|
||||||
os.remove(filepath)
|
|
||||||
|
|
||||||
|
|
||||||
class PoFileTests(MessageCompilationTests):
|
class PoFileTests(MessageCompilationTests):
|
||||||
|
|
||||||
|
@ -87,10 +62,6 @@ class PoFileContentsTests(MessageCompilationTests):
|
||||||
LOCALE = 'fr'
|
LOCALE = 'fr'
|
||||||
MO_FILE = 'locale/%s/LC_MESSAGES/django.mo' % LOCALE
|
MO_FILE = 'locale/%s/LC_MESSAGES/django.mo' % LOCALE
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(PoFileContentsTests, self).setUp()
|
|
||||||
self.addCleanup(os.unlink, os.path.join(self.test_dir, self.MO_FILE))
|
|
||||||
|
|
||||||
def test_percent_symbol_in_po_file(self):
|
def test_percent_symbol_in_po_file(self):
|
||||||
call_command('compilemessages', locale=[self.LOCALE], stdout=StringIO())
|
call_command('compilemessages', locale=[self.LOCALE], stdout=StringIO())
|
||||||
self.assertTrue(os.path.exists(self.MO_FILE))
|
self.assertTrue(os.path.exists(self.MO_FILE))
|
||||||
|
@ -106,8 +77,6 @@ class MultipleLocaleCompilationTests(MessageCompilationTests):
|
||||||
localedir = os.path.join(self.test_dir, 'locale')
|
localedir = os.path.join(self.test_dir, 'locale')
|
||||||
self.MO_FILE_HR = os.path.join(localedir, 'hr/LC_MESSAGES/django.mo')
|
self.MO_FILE_HR = os.path.join(localedir, 'hr/LC_MESSAGES/django.mo')
|
||||||
self.MO_FILE_FR = os.path.join(localedir, 'fr/LC_MESSAGES/django.mo')
|
self.MO_FILE_FR = os.path.join(localedir, 'fr/LC_MESSAGES/django.mo')
|
||||||
self.addCleanup(self.rmfile, os.path.join(localedir, self.MO_FILE_HR))
|
|
||||||
self.addCleanup(self.rmfile, os.path.join(localedir, self.MO_FILE_FR))
|
|
||||||
|
|
||||||
def test_one_locale(self):
|
def test_one_locale(self):
|
||||||
with override_settings(LOCALE_PATHS=[os.path.join(self.test_dir, 'locale')]):
|
with override_settings(LOCALE_PATHS=[os.path.join(self.test_dir, 'locale')]):
|
||||||
|
@ -131,8 +100,7 @@ class ExcludedLocaleCompilationTests(MessageCompilationTests):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(ExcludedLocaleCompilationTests, self).setUp()
|
super(ExcludedLocaleCompilationTests, self).setUp()
|
||||||
shutil.copytree('canned_locale', 'locale')
|
copytree('canned_locale', 'locale')
|
||||||
self.addCleanup(self._rmrf, os.path.join(self.test_dir, 'locale'))
|
|
||||||
|
|
||||||
def test_command_help(self):
|
def test_command_help(self):
|
||||||
with captured_stdout(), captured_stderr():
|
with captured_stdout(), captured_stderr():
|
||||||
|
@ -170,15 +138,11 @@ class ExcludedLocaleCompilationTests(MessageCompilationTests):
|
||||||
class CompilationErrorHandling(MessageCompilationTests):
|
class CompilationErrorHandling(MessageCompilationTests):
|
||||||
def test_error_reported_by_msgfmt(self):
|
def test_error_reported_by_msgfmt(self):
|
||||||
# po file contains wrong po formatting.
|
# po file contains wrong po formatting.
|
||||||
mo_file = 'locale/ja/LC_MESSAGES/django.mo'
|
|
||||||
self.addCleanup(self.rmfile, os.path.join(self.test_dir, mo_file))
|
|
||||||
with self.assertRaises(CommandError):
|
with self.assertRaises(CommandError):
|
||||||
call_command('compilemessages', locale=['ja'], verbosity=0)
|
call_command('compilemessages', locale=['ja'], verbosity=0)
|
||||||
|
|
||||||
def test_msgfmt_error_including_non_ascii(self):
|
def test_msgfmt_error_including_non_ascii(self):
|
||||||
# po file contains invalid msgstr content (triggers non-ascii error content).
|
# po file contains invalid msgstr content (triggers non-ascii error content).
|
||||||
mo_file = 'locale/ko/LC_MESSAGES/django.mo'
|
|
||||||
self.addCleanup(self.rmfile, os.path.join(self.test_dir, mo_file))
|
|
||||||
# Make sure the output of msgfmt is unaffected by the current locale.
|
# Make sure the output of msgfmt is unaffected by the current locale.
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env.update({str('LANG'): str('C')})
|
env.update({str('LANG'): str('C')})
|
||||||
|
@ -202,11 +166,6 @@ class ProjectAndAppTests(MessageCompilationTests):
|
||||||
PROJECT_MO_FILE = 'locale/%s/LC_MESSAGES/django.mo' % LOCALE
|
PROJECT_MO_FILE = 'locale/%s/LC_MESSAGES/django.mo' % LOCALE
|
||||||
APP_MO_FILE = 'app_with_locale/locale/%s/LC_MESSAGES/django.mo' % LOCALE
|
APP_MO_FILE = 'app_with_locale/locale/%s/LC_MESSAGES/django.mo' % LOCALE
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(ProjectAndAppTests, self).setUp()
|
|
||||||
self.addCleanup(self.rmfile, os.path.join(self.test_dir, self.PROJECT_MO_FILE))
|
|
||||||
self.addCleanup(self.rmfile, os.path.join(self.test_dir, self.APP_MO_FILE))
|
|
||||||
|
|
||||||
|
|
||||||
class FuzzyTranslationTest(ProjectAndAppTests):
|
class FuzzyTranslationTest(ProjectAndAppTests):
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,10 @@ import io
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
|
||||||
import time
|
import time
|
||||||
import warnings
|
import warnings
|
||||||
from unittest import SkipTest, skipUnless
|
from unittest import SkipTest, skipUnless
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
from django.core import management
|
from django.core import management
|
||||||
from django.core.management import execute_from_command_line
|
from django.core.management import execute_from_command_line
|
||||||
from django.core.management.base import CommandError
|
from django.core.management.base import CommandError
|
||||||
|
@ -20,62 +18,23 @@ from django.core.management.utils import find_command
|
||||||
from django.test import SimpleTestCase, mock, override_settings
|
from django.test import SimpleTestCase, mock, override_settings
|
||||||
from django.test.utils import captured_stderr, captured_stdout
|
from django.test.utils import captured_stderr, captured_stdout
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
from django.utils._os import upath
|
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.six import StringIO
|
from django.utils.six import StringIO
|
||||||
from django.utils.translation import TranslatorCommentWarning
|
from django.utils.translation import TranslatorCommentWarning
|
||||||
|
|
||||||
|
from .utils import POFileAssertionMixin, RunInTmpDirMixin, copytree
|
||||||
|
|
||||||
LOCALE = 'de'
|
LOCALE = 'de'
|
||||||
has_xgettext = find_command('xgettext')
|
has_xgettext = find_command('xgettext')
|
||||||
source_code_dir = os.path.dirname(upath(__file__))
|
|
||||||
|
|
||||||
|
|
||||||
class POFileAssertionMixin(object):
|
|
||||||
|
|
||||||
def _assertPoKeyword(self, keyword, expected_value, haystack, use_quotes=True):
|
|
||||||
q = '"'
|
|
||||||
if use_quotes:
|
|
||||||
expected_value = '"%s"' % expected_value
|
|
||||||
q = "'"
|
|
||||||
needle = '%s %s' % (keyword, expected_value)
|
|
||||||
expected_value = re.escape(expected_value)
|
|
||||||
return self.assertTrue(re.search('^%s %s' % (keyword, expected_value), haystack, re.MULTILINE),
|
|
||||||
'Could not find %(q)s%(n)s%(q)s in generated PO file' % {'n': needle, 'q': q})
|
|
||||||
|
|
||||||
def assertMsgId(self, msgid, haystack, use_quotes=True):
|
|
||||||
return self._assertPoKeyword('msgid', msgid, haystack, use_quotes=use_quotes)
|
|
||||||
|
|
||||||
|
|
||||||
@skipUnless(has_xgettext, 'xgettext is mandatory for extraction tests')
|
@skipUnless(has_xgettext, 'xgettext is mandatory for extraction tests')
|
||||||
class ExtractorTests(POFileAssertionMixin, SimpleTestCase):
|
class ExtractorTests(POFileAssertionMixin, RunInTmpDirMixin, SimpleTestCase):
|
||||||
|
|
||||||
work_subdir = 'commands'
|
work_subdir = 'commands'
|
||||||
|
|
||||||
PO_FILE = 'locale/%s/LC_MESSAGES/django.po' % LOCALE
|
PO_FILE = 'locale/%s/LC_MESSAGES/django.po' % LOCALE
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.work_dir = tempfile.mkdtemp(prefix='i18n_')
|
|
||||||
self.test_dir = os.path.abspath(os.path.join(self.work_dir, self.work_subdir))
|
|
||||||
shutil.copytree(os.path.join(source_code_dir, self.work_subdir), self.test_dir)
|
|
||||||
self._cwd = os.getcwd()
|
|
||||||
|
|
||||||
def _rmrf(self, dname):
|
|
||||||
if os.path.commonprefix([self.test_dir, os.path.abspath(dname)]) != self.test_dir:
|
|
||||||
return
|
|
||||||
shutil.rmtree(dname)
|
|
||||||
|
|
||||||
def rmfile(self, filepath):
|
|
||||||
if os.path.exists(filepath):
|
|
||||||
os.remove(filepath)
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
os.chdir(self.test_dir)
|
|
||||||
try:
|
|
||||||
self._rmrf('locale/%s' % LOCALE)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
os.chdir(self._cwd)
|
|
||||||
|
|
||||||
def _run_makemessages(self, **options):
|
def _run_makemessages(self, **options):
|
||||||
os.chdir(self.test_dir)
|
os.chdir(self.test_dir)
|
||||||
out = StringIO()
|
out = StringIO()
|
||||||
|
@ -177,7 +136,6 @@ class ExtractorTests(POFileAssertionMixin, SimpleTestCase):
|
||||||
class BasicExtractorTests(ExtractorTests):
|
class BasicExtractorTests(ExtractorTests):
|
||||||
|
|
||||||
def test_comments_extractor(self):
|
def test_comments_extractor(self):
|
||||||
os.chdir(self.test_dir)
|
|
||||||
management.call_command('makemessages', locale=[LOCALE], verbosity=0)
|
management.call_command('makemessages', locale=[LOCALE], verbosity=0)
|
||||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||||
with io.open(self.PO_FILE, 'r', encoding='utf-8') as fp:
|
with io.open(self.PO_FILE, 'r', encoding='utf-8') as fp:
|
||||||
|
@ -211,7 +169,6 @@ class BasicExtractorTests(ExtractorTests):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_special_char_extracted(self):
|
def test_special_char_extracted(self):
|
||||||
os.chdir(self.test_dir)
|
|
||||||
management.call_command('makemessages', locale=[LOCALE], verbosity=0)
|
management.call_command('makemessages', locale=[LOCALE], verbosity=0)
|
||||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||||
with io.open(self.PO_FILE, 'r', encoding='utf-8') as fp:
|
with io.open(self.PO_FILE, 'r', encoding='utf-8') as fp:
|
||||||
|
@ -219,7 +176,6 @@ class BasicExtractorTests(ExtractorTests):
|
||||||
self.assertMsgId("Non-breaking space\u00a0:", po_contents)
|
self.assertMsgId("Non-breaking space\u00a0:", po_contents)
|
||||||
|
|
||||||
def test_blocktrans_trimmed(self):
|
def test_blocktrans_trimmed(self):
|
||||||
os.chdir(self.test_dir)
|
|
||||||
management.call_command('makemessages', locale=[LOCALE], verbosity=0)
|
management.call_command('makemessages', locale=[LOCALE], verbosity=0)
|
||||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||||
with open(self.PO_FILE, 'r') as fp:
|
with open(self.PO_FILE, 'r') as fp:
|
||||||
|
@ -237,7 +193,6 @@ class BasicExtractorTests(ExtractorTests):
|
||||||
self.assertTrue(MakeMessagesCommand.leave_locale_alone)
|
self.assertTrue(MakeMessagesCommand.leave_locale_alone)
|
||||||
|
|
||||||
def test_extraction_error(self):
|
def test_extraction_error(self):
|
||||||
os.chdir(self.test_dir)
|
|
||||||
msg = (
|
msg = (
|
||||||
'Translation blocks must not include other block tags: blocktrans '
|
'Translation blocks must not include other block tags: blocktrans '
|
||||||
'(file %s, line 3)' % os.path.join('templates', 'template_with_error.tpl')
|
'(file %s, line 3)' % os.path.join('templates', 'template_with_error.tpl')
|
||||||
|
@ -248,9 +203,7 @@ class BasicExtractorTests(ExtractorTests):
|
||||||
self.assertFalse(os.path.exists('./templates/template_with_error.tpl.py'))
|
self.assertFalse(os.path.exists('./templates/template_with_error.tpl.py'))
|
||||||
|
|
||||||
def test_unicode_decode_error(self):
|
def test_unicode_decode_error(self):
|
||||||
os.chdir(self.test_dir)
|
|
||||||
shutil.copyfile('./not_utf8.sample', './not_utf8.txt')
|
shutil.copyfile('./not_utf8.sample', './not_utf8.txt')
|
||||||
self.addCleanup(self.rmfile, os.path.join(self.test_dir, 'not_utf8.txt'))
|
|
||||||
out = StringIO()
|
out = StringIO()
|
||||||
management.call_command('makemessages', locale=[LOCALE], stdout=out)
|
management.call_command('makemessages', locale=[LOCALE], stdout=out)
|
||||||
self.assertIn("UnicodeDecodeError: skipped file not_utf8.txt in .",
|
self.assertIn("UnicodeDecodeError: skipped file not_utf8.txt in .",
|
||||||
|
@ -258,9 +211,7 @@ class BasicExtractorTests(ExtractorTests):
|
||||||
|
|
||||||
def test_extraction_warning(self):
|
def test_extraction_warning(self):
|
||||||
"""test xgettext warning about multiple bare interpolation placeholders"""
|
"""test xgettext warning about multiple bare interpolation placeholders"""
|
||||||
os.chdir(self.test_dir)
|
|
||||||
shutil.copyfile('./code.sample', './code_sample.py')
|
shutil.copyfile('./code.sample', './code_sample.py')
|
||||||
self.addCleanup(self.rmfile, os.path.join(self.test_dir, 'code_sample.py'))
|
|
||||||
out = StringIO()
|
out = StringIO()
|
||||||
management.call_command('makemessages', locale=[LOCALE], stdout=out)
|
management.call_command('makemessages', locale=[LOCALE], stdout=out)
|
||||||
self.assertIn("code_sample.py:4", force_text(out.getvalue()))
|
self.assertIn("code_sample.py:4", force_text(out.getvalue()))
|
||||||
|
@ -271,7 +222,6 @@ class BasicExtractorTests(ExtractorTests):
|
||||||
{% trans %} and {% blocktrans %} template tags.
|
{% trans %} and {% blocktrans %} template tags.
|
||||||
Refs #14806.
|
Refs #14806.
|
||||||
"""
|
"""
|
||||||
os.chdir(self.test_dir)
|
|
||||||
management.call_command('makemessages', locale=[LOCALE], verbosity=0)
|
management.call_command('makemessages', locale=[LOCALE], verbosity=0)
|
||||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||||
with open(self.PO_FILE, 'r') as fp:
|
with open(self.PO_FILE, 'r') as fp:
|
||||||
|
@ -302,7 +252,6 @@ class BasicExtractorTests(ExtractorTests):
|
||||||
self.assertMsgId("Translatable literal #8d %(a)s", po_contents)
|
self.assertMsgId("Translatable literal #8d %(a)s", po_contents)
|
||||||
|
|
||||||
def test_context_in_single_quotes(self):
|
def test_context_in_single_quotes(self):
|
||||||
os.chdir(self.test_dir)
|
|
||||||
management.call_command('makemessages', locale=[LOCALE], verbosity=0)
|
management.call_command('makemessages', locale=[LOCALE], verbosity=0)
|
||||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||||
with open(self.PO_FILE, 'r') as fp:
|
with open(self.PO_FILE, 'r') as fp:
|
||||||
|
@ -317,7 +266,6 @@ class BasicExtractorTests(ExtractorTests):
|
||||||
|
|
||||||
def test_template_comments(self):
|
def test_template_comments(self):
|
||||||
"""Template comment tags on the same line of other constructs (#19552)"""
|
"""Template comment tags on the same line of other constructs (#19552)"""
|
||||||
os.chdir(self.test_dir)
|
|
||||||
# Test detection/end user reporting of old, incorrect templates
|
# Test detection/end user reporting of old, incorrect templates
|
||||||
# translator comments syntax
|
# translator comments syntax
|
||||||
with warnings.catch_warnings(record=True) as ws:
|
with warnings.catch_warnings(record=True) as ws:
|
||||||
|
@ -432,9 +380,7 @@ class BasicExtractorTests(ExtractorTests):
|
||||||
def test_po_file_encoding_when_updating(self):
|
def test_po_file_encoding_when_updating(self):
|
||||||
"""Update of PO file doesn't corrupt it with non-UTF-8 encoding on Python3+Windows (#23271)"""
|
"""Update of PO file doesn't corrupt it with non-UTF-8 encoding on Python3+Windows (#23271)"""
|
||||||
BR_PO_BASE = 'locale/pt_BR/LC_MESSAGES/django'
|
BR_PO_BASE = 'locale/pt_BR/LC_MESSAGES/django'
|
||||||
os.chdir(self.test_dir)
|
|
||||||
shutil.copyfile(BR_PO_BASE + '.pristine', BR_PO_BASE + '.po')
|
shutil.copyfile(BR_PO_BASE + '.pristine', BR_PO_BASE + '.po')
|
||||||
self.addCleanup(self.rmfile, os.path.join(self.test_dir, 'locale', 'pt_BR', 'LC_MESSAGES', 'django.po'))
|
|
||||||
management.call_command('makemessages', locale=['pt_BR'], verbosity=0)
|
management.call_command('makemessages', locale=['pt_BR'], verbosity=0)
|
||||||
self.assertTrue(os.path.exists(BR_PO_BASE + '.po'))
|
self.assertTrue(os.path.exists(BR_PO_BASE + '.po'))
|
||||||
with io.open(BR_PO_BASE + '.po', 'r', encoding='utf-8') as fp:
|
with io.open(BR_PO_BASE + '.po', 'r', encoding='utf-8') as fp:
|
||||||
|
@ -447,7 +393,6 @@ class JavascriptExtractorTests(ExtractorTests):
|
||||||
PO_FILE = 'locale/%s/LC_MESSAGES/djangojs.po' % LOCALE
|
PO_FILE = 'locale/%s/LC_MESSAGES/djangojs.po' % LOCALE
|
||||||
|
|
||||||
def test_javascript_literals(self):
|
def test_javascript_literals(self):
|
||||||
os.chdir(self.test_dir)
|
|
||||||
_, po_contents = self._run_makemessages(domain='djangojs')
|
_, po_contents = self._run_makemessages(domain='djangojs')
|
||||||
self.assertMsgId('This literal should be included.', po_contents)
|
self.assertMsgId('This literal should be included.', po_contents)
|
||||||
self.assertMsgId('gettext_noop should, too.', po_contents)
|
self.assertMsgId('gettext_noop should, too.', po_contents)
|
||||||
|
@ -522,15 +467,6 @@ class SymlinkExtractorTests(ExtractorTests):
|
||||||
super(SymlinkExtractorTests, self).setUp()
|
super(SymlinkExtractorTests, self).setUp()
|
||||||
self.symlinked_dir = os.path.join(self.test_dir, 'templates_symlinked')
|
self.symlinked_dir = os.path.join(self.test_dir, 'templates_symlinked')
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
super(SymlinkExtractorTests, self).tearDown()
|
|
||||||
os.chdir(self.test_dir)
|
|
||||||
try:
|
|
||||||
os.remove(self.symlinked_dir)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
os.chdir(self._cwd)
|
|
||||||
|
|
||||||
def test_symlink(self):
|
def test_symlink(self):
|
||||||
# On Python < 3.2 os.symlink() exists only on Unix
|
# On Python < 3.2 os.symlink() exists only on Unix
|
||||||
if hasattr(os, 'symlink'):
|
if hasattr(os, 'symlink'):
|
||||||
|
@ -561,17 +497,7 @@ class CopyPluralFormsExtractorTests(ExtractorTests):
|
||||||
|
|
||||||
PO_FILE_ES = 'locale/es/LC_MESSAGES/django.po'
|
PO_FILE_ES = 'locale/es/LC_MESSAGES/django.po'
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
super(CopyPluralFormsExtractorTests, self).tearDown()
|
|
||||||
os.chdir(self.test_dir)
|
|
||||||
try:
|
|
||||||
self._rmrf('locale/es')
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
os.chdir(self._cwd)
|
|
||||||
|
|
||||||
def test_copy_plural_forms(self):
|
def test_copy_plural_forms(self):
|
||||||
os.chdir(self.test_dir)
|
|
||||||
management.call_command('makemessages', locale=[LOCALE], verbosity=0)
|
management.call_command('makemessages', locale=[LOCALE], verbosity=0)
|
||||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||||
with open(self.PO_FILE, 'r') as fp:
|
with open(self.PO_FILE, 'r') as fp:
|
||||||
|
@ -580,7 +506,6 @@ class CopyPluralFormsExtractorTests(ExtractorTests):
|
||||||
|
|
||||||
def test_override_plural_forms(self):
|
def test_override_plural_forms(self):
|
||||||
"""Ticket #20311."""
|
"""Ticket #20311."""
|
||||||
os.chdir(self.test_dir)
|
|
||||||
management.call_command('makemessages', locale=['es'], extensions=['djtpl'], verbosity=0)
|
management.call_command('makemessages', locale=['es'], extensions=['djtpl'], verbosity=0)
|
||||||
self.assertTrue(os.path.exists(self.PO_FILE_ES))
|
self.assertTrue(os.path.exists(self.PO_FILE_ES))
|
||||||
with io.open(self.PO_FILE_ES, 'r', encoding='utf-8') as fp:
|
with io.open(self.PO_FILE_ES, 'r', encoding='utf-8') as fp:
|
||||||
|
@ -594,7 +519,6 @@ class CopyPluralFormsExtractorTests(ExtractorTests):
|
||||||
found inside a {% trans %} tag and also in another file inside a
|
found inside a {% trans %} tag and also in another file inside a
|
||||||
{% blocktrans %} with a plural (#17375).
|
{% blocktrans %} with a plural (#17375).
|
||||||
"""
|
"""
|
||||||
os.chdir(self.test_dir)
|
|
||||||
management.call_command('makemessages', locale=[LOCALE], extensions=['html', 'djtpl'], verbosity=0)
|
management.call_command('makemessages', locale=[LOCALE], extensions=['html', 'djtpl'], verbosity=0)
|
||||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||||
with open(self.PO_FILE, 'r') as fp:
|
with open(self.PO_FILE, 'r') as fp:
|
||||||
|
@ -607,7 +531,6 @@ class CopyPluralFormsExtractorTests(ExtractorTests):
|
||||||
class NoWrapExtractorTests(ExtractorTests):
|
class NoWrapExtractorTests(ExtractorTests):
|
||||||
|
|
||||||
def test_no_wrap_enabled(self):
|
def test_no_wrap_enabled(self):
|
||||||
os.chdir(self.test_dir)
|
|
||||||
management.call_command('makemessages', locale=[LOCALE], verbosity=0, no_wrap=True)
|
management.call_command('makemessages', locale=[LOCALE], verbosity=0, no_wrap=True)
|
||||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||||
with open(self.PO_FILE, 'r') as fp:
|
with open(self.PO_FILE, 'r') as fp:
|
||||||
|
@ -619,7 +542,6 @@ class NoWrapExtractorTests(ExtractorTests):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_no_wrap_disabled(self):
|
def test_no_wrap_disabled(self):
|
||||||
os.chdir(self.test_dir)
|
|
||||||
management.call_command('makemessages', locale=[LOCALE], verbosity=0, no_wrap=False)
|
management.call_command('makemessages', locale=[LOCALE], verbosity=0, no_wrap=False)
|
||||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||||
with open(self.PO_FILE, 'r') as fp:
|
with open(self.PO_FILE, 'r') as fp:
|
||||||
|
@ -636,14 +558,12 @@ class LocationCommentsTests(ExtractorTests):
|
||||||
|
|
||||||
def test_no_location_enabled(self):
|
def test_no_location_enabled(self):
|
||||||
"""Behavior is correct if --no-location switch is specified. See #16903."""
|
"""Behavior is correct if --no-location switch is specified. See #16903."""
|
||||||
os.chdir(self.test_dir)
|
|
||||||
management.call_command('makemessages', locale=[LOCALE], verbosity=0, no_location=True)
|
management.call_command('makemessages', locale=[LOCALE], verbosity=0, no_location=True)
|
||||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||||
self.assertLocationCommentNotPresent(self.PO_FILE, None, 'test.html')
|
self.assertLocationCommentNotPresent(self.PO_FILE, None, 'test.html')
|
||||||
|
|
||||||
def test_no_location_disabled(self):
|
def test_no_location_disabled(self):
|
||||||
"""Behavior is correct if --no-location switch isn't specified."""
|
"""Behavior is correct if --no-location switch isn't specified."""
|
||||||
os.chdir(self.test_dir)
|
|
||||||
management.call_command('makemessages', locale=[LOCALE], verbosity=0, no_location=False)
|
management.call_command('makemessages', locale=[LOCALE], verbosity=0, no_location=False)
|
||||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||||
# #16903 -- Standard comment with source file relative path should be present
|
# #16903 -- Standard comment with source file relative path should be present
|
||||||
|
@ -654,7 +574,6 @@ class LocationCommentsTests(ExtractorTests):
|
||||||
Ensure no leaky paths in comments, e.g. #: path\to\file.html.py:123
|
Ensure no leaky paths in comments, e.g. #: path\to\file.html.py:123
|
||||||
Refs #21209/#26341.
|
Refs #21209/#26341.
|
||||||
"""
|
"""
|
||||||
os.chdir(self.test_dir)
|
|
||||||
management.call_command('makemessages', locale=[LOCALE], verbosity=0)
|
management.call_command('makemessages', locale=[LOCALE], verbosity=0)
|
||||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||||
with open(self.PO_FILE, 'r') as fp:
|
with open(self.PO_FILE, 'r') as fp:
|
||||||
|
@ -668,28 +587,16 @@ class KeepPotFileExtractorTests(ExtractorTests):
|
||||||
|
|
||||||
POT_FILE = 'locale/django.pot'
|
POT_FILE = 'locale/django.pot'
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
super(KeepPotFileExtractorTests, self).tearDown()
|
|
||||||
os.chdir(self.test_dir)
|
|
||||||
try:
|
|
||||||
os.unlink(self.POT_FILE)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
os.chdir(self._cwd)
|
|
||||||
|
|
||||||
def test_keep_pot_disabled_by_default(self):
|
def test_keep_pot_disabled_by_default(self):
|
||||||
os.chdir(self.test_dir)
|
|
||||||
management.call_command('makemessages', locale=[LOCALE], verbosity=0)
|
management.call_command('makemessages', locale=[LOCALE], verbosity=0)
|
||||||
self.assertFalse(os.path.exists(self.POT_FILE))
|
self.assertFalse(os.path.exists(self.POT_FILE))
|
||||||
|
|
||||||
def test_keep_pot_explicitly_disabled(self):
|
def test_keep_pot_explicitly_disabled(self):
|
||||||
os.chdir(self.test_dir)
|
|
||||||
management.call_command('makemessages', locale=[LOCALE], verbosity=0,
|
management.call_command('makemessages', locale=[LOCALE], verbosity=0,
|
||||||
keep_pot=False)
|
keep_pot=False)
|
||||||
self.assertFalse(os.path.exists(self.POT_FILE))
|
self.assertFalse(os.path.exists(self.POT_FILE))
|
||||||
|
|
||||||
def test_keep_pot_enabled(self):
|
def test_keep_pot_enabled(self):
|
||||||
os.chdir(self.test_dir)
|
|
||||||
management.call_command('makemessages', locale=[LOCALE], verbosity=0,
|
management.call_command('makemessages', locale=[LOCALE], verbosity=0,
|
||||||
keep_pot=True)
|
keep_pot=True)
|
||||||
self.assertTrue(os.path.exists(self.POT_FILE))
|
self.assertTrue(os.path.exists(self.POT_FILE))
|
||||||
|
@ -700,18 +607,7 @@ class MultipleLocaleExtractionTests(ExtractorTests):
|
||||||
PO_FILE_DE = 'locale/de/LC_MESSAGES/django.po'
|
PO_FILE_DE = 'locale/de/LC_MESSAGES/django.po'
|
||||||
LOCALES = ['pt', 'de', 'ch']
|
LOCALES = ['pt', 'de', 'ch']
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
super(MultipleLocaleExtractionTests, self).tearDown()
|
|
||||||
os.chdir(self.test_dir)
|
|
||||||
for locale in self.LOCALES:
|
|
||||||
try:
|
|
||||||
self._rmrf('locale/%s' % locale)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
os.chdir(self._cwd)
|
|
||||||
|
|
||||||
def test_multiple_locales(self):
|
def test_multiple_locales(self):
|
||||||
os.chdir(self.test_dir)
|
|
||||||
management.call_command('makemessages', locale=['pt', 'de'], verbosity=0)
|
management.call_command('makemessages', locale=['pt', 'de'], verbosity=0)
|
||||||
self.assertTrue(os.path.exists(self.PO_FILE_PT))
|
self.assertTrue(os.path.exists(self.PO_FILE_PT))
|
||||||
self.assertTrue(os.path.exists(self.PO_FILE_DE))
|
self.assertTrue(os.path.exists(self.PO_FILE_DE))
|
||||||
|
@ -733,10 +629,8 @@ class ExcludedLocaleExtractionTests(ExtractorTests):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(ExcludedLocaleExtractionTests, self).setUp()
|
super(ExcludedLocaleExtractionTests, self).setUp()
|
||||||
os.chdir(self.test_dir) # ExtractorTests.tearDown() takes care of restoring.
|
copytree('canned_locale', 'locale')
|
||||||
shutil.copytree('canned_locale', 'locale')
|
|
||||||
self._set_times_for_all_po_files()
|
self._set_times_for_all_po_files()
|
||||||
self.addCleanup(self._rmrf, os.path.join(self.test_dir, 'locale'))
|
|
||||||
|
|
||||||
def test_command_help(self):
|
def test_command_help(self):
|
||||||
with captured_stdout(), captured_stderr():
|
with captured_stdout(), captured_stderr():
|
||||||
|
@ -776,7 +670,6 @@ class CustomLayoutExtractionTests(ExtractorTests):
|
||||||
work_subdir = 'project_dir'
|
work_subdir = 'project_dir'
|
||||||
|
|
||||||
def test_no_locale_raises(self):
|
def test_no_locale_raises(self):
|
||||||
os.chdir(self.test_dir)
|
|
||||||
msg = "Unable to find a locale path to store translations for file"
|
msg = "Unable to find a locale path to store translations for file"
|
||||||
with self.assertRaisesMessage(management.CommandError, msg):
|
with self.assertRaisesMessage(management.CommandError, msg):
|
||||||
management.call_command('makemessages', locale=LOCALE, verbosity=0)
|
management.call_command('makemessages', locale=LOCALE, verbosity=0)
|
||||||
|
@ -788,10 +681,6 @@ class CustomLayoutExtractionTests(ExtractorTests):
|
||||||
* translations outside of that app are in LOCALE_PATHS[0]
|
* translations outside of that app are in LOCALE_PATHS[0]
|
||||||
"""
|
"""
|
||||||
with override_settings(LOCALE_PATHS=[os.path.join(self.test_dir, 'project_locale')]):
|
with override_settings(LOCALE_PATHS=[os.path.join(self.test_dir, 'project_locale')]):
|
||||||
os.chdir(self.test_dir)
|
|
||||||
self.addCleanup(shutil.rmtree, os.path.join(settings.LOCALE_PATHS[0], LOCALE), True)
|
|
||||||
self.addCleanup(shutil.rmtree, os.path.join(self.test_dir, 'app_with_locale', 'locale', LOCALE), True)
|
|
||||||
|
|
||||||
management.call_command('makemessages', locale=[LOCALE], verbosity=0)
|
management.call_command('makemessages', locale=[LOCALE], verbosity=0)
|
||||||
project_de_locale = os.path.join(
|
project_de_locale = os.path.join(
|
||||||
self.test_dir, 'project_locale', 'de', 'LC_MESSAGES', 'django.po')
|
self.test_dir, 'project_locale', 'de', 'LC_MESSAGES', 'django.po')
|
||||||
|
|
|
@ -9,7 +9,8 @@ from django.utils._os import upath
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.translation import activate, get_language, trans_real
|
from django.utils.translation import activate, get_language, trans_real
|
||||||
|
|
||||||
from .test_extraction import POFileAssertionMixin
|
from .utils import POFileAssertionMixin
|
||||||
|
|
||||||
|
|
||||||
SAMPLEPROJECT_DIR = os.path.join(os.path.dirname(os.path.abspath(upath(__file__))), 'sampleproject')
|
SAMPLEPROJECT_DIR = os.path.join(os.path.dirname(os.path.abspath(upath(__file__))), 'sampleproject')
|
||||||
SAMPLEPROJECT_LOCALE = os.path.join(SAMPLEPROJECT_DIR, 'locale')
|
SAMPLEPROJECT_LOCALE = os.path.join(SAMPLEPROJECT_DIR, 'locale')
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import shutil
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
from django.utils._os import upath
|
||||||
|
|
||||||
|
|
||||||
|
source_code_dir = os.path.dirname(upath(__file__))
|
||||||
|
|
||||||
|
|
||||||
|
def copytree(src, dst):
|
||||||
|
shutil.copytree(src, dst, ignore=shutil.ignore_patterns('*.pyc', '__pycache__'))
|
||||||
|
|
||||||
|
|
||||||
|
class POFileAssertionMixin(object):
|
||||||
|
|
||||||
|
def _assertPoKeyword(self, keyword, expected_value, haystack, use_quotes=True):
|
||||||
|
q = '"'
|
||||||
|
if use_quotes:
|
||||||
|
expected_value = '"%s"' % expected_value
|
||||||
|
q = "'"
|
||||||
|
needle = '%s %s' % (keyword, expected_value)
|
||||||
|
expected_value = re.escape(expected_value)
|
||||||
|
return self.assertTrue(
|
||||||
|
re.search('^%s %s' % (keyword, expected_value), haystack, re.MULTILINE),
|
||||||
|
'Could not find %(q)s%(n)s%(q)s in generated PO file' % {'n': needle, 'q': q}
|
||||||
|
)
|
||||||
|
|
||||||
|
def assertMsgId(self, msgid, haystack, use_quotes=True):
|
||||||
|
return self._assertPoKeyword('msgid', msgid, haystack, use_quotes=use_quotes)
|
||||||
|
|
||||||
|
|
||||||
|
class RunInTmpDirMixin(object):
|
||||||
|
"""
|
||||||
|
Allow i18n tests that need to generate .po/.mo files to run in an isolated
|
||||||
|
temporary filesystem tree created by tempfile.mkdtemp() that contains a
|
||||||
|
clean copy of the relevant test code.
|
||||||
|
|
||||||
|
Test classes using this mixin need to define a `work_subdir` attribute
|
||||||
|
which designates the subdir under `tests/i18n/` that will be copied to the
|
||||||
|
temporary tree from which its test cases will run.
|
||||||
|
|
||||||
|
The setUp() method sets the current working dir to the temporary tree.
|
||||||
|
It'll be removed when cleaning up.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self._cwd = os.getcwd()
|
||||||
|
self.work_dir = tempfile.mkdtemp(prefix='i18n_')
|
||||||
|
self.test_dir = os.path.abspath(os.path.join(self.work_dir, self.work_subdir))
|
||||||
|
copytree(os.path.join(source_code_dir, self.work_subdir), self.test_dir)
|
||||||
|
# Step out of the temporary working tree before removing it to avoid
|
||||||
|
# deletion problems on Windows. Cleanup actions registered with
|
||||||
|
# addCleanup() are called in reverse so preserve this ordering.
|
||||||
|
self.addCleanup(self._rmrf, self.test_dir)
|
||||||
|
self.addCleanup(os.chdir, self._cwd)
|
||||||
|
os.chdir(self.test_dir)
|
||||||
|
|
||||||
|
def _rmrf(self, dname):
|
||||||
|
if os.path.commonprefix([self.test_dir, os.path.abspath(dname)]) != self.test_dir:
|
||||||
|
return
|
||||||
|
shutil.rmtree(dname)
|
||||||
|
|
||||||
|
def rmfile(self, filepath):
|
||||||
|
if os.path.exists(filepath):
|
||||||
|
os.remove(filepath)
|
Loading…
Reference in New Issue