addons-server/apps/zadmin/forms.py

288 строки
10 KiB
Python

import json
import os
import re
import urllib2
from django import forms
from django.conf import settings
from django.forms import ModelForm
from django.forms.models import modelformset_factory
from django.template import Context, Template, TemplateSyntaxError
import commonware.log
import happyforms
from piston.models import Consumer
from product_details import product_details
from tower import ugettext_lazy as _lazy
from quieter_formset.formset import BaseModelFormSet
import amo
from addons.models import Addon
from amo.urlresolvers import reverse
from applications.models import Application, AppVersion
from bandwagon.models import Collection, FeaturedCollection, MonthlyPick
from compat.forms import CompatForm as BaseCompatForm
from files.models import File
from zadmin.models import SiteEvent, ValidationJob
log = commonware.log.getLogger('z.zadmin')
class DevMailerForm(happyforms.Form):
_choices = [('eula',
'Developers who have set up EULAs for active add-ons'),
('sdk', 'Developers of active SDK add-ons')]
recipients = forms.ChoiceField(choices=_choices, required=True)
subject = forms.CharField(widget=forms.TextInput(attrs=dict(size='100')),
required=True)
preview_only = forms.BooleanField(initial=True, required=False,
label=u'Log emails instead of sending')
message = forms.CharField(widget=forms.Textarea, required=True)
class BulkValidationForm(happyforms.ModelForm):
application = forms.ChoiceField(
label=_lazy(u'Application'),
choices=[(a.id, a.pretty) for a in amo.APPS_ALL.values()])
curr_max_version = forms.ChoiceField(
label=_lazy(u'Current Max. Version'),
choices=[('', _lazy(u'Select an application first'))])
target_version = forms.ChoiceField(
label=_lazy(u'Target Version'),
choices=[('', _lazy(u'Select an application first'))])
finish_email = forms.CharField(required=False,
label=_lazy(u'Email when finished'))
class Meta:
model = ValidationJob
fields = ('application', 'curr_max_version', 'target_version',
'finish_email')
def __init__(self, *args, **kw):
kw.setdefault('initial', {})
kw['initial']['finish_email'] = settings.FLIGTAR
super(BulkValidationForm, self).__init__(*args, **kw)
w = self.fields['application'].widget
# Get the URL after the urlconf has loaded.
w.attrs['data-url'] = reverse('zadmin.application_versions_json')
def version_choices_for_app_id(self, app_id):
versions = AppVersion.objects.filter(application__id=app_id)
return [(v.id, v.version) for v in versions]
def clean_application(self):
app_id = int(self.cleaned_data['application'])
app = Application.objects.get(pk=app_id)
self.cleaned_data['application'] = app
choices = self.version_choices_for_app_id(app_id)
self.fields['target_version'].choices = choices
self.fields['curr_max_version'].choices = choices
return self.cleaned_data['application']
def _clean_appversion(self, field):
return AppVersion.objects.get(pk=int(field))
def clean_curr_max_version(self):
return self._clean_appversion(self.cleaned_data['curr_max_version'])
def clean_target_version(self):
return self._clean_appversion(self.cleaned_data['target_version'])
path = os.path.join(settings.ROOT, 'apps/zadmin/templates/zadmin')
texts = {
'success': open('%s/%s' % (path, 'success.txt')).read(),
'failure': open('%s/%s' % (path, 'failure.txt')).read(),
}
varname = re.compile(r'{{\s*([a-zA-Z0-9_]+)\s*}}')
class NotifyForm(happyforms.Form):
subject = forms.CharField(widget=forms.TextInput, required=True)
preview_only = forms.BooleanField(initial=True, required=False,
label=_lazy(u'Log emails instead of sending'))
text = forms.CharField(widget=forms.Textarea, required=True)
variables = ['{{ADDON_NAME}}', '{{ADDON_VERSION}}', '{{APPLICATION}}',
'{{COMPAT_LINK}}', '{{RESULT_LINKS}}', '{{VERSION}}']
variable_names = [varname.match(v).group(1) for v in variables]
def __init__(self, *args, **kw):
kw.setdefault('initial', {})
if 'text' in kw:
kw['initial']['text'] = texts[kw.pop('text')]
kw['initial']['subject'] = ('{{ADDON_NAME}} {{ADDON_VERSION}} '
'compatibility with '
'{{APPLICATION}} {{VERSION}}')
super(NotifyForm, self).__init__(*args, **kw)
def check_template(self, data):
try:
Template(data).render(Context({}))
except TemplateSyntaxError, err:
raise forms.ValidationError(err)
for name in varname.findall(data):
if name not in self.variable_names:
raise forms.ValidationError(
u'Variable {{%s}} is not a valid variable' % name)
return data
def clean_text(self):
return self.check_template(self.cleaned_data['text'])
def clean_subject(self):
return self.check_template(self.cleaned_data['subject'])
class FeaturedCollectionForm(happyforms.ModelForm):
LOCALES = (('', u'(Default Locale)'),) + tuple(
(i, product_details.languages[i]['native'])
for i in settings.AMO_LANGUAGES)
application = forms.ModelChoiceField(Application.objects.all())
collection = forms.CharField(widget=forms.HiddenInput)
locale = forms.ChoiceField(choices=LOCALES, required=False)
class Meta:
model = FeaturedCollection
fields = ('application', 'locale')
def clean_collection(self):
application = self.cleaned_data.get('application', None)
collection = self.cleaned_data.get('collection', None)
if not Collection.objects.filter(id=collection,
application=application).exists():
raise forms.ValidationError(
u'Invalid collection for this application.')
return collection
def save(self, commit=False):
collection = self.cleaned_data['collection']
f = super(FeaturedCollectionForm, self).save(commit=commit)
f.collection = Collection.objects.get(id=collection)
f.save()
return f
class BaseFeaturedCollectionFormSet(BaseModelFormSet):
def __init__(self, *args, **kw):
super(BaseFeaturedCollectionFormSet, self).__init__(*args, **kw)
for form in self.initial_forms:
try:
form.initial['collection'] = (FeaturedCollection.objects
.get(id=form.instance.id).collection.id)
except (FeaturedCollection.DoesNotExist, Collection.DoesNotExist):
form.initial['collection'] = None
FeaturedCollectionFormSet = modelformset_factory(FeaturedCollection,
form=FeaturedCollectionForm, formset=BaseFeaturedCollectionFormSet,
can_delete=True, extra=0)
class OAuthConsumerForm(happyforms.ModelForm):
class Meta:
model = Consumer
fields = ['name', 'description', 'status']
class MonthlyPickForm(happyforms.ModelForm):
image = forms.CharField(required=False)
blurb = forms.CharField(max_length=200,
widget=forms.Textarea(attrs={'cols': 20,
'rows': 2}))
class Meta:
model = MonthlyPick
widgets = {
'addon': forms.TextInput(),
}
fields = ('addon', 'image', 'blurb', 'locale')
MonthlyPickFormSet = modelformset_factory(MonthlyPick, form=MonthlyPickForm,
can_delete=True, extra=0)
class AddonStatusForm(ModelForm):
class Meta:
model = Addon
fields = ('status', 'highest_status', 'outstanding')
class FileStatusForm(ModelForm):
class Meta:
model = File
fields = ('status',)
FileFormSet = modelformset_factory(File, form=FileStatusForm,
formset=BaseModelFormSet, extra=0)
class JetpackUpgradeForm(happyforms.Form):
minver = forms.CharField()
maxver = forms.CharField()
def __init__(self, *args, **kw):
super(JetpackUpgradeForm, self).__init__(*args, **kw)
fields = self.fields
url = settings.BUILDER_VERSIONS_URL
try:
page = urllib2.urlopen(url)
choices = [('', '')] + [(v, v) for v in json.loads(page.read())]
fields['minver'] = fields['maxver'] = forms.ChoiceField()
fields['minver'].choices = fields['maxver'].choices = choices
except urllib2.URLError, e:
log.error('Could not open %r: %s' % (url, e))
except ValueError, e:
log.error('Could not parse %r: %s' % (url, e))
if not ('minver' in self.data or 'maxver' in self.data):
fields['minver'].required = fields['maxver'].required = False
def clean(self):
if not self.errors:
minver = self.cleaned_data.get('minver')
maxver = self.cleaned_data.get('maxver')
if minver and maxver and minver >= maxver:
raise forms.ValidationError('Invalid version range.')
return self.cleaned_data
class SiteEventForm(ModelForm):
class Meta:
model = SiteEvent
fields = ('start', 'end', 'event_type', 'description',
'more_info_url')
class YesImSure(happyforms.Form):
yes = forms.BooleanField(required=True, label="Yes, I'm sure")
class CompatForm(BaseCompatForm):
_minimum_choices = [(x, x) for x in xrange(100, -10, -10)]
minimum = forms.TypedChoiceField(choices=_minimum_choices, coerce=int,
required=False)
_ratio_choices = [('%.1f' % (x / 10.0), '%.0f%%' % (x * 10))
for x in xrange(9, -1, -1)]
ratio = forms.ChoiceField(choices=_ratio_choices, required=False)
class GenerateErrorForm(happyforms.Form):
error = forms.ChoiceField(choices=(
['zerodivisionerror', 'Zero Division Error (will email)'],
['iorequesterror', 'IORequest Error (no email)']))
def explode(self):
error = self.cleaned_data.get('error')
if error == 'zerodivisionerror':
1/0
elif error == 'iorequesterror':
class IOError(Exception):
pass
raise IOError('request data read error')