Merge pull request #703 from diox/fix-commands
Fix mtime_cache command handle method, add basic tests for compress and mtime_cache
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
import fnmatch
|
import fnmatch
|
||||||
import os
|
import os
|
||||||
from optparse import make_option
|
|
||||||
|
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
|
|
||||||
@@ -10,25 +9,30 @@ from compressor.cache import cache, get_mtime, get_mtime_cachekey
|
|||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = "Add or remove all mtime values from the cache"
|
help = "Add or remove all mtime values from the cache"
|
||||||
option_list = BaseCommand.option_list + (
|
|
||||||
make_option('-i', '--ignore', action='append', default=[],
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
'-i', '--ignore', action='append', default=[],
|
||||||
dest='ignore_patterns', metavar='PATTERN',
|
dest='ignore_patterns', metavar='PATTERN',
|
||||||
help="Ignore files or directories matching this glob-style "
|
help="Ignore files or directories matching this glob-style "
|
||||||
"pattern. Use multiple times to ignore more."),
|
"pattern. Use multiple times to ignore more."),
|
||||||
make_option('--no-default-ignore', action='store_false',
|
parser.add_argument(
|
||||||
|
'--no-default-ignore', action='store_false',
|
||||||
dest='use_default_ignore_patterns', default=True,
|
dest='use_default_ignore_patterns', default=True,
|
||||||
help="Don't ignore the common private glob-style patterns 'CVS', "
|
help="Don't ignore the common private glob-style patterns 'CVS', "
|
||||||
"'.*' and '*~'."),
|
"'.*' and '*~'."),
|
||||||
make_option('--follow-links', dest='follow_links', action='store_true',
|
parser.add_argument(
|
||||||
|
'--follow-links', dest='follow_links', action='store_true',
|
||||||
help="Follow symlinks when traversing the COMPRESS_ROOT "
|
help="Follow symlinks when traversing the COMPRESS_ROOT "
|
||||||
"(which defaults to STATIC_ROOT). Be aware that using this "
|
"(which defaults to STATIC_ROOT). Be aware that using this "
|
||||||
"can lead to infinite recursion if a link points to a parent "
|
"can lead to infinite recursion if a link points to a parent "
|
||||||
"directory of itself."),
|
"directory of itself."),
|
||||||
make_option('-c', '--clean', dest='clean', action='store_true',
|
parser.add_argument(
|
||||||
|
'-c', '--clean', dest='clean', action='store_true',
|
||||||
help="Remove all items"),
|
help="Remove all items"),
|
||||||
make_option('-a', '--add', dest='add', action='store_true',
|
parser.add_argument(
|
||||||
|
'-a', '--add', dest='add', action='store_true',
|
||||||
help="Add all items"),
|
help="Add all items"),
|
||||||
)
|
|
||||||
|
|
||||||
def is_ignored(self, path):
|
def is_ignored(self, path):
|
||||||
"""
|
"""
|
||||||
@@ -40,24 +44,27 @@ class Command(BaseCommand):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def handle_noargs(self, **options):
|
def handle(self, **options):
|
||||||
ignore_patterns = options['ignore_patterns']
|
ignore_patterns = options['ignore_patterns']
|
||||||
if options['use_default_ignore_patterns']:
|
if options['use_default_ignore_patterns']:
|
||||||
ignore_patterns += ['CVS', '.*', '*~']
|
ignore_patterns += ['CVS', '.*', '*~']
|
||||||
options['ignore_patterns'] = ignore_patterns
|
options['ignore_patterns'] = ignore_patterns
|
||||||
self.ignore_patterns = ignore_patterns
|
self.ignore_patterns = ignore_patterns
|
||||||
|
|
||||||
if (options['add'] and options['clean']) or (not options['add'] and not options['clean']):
|
if ((options['add'] and options['clean']) or
|
||||||
|
(not options['add'] and not options['clean'])):
|
||||||
raise CommandError('Please specify either "--add" or "--clean"')
|
raise CommandError('Please specify either "--add" or "--clean"')
|
||||||
|
|
||||||
if not settings.COMPRESS_MTIME_DELAY:
|
if not settings.COMPRESS_MTIME_DELAY:
|
||||||
raise CommandError('mtime caching is currently disabled. Please '
|
raise CommandError(
|
||||||
|
'mtime caching is currently disabled. Please '
|
||||||
'set the COMPRESS_MTIME_DELAY setting to a number of seconds.')
|
'set the COMPRESS_MTIME_DELAY setting to a number of seconds.')
|
||||||
|
|
||||||
files_to_add = set()
|
files_to_add = set()
|
||||||
keys_to_delete = set()
|
keys_to_delete = set()
|
||||||
|
|
||||||
for root, dirs, files in os.walk(settings.COMPRESS_ROOT, followlinks=options['follow_links']):
|
for root, dirs, files in os.walk(settings.COMPRESS_ROOT,
|
||||||
|
followlinks=options['follow_links']):
|
||||||
for dir_ in dirs:
|
for dir_ in dirs:
|
||||||
if self.is_ignored(dir_):
|
if self.is_ignored(dir_):
|
||||||
dirs.remove(dir_)
|
dirs.remove(dir_)
|
||||||
@@ -74,9 +81,11 @@ class Command(BaseCommand):
|
|||||||
|
|
||||||
if keys_to_delete:
|
if keys_to_delete:
|
||||||
cache.delete_many(list(keys_to_delete))
|
cache.delete_many(list(keys_to_delete))
|
||||||
print("Deleted mtimes of %d files from the cache." % len(keys_to_delete))
|
self.stdout.write("Deleted mtimes of %d files from the cache."
|
||||||
|
% len(keys_to_delete))
|
||||||
|
|
||||||
if files_to_add:
|
if files_to_add:
|
||||||
for filename in files_to_add:
|
for filename in files_to_add:
|
||||||
get_mtime(filename)
|
get_mtime(filename)
|
||||||
print("Added mtimes of %d files to cache." % len(files_to_add))
|
self.stdout.write("Added mtimes of %d files to cache."
|
||||||
|
% len(files_to_add))
|
||||||
|
37
compressor/tests/test_mtime_cache.py
Normal file
37
compressor/tests/test_mtime_cache.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
from django.core.management import call_command
|
||||||
|
from django.core.management.base import CommandError
|
||||||
|
from django.test import TestCase
|
||||||
|
from django.utils.six import StringIO
|
||||||
|
|
||||||
|
|
||||||
|
class TestMtimeCacheCommand(TestCase):
|
||||||
|
# FIXME: add actual tests, improve the existing ones.
|
||||||
|
|
||||||
|
exclusion_patterns = [
|
||||||
|
'*CACHE*', '*custom*', '*066cd253eada.js', 'test.txt*'
|
||||||
|
]
|
||||||
|
|
||||||
|
def default_ignore(self):
|
||||||
|
return ['--ignore=%s' % pattern for pattern in self.exclusion_patterns]
|
||||||
|
|
||||||
|
def test_handle_no_args(self):
|
||||||
|
with self.assertRaises(CommandError):
|
||||||
|
call_command('mtime_cache')
|
||||||
|
|
||||||
|
def test_handle_add(self):
|
||||||
|
out = StringIO()
|
||||||
|
with self.settings(CACHES={}):
|
||||||
|
call_command(
|
||||||
|
'mtime_cache', '--add', *self.default_ignore(), stdout=out)
|
||||||
|
output = out.getvalue()
|
||||||
|
self.assertIn('Deleted mtimes of 19 files from the cache.', output)
|
||||||
|
self.assertIn('Added mtimes of 19 files to cache.', output)
|
||||||
|
|
||||||
|
def test_handle_clean(self):
|
||||||
|
out = StringIO()
|
||||||
|
with self.settings(CACHES={}):
|
||||||
|
call_command(
|
||||||
|
'mtime_cache', '--clean', *self.default_ignore(), stdout=out)
|
||||||
|
output = out.getvalue()
|
||||||
|
self.assertIn('Deleted mtimes of 19 files from the cache.', output)
|
||||||
|
self.assertNotIn('Added mtimes of 19 files to cache.', output)
|
@@ -5,6 +5,8 @@ import sys
|
|||||||
import unittest
|
import unittest
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
|
|
||||||
|
from mock import patch
|
||||||
|
|
||||||
import django
|
import django
|
||||||
from django.core.management.base import CommandError
|
from django.core.management.base import CommandError
|
||||||
from django.template import Template, Context
|
from django.template import Template, Context
|
||||||
@@ -171,6 +173,31 @@ class OfflineCompressBasicTestCase(OfflineTestCaseMixin, TestCase):
|
|||||||
templates_dir = 'basic'
|
templates_dir = 'basic'
|
||||||
expected_hash = 'f5e179b8eca4'
|
expected_hash = 'f5e179b8eca4'
|
||||||
|
|
||||||
|
@patch.object(CompressCommand, 'compress')
|
||||||
|
def test_handle_no_args(self, compress_mock):
|
||||||
|
CompressCommand().handle()
|
||||||
|
self.assertEqual(compress_mock.call_count, 1)
|
||||||
|
|
||||||
|
@patch.object(CompressCommand, 'compress')
|
||||||
|
def test_handle_compress_disabled(self, compress_mock):
|
||||||
|
with self.settings(COMPRESS_ENABLED=False):
|
||||||
|
with self.assertRaises(CommandError):
|
||||||
|
CompressCommand().handle()
|
||||||
|
self.assertEqual(compress_mock.call_count, 0)
|
||||||
|
|
||||||
|
@patch.object(CompressCommand, 'compress')
|
||||||
|
def test_handle_compress_offline_disabled(self, compress_mock):
|
||||||
|
with self.settings(COMPRESS_OFFLINE=False):
|
||||||
|
with self.assertRaises(CommandError):
|
||||||
|
CompressCommand().handle()
|
||||||
|
self.assertEqual(compress_mock.call_count, 0)
|
||||||
|
|
||||||
|
@patch.object(CompressCommand, 'compress')
|
||||||
|
def test_handle_compress_offline_disabled_force(self, compress_mock):
|
||||||
|
with self.settings(COMPRESS_OFFLINE=False):
|
||||||
|
CompressCommand().handle(force=True)
|
||||||
|
self.assertEqual(compress_mock.call_count, 1)
|
||||||
|
|
||||||
def test_rendering_without_manifest_raises_exception(self):
|
def test_rendering_without_manifest_raises_exception(self):
|
||||||
# flush cached manifest
|
# flush cached manifest
|
||||||
flush_offline_manifest()
|
flush_offline_manifest()
|
||||||
|
Reference in New Issue
Block a user