mirror of
				https://github.com/django/django.git
				synced 2025-10-26 07:06:08 +00:00 
			
		
		
		
	Fixed #22328 -- Added --exclude option to compilemessages and makemessages.
This commit is contained in:
		
				
					committed by
					
						 Loic Bistuer
						Loic Bistuer
					
				
			
			
				
	
			
			
			
						parent
						
							d1f93e9c1e
						
					
				
				
					commit
					0707b824fe
				
			
							
								
								
									
										1
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								AUTHORS
									
									
									
									
									
								
							| @@ -367,6 +367,7 @@ answer newbie questions, and generally made Django that much better: | ||||
|     Martin Kosír <martin@martinkosir.net> | ||||
|     Arthur Koziel <http://arthurkoziel.com> | ||||
|     Meir Kriheli <http://mksoft.co.il/> | ||||
|     Ana Krivokapic <https://github.com/infraredgirl> | ||||
|     Bruce Kroeze <http://coderseye.com/> | ||||
|     krzysiek.pawlik@silvermedia.pl | ||||
|     konrad@gwu.edu | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| from __future__ import unicode_literals | ||||
|  | ||||
| import codecs | ||||
| import glob | ||||
| import os | ||||
| from optparse import make_option | ||||
|  | ||||
| @@ -30,8 +31,11 @@ def is_writable(path): | ||||
|  | ||||
| class Command(BaseCommand): | ||||
|     option_list = BaseCommand.option_list + ( | ||||
|         make_option('--locale', '-l', dest='locale', action='append', | ||||
|                     help='locale(s) to process (e.g. de_AT). Default is to process all. Can be used multiple times.'), | ||||
|         make_option('--locale', '-l', dest='locale', action='append', default=[], | ||||
|                     help='Locale(s) to process (e.g. de_AT). Default is to process all. Can be ' | ||||
|                          'used multiple times.'), | ||||
|         make_option('--exclude', '-e', dest='exclude', action='append', default=[], | ||||
|                     help='Locales to exclude. Default is none. Can be used multiple times.'), | ||||
|     ) | ||||
|     help = 'Compiles .po files to .mo files for use with builtin gettext support.' | ||||
|  | ||||
| @@ -43,6 +47,7 @@ class Command(BaseCommand): | ||||
|  | ||||
|     def handle(self, **options): | ||||
|         locale = options.get('locale') | ||||
|         exclude = options.get('exclude') | ||||
|         self.verbosity = int(options.get('verbosity')) | ||||
|  | ||||
|         if find_command(self.program) is None: | ||||
| @@ -62,9 +67,19 @@ class Command(BaseCommand): | ||||
|                                "checkout or your project or app tree, or with " | ||||
|                                "the settings module specified.") | ||||
|  | ||||
|         # Build locale list | ||||
|         all_locales = [] | ||||
|         for basedir in basedirs: | ||||
|             if locale: | ||||
|                 dirs = [os.path.join(basedir, l, 'LC_MESSAGES') for l in locale] | ||||
|             locale_dirs = filter(os.path.isdir, glob.glob('%s/*' % basedir)) | ||||
|             all_locales.extend(map(os.path.basename, locale_dirs)) | ||||
|  | ||||
|         # Account for excluded locales | ||||
|         locales = locale or all_locales | ||||
|         locales = set(locales) - set(exclude) | ||||
|  | ||||
|         for basedir in basedirs: | ||||
|             if locales: | ||||
|                 dirs = [os.path.join(basedir, l, 'LC_MESSAGES') for l in locales] | ||||
|             else: | ||||
|                 dirs = [basedir] | ||||
|             locations = [] | ||||
| @@ -90,8 +105,8 @@ class Command(BaseCommand): | ||||
|  | ||||
|             # Check writability on first location | ||||
|             if i == 0 and not is_writable(npath(base_path + '.mo')): | ||||
|                 self.stderr.write("The po files under %s are in a seemingly not " | ||||
|                                   "writable location. mo files will not be updated/created." % dirpath) | ||||
|                 self.stderr.write("The po files under %s are in a seemingly not writable location. " | ||||
|                                   "mo files will not be updated/created." % dirpath) | ||||
|                 return | ||||
|  | ||||
|             args = [self.program] + self.program_options + ['-o', | ||||
|   | ||||
| @@ -160,9 +160,11 @@ def write_pot_file(potfile, msgs): | ||||
|  | ||||
| class Command(NoArgsCommand): | ||||
|     option_list = NoArgsCommand.option_list + ( | ||||
|         make_option('--locale', '-l', default=None, dest='locale', action='append', | ||||
|         make_option('--locale', '-l', default=[], dest='locale', action='append', | ||||
|             help='Creates or updates the message files for the given locale(s) (e.g. pt_BR). ' | ||||
|                  'Can be used multiple times.'), | ||||
|         make_option('--exclude', '-e', default=[], dest='exclude', action='append', | ||||
|                     help='Locales to exclude. Default is none. Can be used multiple times.'), | ||||
|         make_option('--domain', '-d', default='django', dest='domain', | ||||
|             help='The domain of the message files (default: "django").'), | ||||
|         make_option('--all', '-a', action='store_true', dest='all', | ||||
| @@ -189,7 +191,7 @@ class Command(NoArgsCommand): | ||||
| "pulls out all strings marked for translation. It creates (or updates) a message " | ||||
| "file in the conf/locale (in the django tree) or locale (for projects and " | ||||
| "applications) directory.\n\nYou must run this command with one of either the " | ||||
| "--locale or --all options.") | ||||
| "--locale, --exclude or --all options.") | ||||
|  | ||||
|     requires_system_checks = False | ||||
|     leave_locale_alone = True | ||||
| @@ -201,6 +203,7 @@ class Command(NoArgsCommand): | ||||
|  | ||||
|     def handle_noargs(self, *args, **options): | ||||
|         locale = options.get('locale') | ||||
|         exclude = options.get('exclude') | ||||
|         self.domain = options.get('domain') | ||||
|         self.verbosity = int(options.get('verbosity')) | ||||
|         process_all = options.get('all') | ||||
| @@ -235,7 +238,7 @@ class Command(NoArgsCommand): | ||||
|             exts = extensions if extensions else ['html', 'txt'] | ||||
|         self.extensions = handle_extensions(exts) | ||||
|  | ||||
|         if (locale is None and not process_all) or self.domain is None: | ||||
|         if (locale is None and not exclude and not process_all) or self.domain is None: | ||||
|             raise CommandError("Type '%s help %s' for usage information." % ( | ||||
|                 os.path.basename(sys.argv[0]), sys.argv[1])) | ||||
|  | ||||
| @@ -270,12 +273,16 @@ class Command(NoArgsCommand): | ||||
|                     os.makedirs(self.default_locale_path) | ||||
|  | ||||
|         # Build locale list | ||||
|         locales = [] | ||||
|         if locale is not None: | ||||
|             locales = locale | ||||
|         elif process_all: | ||||
|             locale_dirs = filter(os.path.isdir, glob.glob('%s/*' % self.default_locale_path)) | ||||
|             locales = [os.path.basename(l) for l in locale_dirs] | ||||
|         locale_dirs = filter(os.path.isdir, glob.glob('%s/*' % self.default_locale_path)) | ||||
|         all_locales = map(os.path.basename, locale_dirs) | ||||
|  | ||||
|         # Account for excluded locales | ||||
|         if process_all: | ||||
|             locales = all_locales | ||||
|         else: | ||||
|             locales = locale or all_locales | ||||
|             locales = set(locales) - set(exclude) | ||||
|  | ||||
|         if locales: | ||||
|             check_programs('msguniq', 'msgmerge', 'msgattrib') | ||||
|  | ||||
|   | ||||
| @@ -21,7 +21,7 @@ script found at the top level of each Django project directory. | ||||
| .BI cleanup | ||||
| Cleans out old data from the database (only expired sessions at the moment). | ||||
| .TP | ||||
| .BI "compilemessages [" "\-\-locale=LOCALE" "]" | ||||
| .BI "compilemessages [" "\-\-locale=LOCALE" "] [" "\-\-exclude=LOCALE" "]" | ||||
| Compiles .po files to .mo files for use with builtin gettext support. | ||||
| .TP | ||||
| .BI "createcachetable [" "tablename" "]" | ||||
| @@ -59,7 +59,7 @@ Executes | ||||
| .B sqlall | ||||
| for the given app(s) in the current database. | ||||
| .TP | ||||
| .BI "makemessages [" "\-\-locale=LOCALE" "] [" "\-\-domain=DOMAIN" "] [" "\-\-extension=EXTENSION" "] [" "\-\-all" "] [" "\-\-symlinks" "] [" "\-\-ignore=PATTERN" "] [" "\-\-no\-default\-ignore" "] [" "\-\-no\-wrap" "] [" "\-\-no\-location" "]" | ||||
| .BI "makemessages [" "\-\-locale=LOCALE" "] [" "\-\-exclude=LOCALE" "] [" "\-\-domain=DOMAIN" "] [" "\-\-extension=EXTENSION" "] [" "\-\-all" "] [" "\-\-symlinks" "] [" "\-\-ignore=PATTERN" "] [" "\-\-no\-default\-ignore" "] [" "\-\-no\-wrap" "] [" "\-\-no\-location" "]" | ||||
| Runs over the entire source tree of the current directory and pulls out all | ||||
| strings marked for translation. It creates (or updates) a message file in the | ||||
| conf/locale (in the django tree) or locale (for project and application) directory. | ||||
| @@ -176,6 +176,9 @@ output a full stack trace whenever an exception is raised. | ||||
| .I \-l, \-\-locale=LOCALE | ||||
| The locale to process when using makemessages or compilemessages. | ||||
| .TP | ||||
| .I \-e, \-\-exclude=LOCALE | ||||
| The locale to exclude from processing when using makemessages or compilemessages. | ||||
| .TP | ||||
| .I \-d, \-\-domain=DOMAIN | ||||
| The domain of the message files (default: "django") when using makemessages. | ||||
| .TP | ||||
|   | ||||
| @@ -141,12 +141,22 @@ the builtin gettext support. See :doc:`/topics/i18n/index`. | ||||
| Use the :djadminopt:`--locale` option (or its shorter version ``-l``) to | ||||
| specify the locale(s) to process. If not provided, all locales are processed. | ||||
|  | ||||
| .. versionadded:: 1.8 | ||||
|  | ||||
| Use the :djadminopt:`--exclude` option (or its shorter version ``-e``) to | ||||
| specify the locale(s) to exclude from processing. If not provided, no locales | ||||
| are excluded. | ||||
|  | ||||
| Example usage:: | ||||
|  | ||||
|     django-admin.py compilemessages --locale=pt_BR | ||||
|     django-admin.py compilemessages --locale=pt_BR --locale=fr | ||||
|     django-admin.py compilemessages -l pt_BR | ||||
|     django-admin.py compilemessages -l pt_BR -l fr | ||||
|     django-admin.py compilemessages --exclude=pt_BR | ||||
|     django-admin.py compilemessages --exclude=pt_BR --exclude=fr | ||||
|     django-admin.py compilemessages -e pt_BR | ||||
|     django-admin.py compilemessages -e pt_BR -e fr | ||||
|  | ||||
| createcachetable | ||||
| ---------------- | ||||
| @@ -551,12 +561,23 @@ Separate multiple extensions with commas or use -e or --extension multiple times | ||||
| Use the :djadminopt:`--locale` option (or its shorter version ``-l``) to | ||||
| specify the locale(s) to process. | ||||
|  | ||||
| .. versionadded:: 1.8 | ||||
|  | ||||
| Use the :djadminopt:`--exclude` option (or its shorter version ``-e``) to | ||||
| specify the locale(s) to exclude from processing. If not provided, no locales | ||||
| are excluded. | ||||
|  | ||||
| Example usage:: | ||||
|  | ||||
|     django-admin.py makemessages --locale=pt_BR | ||||
|     django-admin.py makemessages --locale=pt_BR --locale=fr | ||||
|     django-admin.py makemessages -l pt_BR | ||||
|     django-admin.py makemessages -l pt_BR -l fr | ||||
|     django-admin.py makemessages --exclude=pt_BR | ||||
|     django-admin.py makemessages --exclude=pt_BR --exclude=fr | ||||
|     django-admin.py makemessages -e pt_BR | ||||
|     django-admin.py makemessages -e pt_BR -e fr | ||||
|  | ||||
|  | ||||
| .. versionchanged:: 1.7 | ||||
|  | ||||
|   | ||||
| @@ -128,6 +128,10 @@ Management Commands | ||||
| * :djadmin:`dumpdata` now has the option :djadminopt:`--output` which allows | ||||
|   specifying the file to which the serialized data is written. | ||||
|  | ||||
| * :djadmin:`makemessages` and :djadmin:`compilemessages` now have the option | ||||
|   :djadminopt:`--exclude` which allows exclusion of specific locales from | ||||
|   processing. | ||||
|  | ||||
| Models | ||||
| ^^^^^^ | ||||
|  | ||||
|   | ||||
							
								
								
									
										12
									
								
								tests/i18n/exclude/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								tests/i18n/exclude/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| # This package is used to test the --exclude option of | ||||
| # the makemessages and compilemessages management commands. | ||||
| # The locale directory for this app is generated automatically | ||||
| # by the test cases. | ||||
|  | ||||
| from django.utils.translation import ugettext as _ | ||||
|  | ||||
| # Translators: This comment should be extracted | ||||
| dummy1 = _("This is a translatable string.") | ||||
|  | ||||
| # This comment should not be extracted | ||||
| dummy2 = _("This is another translatable string.") | ||||
							
								
								
									
										27
									
								
								tests/i18n/exclude/canned_locale/en/LC_MESSAGES/django.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								tests/i18n/exclude/canned_locale/en/LC_MESSAGES/django.po
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| # SOME DESCRIPTIVE TITLE. | ||||
| # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER | ||||
| # This file is distributed under the same license as the PACKAGE package. | ||||
| # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. | ||||
| # | ||||
| #, fuzzy | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: PACKAGE VERSION\n" | ||||
| "Report-Msgid-Bugs-To: \n" | ||||
| "POT-Creation-Date: 2014-04-25 15:39-0500\n" | ||||
| "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | ||||
| "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||||
| "Language-Team: LANGUAGE <LL@li.org>\n" | ||||
| "Language: \n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
|  | ||||
| #. Translators: This comment should be extracted | ||||
| #: __init__.py:8 | ||||
| msgid "This is a translatable string." | ||||
| msgstr "" | ||||
|  | ||||
| #: __init__.py:11 | ||||
| msgid "This is another translatable string." | ||||
| msgstr "" | ||||
							
								
								
									
										28
									
								
								tests/i18n/exclude/canned_locale/fr/LC_MESSAGES/django.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								tests/i18n/exclude/canned_locale/fr/LC_MESSAGES/django.po
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| # SOME DESCRIPTIVE TITLE. | ||||
| # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER | ||||
| # This file is distributed under the same license as the PACKAGE package. | ||||
| # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. | ||||
| # | ||||
| #, fuzzy | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: PACKAGE VERSION\n" | ||||
| "Report-Msgid-Bugs-To: \n" | ||||
| "POT-Creation-Date: 2014-04-25 15:39-0500\n" | ||||
| "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | ||||
| "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||||
| "Language-Team: LANGUAGE <LL@li.org>\n" | ||||
| "Language: \n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=2; plural=(n > 1);\n" | ||||
|  | ||||
| #. Translators: This comment should be extracted | ||||
| #: __init__.py:8 | ||||
| msgid "This is a translatable string." | ||||
| msgstr "" | ||||
|  | ||||
| #: __init__.py:11 | ||||
| msgid "This is another translatable string." | ||||
| msgstr "" | ||||
							
								
								
									
										28
									
								
								tests/i18n/exclude/canned_locale/it/LC_MESSAGES/django.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								tests/i18n/exclude/canned_locale/it/LC_MESSAGES/django.po
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| # SOME DESCRIPTIVE TITLE. | ||||
| # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER | ||||
| # This file is distributed under the same license as the PACKAGE package. | ||||
| # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. | ||||
| # | ||||
| #, fuzzy | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: PACKAGE VERSION\n" | ||||
| "Report-Msgid-Bugs-To: \n" | ||||
| "POT-Creation-Date: 2014-04-25 15:39-0500\n" | ||||
| "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | ||||
| "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||||
| "Language-Team: LANGUAGE <LL@li.org>\n" | ||||
| "Language: \n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=2; plural=(n != 1);\n" | ||||
|  | ||||
| #. Translators: This comment should be extracted | ||||
| #: __init__.py:8 | ||||
| msgid "This is a translatable string." | ||||
| msgstr "" | ||||
|  | ||||
| #: __init__.py:11 | ||||
| msgid "This is another translatable string." | ||||
| msgstr "" | ||||
| @@ -1,4 +1,5 @@ | ||||
| import os | ||||
| import shutil | ||||
| import stat | ||||
| import unittest | ||||
|  | ||||
| @@ -10,17 +11,23 @@ from django.utils import translation | ||||
| from django.utils._os import upath | ||||
| from django.utils.six import StringIO | ||||
|  | ||||
| test_dir = os.path.abspath(os.path.join(os.path.dirname(upath(__file__)), 'commands')) | ||||
| has_msgfmt = find_command('msgfmt') | ||||
|  | ||||
|  | ||||
| @unittest.skipUnless(has_msgfmt, 'msgfmt is mandatory for compilation tests') | ||||
| class MessageCompilationTests(SimpleTestCase): | ||||
|  | ||||
|     test_dir = os.path.abspath(os.path.join(os.path.dirname(upath(__file__)), 'commands')) | ||||
|  | ||||
|     def setUp(self): | ||||
|         self._cwd = os.getcwd() | ||||
|         self.addCleanup(os.chdir, self._cwd) | ||||
|         os.chdir(test_dir) | ||||
|         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): | ||||
| @@ -60,7 +67,7 @@ class PoFileContentsTests(MessageCompilationTests): | ||||
|  | ||||
|     def setUp(self): | ||||
|         super(PoFileContentsTests, self).setUp() | ||||
|         self.addCleanup(os.unlink, os.path.join(test_dir, self.MO_FILE)) | ||||
|         self.addCleanup(os.unlink, os.path.join(self.test_dir, self.MO_FILE)) | ||||
|  | ||||
|     def test_percent_symbol_in_po_file(self): | ||||
|         call_command('compilemessages', locale=[self.LOCALE], stdout=StringIO()) | ||||
| @@ -76,45 +83,85 @@ class PercentRenderingTests(MessageCompilationTests): | ||||
|  | ||||
|     def setUp(self): | ||||
|         super(PercentRenderingTests, self).setUp() | ||||
|         self.addCleanup(os.unlink, os.path.join(test_dir, self.MO_FILE)) | ||||
|         self.addCleanup(os.unlink, os.path.join(self.test_dir, self.MO_FILE)) | ||||
|  | ||||
|     @override_settings(LOCALE_PATHS=(os.path.join(test_dir, 'locale'),)) | ||||
|     def test_percent_symbol_escaping(self): | ||||
|         from django.template import Template, Context | ||||
|         call_command('compilemessages', locale=[self.LOCALE], stdout=StringIO()) | ||||
|         with translation.override(self.LOCALE): | ||||
|             t = Template('{% load i18n %}{% trans "Looks like a str fmt spec %% o but shouldn\'t be interpreted as such" %}') | ||||
|             rendered = t.render(Context({})) | ||||
|             self.assertEqual(rendered, 'IT translation contains %% for the above string') | ||||
|         with override_settings(LOCALE_PATHS=(os.path.join(self.test_dir, 'locale'),)): | ||||
|             from django.template import Template, Context | ||||
|             call_command('compilemessages', locale=[self.LOCALE], stdout=StringIO()) | ||||
|             with translation.override(self.LOCALE): | ||||
|                 t = Template('{% load i18n %}{% trans "Looks like a str fmt spec %% o but shouldn\'t be interpreted as such" %}') | ||||
|                 rendered = t.render(Context({})) | ||||
|                 self.assertEqual(rendered, 'IT translation contains %% for the above string') | ||||
|  | ||||
|             t = Template('{% load i18n %}{% trans "Completed 50%% of all the tasks" %}') | ||||
|             rendered = t.render(Context({})) | ||||
|             self.assertEqual(rendered, 'IT translation of Completed 50%% of all the tasks') | ||||
|                 t = Template('{% load i18n %}{% trans "Completed 50%% of all the tasks" %}') | ||||
|                 rendered = t.render(Context({})) | ||||
|                 self.assertEqual(rendered, 'IT translation of Completed 50%% of all the tasks') | ||||
|  | ||||
|  | ||||
| @override_settings(LOCALE_PATHS=(os.path.join(test_dir, 'locale'),)) | ||||
| class MultipleLocaleCompilationTests(MessageCompilationTests): | ||||
|  | ||||
|     MO_FILE_HR = None | ||||
|     MO_FILE_FR = None | ||||
|  | ||||
|     def setUp(self): | ||||
|         super(MultipleLocaleCompilationTests, self).setUp() | ||||
|         localedir = os.path.join(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_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): | ||||
|         call_command('compilemessages', locale=['hr'], stdout=StringIO()) | ||||
|         with override_settings(LOCALE_PATHS=(os.path.join(self.test_dir, 'locale'),)): | ||||
|             call_command('compilemessages', locale=['hr'], stdout=StringIO()) | ||||
|  | ||||
|         self.assertTrue(os.path.exists(self.MO_FILE_HR)) | ||||
|             self.assertTrue(os.path.exists(self.MO_FILE_HR)) | ||||
|  | ||||
|     def test_multiple_locales(self): | ||||
|         call_command('compilemessages', locale=['hr', 'fr'], stdout=StringIO()) | ||||
|         with override_settings(LOCALE_PATHS=(os.path.join(self.test_dir, 'locale'),)): | ||||
|             call_command('compilemessages', locale=['hr', 'fr'], stdout=StringIO()) | ||||
|  | ||||
|         self.assertTrue(os.path.exists(self.MO_FILE_HR)) | ||||
|         self.assertTrue(os.path.exists(self.MO_FILE_FR)) | ||||
|             self.assertTrue(os.path.exists(self.MO_FILE_HR)) | ||||
|             self.assertTrue(os.path.exists(self.MO_FILE_FR)) | ||||
|  | ||||
|  | ||||
| class ExcludedLocaleCompilationTests(MessageCompilationTests): | ||||
|  | ||||
|     test_dir = os.path.abspath(os.path.join(os.path.dirname(upath(__file__)), 'exclude')) | ||||
|  | ||||
|     MO_FILE = 'locale/%s/LC_MESSAGES/django.mo' | ||||
|  | ||||
|     def setUp(self): | ||||
|         super(ExcludedLocaleCompilationTests, self).setUp() | ||||
|  | ||||
|         shutil.copytree('canned_locale', 'locale') | ||||
|         self.addCleanup(self._rmrf, os.path.join(self.test_dir, 'locale')) | ||||
|  | ||||
|     def test_one_locale_excluded(self): | ||||
|         call_command('compilemessages', exclude=['it'], stdout=StringIO()) | ||||
|         self.assertTrue(os.path.exists(self.MO_FILE % 'en')) | ||||
|         self.assertTrue(os.path.exists(self.MO_FILE % 'fr')) | ||||
|         self.assertFalse(os.path.exists(self.MO_FILE % 'it')) | ||||
|  | ||||
|     def test_multiple_locales_excluded(self): | ||||
|         call_command('compilemessages', exclude=['it', 'fr'], stdout=StringIO()) | ||||
|         self.assertTrue(os.path.exists(self.MO_FILE % 'en')) | ||||
|         self.assertFalse(os.path.exists(self.MO_FILE % 'fr')) | ||||
|         self.assertFalse(os.path.exists(self.MO_FILE % 'it')) | ||||
|  | ||||
|     def test_one_locale_excluded_with_locale(self): | ||||
|         call_command('compilemessages', locale=['en', 'fr'], exclude=['fr'], stdout=StringIO()) | ||||
|         self.assertTrue(os.path.exists(self.MO_FILE % 'en')) | ||||
|         self.assertFalse(os.path.exists(self.MO_FILE % 'fr')) | ||||
|         self.assertFalse(os.path.exists(self.MO_FILE % 'it')) | ||||
|  | ||||
|     def test_multiple_locales_excluded_with_locale(self): | ||||
|         call_command('compilemessages', locale=['en', 'fr', 'it'], exclude=['fr', 'it'], | ||||
|                      stdout=StringIO()) | ||||
|         self.assertTrue(os.path.exists(self.MO_FILE % 'en')) | ||||
|         self.assertFalse(os.path.exists(self.MO_FILE % 'fr')) | ||||
|         self.assertFalse(os.path.exists(self.MO_FILE % 'it')) | ||||
|  | ||||
|  | ||||
| class CompilationErrorHandling(MessageCompilationTests): | ||||
| @@ -124,7 +171,7 @@ class CompilationErrorHandling(MessageCompilationTests): | ||||
|  | ||||
|     def setUp(self): | ||||
|         super(CompilationErrorHandling, self).setUp() | ||||
|         self.addCleanup(self.rmfile, os.path.join(test_dir, self.MO_FILE)) | ||||
|         self.addCleanup(self.rmfile, os.path.join(self.test_dir, self.MO_FILE)) | ||||
|  | ||||
|     def test_error_reported_by_msgfmt(self): | ||||
|         with self.assertRaises(CommandError): | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import io | ||||
| import os | ||||
| import re | ||||
| import shutil | ||||
| import time | ||||
| from unittest import SkipTest, skipUnless | ||||
| import warnings | ||||
|  | ||||
| @@ -27,12 +28,12 @@ has_xgettext = find_command('xgettext') | ||||
| @skipUnless(has_xgettext, 'xgettext is mandatory for extraction tests') | ||||
| class ExtractorTests(SimpleTestCase): | ||||
|  | ||||
|     test_dir = os.path.abspath(os.path.join(os.path.dirname(upath(__file__)), 'commands')) | ||||
|  | ||||
|     PO_FILE = 'locale/%s/LC_MESSAGES/django.po' % LOCALE | ||||
|  | ||||
|     def setUp(self): | ||||
|         self._cwd = os.getcwd() | ||||
|         self.test_dir = os.path.abspath( | ||||
|             os.path.join(os.path.dirname(upath(__file__)), 'commands')) | ||||
|  | ||||
|     def _rmrf(self, dname): | ||||
|         if os.path.commonprefix([self.test_dir, os.path.abspath(dname)]) != self.test_dir: | ||||
| @@ -103,6 +104,20 @@ class ExtractorTests(SimpleTestCase): | ||||
|         """Check the opposite of assertLocationComment()""" | ||||
|         return self._assertPoLocComment(False, po_filename, line_number, *comment_parts) | ||||
|  | ||||
|     def assertRecentlyModified(self, path): | ||||
|         """ | ||||
|         Assert that file was recently modified (modification time was less than 10 seconds ago). | ||||
|         """ | ||||
|         delta = time.time() - os.stat(path).st_mtime | ||||
|         self.assertLess(delta, 10, "%s was recently modified" % path) | ||||
|  | ||||
|     def assertNotRecentlyModified(self, path): | ||||
|         """ | ||||
|         Assert that file was not recently modified (modification time was more than 10 seconds ago). | ||||
|         """ | ||||
|         delta = time.time() - os.stat(path).st_mtime | ||||
|         self.assertGreater(delta, 10, "%s wasn't recently modified" % path) | ||||
|  | ||||
|  | ||||
| class BasicExtractorTests(ExtractorTests): | ||||
|  | ||||
| @@ -402,6 +417,7 @@ class SymlinkExtractorTests(ExtractorTests): | ||||
|  | ||||
|  | ||||
| class CopyPluralFormsExtractorTests(ExtractorTests): | ||||
|  | ||||
|     PO_FILE_ES = 'locale/es/LC_MESSAGES/django.po' | ||||
|  | ||||
|     def tearDown(self): | ||||
| @@ -527,7 +543,56 @@ class MultipleLocaleExtractionTests(ExtractorTests): | ||||
|         self.assertTrue(os.path.exists(self.PO_FILE_DE)) | ||||
|  | ||||
|  | ||||
| class ExcludedLocaleExtractionTests(ExtractorTests): | ||||
|  | ||||
|     LOCALES = ['en', 'fr', 'it'] | ||||
|     PO_FILE = 'locale/%s/LC_MESSAGES/django.po' | ||||
|  | ||||
|     test_dir = os.path.abspath(os.path.join(os.path.dirname(upath(__file__)), 'exclude')) | ||||
|  | ||||
|     def _set_times_for_all_po_files(self): | ||||
|         """ | ||||
|         Set access and modification times to the Unix epoch time for all the .po files. | ||||
|         """ | ||||
|         for locale in self.LOCALES: | ||||
|             os.utime(self.PO_FILE % locale, (0, 0)) | ||||
|  | ||||
|     def setUp(self): | ||||
|         super(ExcludedLocaleExtractionTests, self).setUp() | ||||
|  | ||||
|         os.chdir(self.test_dir)  # ExtractorTests.tearDown() takes care of restoring. | ||||
|         shutil.copytree('canned_locale', 'locale') | ||||
|         self._set_times_for_all_po_files() | ||||
|         self.addCleanup(self._rmrf, os.path.join(self.test_dir, 'locale')) | ||||
|  | ||||
|     def test_one_locale_excluded(self): | ||||
|         management.call_command('makemessages', exclude=['it'], stdout=StringIO()) | ||||
|         self.assertRecentlyModified(self.PO_FILE % 'en') | ||||
|         self.assertRecentlyModified(self.PO_FILE % 'fr') | ||||
|         self.assertNotRecentlyModified(self.PO_FILE % 'it') | ||||
|  | ||||
|     def test_multiple_locales_excluded(self): | ||||
|         management.call_command('makemessages', exclude=['it', 'fr'], stdout=StringIO()) | ||||
|         self.assertRecentlyModified(self.PO_FILE % 'en') | ||||
|         self.assertNotRecentlyModified(self.PO_FILE % 'fr') | ||||
|         self.assertNotRecentlyModified(self.PO_FILE % 'it') | ||||
|  | ||||
|     def test_one_locale_excluded_with_locale(self): | ||||
|         management.call_command('makemessages', locale=['en', 'fr'], exclude=['fr'], stdout=StringIO()) | ||||
|         self.assertRecentlyModified(self.PO_FILE % 'en') | ||||
|         self.assertNotRecentlyModified(self.PO_FILE % 'fr') | ||||
|         self.assertNotRecentlyModified(self.PO_FILE % 'it') | ||||
|  | ||||
|     def test_multiple_locales_excluded_with_locale(self): | ||||
|         management.call_command('makemessages', locale=['en', 'fr', 'it'], exclude=['fr', 'it'], | ||||
|                                 stdout=StringIO()) | ||||
|         self.assertRecentlyModified(self.PO_FILE % 'en') | ||||
|         self.assertNotRecentlyModified(self.PO_FILE % 'fr') | ||||
|         self.assertNotRecentlyModified(self.PO_FILE % 'it') | ||||
|  | ||||
|  | ||||
| class CustomLayoutExtractionTests(ExtractorTests): | ||||
|  | ||||
|     def setUp(self): | ||||
|         self._cwd = os.getcwd() | ||||
|         self.test_dir = os.path.join(os.path.dirname(upath(__file__)), 'project_dir') | ||||
|   | ||||
		Reference in New Issue
	
	Block a user