make checksumming a task so it queues after image save
This commit is contained in:
Родитель
655892f8ba
Коммит
f9f5ddab69
|
@ -1,5 +1,4 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import hashlib
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
@ -18,10 +17,10 @@ import amo
|
||||||
import captcha.fields
|
import captcha.fields
|
||||||
from amo.fields import ColorField
|
from amo.fields import ColorField
|
||||||
from amo.urlresolvers import reverse
|
from amo.urlresolvers import reverse
|
||||||
from amo.utils import (LocalFileStorage, slug_validator, slugify,
|
from amo.utils import slug_validator, slugify, sorted_groupby, remove_icons
|
||||||
sorted_groupby, remove_icons)
|
|
||||||
from addons.models import (Addon, AddonCategory, BlacklistedSlug, Category,
|
from addons.models import (Addon, AddonCategory, BlacklistedSlug, Category,
|
||||||
Persona)
|
Persona)
|
||||||
|
from addons.tasks import rereviewqueuetheme_checksum, theme_checksum
|
||||||
from addons.utils import reverse_name_lookup
|
from addons.utils import reverse_name_lookup
|
||||||
from addons.widgets import IconWidgetRenderer, CategoriesSelectMultiple
|
from addons.widgets import IconWidgetRenderer, CategoriesSelectMultiple
|
||||||
from applications.models import Application
|
from applications.models import Application
|
||||||
|
@ -591,14 +590,10 @@ class ThemeForm(ThemeFormBase):
|
||||||
p.submit = datetime.now()
|
p.submit = datetime.now()
|
||||||
p.author = user.username
|
p.author = user.username
|
||||||
p.display_username = user.name
|
p.display_username = user.name
|
||||||
|
|
||||||
# To spot duplicate submissions.
|
|
||||||
# p.checksum = make_checksum(p.header_path, p.footer_path)
|
|
||||||
# dupe_personas = Persona.objects.filter(checksum=p.checksum)
|
|
||||||
# if dupe_personas.exists():
|
|
||||||
# p.dupe_persona = dupe_personas[0]
|
|
||||||
p.save()
|
p.save()
|
||||||
|
|
||||||
|
theme_checksum.delay(theme=p)
|
||||||
|
|
||||||
# Save tags.
|
# Save tags.
|
||||||
for t in data['tags']:
|
for t in data['tags']:
|
||||||
Tag(tag_text=t).save_tag(addon)
|
Tag(tag_text=t).save_tag(addon)
|
||||||
|
@ -609,12 +604,6 @@ class ThemeForm(ThemeFormBase):
|
||||||
return addon
|
return addon
|
||||||
|
|
||||||
|
|
||||||
def make_checksum(header_path, footer_path):
|
|
||||||
ls = LocalFileStorage()
|
|
||||||
raw_checksum = ls._open(header_path).read() + ls._open(footer_path).read()
|
|
||||||
return hashlib.sha224(raw_checksum).hexdigest()
|
|
||||||
|
|
||||||
|
|
||||||
class EditThemeForm(AddonFormBase):
|
class EditThemeForm(AddonFormBase):
|
||||||
name = forms.CharField(max_length=50)
|
name = forms.CharField(max_length=50)
|
||||||
slug = forms.CharField(max_length=30)
|
slug = forms.CharField(max_length=30)
|
||||||
|
@ -764,14 +753,7 @@ class EditThemeForm(AddonFormBase):
|
||||||
RereviewQueueTheme.objects.filter(theme=persona).delete()
|
RereviewQueueTheme.objects.filter(theme=persona).delete()
|
||||||
rqt = RereviewQueueTheme.objects.create(
|
rqt = RereviewQueueTheme.objects.create(
|
||||||
theme=persona, header=header, footer=footer)
|
theme=persona, header=header, footer=footer)
|
||||||
|
rereviewqueuetheme_checksum.delay(rqt=rqt)
|
||||||
# Check for possible duplicate theme images.
|
|
||||||
dupe_personas = Persona.objects.filter(
|
|
||||||
checksum=make_checksum(header_dst or persona.header_path,
|
|
||||||
footer_dst or persona.footer_path))
|
|
||||||
if dupe_personas.exists():
|
|
||||||
rqt.dupe_persona = dupe_personas[0]
|
|
||||||
rqt.save()
|
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
log.error(str(e))
|
log.error(str(e))
|
||||||
raise
|
raise
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import hashlib
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -7,9 +8,10 @@ from django.db import connection, transaction
|
||||||
from celeryutils import task
|
from celeryutils import task
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
|
from addons.models import Persona
|
||||||
import amo
|
import amo
|
||||||
from amo.decorators import set_modified_on, write
|
from amo.decorators import set_modified_on, write
|
||||||
from amo.utils import cache_ns_key, ImageCheck
|
from amo.utils import cache_ns_key, ImageCheck, LocalFileStorage
|
||||||
from lib.es.utils import index_objects
|
from lib.es.utils import index_objects
|
||||||
from versions.models import Version
|
from versions.models import Version
|
||||||
|
|
||||||
|
@ -263,3 +265,29 @@ def update_incompatible_appversions(data, **kw):
|
||||||
# Increment namespace cache of compat versions.
|
# Increment namespace cache of compat versions.
|
||||||
for addon_id in addon_ids:
|
for addon_id in addon_ids:
|
||||||
cache_ns_key('d2c-versions:%s' % addon_id, increment=True)
|
cache_ns_key('d2c-versions:%s' % addon_id, increment=True)
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def theme_checksum(theme, **kw):
|
||||||
|
theme.checksum = make_checksum(theme.header_path, theme.footer_path)
|
||||||
|
dupe_personas = Persona.objects.filter(checksum=theme.checksum)
|
||||||
|
if dupe_personas.exists():
|
||||||
|
theme.dupe_persona = dupe_personas[0]
|
||||||
|
theme.save()
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def rereviewqueuetheme_checksum(rqt, **kw):
|
||||||
|
"""Check for possible duplicate theme images."""
|
||||||
|
dupe_personas = Persona.objects.filter(
|
||||||
|
checksum=make_checksum(rqt.header_path or rqt.theme.header_path,
|
||||||
|
rqt.footer_path or rqt.theme.footer_path))
|
||||||
|
if dupe_personas.exists():
|
||||||
|
rqt.dupe_persona = dupe_personas[0]
|
||||||
|
rqt.save()
|
||||||
|
|
||||||
|
|
||||||
|
def make_checksum(header_path, footer_path):
|
||||||
|
ls = LocalFileStorage()
|
||||||
|
raw_checksum = ls._open(header_path).read() + ls._open(footer_path).read()
|
||||||
|
return hashlib.sha224(raw_checksum).hexdigest()
|
||||||
|
|
|
@ -277,13 +277,14 @@ class TestThemeForm(amo.tests.TestCase):
|
||||||
{'data-allowed-types': 'image/jpeg|image/png',
|
{'data-allowed-types': 'image/jpeg|image/png',
|
||||||
'data-upload-url': footer_url})
|
'data-upload-url': footer_url})
|
||||||
|
|
||||||
@mock.patch('addons.forms.make_checksum')
|
@mock.patch('addons.tasks.make_checksum')
|
||||||
@mock.patch('addons.tasks.create_persona_preview_images.delay')
|
@mock.patch('addons.tasks.create_persona_preview_images.delay')
|
||||||
@mock.patch('addons.tasks.save_persona_image.delay')
|
@mock.patch('addons.tasks.save_persona_image.delay')
|
||||||
def test_success(self, save_persona_image_mock,
|
def test_success(self, save_persona_image_mock,
|
||||||
create_persona_preview_images_mock, mock1):
|
create_persona_preview_images_mock, make_checksum_mock):
|
||||||
if not hasattr(Image.core, 'jpeg_encoder'):
|
if not hasattr(Image.core, 'jpeg_encoder'):
|
||||||
raise SkipTest
|
raise SkipTest
|
||||||
|
make_checksum_mock.return_value = 'hashyourselfbeforeyoucrashyourself'
|
||||||
|
|
||||||
self.request.amo_user = UserProfile.objects.get(pk=2519)
|
self.request.amo_user = UserProfile.objects.get(pk=2519)
|
||||||
|
|
||||||
|
@ -349,7 +350,7 @@ class TestThemeForm(amo.tests.TestCase):
|
||||||
|
|
||||||
@mock.patch('addons.tasks.create_persona_preview_images.delay')
|
@mock.patch('addons.tasks.create_persona_preview_images.delay')
|
||||||
@mock.patch('addons.tasks.save_persona_image.delay')
|
@mock.patch('addons.tasks.save_persona_image.delay')
|
||||||
@mock.patch('addons.forms.make_checksum')
|
@mock.patch('addons.tasks.make_checksum')
|
||||||
def test_dupe_persona(self, make_checksum_mock, mock1, mock2):
|
def test_dupe_persona(self, make_checksum_mock, mock1, mock2):
|
||||||
"""
|
"""
|
||||||
Submitting persona with checksum already in db should be marked
|
Submitting persona with checksum already in db should be marked
|
||||||
|
@ -468,7 +469,7 @@ class TestEditThemeForm(amo.tests.TestCase):
|
||||||
eq_(self.form.errors,
|
eq_(self.form.errors,
|
||||||
{'name': ['This name is already in use. Please choose another.']})
|
{'name': ['This name is already in use. Please choose another.']})
|
||||||
|
|
||||||
@mock.patch('addons.forms.make_checksum')
|
@mock.patch('addons.tasks.make_checksum')
|
||||||
@mock.patch('addons.tasks.create_persona_preview_images.delay')
|
@mock.patch('addons.tasks.create_persona_preview_images.delay')
|
||||||
@mock.patch('addons.tasks.save_persona_image.delay')
|
@mock.patch('addons.tasks.save_persona_image.delay')
|
||||||
def test_reupload(self, save_persona_image_mock,
|
def test_reupload(self, save_persona_image_mock,
|
||||||
|
@ -498,7 +499,7 @@ class TestEditThemeForm(amo.tests.TestCase):
|
||||||
eq_(rqt[0].footer, 'pending_footer.png')
|
eq_(rqt[0].footer, 'pending_footer.png')
|
||||||
assert not rqt[0].dupe_persona
|
assert not rqt[0].dupe_persona
|
||||||
|
|
||||||
@mock.patch('addons.forms.make_checksum')
|
@mock.patch('addons.tasks.make_checksum')
|
||||||
@mock.patch('addons.tasks.create_persona_preview_images.delay')
|
@mock.patch('addons.tasks.create_persona_preview_images.delay')
|
||||||
@mock.patch('addons.tasks.save_persona_image.delay')
|
@mock.patch('addons.tasks.save_persona_image.delay')
|
||||||
def test_reupload_duplicate(self, save_persona_image_mock,
|
def test_reupload_duplicate(self, save_persona_image_mock,
|
||||||
|
|
|
@ -1,43 +1,2 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from celeryutils import task
|
|
||||||
import commonware.log
|
|
||||||
from PIL import Image
|
|
||||||
|
|
||||||
from addons.forms import make_checksum
|
|
||||||
from addons.models import Persona
|
|
||||||
from amo.decorators import write
|
|
||||||
from amo.utils import chunked
|
|
||||||
|
|
||||||
log = commonware.log.getLogger('z.addons')
|
|
||||||
|
|
||||||
|
|
||||||
@task
|
|
||||||
@write
|
|
||||||
def calc_checksum(theme_id, **kw):
|
|
||||||
theme = Persona.objects.get(id=theme_id)
|
|
||||||
header = theme.header_path
|
|
||||||
footer = theme.footer_path
|
|
||||||
|
|
||||||
# Delete invalid themes that are not images (e.g. PDF, EXE).
|
|
||||||
try:
|
|
||||||
Image.open(header)
|
|
||||||
Image.open(footer)
|
|
||||||
except IOError:
|
|
||||||
theme.addon.delete()
|
|
||||||
theme.delete()
|
|
||||||
return
|
|
||||||
|
|
||||||
# Calculate checksum and save.
|
|
||||||
try:
|
|
||||||
theme.checksum = make_checksum(header, footer)
|
|
||||||
theme.save()
|
|
||||||
except Exception as e:
|
|
||||||
log.error(str(e))
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
"""Calculate checksums for all themes."""
|
pass
|
||||||
pks = Persona.objects.filter(checksum='').values_list('id', flat=True)
|
|
||||||
for chunk in chunked(pks, 1000):
|
|
||||||
[calc_checksum.delay(pk) for pk in chunk]
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче