r80939 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r80938‎ | r80939 | r80940 >
Date:23:37, 24 January 2011
Author:diederik
Status:deferred
Tags:
Comment:
Fixed SVN props.
Modified paths:
  • /trunk/tools/editor_trends/wikilytics/api/__init__.py (modified) (history)
  • /trunk/tools/editor_trends/wikilytics/api/forms.py (modified) (history)
  • /trunk/tools/editor_trends/wikilytics/api/helpers.py (modified) (history)
  • /trunk/tools/editor_trends/wikilytics/api/models.py (modified) (history)
  • /trunk/tools/editor_trends/wikilytics/api/tasks.py (modified) (history)
  • /trunk/tools/editor_trends/wikilytics/api/tests.py (modified) (history)
  • /trunk/tools/editor_trends/wikilytics/api/views.py (modified) (history)
  • /trunk/tools/editor_trends/wikilytics/api/widgets.py (modified) (history)

Diff [purge]

Index: trunk/tools/editor_trends/wikilytics/api/views.py
@@ -1 +1,68 @@
2 -# Create your views here.
 2+import datetime
 3+import time
 4+import json
 5+
 6+from django.shortcuts import render_to_response
 7+from django.http import HttpResponseRedirect, HttpResponse
 8+from django.core.urlresolvers import reverse
 9+from django.conf import settings
 10+from django.core import serializers
 11+
 12+
 13+from wikilytics.api.forms import SearchForm
 14+from wikilytics.api.models import Editor, Dataset, Job, Dump
 15+import wikilytics.api.helpers as helpers
 16+
 17+
 18+def search(request):
 19+ #print request
 20+ if request.GET:
 21+ #form = SearchForm(request.GET)
 22+ #print form
 23+ project = request.GET.get('project', '')
 24+ language = request.GET.get('language', '')
 25+ #year = request.GET.get('date_year', '')
 26+ #month = request.GET.get('date_month', '')
 27+ return HttpResponseRedirect(reverse('dataset_dispatcher', args=[project, language]))
 28+ else:
 29+ form = SearchForm()
 30+
 31+ return render_to_response('search.html', {'form': form})
 32+
 33+
 34+def dataset_dispatcher(request, project, language):
 35+ dbname = '%s%s' % (language, project)
 36+ editors = Editor.objects.count()
 37+ if editors == 0:
 38+ #Dataset has not yet been made, put job in queue to create the dataset
 39+ hash = helpers.create_hash(project, language)
 40+ job, created = Job.objects.get_or_create(hash=hash, defaults={'project':project, 'language_code': language, 'hash':hash})
 41+ print job.hash
 42+ if created:
 43+ job.save()
 44+ jobs = Job.objects.filter(jobtype='dataset', finished=False, in_progress=True)
 45+ return render_to_response('queue.html', {'jobs': jobs})
 46+ else:
 47+ ds = Dataset.objects.filter(project=project, language_code=language)
 48+ print ds
 49+ return render_to_response('datasets_available.html', {'datasets': ds})
 50+
 51+
 52+def chart_dispatcher(request, project, language):
 53+ #project = '%s%s' % (project, language)
 54+ analyses = Job.objects.filter(jobtype='chart')
 55+ print analyses
 56+ return render_to_response('analyses_available.html', {'analyses': analyses})
 57+
 58+
 59+def chart_generator(request, project, language, chart):
 60+ xhr = request.GET.has_key('json')
 61+ print xhr
 62+ ds = Dataset.objects.using('enwiki').get(project=project, language_code=language, name=chart)
 63+ if xhr:
 64+ dthandler = lambda obj:'new Date("%s")' % datetime.date.ctime(obj) if isinstance(obj, datetime.datetime) else obj
 65+ data = helpers.transform_to_stacked_bar_json(ds)
 66+ return HttpResponse(json.dumps(data, default=dthandler), mimetype='application/json')
 67+ else:
 68+ url = ds.get_absolute_url()
 69+ return render_to_response('chart.html', {'url': url})
