Browse Source

Fixed #29973 -- Added compilemessages --ignore option.

rsiemens 6 years ago
parent
commit
a168e5616c

+ 13 - 2
django/core/management/commands/compilemessages.py

@@ -4,7 +4,9 @@ import glob
 import os
 
 from django.core.management.base import BaseCommand, CommandError
-from django.core.management.utils import find_command, popen_wrapper
+from django.core.management.utils import (
+    find_command, is_ignored_path, popen_wrapper,
+)
 
 
 def has_bom(fn):
@@ -46,10 +48,17 @@ class Command(BaseCommand):
             '--use-fuzzy', '-f', dest='fuzzy', action='store_true',
             help='Use fuzzy translations.',
         )
+        parser.add_argument(
+            '--ignore', '-i', action='append', dest='ignore_patterns',
+            default=[], metavar='PATTERN',
+            help='Ignore directories matching this glob-style pattern. '
+                 'Use multiple times to ignore more.',
+        )
 
     def handle(self, **options):
         locale = options['locale']
         exclude = options['exclude']
+        ignore_patterns = set(options['ignore_patterns'])
         self.verbosity = options['verbosity']
         if options['fuzzy']:
             self.program_options = self.program_options + ['-f']
@@ -66,7 +75,9 @@ class Command(BaseCommand):
         # Walk entire tree, looking for locale directories
         for dirpath, dirnames, filenames in os.walk('.', topdown=True):
             for dirname in dirnames:
-                if dirname == 'locale':
+                if is_ignored_path(os.path.normpath(os.path.join(dirpath, dirname)), ignore_patterns):
+                    dirnames.remove(dirname)
+                elif dirname == 'locale':
                     basedirs.append(os.path.join(dirpath, dirname))
 
         # Gather existing directories.

+ 11 - 0
docs/ref/django-admin.txt

@@ -173,6 +173,17 @@ Example usage::
     django-admin compilemessages -x pt_BR
     django-admin compilemessages -x pt_BR -x fr
 
+.. django-admin-option:: --ignore PATTERN, -i PATTERN
+
+.. versionadded:: 3.0
+
+Ignores directories matching the given :mod:`glob`-style pattern. Use
+multiple times to ignore more.
+
+Example usage::
+
+    django-admin compilemessages --ignore=cache --ignore=outdated/*/locale
+
 ``createcachetable``
 --------------------
 

+ 2 - 1
docs/releases/3.0.txt

@@ -150,7 +150,8 @@ Internationalization
 Management Commands
 ~~~~~~~~~~~~~~~~~~~
 
-* ...
+* The new :option:`compilemessages --ignore` option allows ignoring specific
+  directories when searching for ``.po`` files to compile.
 
 Migrations
 ~~~~~~~~~~

+ 39 - 0
tests/i18n/test_compilation.py

@@ -3,6 +3,7 @@ import os
 import stat
 import unittest
 from io import StringIO
+from pathlib import Path
 from subprocess import Popen
 from unittest import mock
 
@@ -134,6 +135,44 @@ class ExcludedLocaleCompilationTests(MessageCompilationTests):
         self.assertFalse(os.path.exists(self.MO_FILE % 'it'))
 
 
+class IgnoreDirectoryCompilationTests(MessageCompilationTests):
+    # Reuse the exclude directory since it contains some locale fixtures.
+    work_subdir = 'exclude'
+    MO_FILE = '%s/%s/LC_MESSAGES/django.mo'
+    CACHE_DIR = Path('cache') / 'locale'
+    NESTED_DIR = Path('outdated') / 'v1' / 'locale'
+
+    def setUp(self):
+        super().setUp()
+        copytree('canned_locale', 'locale')
+        copytree('canned_locale', self.CACHE_DIR)
+        copytree('canned_locale', self.NESTED_DIR)
+
+    def assertAllExist(self, dir, langs):
+        self.assertTrue(all(Path(self.MO_FILE % (dir, lang)).exists() for lang in langs))
+
+    def assertNoneExist(self, dir, langs):
+        self.assertTrue(all(Path(self.MO_FILE % (dir, lang)).exists() is False for lang in langs))
+
+    def test_one_locale_dir_ignored(self):
+        call_command('compilemessages', ignore=['cache'], verbosity=0)
+        self.assertAllExist('locale', ['en', 'fr', 'it'])
+        self.assertNoneExist(self.CACHE_DIR, ['en', 'fr', 'it'])
+        self.assertAllExist(self.NESTED_DIR, ['en', 'fr', 'it'])
+
+    def test_multiple_locale_dirs_ignored(self):
+        call_command('compilemessages', ignore=['cache/locale', 'outdated'], verbosity=0)
+        self.assertAllExist('locale', ['en', 'fr', 'it'])
+        self.assertNoneExist(self.CACHE_DIR, ['en', 'fr', 'it'])
+        self.assertNoneExist(self.NESTED_DIR, ['en', 'fr', 'it'])
+
+    def test_ignores_based_on_pattern(self):
+        call_command('compilemessages', ignore=['*/locale'], verbosity=0)
+        self.assertAllExist('locale', ['en', 'fr', 'it'])
+        self.assertNoneExist(self.CACHE_DIR, ['en', 'fr', 'it'])
+        self.assertNoneExist(self.NESTED_DIR, ['en', 'fr', 'it'])
+
+
 class CompilationErrorHandling(MessageCompilationTests):
     def test_error_reported_by_msgfmt(self):
         # po file contains wrong po formatting.