Property changes on: trunk/tools/editor_trends/wikilytics/api/views.py
___________________________________________________________________
Added: svn:eol-style
370 + native
Property changes on: trunk/tools/editor_trends/wikilytics/api/__init__.py
___________________________________________________________________
Added: svn:eol-style
471 + native
Index: trunk/tools/editor_trends/wikilytics/api/helpers.py
@@ -1,17 +1,72 @@
2 -def init_database(dbname):
3 - if dbname not in settings.DATABASES:
4 - settings.DATABASES[dbname] = {
5 - 'ENGINE': 'django_mongodb_engine',
6 - 'NAME': '%s' % dbname,
7 - 'USER': '',
8 - 'PASSWORD': '',
9 - 'HOST': 'localhost',
10 - 'PORT': '27017',
11 - }
12 -
13 -
14 -def create_hash(project, language):
15 - today = datetime.datetime.today()
16 - datum = datetime.date(today.year, today.month, 1)
17 - secs = time.mktime(datum.timetuple())
18 - return hash('%s%s' % (project, language)) + hash(secs)
 2+import datetime
 3+import time
 4+
 5+
 6+from editor_trends.utils import data_converter
 7+
 8+
 9+def transform_to_stacked_bar_json(ds):
 10+ '''
 11+ This function outputs data in a format that is understood by jquery
 12+ flot plugin. Example JSON object:
 13+ var data = [
 14+ {label: 'foo', data: [[1, 300], [2, 300], [3, 300], [4, 300], [5, 300]]},
 15+ {label: 'bar', data: [[1, 800], [2, 600], [3, 400], [4, 200], [5, 0]]},
 16+ {label: 'baz', data: [[1, 100], [2, 200], [3, 300], [4, 400], [5, 500]]},
 17+ ];
 18+ var options = {
 19+ series: {stack: 0,
 20+ lines: {show: false, steps: false },
 21+ bars: {show: true, barWidth: 0.9, align: 'center', }, },
 22+ xaxis: {ticks: [[1, 'One'], [2, 'Two'], [3, 'Three'], [4, 'Four'], [5, 'Five']]},
 23+ };
 24+ '''
 25+ options = {}
 26+ options['xaxis'] = {}
 27+ options['xaxis']['ticks'] = []
 28+ options['series'] = {}
 29+ options['series']['stack'] = 0
 30+ options['series']['lines'] = {}
 31+ options['series']['lines']['show'] = False
 32+ options['series']['lines']['steps'] = False
 33+ options['series']['bars'] = {}
 34+ options['series']['bars']['show'] = True
 35+ options['series']['bars']['barWidth'] = 0.9
 36+ options['series']['bars']['align'] = 'center'
 37+
 38+ data = []
 39+ obs, all_keys = data_converter.convert_dataset_to_lists(ds, 'django')
 40+
 41+ for ob in obs:
 42+ d = {}
 43+ d['label'] = str(ob[0].year)
 44+ d['data'] = []
 45+ ob = ob[1:]
 46+ for x, o in enumerate(ob):
 47+ d['data'].append([x, o])
 48+ data.append(d)
 49+ for x, date in enumerate(obs):
 50+ options['xaxis']['ticks'].append([x, date[0].year])
 51+
 52+ d = {}
 53+ d['data'] = data
 54+ d['options'] = options
 55+ return d
 56+
 57+def create_hash(project, language):
 58+ today = datetime.datetime.today()
 59+ datum = datetime.date(today.year, today.month, 1)
 60+ secs = time.mktime(datum.timetuple())
 61+ return hash('%s%s' % (project, language)) + hash(secs)
 62+
 63+
 64+#def init_database(dbname):
 65+# if dbname not in settings.DATABASES:
 66+# settings.DATABASES[dbname] = {
 67+# 'ENGINE': 'django_mongodb_engine',
 68+# 'NAME': '%s' % dbname,
 69+# 'USER': '',
 70+# 'PASSWORD': '',
 71+# 'HOST': 'localhost',
 72+# 'PORT': '27017',
 73+# }
Property changes on: trunk/tools/editor_trends/wikilytics/api/helpers.py
___________________________________________________________________
Added: svn:eol-style
1974 + native
Index: trunk/tools/editor_trends/wikilytics/api/tests.py
@@ -1,23 +1,23 @@
2 -"""
3 -This file demonstrates two different styles of tests (one doctest and one
4 -unittest). These will both pass when you run "manage.py test".
5 -
6 -Replace these with more appropriate tests for your application.
7 -"""
8 -
9 -from django.test import TestCase
10 -
11 -class SimpleTest(TestCase):
12 - def test_basic_addition(self):
13 - """
14 - Tests that 1 + 1 always equals 2.
15 - """
16 - self.failUnlessEqual(1 + 1, 2)
17 -
18 -__test__ = {"doctest": """
19 -Another way to test that 1 + 1 is equal to 2.
20 -
21 ->>> 1 + 1 == 2
22 -True
23 -"""}
24 -
 2+"""
 3+This file demonstrates two different styles of tests (one doctest and one
 4+unittest). These will both pass when you run "manage.py test".
 5+
 6+Replace these with more appropriate tests for your application.
 7+"""
 8+
 9+from django.test import TestCase
 10+
 11+class SimpleTest(TestCase):
 12+ def test_basic_addition(self):
 13+ """
 14+ Tests that 1 + 1 always equals 2.
 15+ """
 16+ self.failUnlessEqual(1 + 1, 2)
 17+
 18+__test__ = {"doctest": """
 19+Another way to test that 1 + 1 is equal to 2.
 20+
 21+>>> 1 + 1 == 2
 22+True
 23+"""}
 24+
Property changes on: trunk/tools/editor_trends/wikilytics/api/tests.py
___________________________________________________________________
Added: svn:eol-style
2525 + native
Index: trunk/tools/editor_trends/wikilytics/api/models.py
@@ -1,30 +1,102 @@
2 -from django.db import models
3 -from django.contrib import databrowse
4 -from django.contrib import admin
5 -from djangotoolbox.fields import DictField, ListField
6 -
7 -
8 -class Editor(models.Model):
9 - username = models.CharField(max_length=64)
10 - editor = models.IntegerField()
11 - first_edit = models.DateField()
12 - final_edit = models.DateField()
13 - new_wikipedian = models.DateField()
14 - monthly_edits = DictField()
15 - edit_count = models.IntegerField()
16 - articles_by_year = DictField()
17 - edits_by_year = DictField()
18 - edits = ListField()
19 -
20 - class Meta:
21 - db_table = 'editors_dataset'
22 -
23 - def __unicode__(self):
24 - return u'%s, total edits: %s' % (self.username, self.edit_count)
25 -
26 -
27 -class EditorAdmin(admin.ModelAdmin):
28 - pass
29 -
30 -admin.site.register(Editor, EditorAdmin)
31 -databrowse.site.register(Editor)
 2+from django.db import models
 3+from django.contrib import databrowse
 4+from django.contrib import admin
 5+from django.core.urlresolvers import reverse
 6+from django.db.models import permalink
 7+
 8+from djangotoolbox.fields import DictField, ListField
 9+
 10+
 11+class Dataset(models.Model):
 12+ name = models.CharField(max_length=128)
 13+ project = models.CharField(max_length=48)
 14+ collection = models.CharField(max_length=48)
 15+ format = models.CharField(max_length=12)
 16+ _type = models.CharField(max_length=15)
 17+ filename = models.CharField(max_length=48)
 18+ created = models.DateField()
 19+ language_code = models.CharField(max_length=15)
 20+ variables = DictField()
 21+
 22+ class Meta:
 23+ db_table = 'enwiki_charts'
 24+
 25+ def __iter__(self):
 26+ for key, value in self.variables.items():
 27+ #print 'KEY: %s; ValUE: %s' % (key, value)
 28+ if isinstance(value, dict):
 29+ print value
 30+ for k, v in value.items():
 31+ print k, v
 32+ yield k, v
 33+
 34+ def get_absolute_url(self):
 35+ return reverse('chart_generator', args=[self.project, self.language_code, self.name])
 36+
 37+
 38+class Editor(models.Model):
 39+ username = models.CharField(max_length=64)
 40+ editor = models.IntegerField()
 41+ first_edit = models.DateField()
 42+ final_edit = models.DateField()
 43+ new_wikipedian = models.DateField()
 44+ monthly_edits = DictField()
 45+ edit_count = models.IntegerField()
 46+ articles_by_year = DictField()
 47+ edits_by_year = DictField()
 48+ edits = ListField()
 49+
 50+ class Meta:
 51+ db_table = 'editors_dataset'
 52+
 53+ def __unicode__(self):
 54+ return u'%s, total edits: %s' % (self.username, self.edit_count)
 55+
 56+class EditorAdmin(admin.ModelAdmin):
 57+ pass
 58+
 59+
 60+class Job(models.Model):
 61+ hash = models.CharField(max_length=48)
 62+ project = models.CharField(max_length=15)
 63+ language_code = models.CharField(max_length=15)
 64+ created = models.DateField(auto_now_add=True)
 65+ finished = models.BooleanField(default=False)
 66+ in_progress = models.BooleanField(default=False)
 67+ jobtype = models.CharField(max_length=15, default='dataset')
 68+
 69+ def __unicode__(self):
 70+ return u'%s%s' % (self.language_code, self.project)
 71+
 72+
 73+ @permalink
 74+ def get_absolute_url(self):
 75+ if self.jobtype == 'chart':
 76+ print reverse('chart_generator', args=[self.project, self.language_code, self.hash])
 77+ return ('chart_generator', (),
 78+ {'project': self.project,
 79+ 'language': self.language_code,
 80+ 'chart': self.hash})
 81+ elif self.jobtype == 'dataset':
 82+ return ('dataset_dispatcher', (),
 83+ {'project': self.project,
 84+ 'language': self.language_code,
 85+ 'dataset': self.hash})
 86+ class Meta:
 87+ db_table = 'jobs'
 88+
 89+class JobAdmin(admin.ModelAdmin):
 90+ pass
 91+
 92+
 93+
 94+class Dump(models.Model):
 95+ project = models.CharField(max_length=15)
 96+ dumps = DictField()
 97+
 98+ class Meta:
 99+ db_table = 'available_dumps'
 100+#admin.site.register(Editor, EditorAdmin)
 101+#admin.site.register(Job, JobAdmin)
 102+#databrowse.site.register(Editor)
 103+#databrowse.site.register(Job)
Property changes on: trunk/tools/editor_trends/wikilytics/api/models.py
___________________________________________________________________
Added: svn:eol-style
32104 + native
Index: trunk/tools/editor_trends/wikilytics/api/tasks.py
@@ -1,57 +1,57 @@
2 -from multiprocessing import Process
3 -
4 -from celery.decorators import task
5 -from celery.registry import tasks
6 -
7 -from editor_trends.utils import wikiprojects
8 -from editor_trends import manage as manager
9 -
10 -from wikilytics.api.models import Job
11 -
12 -@task
13 -def launcher():
14 - jobs = Job.objects.filter(finished=False)
15 - n = len(jobs)
16 - if n > 0:
17 -
18 - job = jobs[0]
19 - job.in_progress = True
20 - job.save()
21 - print 'Launching %s task' % job.type
22 - if job.type == 'dataset':
23 - res = launch_editor_trends_toolkit(job.project, job.language)
24 - elif job.type == 'chart':
25 - res = launch_chart(job.project, job.language)
26 - else:
27 - print 'Unknown job type, no handler has been configured.'
28 -
29 - if res == True:
30 - job.finished = True
31 - job.in_progress = False
32 - job.save()
33 -
34 -
35 -def launch_editor_trends_toolkit(project, language):
36 - '''
37 - This function should only be called from within Django Wikilytics.
38 - '''
39 - res = False
40 - parser, settings, wiki = manager.init_args_parser()
41 - args = parser.parse_args(['dummy'])
42 - args.language = language
43 - args.project = project
44 - print args
45 - wiki = wikiprojects.Wiki(settings, args)
46 - p = Process(target=manager.all_launcher, args=(wiki, settings, None))
47 - p.start()
48 - #res = manager.all_launcher(wiki, settings, None)
49 - return res
50 -
51 -def launch_chart(project, language):
52 - res = False
53 -
54 -
55 - return False
56 -
57 -
58 -tasks.register(launcher)
 2+from multiprocessing import Process
 3+
 4+from celery.decorators import task
 5+from celery.registry import tasks
 6+
 7+from editor_trends.classes import wikiprojects
 8+from editor_trends import manage as manager
 9+
 10+from wikilytics.api.models import Job
 11+
 12+@task
 13+def launcher():
 14+ jobs = Job.objects.filter(finished=False)
 15+ n = len(jobs)
 16+ if n > 0:
 17+
 18+ job = jobs[0]
 19+ job.in_progress = True
 20+ job.save()
 21+ print 'Launching %s task' % job.type
 22+ if job.type == 'dataset':
 23+ res = launch_editor_trends_toolkit(job.project, job.language)
 24+ elif job.type == 'chart':
 25+ res = launch_chart(job.project, job.language)
 26+ else:
 27+ print 'Unknown job type, no handler has been configured.'
 28+
 29+ if res == True:
 30+ job.finished = True
 31+ job.in_progress = False
 32+ job.save()
 33+
 34+
 35+def launch_editor_trends_toolkit(project, language):
 36+ '''
 37+ This function should only be called from within Django Wikilytics.
 38+ '''
 39+ res = False
 40+ parser, settings, wiki = manager.init_args_parser()
 41+ args = parser.parse_args(['dummy'])
 42+ args.language = language
 43+ args.project = project
 44+ print args
 45+ wiki = wikiprojects.Wiki(settings, args)
 46+ p = Process(target=manager.all_launcher, args=(wiki, settings, None))
 47+ p.start()
 48+ #res = manager.all_launcher(wiki, settings, None)
 49+ return res
 50+
 51+def launch_chart(project, language):
 52+ res = False
 53+
 54+
 55+ return False
 56+
 57+
 58+tasks.register(launcher)
Property changes on: trunk/tools/editor_trends/wikilytics/api/tasks.py
___________________________________________________________________
Added: svn:eol-style
5959 + native
Index: trunk/tools/editor_trends/wikilytics/api/forms.py
@@ -1,23 +1,23 @@
2 -import datetime
3 -from django import forms
4 -
5 -from wikilytics.api.widgets import MonthYearWidget
6 -from editor_trends.utils import wikiprojects
7 -
8 -
9 -wiki = wikiprojects.Wiki('settings')
10 -
11 -
12 -years = [year for year in xrange(2001, datetime.date.today().year + 1)]
13 -#print wiki.supported_languages()
14 -#print wiki.supported_projects()
15 -
16 -class SearchForm(forms.Form):
17 - project = forms.CharField(initial='wiki',
18 - widget=forms.Select(choices=wiki.supported_projects()))
19 -
20 - language = forms.CharField(initial='en',
21 - widget=forms.Select(choices=wiki.supported_languages(output='django')))
22 - print 'Project: %s' % language
23 - date = forms.DateField(widget=MonthYearWidget(years=years))
24 -
 2+import datetime
 3+from django import forms
 4+
 5+from wikilytics.api.widgets import MonthYearWidget
 6+from editor_trends.classes import wikiprojects
 7+
 8+
 9+wiki = wikiprojects.Wiki('settings')
 10+
 11+
 12+years = [year for year in xrange(2001, datetime.date.today().year + 1)]
 13+#print wiki.supported_languages()
 14+#print wiki.supported_projects()
 15+
 16+class SearchForm(forms.Form):
 17+ project = forms.CharField(initial='wiki',
 18+ widget=forms.Select(choices=wiki.supported_projects()))
 19+
 20+ language = forms.CharField(initial='en',
 21+ widget=forms.Select(choices=wiki.supported_languages(output='django')))
 22+ #print 'Project: %s' % language
 23+ #date = forms.DateField(widget=MonthYearWidget(years=years))
 24+
Property changes on: trunk/tools/editor_trends/wikilytics/api/forms.py
___________________________________________________________________
Added: svn:eol-style
2525 + native
Index: trunk/tools/editor_trends/wikilytics/api/widgets.py
@@ -1,84 +1,84 @@
2 -import datetime
3 -import re
4 -
5 -from django.forms.widgets import Widget, Select
6 -from django.utils.dates import MONTHS
7 -from django.utils.safestring import mark_safe
8 -
9 -__all__ = ('MonthYearWidget',)
10 -
11 -RE_DATE = re.compile(r'(\d{4})-(\d\d?)-(\d\d?)$')
12 -
13 -class MonthYearWidget(Widget):
14 - """
15 - A Widget that splits date input into two <select> boxes for month and year,
16 - with 'day' defaulting to the first of the month.
17 -
18 - Based on SelectDateWidget, in
19 -
20 - django/trunk/django/forms/extras/widgets.py
21 -
22 -
23 - """
24 - none_value = (0, '---')
25 - month_field = '%s_month'
26 - year_field = '%s_year'
27 -
28 - def __init__(self, attrs=None, years=None, required=True):
29 - # years is an optional list/tuple of years to use in the "year" select box.
30 - self.attrs = attrs or {}
31 - self.required = required
32 - if years:
33 - self.years = years
34 - else:
35 - this_year = datetime.date.today().year
36 - self.years = range(this_year, this_year + 10)
37 -
38 - def render(self, name, value, attrs=None):
39 - try:
40 - year_val, month_val = value.year, value.month
41 - except AttributeError:
42 - year_val = month_val = None
43 - if isinstance(value, basestring):
44 - match = RE_DATE.match(value)
45 - if match:
46 - year_val, month_val, day_val = [int(v) for v in match.groups()]
47 -
48 - output = []
49 -
50 - if 'id' in self.attrs:
51 - id_ = self.attrs['id']
52 - else:
53 - id_ = 'id_%s' % name
54 -
55 - month_choices = MONTHS.items()
56 - if not (self.required and value):
57 - month_choices.append(self.none_value)
58 - month_choices.sort()
59 - local_attrs = self.build_attrs(id=self.month_field % id_)
60 - s = Select(choices=month_choices)
61 - select_html = s.render(self.month_field % name, month_val, local_attrs)
62 - output.append(select_html)
63 -
64 - year_choices = [(i, i) for i in self.years]
65 - if not (self.required and value):
66 - year_choices.insert(0, self.none_value)
67 - local_attrs['id'] = self.year_field % id_
68 - s = Select(choices=year_choices)
69 - select_html = s.render(self.year_field % name, year_val, local_attrs)
70 - output.append(select_html)
71 -
72 - return mark_safe(u'\n'.join(output))
73 -
74 - def id_for_label(self, id_):
75 - return '%s_month' % id_
76 - id_for_label = classmethod(id_for_label)
77 -
78 - def value_from_datadict(self, data, files, name):
79 - y = data.get(self.year_field % name)
80 - m = data.get(self.month_field % name)
81 - if y == m == "0":
82 - return None
83 - if y and m:
84 - return '%s-%s-%s' % (y, m, 1)
85 - return data.get(name, None)
 2+import datetime
 3+import re
 4+
 5+from django.forms.widgets import Widget, Select
 6+from django.utils.dates import MONTHS
 7+from django.utils.safestring import mark_safe
 8+
 9+__all__ = ('MonthYearWidget',)
 10+
 11+RE_DATE = re.compile(r'(\d{4})-(\d\d?)-(\d\d?)$')
 12+
 13+class MonthYearWidget(Widget):
 14+ """
 15+ A Widget that splits date input into two <select> boxes for month and year,
 16+ with 'day' defaulting to the first of the month.
 17+
 18+ Based on SelectDateWidget, in
 19+
 20+ django/trunk/django/forms/extras/widgets.py
 21+
 22+
 23+ """
 24+ none_value = (0, '---')
 25+ month_field = '%s_month'
 26+ year_field = '%s_year'
 27+
 28+ def __init__(self, attrs=None, years=None, required=True):
 29+ # years is an optional list/tuple of years to use in the "year" select box.
 30+ self.attrs = attrs or {}
 31+ self.required = required
 32+ if years:
 33+ self.years = years
 34+ else:
 35+ this_year = datetime.date.today().year
 36+ self.years = range(this_year, this_year + 10)
 37+
 38+ def render(self, name, value, attrs=None):
 39+ try:
 40+ year_val, month_val = value.year, value.month
 41+ except AttributeError:
 42+ year_val = month_val = None
 43+ if isinstance(value, basestring):
 44+ match = RE_DATE.match(value)
 45+ if match:
 46+ year_val, month_val, day_val = [int(v) for v in match.groups()]
 47+
 48+ output = []
 49+
 50+ if 'id' in self.attrs:
 51+ id_ = self.attrs['id']
 52+ else:
 53+ id_ = 'id_%s' % name
 54+
 55+ month_choices = MONTHS.items()
 56+ if not (self.required and value):
 57+ month_choices.append(self.none_value)
 58+ month_choices.sort()
 59+ local_attrs = self.build_attrs(id=self.month_field % id_)
 60+ s = Select(choices=month_choices)
 61+ select_html = s.render(self.month_field % name, month_val, local_attrs)
 62+ output.append(select_html)
 63+
 64+ year_choices = [(i, i) for i in self.years]
 65+ if not (self.required and value):
 66+ year_choices.insert(0, self.none_value)
 67+ local_attrs['id'] = self.year_field % id_
 68+ s = Select(choices=year_choices)
 69+ select_html = s.render(self.year_field % name, year_val, local_attrs)
 70+ output.append(select_html)
 71+
 72+ return mark_safe(u'\n'.join(output))
 73+
 74+ def id_for_label(self, id_):
 75+ return '%s_month' % id_
 76+ id_for_label = classmethod(id_for_label)
 77+
 78+ def value_from_datadict(self, data, files, name):
 79+ y = data.get(self.year_field % name)
 80+ m = data.get(self.month_field % name)
 81+ if y == m == "0":
 82+ return None
 83+ if y and m:
 84+ return '%s-%s-%s' % (y, m, 1)
 85+ return data.get(name, None)
Property changes on: trunk/tools/editor_trends/wikilytics/api/widgets.py
___________________________________________________________________
Added: svn:eol-style
8686 + native

Status & tagging log