diff --git a/.coveragerc b/.coveragerc
new file mode 100644
index 000000000..8655e4714
--- /dev/null
+++ b/.coveragerc
@@ -0,0 +1,4 @@
+[run]
+source=openslides
+[report]
+exclude_lines = def __(unicode|repr)__
diff --git a/.gitignore b/.gitignore
index 6fa3cff77..d5edd3499 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,8 @@ docs/_build/*
build/*
dist/*
.DS_Store
+settings.py
+
+# Unit test / coverage reports
+.coverage
+htmlcov
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 000000000..b65d5b1dd
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,10 @@
+language: python
+python:
+ - "2.5"
+ - "2.6"
+ - "2.7"
+install:
+ - pip install -r requirements.txt --use-mirrors
+ - pip install coverage django-discover-runner
+ - python extras/scripts/create_local_settings.py
+script: coverage run ./manage.py test tests && coverage report -m
diff --git a/extras/scripts/create_local_settings.py b/extras/scripts/create_local_settings.py
new file mode 100644
index 000000000..1702992e0
--- /dev/null
+++ b/extras/scripts/create_local_settings.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import os
+import sys
+
+script_path = os.path.realpath(os.path.dirname(__file__))
+sys.path.append(os.path.join(script_path, '..', '..'))
+
+from openslides.main import create_settings
+
+if __name__ == "__main__":
+ cwd = os.getcwd()
+ create_settings(os.path.join(cwd, 'settings.py'),
+ os.path.join(cwd, 'database.sqlite'))
diff --git a/openslides/agenda/forms.py b/openslides/agenda/forms.py
index bfaa30af6..66a4ee7a7 100644
--- a/openslides/agenda/forms.py
+++ b/openslides/agenda/forms.py
@@ -24,8 +24,8 @@ class ItemForm(forms.ModelForm, CssClassMixin):
"""
Form to create of update an item.
"""
- parent = TreeNodeChoiceField(queryset=Item.objects.all(),
- label=_("Parent item"), required=False)
+ parent = TreeNodeChoiceField(
+ queryset=Item.objects.all(), label=_("Parent item"), required=False)
class Meta:
model = Item
diff --git a/openslides/agenda/models.py b/openslides/agenda/models.py
index d887d553c..0356607dd 100644
--- a/openslides/agenda/models.py
+++ b/openslides/agenda/models.py
@@ -10,12 +10,6 @@
:license: GNU GPL, see LICENSE for more details.
"""
-try:
- import json
-except ImportError:
- # for python 2.5 support
- import simplejson as json
-
from django.db import models
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _, ugettext_noop, ugettext
@@ -23,11 +17,9 @@ from django.utils.translation import ugettext_lazy as _, ugettext_noop, ugettext
from mptt.models import MPTTModel, TreeForeignKey
from openslides.config.models import config
-
from openslides.projector.projector import SlideMixin
-from openslides.projector.api import (register_slidemodel, get_slide_from_sid,
- register_slidefunc, split_sid)
-
+from openslides.projector.api import (
+ register_slidemodel, get_slide_from_sid, register_slidefunc)
from openslides.agenda.slides import agenda_show
@@ -45,7 +37,7 @@ class Item(MPTTModel, SlideMixin):
closed = models.BooleanField(default=False, verbose_name=_("Closed"))
weight = models.IntegerField(default=0, verbose_name=_("Weight"))
parent = TreeForeignKey('self', null=True, blank=True,
- related_name='children')
+ related_name='children')
related_sid = models.CharField(null=True, blank=True, max_length=63)
def get_related_slide(self):
@@ -84,7 +76,6 @@ class Item(MPTTModel, SlideMixin):
return self.title
return self.get_related_slide().get_agenda_title()
-
def get_title_supplement(self):
"""
return a supplement for the title.
diff --git a/openslides/agenda/views.py b/openslides/agenda/views.py
index 863bd9da4..55b42e204 100644
--- a/openslides/agenda/views.py
+++ b/openslides/agenda/views.py
@@ -11,7 +11,6 @@
"""
from reportlab.platypus import Paragraph
-from django.core.context_processors import csrf
from django.core.urlresolvers import reverse
from django.contrib import messages
from django.db import transaction
@@ -20,18 +19,15 @@ from django.utils.translation import ugettext as _, ugettext_lazy
from django.views.generic.detail import SingleObjectMixin
from openslides.utils.pdf import stylesheet
-from openslides.utils.views import (TemplateView, RedirectView, UpdateView,
- CreateView, DeleteView, PDFView, DetailView)
+from openslides.utils.views import (
+ TemplateView, RedirectView, UpdateView, CreateView, DeleteView, PDFView,
+ DetailView)
from openslides.utils.template import Tab
from openslides.utils.utils import html_strong
-
-from openslides.config.models import config
-
from openslides.projector.api import get_active_slide
from openslides.projector.projector import Widget, SLIDE
-
-from openslides.agenda.models import Item
-from openslides.agenda.forms import ItemOrderForm, ItemForm
+from .models import Item
+from .forms import ItemOrderForm, ItemForm
class Overview(TemplateView):
@@ -53,7 +49,8 @@ class Overview(TemplateView):
def post(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
if not request.user.has_perm('agenda.can_manage_agenda'):
- messages.error(request,
+ messages.error(
+ request,
_('You are not authorized to manage the agenda.'))
return self.render_to_response(context)
transaction.commit()
@@ -69,8 +66,8 @@ class Overview(TemplateView):
Model.save(item)
else:
transaction.rollback()
- messages.error(request,
- _('Errors when reordering of the agenda'))
+ messages.error(
+ request, _('Errors when reordering of the agenda'))
return self.render_to_response(context)
Item.objects.rebuild()
# TODO: assure, that it is a valid tree
@@ -130,8 +127,8 @@ class ItemUpdate(UpdateView):
apply_url = 'item_edit'
def get_success_url(self):
- messages.success(self.request,
- _("Item %s was successfully modified.") \
+ messages.success(
+ self.request, _("Item %s was successfully modified.")
% html_strong(self.request.POST['title']))
if 'apply' in self.request.POST:
return ''
@@ -151,8 +148,8 @@ class ItemCreate(CreateView):
apply_url = 'item_edit'
def get_success_url(self):
- messages.success(self.request,
- _("Item %s was successfully created.") \
+ messages.success(
+ self.request, _("Item %s was successfully created.")
% html_strong(self.request.POST['title']))
if 'apply' in self.request.POST:
return reverse(self.get_apply_url(), args=[self.object.id])
@@ -176,13 +173,13 @@ class ItemDelete(DeleteView):
def pre_post_redirect(self, request, *args, **kwargs):
if self.get_answer() == 'all':
self.object.delete(with_children=True)
- messages.success(request,
- _("Item %s and his children were successfully deleted.")
+ messages.success(
+ request, _("Item %s and his children were successfully deleted.")
% html_strong(self.object))
elif self.get_answer() == 'yes':
self.object.delete(with_children=False)
- messages.success(request,
- _("Item %s was successfully deleted.")
+ messages.success(
+ request, _("Item %s was successfully deleted.")
% html_strong(self.object))
@@ -199,7 +196,8 @@ class AgendaPDF(PDFView):
ancestors = item.get_ancestors()
if ancestors:
space = " " * 6 * ancestors.count()
- story.append(Paragraph("%s%s" % (space, item.get_title()),
+ story.append(Paragraph(
+ "%s%s" % (space, item.get_title()),
stylesheet['Subitem']))
else:
story.append(Paragraph(item.get_title(), stylesheet['Item']))
@@ -213,10 +211,9 @@ def register_tab(request):
return Tab(
title=_('Agenda'),
url=reverse('item_overview'),
- permission=request.user.has_perm('agenda.can_see_agenda')
- or request.user.has_perm('agenda.can_manage_agenda'),
- selected=selected,
- )
+ permission=(request.user.has_perm('agenda.can_see_agenda') or
+ request.user.has_perm('agenda.can_manage_agenda')),
+ selected=selected)
def get_widgets(request):
diff --git a/openslides/assignment/forms.py b/openslides/assignment/forms.py
index cf4dfcba2..9adf16dbd 100644
--- a/openslides/assignment/forms.py
+++ b/openslides/assignment/forms.py
@@ -11,7 +11,7 @@
"""
from django import forms
-from django.utils.translation import ugettext_lazy as _, ugettext_noop
+from django.utils.translation import ugettext_lazy as _
from openslides.utils.forms import CssClassMixin
from openslides.utils.person import PersonFormField
@@ -20,8 +20,8 @@ from openslides.assignment.models import Assignment
class AssignmentForm(forms.ModelForm, CssClassMixin):
- posts = forms.IntegerField(min_value=1, initial=1,
- label=_("Number of available posts"))
+ posts = forms.IntegerField(
+ min_value=1, initial=1, label=_("Number of available posts"))
class Meta:
model = Assignment
@@ -39,8 +39,7 @@ class ConfigForm(forms.Form, CssClassMixin):
assignment_publish_winner_results_only = forms.BooleanField(
required=False,
label=_("Only publish voting results for selected winners "
- "(Projector view only)")
- )
+ "(Projector view only)"))
assignment_pdf_ballot_papers_selection = forms.ChoiceField(
widget=forms.Select(),
required=False,
@@ -48,31 +47,25 @@ class ConfigForm(forms.Form, CssClassMixin):
choices=(
("NUMBER_OF_DELEGATES", _("Number of all delegates")),
("NUMBER_OF_ALL_PARTICIPANTS", _("Number of all participants")),
- ("CUSTOM_NUMBER", _("Use the following custom number"))
- )
- )
+ ("CUSTOM_NUMBER", _("Use the following custom number"))))
assignment_pdf_ballot_papers_number = forms.IntegerField(
- widget=forms.TextInput(attrs={'class':'small-input'}),
+ widget=forms.TextInput(attrs={'class': 'small-input'}),
required=False,
min_value=1,
- label=_("Custom number of ballot papers")
- )
+ label=_("Custom number of ballot papers"))
assignment_pdf_title = forms.CharField(
widget=forms.TextInput(),
required=False,
- label=_("Title for PDF document (all elections)")
- )
+ label=_("Title for PDF document (all elections)"))
assignment_pdf_preamble = forms.CharField(
widget=forms.Textarea(),
required=False,
- label=_("Preamble text for PDF document (all elections)")
- )
- assignment_poll_vote_values = forms.ChoiceField(widget=forms.Select(),
+ label=_("Preamble text for PDF document (all elections)"))
+ assignment_poll_vote_values = forms.ChoiceField(
+ widget=forms.Select(),
required=False,
label=_("Election method"),
choices=(
("auto", _("Automatic assign of method.")),
("votes", _("Always one option per candidate.")),
- ("yesnoabstain", _("Always Yes-No-Abstain per candidate.")),
- )
- )
+ ("yesnoabstain", _("Always Yes-No-Abstain per candidate."))))
diff --git a/openslides/assignment/models.py b/openslides/assignment/models.py
index b70972234..fe0641934 100644
--- a/openslides/assignment/models.py
+++ b/openslides/assignment/models.py
@@ -16,16 +16,12 @@ from django.dispatch import receiver
from django.utils.translation import ugettext_lazy as _, ugettext_noop
from openslides.utils.person import PersonField
-
from openslides.config.models import config
from openslides.config.signals import default_config_value
-
from openslides.projector.api import register_slidemodel
from openslides.projector.projector import SlideMixin
-
-from openslides.poll.models import (BasePoll, CountInvalid, CountVotesCast,
- BaseOption, PublishPollMixin, BaseVote)
-
+from openslides.poll.models import (
+ BasePoll, CountInvalid, CountVotesCast, BaseOption, PublishPollMixin, BaseVote)
from openslides.agenda.models import Item
@@ -51,11 +47,10 @@ class Assignment(models.Model, SlideMixin):
)
name = models.CharField(max_length=100, verbose_name=_("Name"))
- description = models.TextField(null=True, blank=True,
- verbose_name=_("Description"))
- posts = models.PositiveSmallIntegerField(
- verbose_name=_("Number of available posts"))
- polldescription = models.CharField(max_length=100, null=True, blank=True,
+ description = models.TextField(null=True, blank=True, verbose_name=_("Description"))
+ posts = models.PositiveSmallIntegerField(verbose_name=_("Number of available posts"))
+ polldescription = models.CharField(
+ max_length=100, null=True, blank=True,
verbose_name=_("Comment on the ballot paper"))
status = models.CharField(max_length=3, choices=STATUS, default='sea')
@@ -68,8 +63,8 @@ class Assignment(models.Model, SlideMixin):
if error:
raise NameError(_('%s is not a valid status.') % status)
if self.status == status:
- raise NameError(_('The assignment status is already %s.')
- % self.status)
+ raise NameError(
+ _('The assignment status is already %s.') % self.status)
self.status = status
self.save()
@@ -116,14 +111,12 @@ class Assignment(models.Model, SlideMixin):
else:
candidation.delete()
-
def is_candidate(self, person):
"""
return True, if person is a candidate.
"""
try:
- return self.assignment_candidates.filter(person=person) \
- .exclude(blocked=True).exists()
+ return self.assignment_candidates.filter(person=person).exclude(blocked=True).exists()
except AttributeError:
return False
@@ -131,8 +124,7 @@ class Assignment(models.Model, SlideMixin):
"""
return True, if the person is blockt for candidation.
"""
- return self.assignment_candidates.filter(person=person) \
- .filter(blocked=True).exists()
+ return self.assignment_candidates.filter(person=person).filter(blocked=True).exists()
@property
def assignment_candidates(self):
@@ -164,7 +156,6 @@ class Assignment(models.Model, SlideMixin):
return participants
#return candidates.values_list('person', flat=True)
-
def set_elected(self, person, value=True):
candidate = self.assignment_candidates.get(person=person)
candidate.elected = value
@@ -212,7 +203,6 @@ class Assignment(models.Model, SlideMixin):
vote_results_dict[candidate].append(votes)
return vote_results_dict
-
def get_agenda_title(self):
return self.name
@@ -298,8 +288,7 @@ class AssignmentPoll(BasePoll, CountInvalid, CountVotesCast, PublishPollMixin):
self.yesnoabstain = False
self.save()
if self.yesnoabstain:
- return [ugettext_noop('Yes'), ugettext_noop('No'),
- ugettext_noop('Abstain')]
+ return [ugettext_noop('Yes'), ugettext_noop('No'), ugettext_noop('Abstain')]
else:
return [ugettext_noop('Votes')]
diff --git a/openslides/assignment/views.py b/openslides/assignment/views.py
index 5adbf0188..f5e244732 100644
--- a/openslides/assignment/views.py
+++ b/openslides/assignment/views.py
@@ -13,39 +13,31 @@
import os
from reportlab.lib import colors
-from reportlab.platypus import (SimpleDocTemplate, PageBreak, Paragraph,
- Spacer, Table, TableStyle)
+from reportlab.platypus import (
+ SimpleDocTemplate, PageBreak, Paragraph, Spacer, Table, TableStyle)
from reportlab.lib.units import cm
from django.conf import settings
from django.core.urlresolvers import reverse
from django.contrib import messages
from django.contrib.auth.decorators import login_required
-from django.contrib.auth.models import User
from django.shortcuts import redirect
from django.utils.translation import ungettext, ugettext as _
from openslides.utils.pdf import stylesheet
from openslides.utils.template import Tab
-from openslides.utils.utils import (template, permission_required,
- gen_confirm_form, del_confirm_form, ajax_request)
+from openslides.utils.utils import (
+ template, permission_required, gen_confirm_form, del_confirm_form, ajax_request)
from openslides.utils.views import FormView, DeleteView, PDFView, RedirectView
from openslides.utils.person import get_person
-
from openslides.config.models import config
-
from openslides.participant.models import User
-
from openslides.projector.projector import Widget
-
from openslides.poll.views import PollFormView
-
from openslides.agenda.models import Item
-
-from openslides.assignment.models import (Assignment, AssignmentPoll,
- AssignmentOption)
-from openslides.assignment.forms import (AssignmentForm, AssignmentRunForm,
- ConfigForm)
+from openslides.assignment.models import Assignment, AssignmentPoll
+from openslides.assignment.forms import (
+ AssignmentForm, AssignmentRunForm, ConfigForm)
@permission_required('assignment.can_see_assignment')
@@ -56,7 +48,7 @@ def get_overview(request):
query = query.filter(status__iexact=request.GET['status'])
try:
sort = request.GET['sort']
- if sort in ['name','status']:
+ if sort in ['name', 'status']:
query = query.order_by(sort)
except KeyError:
pass
@@ -91,7 +83,6 @@ def view(request, assignment_id=None):
if request.user.has_perm('assignment.can_nominate_other'):
form = AssignmentRunForm()
-
polls = assignment.poll_set.all()
if not request.user.has_perm('assignment.can_manage_assignment'):
polls = assignment.poll_set.filter(published=True)
@@ -100,7 +91,8 @@ def view(request, assignment_id=None):
polls = assignment.poll_set.all()
vote_results = assignment.vote_results(only_published=False)
- blocked_candidates = [candidate.person for candidate in \
+ blocked_candidates = [
+ candidate.person for candidate in
assignment.assignment_candidates.filter(blocked=True)]
return {
'assignment': assignment,
@@ -180,7 +172,7 @@ def run(request, assignment_id):
assignment = Assignment.objects.get(pk=assignment_id)
try:
assignment.run(request.user, request.user)
- messages.success(request, _('You have set your candidature successfully.') )
+ messages.success(request, _('You have set your candidature successfully.'))
except NameError, e:
messages.error(request, e)
return redirect(reverse('assignment_view', args=[assignment_id]))
@@ -195,7 +187,8 @@ def delrun(request, assignment_id):
except Exception, e:
messages.error(request, e)
else:
- messages.success(request,
+ messages.success(
+ request,
_("You have withdrawn your candidature successfully. "
"You can not be nominated by other participants anymore."))
else:
@@ -240,7 +233,7 @@ def set_active(request, assignment_id):
@permission_required('assignment.can_manage_assignment')
def gen_poll(request, assignment_id):
poll = Assignment.objects.get(pk=assignment_id).gen_poll()
- messages.success(request, _("New ballot was successfully created.") )
+ messages.success(request, _("New ballot was successfully created."))
return redirect(reverse('assignment_poll_view', args=[poll.id]))
@@ -279,9 +272,9 @@ def set_publish_status(request, poll_id):
return ajax_request({'published': poll.published})
if poll.published:
- messages.success(request, _("Ballot successfully published.") )
+ messages.success(request, _("Ballot successfully published."))
else:
- messages.success(request, _("Ballot successfully unpublished.") )
+ messages.success(request, _("Ballot successfully unpublished."))
return redirect(reverse('assignment_view', args=[poll.assignment.id]))
@@ -336,8 +329,9 @@ class AssignmentPDF(PDFView):
try:
assignment_id = self.kwargs['assignment_id']
assignment = Assignment.objects.get(id=assignment_id)
- filename = u'%s-%s' % (_("Assignment"),
- assignment.name.replace(' ','_'))
+ filename = u'%s-%s' % (
+ _("Assignment"),
+ assignment.name.replace(' ', '_'))
except:
filename = _("Elections")
return filename
@@ -347,23 +341,24 @@ class AssignmentPDF(PDFView):
assignment_id = self.kwargs['assignment_id']
except KeyError:
assignment_id = None
- if assignment_id is None: #print all assignments
+ if assignment_id is None: # print all assignments
title = config["assignment_pdf_title"]
story.append(Paragraph(title, stylesheet['Heading1']))
preamble = config["assignment_pdf_preamble"]
if preamble:
- story.append(Paragraph("%s" % preamble.replace('\r\n', '
'),
+ story.append(Paragraph(
+ "%s" % preamble.replace('\r\n', '
'),
stylesheet['Paragraph']))
story.append(Spacer(0, 0.75 * cm))
assignments = Assignment.objects.all()
- if not assignments: # No assignments existing
- story.append(Paragraph(_("No assignments available."),
- stylesheet['Heading3']))
- else: # Print all assignments
+ if not assignments: # No assignments existing
+ story.append(Paragraph(
+ _("No assignments available."), stylesheet['Heading3']))
+ else: # Print all assignments
# List of assignments
for assignment in assignments:
- story.append(Paragraph(assignment.name,
- stylesheet['Heading3']))
+ story.append(Paragraph(
+ assignment.name, stylesheet['Heading3']))
# Assignment details (each assignment on single page)
for assignment in assignments:
story.append(PageBreak())
@@ -376,28 +371,33 @@ class AssignmentPDF(PDFView):
def get_assignment(self, assignment, story):
# title
- story.append(Paragraph(_("Election: %s") % assignment.name,
- stylesheet['Heading1']))
+ story.append(Paragraph(
+ _("Election: %s") % assignment.name, stylesheet['Heading1']))
story.append(Spacer(0, 0.5 * cm))
# posts
cell1a = []
- cell1a.append(Paragraph("%s:" %
+ cell1a.append(Paragraph(
+ "%s:" %
_("Number of available posts"), stylesheet['Bold']))
cell1b = []
cell1b.append(Paragraph(str(assignment.posts), stylesheet['Paragraph']))
# candidates
cell2a = []
- cell2a.append(Paragraph("%s:%s:" % _("Candidates"), stylesheet['Heading4']))
cell2b = []
for candidate in assignment.candidates:
- cell2b.append(Paragraph(". %s" % candidate,
+ cell2b.append(Paragraph(
+ ". %s" % candidate,
stylesheet['Signaturefield']))
if assignment.status == "sea":
for x in range(0, 2 * assignment.posts):
- cell2b.append(Paragraph(". "
- "__________________________________________",
- stylesheet['Signaturefield']))
+ cell2b.append(
+ Paragraph(
+ ". "
+ "__________________________________________",
+ stylesheet['Signaturefield']))
cell2b.append(Spacer(0, 0.2 * cm))
# Vote results
@@ -409,15 +409,15 @@ class AssignmentPDF(PDFView):
# Left side
cell3a = []
- cell3a.append(Paragraph("%s:" % (_("Vote results")),
- stylesheet['Heading4']))
+ cell3a.append(Paragraph(
+ "%s:" % (_("Vote results")), stylesheet['Heading4']))
if polls.count() == 1:
- cell3a.append(Paragraph("%s %s" % (polls.count(), _("ballot")),
- stylesheet['Normal']))
+ cell3a.append(Paragraph(
+ "%s %s" % (polls.count(), _("ballot")), stylesheet['Normal']))
elif polls.count() > 1:
- cell3a.append(Paragraph("%s %s" % (polls.count(), _("ballots")),
- stylesheet['Normal']))
+ cell3a.append(Paragraph(
+ "%s %s" % (polls.count(), _("ballots")), stylesheet['Normal']))
# Add table head row
headrow = []
@@ -426,7 +426,6 @@ class AssignmentPDF(PDFView):
headrow.append("%s." % poll.get_ballot())
data_votes.append(headrow)
-
# Add result rows
elected_candidates = list(assignment.elected)
for candidate, poll_list in vote_results.iteritems():
@@ -439,12 +438,13 @@ class AssignmentPDF(PDFView):
candidate_string += "\n(%s)" % candidate.name_suffix
row.append(candidate_string)
for vote in poll_list:
- if vote == None:
+ if vote is None:
row.append('–')
elif 'Yes' in vote and 'No' in vote and 'Abstain' in vote:
- row.append(_("Y: %(YES)s\nN: %(NO)s\nA: %(ABSTAIN)s")
- % {'YES':vote['Yes'], 'NO': vote['No'],
- 'ABSTAIN': vote['Abstain']})
+ row.append(
+ _("Y: %(YES)s\nN: %(NO)s\nA: %(ABSTAIN)s")
+ % {'YES': vote['Yes'], 'NO': vote['No'],
+ 'ABSTAIN': vote['Abstain']})
elif 'Votes' in vote:
row.append(vote['Votes'])
else:
@@ -465,15 +465,14 @@ class AssignmentPDF(PDFView):
footrow_two.append(poll.print_votescast())
data_votes.append(footrow_two)
- table_votes=Table(data_votes)
- table_votes.setStyle( TableStyle([
+ table_votes = Table(data_votes)
+ table_votes.setStyle(TableStyle([
('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
- ('VALIGN',(0, 0),(-1, -1), 'TOP'),
- ('LINEABOVE',(0, 0),(-1, 0), 2, colors.black),
- ('LINEABOVE',(0, 1),(-1, 1), 1, colors.black),
- ('LINEBELOW',(0, -1),(-1, -1), 2, colors.black),
- ('ROWBACKGROUNDS', (0, 1), (-1, -1), (colors.white, (.9, .9, .9))),
- ]))
+ ('VALIGN', (0, 0), (-1, -1), 'TOP'),
+ ('LINEABOVE', (0, 0), (-1, 0), 2, colors.black),
+ ('LINEABOVE', (0, 1), (-1, 1), 1, colors.black),
+ ('LINEBELOW', (0, -1), (-1, -1), 2, colors.black),
+ ('ROWBACKGROUNDS', (0, 1), (-1, -1), (colors.white, (.9, .9, .9)))]))
# table
data = []
@@ -484,17 +483,18 @@ class AssignmentPDF(PDFView):
else:
data.append([cell2a, cell2b])
data.append([Spacer(0, 0.2 * cm), ''])
- t=Table(data)
+ t = Table(data)
t._argW[0] = 4.5 * cm
t._argW[1] = 11 * cm
- t.setStyle(TableStyle([ ('BOX', (0,0), (-1, -1), 1, colors.black),
- ('VALIGN', (0, 0), (-1, -1), 'TOP'),
- ]))
+ t.setStyle(TableStyle([
+ ('BOX', (0, 0), (-1, -1), 1, colors.black),
+ ('VALIGN', (0, 0), (-1, -1), 'TOP')]))
story.append(t)
story.append(Spacer(0, 1 * cm))
# text
- story.append(Paragraph("%s" % assignment.description.replace('\r\n',
+ story.append(Paragraph(
+ "%s" % assignment.description.replace('\r\n',
'
'), stylesheet['Paragraph']))
@@ -519,13 +519,15 @@ class AssignmentPollPDF(PDFView):
return super(AssignmentPollPDF, self).get(request, *args, **kwargs)
def get_filename(self):
- filename = u'%s-%s_%s' % (_("Election"), self.poll.assignment.name.replace(' ', '_'),
+ filename = u'%s-%s_%s' % (
+ _("Election"), self.poll.assignment.name.replace(' ', '_'),
self.poll.get_ballot())
return filename
def get_template(self, buffer):
- return SimpleDocTemplate(buffer, topMargin=-6, bottomMargin=-6,
- leftMargin=0, rightMargin=0, showBoundary=False)
+ return SimpleDocTemplate(
+ buffer, topMargin=-6, bottomMargin=-6, leftMargin=0, rightMargin=0,
+ showBoundary=False)
def build_document(self, pdf_document, story):
pdf_document.build(story)
@@ -534,23 +536,27 @@ class AssignmentPollPDF(PDFView):
imgpath = os.path.join(settings.SITE_ROOT, 'static/images/circle.png')
circle = " " % imgpath
cell = []
- cell.append(Spacer(0,0.8*cm))
- cell.append(Paragraph(_("Election") + ": " + self.poll.assignment.name,
+ cell.append(Spacer(0, 0.8 * cm))
+ cell.append(Paragraph(
+ _("Election") + ": " + self.poll.assignment.name,
stylesheet['Ballot_title']))
- cell.append(Paragraph(self.poll.assignment.polldescription,
+ cell.append(Paragraph(
+ self.poll.assignment.polldescription,
stylesheet['Ballot_subtitle']))
options = self.poll.get_options()
ballot_string = _("%d. ballot") % self.poll.get_ballot()
- candidate_string = ungettext("%d candidate", "%d candidates",
- len(options)) % len(options)
- available_posts_string = ungettext("%d available post", "%d available posts",
+ candidate_string = ungettext(
+ "%d candidate", "%d candidates", len(options)) % len(options)
+ available_posts_string = ungettext(
+ "%d available post", "%d available posts",
self.poll.assignment.posts) % self.poll.assignment.posts
- cell.append(Paragraph("%s, %s, %s" % (ballot_string, candidate_string,
+ cell.append(Paragraph(
+ "%s, %s, %s" % (ballot_string, candidate_string,
available_posts_string), stylesheet['Ballot_description']))
cell.append(Spacer(0, 0.4 * cm))
- data= []
+ data = []
# get ballot papers config values
ballot_papers_selection = config["assignment_pdf_ballot_papers_selection"]
ballot_papers_number = config["assignment_pdf_ballot_papers_number"]
@@ -560,7 +566,7 @@ class AssignmentPollPDF(PDFView):
number = User.objects.filter(type__iexact="delegate").count()
elif ballot_papers_selection == "NUMBER_OF_ALL_PARTICIPANTS":
number = int(User.objects.count())
- else: # ballot_papers_selection == "CUSTOM_NUMBER"
+ else: # ballot_papers_selection == "CUSTOM_NUMBER"
number = int(ballot_papers_number)
number = max(1, number)
@@ -568,16 +574,18 @@ class AssignmentPollPDF(PDFView):
if self.poll.yesnoabstain:
for option in options:
candidate = option.candidate
- cell.append(Paragraph(candidate.clean_name,
- stylesheet['Ballot_option_name']))
+ cell.append(Paragraph(
+ candidate.clean_name, stylesheet['Ballot_option_name']))
if candidate.name_suffix:
- cell.append(Paragraph("(%s)" % candidate.name_suffix,
+ cell.append(Paragraph(
+ "(%s)" % candidate.name_suffix,
stylesheet['Ballot_option_group']))
else:
- cell.append(Paragraph(" ",
- stylesheet['Ballot_option_group']))
- cell.append(Paragraph(circle + _("Yes") + " " * 3 + circle
- + _("No") + " " * 3 + circle+ _("Abstention"),
+ cell.append(Paragraph(
+ " ", stylesheet['Ballot_option_group']))
+ cell.append(Paragraph(
+ circle + _("Yes") + " " * 3 + circle
+ + _("No") + " " * 3 + circle + _("Abstention"),
stylesheet['Ballot_option_YNA']))
# print ballot papers
for user in xrange(number / 2):
@@ -594,14 +602,16 @@ class AssignmentPollPDF(PDFView):
else:
for option in options:
candidate = option.candidate
- cell.append(Paragraph(circle + candidate.clean_name,
+ cell.append(Paragraph(
+ circle + candidate.clean_name,
stylesheet['Ballot_option_name']))
if candidate.name_suffix:
- cell.append(Paragraph("(%s)" % candidate.name_suffix,
+ cell.append(Paragraph(
+ "(%s)" % candidate.name_suffix,
stylesheet['Ballot_option_group_right']))
else:
- cell.append(Paragraph(" ",
- stylesheet['Ballot_option_group_right']))
+ cell.append(Paragraph(
+ " ", stylesheet['Ballot_option_group_right']))
# print ballot papers
for user in xrange(number / 2):
data.append([cell, cell])
@@ -615,9 +625,9 @@ class AssignmentPollPDF(PDFView):
else:
t = Table(data, 10.5 * cm, 29.7 * cm)
- t.setStyle(TableStyle([('GRID', (0, 0), (-1, -1), 0.25, colors.grey),
- ('VALIGN', (0, 0), (-1, -1), 'TOP'),
- ]))
+ t.setStyle(TableStyle([
+ ('GRID', (0, 0), (-1, -1), 0.25, colors.grey),
+ ('VALIGN', (0, 0), (-1, -1), 'TOP')]))
story.append(t)
@@ -629,16 +639,15 @@ class Config(FormView):
def get_initial(self):
return {
'assignment_publish_winner_results_only':
- config['assignment_publish_winner_results_only'],
+ config['assignment_publish_winner_results_only'],
'assignment_pdf_ballot_papers_selection':
- config['assignment_pdf_ballot_papers_selection'],
+ config['assignment_pdf_ballot_papers_selection'],
'assignment_pdf_ballot_papers_number':
- config['assignment_pdf_ballot_papers_number'],
+ config['assignment_pdf_ballot_papers_number'],
'assignment_pdf_title': config['assignment_pdf_title'],
'assignment_pdf_preamble': config['assignment_pdf_preamble'],
'assignment_poll_vote_values':
- config['assignment_poll_vote_values'],
- }
+ config['assignment_poll_vote_values']}
def form_valid(self, form):
if form.cleaned_data['assignment_publish_winner_results_only']:
@@ -655,8 +664,8 @@ class Config(FormView):
form.cleaned_data['assignment_pdf_preamble']
config['assignment_poll_vote_values'] = \
form.cleaned_data['assignment_poll_vote_values']
- messages.success(self.request,
- _('Election settings successfully saved.'))
+ messages.success(
+ self.request, _('Election settings successfully saved.'))
return super(Config, self).form_valid(form)
@@ -665,10 +674,11 @@ def register_tab(request):
return Tab(
title=_('Elections'),
url=reverse('assignment_overview'),
- permission=request.user.has_perm('assignment.can_see_assignment')
- or request.user.has_perm('assignment.can_nominate_other')
- or request.user.has_perm('assignment.can_nominate_self')
- or request.user.has_perm('assignment.can_manage_assignment'),
+ permission=(
+ request.user.has_perm('assignment.can_see_assignment') or
+ request.user.has_perm('assignment.can_nominate_other') or
+ request.user.has_perm('assignment.can_nominate_self') or
+ request.user.has_perm('assignment.can_manage_assignment')),
selected=selected,
)
diff --git a/openslides/config/forms.py b/openslides/config/forms.py
index ef1a9b4d8..5e7f001d2 100644
--- a/openslides/config/forms.py
+++ b/openslides/config/forms.py
@@ -15,8 +15,6 @@ from django.utils.translation import ugettext_lazy as _
from openslides.utils.forms import CssClassMixin
-from openslides.config.models import config
-
class GeneralConfigForm(forms.Form, CssClassMixin):
event_name = forms.CharField(
diff --git a/openslides/config/models.py b/openslides/config/models.py
index a816be865..01ac2fd1d 100644
--- a/openslides/config/models.py
+++ b/openslides/config/models.py
@@ -51,7 +51,7 @@ class Config(object):
pass
for receiver, value in default_config_value.send(sender='config',
- key=key):
+ key=key):
if value is not None:
return value
if settings.DEBUG:
@@ -69,7 +69,6 @@ class Config(object):
def __contains__(self, item):
return ConfigStore.objects.filter(key=item).exists()
-
config = Config()
@@ -81,7 +80,7 @@ def default_config(sender, key, **kwargs):
return {
'event_name': 'OpenSlides',
'event_description':
- _('Presentation and assembly system'),
+ _('Presentation and assembly system'),
'event_date': '',
'event_location': '',
'event_organizer': '',
@@ -123,11 +122,9 @@ def set_submenu(sender, request, context, **kwargs):
(reverse('config_%s' % appname), _(title), selected)
)
- menu_links.append (
- (reverse('config_version'), _('Version'),
- request.path == reverse('config_version'))
- )
+ menu_links.append((
+ reverse('config_version'), _('Version'),
+ request.path == reverse('config_version')))
context.update({
- 'menu_links': menu_links,
- })
+ 'menu_links': menu_links})
diff --git a/openslides/config/views.py b/openslides/config/views.py
index dfeb6182e..c70fa781b 100644
--- a/openslides/config/views.py
+++ b/openslides/config/views.py
@@ -17,12 +17,12 @@ from django.utils.importlib import import_module
from django.utils.translation import ugettext as _
from openslides import get_version
-
from openslides.utils.template import Tab
from openslides.utils.views import FormView, TemplateView
+from .forms import GeneralConfigForm
+from .models import config
-from openslides.config.forms import GeneralConfigForm
-from openslides.config.models import config
+# TODO: Do not import the participant module in config
from openslides.participant.api import get_or_create_anonymous_group
@@ -61,12 +61,12 @@ class GeneralConfig(FormView):
# system
if form.cleaned_data['system_enable_anonymous']:
config['system_enable_anonymous'] = True
- anonymous = get_or_create_anonymous_group()
+ get_or_create_anonymous_group()
else:
config['system_enable_anonymous'] = False
- messages.success(self.request,
- _('General settings successfully saved.'))
+ messages.success(
+ self.request, _('General settings successfully saved.'))
return super(GeneralConfig, self).form_valid(form)
diff --git a/openslides/global_settings.py b/openslides/global_settings.py
index 0186a3219..174d57d09 100644
--- a/openslides/global_settings.py
+++ b/openslides/global_settings.py
@@ -13,15 +13,12 @@
import os
import sys
-_fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
-def _fs2unicode(s):
- if isinstance(s, unicode):
- return s
- return s.decode(_fs_encoding)
+from openslides.main import fs2unicode
SITE_ROOT = os.path.realpath(os.path.dirname(__file__))
-AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',
+AUTHENTICATION_BACKENDS = (
+ 'django.contrib.auth.backends.ModelBackend',
'openslides.utils.auth.AnonymousAuth',)
LOGIN_URL = '/login/'
@@ -48,12 +45,12 @@ USE_I18N = True
USE_L10N = True
LOCALE_PATHS = (
- _fs2unicode(os.path.join(SITE_ROOT, 'locale')),
+ fs2unicode(os.path.join(SITE_ROOT, 'locale')),
)
# Absolute path to the directory that holds media.
# Example: "/home/media/media.lawrence.com/"
-MEDIA_ROOT = _fs2unicode(os.path.join(SITE_ROOT, './static/'))
+MEDIA_ROOT = fs2unicode(os.path.join(SITE_ROOT, './static/'))
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash if there is a path component (optional in other cases).
@@ -62,17 +59,17 @@ MEDIA_URL = ''
# Absolute path to the directory that holds static media from ``collectstatic``
# Example: "/home/media/static.lawrence.com/"
-STATIC_ROOT = _fs2unicode(os.path.join(SITE_ROOT, '../site-static'))
+STATIC_ROOT = fs2unicode(os.path.join(SITE_ROOT, '../site-static'))
# URL that handles the media served from STATIC_ROOT. Make sure to use a
# trailing slash if there is a path component (optional in other cases).
# Examples: "http://static.lawrence.com", "http://example.com/static/"
-STATIC_URL = '/static/'
+STATIC_URL = '/static/'
# Additional directories containing static files (not application specific)
# Examples: "/home/media/lawrence.com/extra-static/"
STATICFILES_DIRS = (
- _fs2unicode(os.path.join(SITE_ROOT, 'static')),
+ fs2unicode(os.path.join(SITE_ROOT, 'static')),
)
#XXX: Note this setting (as well as our workaround finder)
@@ -106,7 +103,7 @@ TEMPLATE_DIRS = (
# "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
- _fs2unicode(os.path.join(SITE_ROOT, 'templates')),
+ fs2unicode(os.path.join(SITE_ROOT, 'templates')),
)
INSTALLED_APPS = (
@@ -142,3 +139,6 @@ CACHES = {
'LOCATION': 'openslidecache'
}
}
+
+TEST_RUNNER = 'discover_runner.DiscoverRunner'
+TEST_DISCOVER_TOP_LEVEL = os.path.dirname(os.path.dirname(__file__))
diff --git a/openslides/main.py b/openslides/main.py
index fa3ce3c98..11f543ab9 100755
--- a/openslides/main.py
+++ b/openslides/main.py
@@ -72,15 +72,6 @@ KEY_LENGTH = 30
_portable_db_path = object()
-_fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
-
-
-def _fs2unicode(s):
- if isinstance(s, unicode):
- return s
- return s.decode(_fs_encoding)
-
-
def process_options(argv=None):
if argv is None:
argv = sys.argv[1:]
@@ -95,9 +86,11 @@ def process_options(argv=None):
parser.add_option(
"--reset-admin", action="store_true",
help="Make sure the user 'admin' exists and uses 'admin' as password")
- parser.add_option("-s", "--settings", help="Path to the openslides configuration.")
parser.add_option(
- "--no-reload", action="store_true", help="Do not reload the development server")
+ "-s", "--settings", help="Path to the openslides configuration.")
+ parser.add_option(
+ "--no-reload", action="store_true",
+ help="Do not reload the development server")
opts, args = parser.parse_args(argv)
if args:
@@ -186,7 +179,7 @@ def create_settings(settings_path, database_path=None):
else:
if database_path is None:
database_path = get_user_data_path('openslides', 'database.sqlite')
- dbpath_value = repr(_fs2unicode(database_path))
+ dbpath_value = repr(fs2unicode(database_path))
settings_content = CONFIG_TEMPLATE % dict(
default_key=base64.b64encode(os.urandom(KEY_LENGTH)),
@@ -312,6 +305,13 @@ def start_browser(url):
t.start()
+def fs2unicode(s):
+ if isinstance(s, unicode):
+ return s
+ fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
+ return s.decode(fs_encoding)
+
+
def get_user_config_path(*args):
if sys.platform == "win32":
return win32_get_app_data_path(*args)
@@ -319,7 +319,7 @@ def get_user_config_path(*args):
config_home = os.environ.get(
'XDG_CONFIG_HOME', os.path.join(os.path.expanduser('~'), '.config'))
- return os.path.join(_fs2unicode(config_home), *args)
+ return os.path.join(fs2unicode(config_home), *args)
def get_user_data_path(*args):
@@ -330,7 +330,7 @@ def get_user_data_path(*args):
'XDG_DATA_HOME', os.path.join(
os.path.expanduser('~'), '.local', 'share'))
- return os.path.join(_fs2unicode(data_home), *args)
+ return os.path.join(fs2unicode(data_home), *args)
def get_portable_path(*args):
@@ -344,7 +344,7 @@ def get_portable_path(*args):
"Cannot determine portable path when "
"not running as portable")
- portable_dir = _fs2unicode(os.path.dirname(os.path.abspath(sys.executable)))
+ portable_dir = fs2unicode(os.path.dirname(os.path.abspath(sys.executable)))
return os.path.join(portable_dir, *args)
diff --git a/openslides/motion/forms.py b/openslides/motion/forms.py
index 64f949bf4..6fbfc9cff 100644
--- a/openslides/motion/forms.py
+++ b/openslides/motion/forms.py
@@ -11,7 +11,7 @@
"""
from django import forms
-from django.utils.translation import ugettext_lazy as _, ugettext_noop
+from django.utils.translation import ugettext_lazy as _
from openslides.utils.forms import CssClassMixin
from openslides.utils.person import PersonFormField, MultiplePersonFormField
@@ -21,18 +21,18 @@ from openslides.motion.models import Motion
class MotionForm(forms.Form, CssClassMixin):
title = forms.CharField(widget=forms.TextInput(), label=_("Title"))
text = forms.CharField(widget=forms.Textarea(), label=_("Text"))
- reason = forms.CharField(widget=forms.Textarea(), required=False,
- label=_("Reason"))
+ reason = forms.CharField(
+ widget=forms.Textarea(), required=False, label=_("Reason"))
class MotionFormTrivialChanges(MotionForm):
- trivial_change = forms.BooleanField(required=False,
- label=_("Trivial change"),
+ trivial_change = forms.BooleanField(
+ required=False, label=_("Trivial change"),
help_text=_("Trivial changes don't create a new version."))
class MotionManagerForm(forms.ModelForm, CssClassMixin):
- submitter = PersonFormField(label = _("Submitter"))
+ submitter = PersonFormField(label=_("Submitter"))
class Meta:
model = Motion
@@ -46,20 +46,20 @@ class MotionManagerFormSupporter(MotionManagerForm):
class MotionImportForm(forms.Form, CssClassMixin):
csvfile = forms.FileField(
- widget=forms.FileInput(attrs={'size':'50'}),
+ widget=forms.FileInput(attrs={'size': '50'}),
label=_("CSV File"),
)
import_permitted = forms.BooleanField(
required=False,
label=_("Import motions with status \"authorized\""),
help_text=_('Set the initial status for each motion to '
- '"authorized"'),
+ '"authorized"'),
)
class ConfigForm(forms.Form, CssClassMixin):
motion_min_supporters = forms.IntegerField(
- widget=forms.TextInput(attrs={'class':'small-input'}),
+ widget=forms.TextInput(attrs={'class': 'small-input'}),
label=_("Number of (minimum) required supporters for a motion"),
initial=4,
min_value=0,
@@ -82,7 +82,7 @@ class ConfigForm(forms.Form, CssClassMixin):
]
)
motion_pdf_ballot_papers_number = forms.IntegerField(
- widget=forms.TextInput(attrs={'class':'small-input'}),
+ widget=forms.TextInput(attrs={'class': 'small-input'}),
required=False,
min_value=1,
label=_("Custom number of ballot papers")
@@ -101,6 +101,6 @@ class ConfigForm(forms.Form, CssClassMixin):
motion_allow_trivial_change = forms.BooleanField(
label=_("Allow trivial changes"),
help_text=_('Warning: Trivial changes undermine the motions '
- 'autorisation system.'),
+ 'autorisation system.'),
required=False,
)
diff --git a/openslides/motion/models.py b/openslides/motion/models.py
index 380b7de3a..7127e521c 100644
--- a/openslides/motion/models.py
+++ b/openslides/motion/models.py
@@ -21,18 +21,13 @@ from django.utils.translation import ugettext_lazy as _, ugettext_noop, ugettext
from openslides.utils.utils import _propper_unicode
from openslides.utils.person import PersonField
-
from openslides.config.models import config
from openslides.config.signals import default_config_value
-
-from openslides.poll.models import (BaseOption, BasePoll, CountVotesCast,
- CountInvalid, BaseVote)
-
-from openslides.participant.models import User, Group
-
+from openslides.poll.models import (
+ BaseOption, BasePoll, CountVotesCast, CountInvalid, BaseVote)
+from openslides.participant.models import User
from openslides.projector.api import register_slidemodel
from openslides.projector.models import SlideMixin
-
from openslides.agenda.models import Item
@@ -53,7 +48,7 @@ class Motion(models.Model, SlideMixin):
('noc', _('Not Concerned')),
('com', _('Commited a bill')),
('nop', _('Rejected (not authorized)')),
- ('rev', _('Needs Review')), # Where is this status used?
+ ('rev', _('Needs Review')), # Where is this status used?
#additional actions:
# edit
# delete
@@ -67,9 +62,9 @@ class Motion(models.Model, SlideMixin):
submitter = PersonField(verbose_name=_("Submitter"))
number = models.PositiveSmallIntegerField(blank=True, null=True,
- unique=True)
+ unique=True)
status = models.CharField(max_length=3, choices=STATUS, default='pub')
- permitted = models.ForeignKey('AVersion', related_name='permitted', \
+ permitted = models.ForeignKey('AVersion', related_name='permitted',
null=True, blank=True)
log = models.TextField(blank=True, null=True)
@@ -94,7 +89,7 @@ class Motion(models.Model, SlideMixin):
else:
return self.last_version
- def accept_version(self, version, user = None):
+ def accept_version(self, version, user=None):
"""
accept a Version
"""
@@ -102,15 +97,15 @@ class Motion(models.Model, SlideMixin):
self.save(nonewversion=True)
version.rejected = False
version.save()
- self.writelog(_("Version %d authorized") % (version.aid, ),
- user)
+ self.writelog(_("Version %d authorized") % version.aid, user)
- def reject_version(self, version, user = None):
+ def reject_version(self, version, user=None):
if version.id > self.permitted.id:
version.rejected = True
version.save()
- self.writelog(pgettext("Rejected means not authorized", "Version %d rejected")
- % (version.aid, ), user)
+ self.writelog(pgettext(
+ "Rejected means not authorized", "Version %d rejected")
+ % version.aid, user)
return True
return False
@@ -154,8 +149,8 @@ class Motion(models.Model, SlideMixin):
is not the lastone and the lastone is not rejected.
TODO: rename the property in unchecked__changes
"""
- if (self.last_version != self.permitted
- and not self.last_version.rejected):
+ if (self.last_version != self.permitted and
+ not self.last_version.rejected):
return True
else:
return False
@@ -207,7 +202,8 @@ class Motion(models.Model, SlideMixin):
last_version = self.last_version
fields = ["text", "title", "reason"]
if last_version is not None:
- changed_fields = [f for f in fields
+ changed_fields = [
+ f for f in fields
if getattr(last_version, f) != getattr(self, f)]
if not changed_fields:
return # No changes
@@ -219,19 +215,22 @@ class Motion(models.Model, SlideMixin):
last_version.save()
meta = AVersion._meta
- field_names = [unicode(meta.get_field(f).verbose_name)
+ field_names = [
+ unicode(meta.get_field(f).verbose_name)
for f in changed_fields]
- self.writelog(_("Trivial changes to version %(version)d; "
- "changed fields: %(changed_fields)s")
- % dict(version = last_version.aid,
- changed_fields = ", ".join(field_names)))
- return # Done
+ self.writelog(
+ _("Trivial changes to version %(version)d; "
+ "changed fields: %(changed_fields)s")
+ % dict(version=last_version.aid,
+ changed_fields=", ".join(field_names)))
+ return # Done
- version = AVersion(title=getattr(self, 'title', ''),
- text=getattr(self, 'text', ''),
- reason=getattr(self, 'reason', ''),
- motion=self)
+ version = AVersion(
+ title=getattr(self, 'title', ''),
+ text=getattr(self, 'text', ''),
+ reason=getattr(self, 'reason', ''),
+ motion=self)
version.save()
self.writelog(_("Version %s created") % version.aid, user)
is_manager = user.has_perm('motion.can_manage_motion')
@@ -239,9 +238,8 @@ class Motion(models.Model, SlideMixin):
is_manager = False
supporters = self.motionsupporter_set.all()
- if (self.status == "pub"
- and supporters
- and not is_manager):
+ if (self.status == "pub" and
+ supporters and not is_manager):
supporters.delete()
self.writelog(_("Supporters removed"), user)
@@ -272,7 +270,7 @@ class Motion(models.Model, SlideMixin):
remove a supporter from the list of supporters of the motion
"""
try:
- object = self.motionsupporter_set.get(person=person).delete()
+ self.motionsupporter_set.get(person=person).delete()
except MotionSupporter.DoesNotExist:
# TODO: Don't do nothing but raise a precise exception for the view
pass
@@ -288,8 +286,7 @@ class Motion(models.Model, SlideMixin):
raise NameError('This motion has already a number.')
if number is None:
try:
- number = Motion.objects.aggregate(Max('number')) \
- ['number__max'] + 1
+ number = Motion.objects.aggregate(Max('number'))['number__max'] + 1
except TypeError:
number = 1
self.number = number
@@ -316,8 +313,6 @@ class Motion(models.Model, SlideMixin):
"""
self.set_status(user, "nop")
#TODO: reject last version
- aversion = self.last_version
- #self.permitted = aversion
if self.number is None:
self.set_number()
self.save()
@@ -333,11 +328,11 @@ class Motion(models.Model, SlideMixin):
error = False
break
if error:
- #TODO: Use the Right Error
+ # TODO: Use the Right Error
raise NameError(_('%s is not a valid status.') % status)
if self.status == status:
- #TODO: Use the Right Error
- raise NameError(_('The motion status is already \'%s.\'') \
+ # TODO: Use the Right Error
+ raise NameError(_('The motion status is already \'%s.\'')
% self.status)
actions = []
@@ -353,7 +348,7 @@ class Motion(models.Model, SlideMixin):
oldstatus = self.get_status_display()
self.status = status
self.save()
- self.writelog(_("Status modified")+": %s -> %s" \
+ self.writelog(_("Status modified") + ": %s -> %s"
% (oldstatus, self.get_status_display()), user)
def get_allowed_actions(self, user):
@@ -432,10 +427,9 @@ class Motion(models.Model, SlideMixin):
allready a number
"""
if self.number and not force:
- raise NameError('The motion has already a number. ' \
+ raise NameError('The motion has already a number. '
'You can not delete it.')
-
for item in Item.objects.filter(related_sid=self.sid):
item.delete()
super(Motion, self).delete()
@@ -501,12 +495,12 @@ class Motion(models.Model, SlideMixin):
for poll in self.polls:
for option in poll.get_options():
if option.get_votes().exists():
- results.append((option['Yes'], option['No'],
+ results.append((
+ option['Yes'], option['No'],
option['Abstain'], poll.print_votesinvalid(),
poll.print_votescast()))
return results
-
def slide(self):
"""
return the slide dict
@@ -542,10 +536,10 @@ class Motion(models.Model, SlideMixin):
class AVersion(models.Model):
- title = models.CharField(max_length=100, verbose_name = _("Title"))
- text = models.TextField(verbose_name = _("Text"))
- reason = models.TextField(null=True, blank=True, verbose_name = _("Reason"))
- rejected = models.BooleanField() # = Not Permitted
+ title = models.CharField(max_length=100, verbose_name=_("Title"))
+ text = models.TextField(verbose_name=_("Text"))
+ reason = models.TextField(null=True, blank=True, verbose_name=_("Reason"))
+ rejected = models.BooleanField() # = Not Permitted
time = models.DateTimeField(auto_now=True)
motion = models.ForeignKey(Motion)
@@ -576,8 +570,8 @@ class MotionOption(BaseOption):
class MotionPoll(BasePoll, CountInvalid, CountVotesCast):
option_class = MotionOption
- vote_values = [ugettext_noop('Yes'), ugettext_noop('No'),
- ugettext_noop('Abstain')]
+ vote_values = [
+ ugettext_noop('Yes'), ugettext_noop('No'), ugettext_noop('Abstain')]
motion = models.ForeignKey(Motion)
diff --git a/openslides/motion/views.py b/openslides/motion/views.py
index 15dbf4913..76b2ba4c3 100644
--- a/openslides/motion/views.py
+++ b/openslides/motion/views.py
@@ -18,19 +18,17 @@ import os
try:
from urlparse import parse_qs
-except ImportError: # python <= 2.5
+except ImportError: # python <= 2.5
from cgi import parse_qs
from reportlab.lib import colors
from reportlab.lib.units import cm
-from reportlab.platypus import (SimpleDocTemplate, PageBreak, Paragraph, Spacer,
- Table, TableStyle)
+from reportlab.platypus import (
+ SimpleDocTemplate, PageBreak, Paragraph, Spacer, Table, TableStyle)
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import login_required
-from django.contrib.auth.models import User
-from django.core.context_processors import csrf
from django.core.urlresolvers import reverse
from django.db import transaction
from django.shortcuts import redirect
@@ -39,26 +37,21 @@ from django.utils.translation import ugettext as _, ungettext
from openslides.utils import csv_ext
from openslides.utils.pdf import stylesheet
from openslides.utils.template import Tab
-from openslides.utils.utils import (template, permission_required,
- del_confirm_form, gen_confirm_form)
-from openslides.utils.views import (PDFView, RedirectView, DeleteView,
- FormView, SingleObjectMixin, QuestionMixin)
+from openslides.utils.utils import (
+ template, permission_required, del_confirm_form, gen_confirm_form)
+from openslides.utils.views import (
+ PDFView, RedirectView, DeleteView, FormView, SingleObjectMixin,
+ QuestionMixin)
from openslides.utils.person import get_person
-
from openslides.config.models import config
-
from openslides.projector.projector import Widget
-
from openslides.poll.views import PollFormView
-
from openslides.participant.api import gen_username, gen_password
from openslides.participant.models import User, Group
-
from openslides.agenda.models import Item
-
from openslides.motion.models import Motion, AVersion, MotionPoll
-from openslides.motion.forms import (MotionForm,
- MotionFormTrivialChanges, MotionManagerForm,
+from openslides.motion.forms import (
+ MotionForm, MotionFormTrivialChanges, MotionManagerForm,
MotionManagerFormSupporter, MotionImportForm, ConfigForm)
@@ -124,14 +117,14 @@ def overview(request):
for (i, motion) in enumerate(motions):
try:
motions[i] = {
- 'actions' : motion.get_allowed_actions(request.user),
- 'motion' : motion
+ 'actions': motion.get_allowed_actions(request.user),
+ 'motion': motion
}
except:
# todo: except what?
motions[i] = {
- 'actions' : [],
- 'motion' : motion
+ 'actions': [],
+ 'motion': motion
}
return {
@@ -210,12 +203,7 @@ def edit(request, motion_id=None):
managerform = None
if valid:
- del_supporters = True
if is_manager:
- if motion: # Edit motion
- original_supporters = list(motion.supporters)
- else:
- original_supporters = []
motion = managerform.save(commit=False)
elif motion_id is None:
motion = Motion(submitter=request.user)
@@ -611,7 +599,7 @@ def motion_import(request):
except ValueError:
messages.error(request, _('Ignoring malformed line %d in import file.') % (lno + 1))
continue
-
+
if is_group:
# fetch existing groups or issue an error message
try:
@@ -694,7 +682,7 @@ def motion_import(request):
return redirect(reverse('motion_overview'))
except csv.Error:
- message.error(request, _('Import aborted because of severe errors in the input file.'))
+ messages.error(request, _('Import aborted because of severe errors in the input file.'))
except UnicodeDecodeError:
messages.error(request, _('Import file has wrong character encoding, only UTF-8 is supported!'))
else:
diff --git a/openslides/participant/api.py b/openslides/participant/api.py
index 5544af64c..fb5325628 100644
--- a/openslides/participant/api.py
+++ b/openslides/participant/api.py
@@ -14,11 +14,11 @@
from __future__ import with_statement
from random import choice
-import string
import csv
from django.contrib.auth.models import Permission
from django.db import transaction
+from django.utils.translation import ugettext as _
from openslides.utils import csv_ext
@@ -78,7 +78,7 @@ def import_users(csv_file):
try:
(first_name, last_name, gender, structure_level, type, committee, comment) = line[:7]
except ValueError:
- error_messages.append(_('Ignoring malformed line %d in import file.') % line_no + 1)
+ error_messages.append(_('Ignoring malformed line %d in import file.') % (line_no + 1))
continue
user = User()
user.last_name = last_name
@@ -105,7 +105,7 @@ def get_or_create_registered_group():
name__iexact='Registered', defaults={'name': 'Registered'})
if created:
registered.permissions = Permission.objects.filter(
- codename__in=DEFAULT_PERMS)
+ codename__in=DEFAULT_PERMS)
registered.save()
return registered
@@ -115,6 +115,6 @@ def get_or_create_anonymous_group():
name__iexact='Anonymous', defaults={'name': 'Anonymous'})
if created:
anonymous.permissions = Permission.objects.filter(
- codename__in=DEFAULT_PERMS)
+ codename__in=DEFAULT_PERMS)
anonymous.save()
return anonymous
diff --git a/openslides/participant/forms.py b/openslides/participant/forms.py
index b1fcea525..8085f313f 100644
--- a/openslides/participant/forms.py
+++ b/openslides/participant/forms.py
@@ -66,12 +66,13 @@ class GroupForm(forms.ModelForm, CssClassMixin):
instance = forms.ModelForm.save(self, False)
old_save_m2m = self.save_m2m
- def save_m2m():
- old_save_m2m()
- instance.user_set.clear()
- for user in self.cleaned_data['users']:
- instance.user_set.add(user)
+ def save_m2m():
+ old_save_m2m()
+
+ instance.user_set.clear()
+ for user in self.cleaned_data['users']:
+ instance.user_set.add(user)
self.save_m2m = save_m2m
if commit:
@@ -102,7 +103,7 @@ class GroupForm(forms.ModelForm, CssClassMixin):
class UsersettingsForm(forms.ModelForm, CssClassMixin):
class Meta:
model = User
- fields = ('username', 'first_name', 'last_name', 'gender', 'email', 'committee', 'about_me' )
+ fields = ('username', 'first_name', 'last_name', 'gender', 'email', 'committee', 'about_me')
class UserImportForm(forms.Form, CssClassMixin):
diff --git a/openslides/participant/models.py b/openslides/participant/models.py
index 7f047a9c4..0adb6219d 100644
--- a/openslides/participant/models.py
+++ b/openslides/participant/models.py
@@ -25,8 +25,9 @@ from openslides.config.signals import default_config_value
from openslides.projector.api import register_slidemodel
from openslides.projector.projector import SlideMixin
+
class User(DjangoUser, PersonMixin, Person, SlideMixin):
- prefix = 'user' # This is for the slides
+ prefix = 'user' # This is for the slides
person_prefix = 'user'
GENDER_CHOICES = (
('male', _('Male')),
@@ -131,8 +132,9 @@ class User(DjangoUser, PersonMixin, Person, SlideMixin):
register_slidemodel(User)
+
class Group(DjangoGroup, PersonMixin, Person, SlideMixin):
- prefix = 'group' # This is for the slides
+ prefix = 'group' # This is for the slides
person_prefix = 'group'
django_group = models.OneToOneField(DjangoGroup, editable=False, parent_link=True)
@@ -173,6 +175,7 @@ class Group(DjangoGroup, PersonMixin, Person, SlideMixin):
register_slidemodel(Group)
+
class UsersAndGroupsToPersons(object):
"""
Object to send all Users and Groups or a special User or Group to
@@ -216,8 +219,9 @@ def receive_persons(sender, **kwargs):
"""
Answers to the Person-API
"""
- return UsersAndGroupsToPersons(person_prefix_filter=kwargs['person_prefix_filter'],
- id_filter=kwargs['id_filter'])
+ return UsersAndGroupsToPersons(
+ person_prefix_filter=kwargs['person_prefix_filter'],
+ id_filter=kwargs['id_filter'])
@receiver(default_config_value, dispatch_uid="participant_default_config")
diff --git a/openslides/participant/urls.py b/openslides/participant/urls.py
index e3ac2e553..569f8b85f 100644
--- a/openslides/participant/urls.py
+++ b/openslides/participant/urls.py
@@ -11,7 +11,6 @@
"""
from django.conf.urls.defaults import url, patterns
-from django.core.urlresolvers import reverse
from openslides.participant.views import (
UserOverview, UserCreateView, UserDetailView, UserUpdateView,
diff --git a/openslides/participant/views.py b/openslides/participant/views.py
index b4be8b998..c0fa8d6c5 100644
--- a/openslides/participant/views.py
+++ b/openslides/participant/views.py
@@ -28,7 +28,6 @@ from reportlab.platypus import (
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import PasswordChangeForm
-from django.contrib.auth.models import User
from django.contrib.auth.views import login as django_login
from django.core.urlresolvers import reverse
from django.shortcuts import redirect
@@ -39,16 +38,12 @@ from openslides.utils.template import Tab
from openslides.utils.utils import (
template, decodedict, encodedict, delete_default_permissions, html_strong)
from openslides.utils.views import (
- FormView, PDFView, CreateView, UpdateView, DeleteView,
- RedirectView, SingleObjectMixin, ListView, QuestionMixin)
-
+ FormView, PDFView, CreateView, UpdateView, DeleteView, PermissionMixin,
+ RedirectView, SingleObjectMixin, ListView, QuestionMixin, DetailView)
from openslides.config.models import config
-
from openslides.projector.projector import Widget
-
from openslides.motion.models import Motion
from openslides.assignment.models import Assignment
-
from openslides.participant.api import gen_username, gen_password, import_users
from openslides.participant.forms import (
UserCreateForm, UserUpdateForm, UsersettingsForm,
@@ -125,11 +120,13 @@ class UserOverview(ListView):
percent = 0
# list of all existing categories
- structure_levels = [p['structure_level'] for p in User.objects.values('structure_level')
- .exclude(structure_level='').distinct()]
+ structure_levels = [
+ p['structure_level'] for p in
+ User.objects.values('structure_level').exclude(structure_level='').distinct()]
# list of all existing committees
- committees = [p['committee'] for p in User.objects.values('committee')
- .exclude(committee='').distinct()]
+ committees = [
+ p['committee'] for p in
+ User.objects.values('committee').exclude(committee='').distinct()]
# context vars
context.update({
'allusers': all_users,
@@ -137,13 +134,13 @@ class UserOverview(ListView):
'percent': round(percent, 1),
'structure_levels': structure_levels,
'committees': committees,
- 'cookie': ['participant_sortfilter', urlencode(decodedict(self.sortfilter),
+ 'cookie': [
+ 'participant_sortfilter', urlencode(decodedict(self.sortfilter),
doseq=True)],
'sortfilter': self.sortfilter})
return context
-from openslides.utils.views import DetailView, PermissionMixin
class UserDetailView(DetailView, PermissionMixin):
"""
Classed based view to show a specific user in the interface.
@@ -177,8 +174,8 @@ class UserCreateView(CreateView):
apply_url = 'user_edit'
def manipulate_object(self, form):
- self.object.username = gen_username(form.cleaned_data['first_name'],
- form.cleaned_data['last_name'])
+ self.object.username = gen_username(
+ form.cleaned_data['first_name'], form.cleaned_data['last_name'])
if not self.object.default_password:
self.object.default_password = gen_password()
self.object.set_password(self.object.default_password)
@@ -211,6 +208,7 @@ class UserDeleteView(DeleteView):
else:
super(UserDeleteView, self).pre_redirect(request, *args, **kwargs)
+
class SetUserStatusView(RedirectView, SingleObjectMixin):
"""
Activate or deactivate an user.
@@ -547,8 +545,9 @@ def register_tab(request):
return Tab(
title=_('Participants'),
url=reverse('user_overview'),
- permission=request.user.has_perm('participant.can_see_participant') or
- request.user.has_perm('participant.can_manage_participant'),
+ permission=(
+ request.user.has_perm('participant.can_see_participant') or
+ request.user.has_perm('participant.can_manage_participant')),
selected=selected)
@@ -569,12 +568,12 @@ def get_personal_info_widget(request):
and where you are supporter or candidate.
"""
personal_info_context = {
- 'submitted_motions': Motion.objects.filter(submitter=request.user),
- 'config_motion_min_supporters': config['motion_min_supporters'],
- 'supported_motions': Motion.objects.filter(motionsupporter=request.user),
- 'assignments': Assignment.objects.filter(
- assignmentcandidate__person=request.user,
- assignmentcandidate__blocked=False),}
+ 'submitted_motions': Motion.objects.filter(submitter=request.user),
+ 'config_motion_min_supporters': config['motion_min_supporters'],
+ 'supported_motions': Motion.objects.filter(motionsupporter=request.user),
+ 'assignments': Assignment.objects.filter(
+ assignmentcandidate__person=request.user,
+ assignmentcandidate__blocked=False)}
return Widget(
name='personal_info',
display_name=_('My motions and elections'),
@@ -593,7 +592,7 @@ def get_user_widget(request):
name='user',
display_name=_('Participants'),
template='participant/user_widget.html',
- context={'users': User.objects.all(),},
+ context={'users': User.objects.all()},
permission_required='projector.can_manage_projector',
default_column=1)
@@ -607,6 +606,6 @@ def get_group_widget(request):
name='group',
display_name=_('Groups'),
template='participant/group_widget.html',
- context={'groups': Group.objects.all(),},
+ context={'groups': Group.objects.all()},
permission_required='projector.can_manage_projector',
default_column=1)
diff --git a/openslides/poll/forms.py b/openslides/poll/forms.py
index 2fd893b11..7d4db9822 100644
--- a/openslides/poll/forms.py
+++ b/openslides/poll/forms.py
@@ -11,7 +11,6 @@
"""
from django import forms
-from django.utils.translation import ugettext_lazy as _
from openslides.utils.forms import CssClassMixin
diff --git a/openslides/poll/models.py b/openslides/poll/models.py
index a38514619..19821b3d1 100644
--- a/openslides/poll/models.py
+++ b/openslides/poll/models.py
@@ -47,7 +47,7 @@ class BaseVote(models.Model):
Subclasses have to define a option-field, which are a subclass of
BaseOption.
"""
- weight = models.IntegerField(default=1, null=True) # Use MinMaxIntegerField
+ weight = models.IntegerField(default=1, null=True) # Use MinMaxIntegerField
value = models.CharField(max_length=255, null=True)
def print_weight(self, raw=False):
@@ -73,7 +73,7 @@ class BaseVote(models.Model):
class CountVotesCast(models.Model):
votescast = MinMaxIntegerField(null=True, blank=True, min_value=-2,
- verbose_name=_("Votes cast"))
+ verbose_name=_("Votes cast"))
def append_pollform_fields(self, fields):
fields.append('votescast')
@@ -92,7 +92,7 @@ class CountVotesCast(models.Model):
class CountInvalid(models.Model):
votesinvalid = MinMaxIntegerField(null=True, blank=True, min_value=-2,
- verbose_name=_("Votes invalid"))
+ verbose_name=_("Votes invalid"))
def append_pollform_fields(self, fields):
fields.append('votesinvalid')
@@ -164,7 +164,6 @@ class BasePoll(models.Model):
"""
return self.vote_values
-
def get_vote_class(self):
"""
Return the releatet vote class.
@@ -212,7 +211,7 @@ class BasePoll(models.Model):
"""
from openslides.poll.forms import OptionForm
return OptionForm(extra=self.get_form_values(kwargs['formid']),
- **kwargs)
+ **kwargs)
def get_vote_forms(self, **kwargs):
"""
diff --git a/openslides/poll/views.py b/openslides/poll/views.py
index ef58218d9..70c48e7cc 100644
--- a/openslides/poll/views.py
+++ b/openslides/poll/views.py
@@ -35,7 +35,7 @@ class PollFormView(TemplateView):
context['forms'] = self.poll.get_vote_forms()
FormClass = self.get_modelform_class()
context['pollform'] = FormClass(instance=self.poll,
- prefix='pollform')
+ prefix='pollform')
return context
def get_success_url(self):
@@ -52,7 +52,7 @@ class PollFormView(TemplateView):
FormClass = self.get_modelform_class()
pollform = FormClass(data=self.request.POST, instance=self.poll,
- prefix='pollform')
+ prefix='pollform')
error = False
for form in option_forms:
diff --git a/openslides/projector/api.py b/openslides/projector/api.py
index 6bcc04772..7cbd5da02 100644
--- a/openslides/projector/api.py
+++ b/openslides/projector/api.py
@@ -12,12 +12,11 @@
from django.conf import settings
from django.core.cache import cache
-from django.template.loader import render_to_string
from django.utils.datastructures import SortedDict
from django.utils.importlib import import_module
from openslides.config.models import config
-from openslides.projector.projector import SLIDE, Slide, Widget
+from openslides.projector.projector import SLIDE, Slide
def split_sid(sid):
@@ -95,27 +94,18 @@ def clear_projector_cache():
cache.delete('projector_data')
-def register_slidemodel(model, model_name=None, control_template=None,
- weight=0):
+def register_slidemodel(model, model_name=None, control_template=None, weight=0):
"""
Register a Model as a slide.
"""
+ # TODO: control_template should never be None
if model_name is None:
model_name = model.prefix
- if control_template is None:
- control_template = 'projector/default_control_slidemodel.html'
-
category = model.__module__.split('.')[0]
- SLIDE[model_name] = Slide(
- model_slide=True,
- model=model,
- category=category,
- key=model.prefix,
- model_name=model_name,
- control_template=control_template,
- weight=weight,
- )
+ SLIDE[model_name] = Slide(model_slide=True, model=model, category=category,
+ key=model.prefix, model_name=model_name,
+ control_template=control_template, weight=weight)
def register_slidefunc(key, func, control_template=None, weight=0, name=''):
@@ -125,15 +115,9 @@ def register_slidefunc(key, func, control_template=None, weight=0, name=''):
if control_template is None:
control_template = 'projector/default_control_slidefunc.html'
category = func.__module__.split('.')[0]
- SLIDE[key] = Slide(
- model_slide=False,
- func=func,
- category=category,
- key=key,
- control_template=control_template,
- weight=weight,
- name=name,
- )
+ SLIDE[key] = Slide(model_slide=False, func=func, category=category,
+ key=key, control_template=control_template, weight=weight,
+ name=name,)
def projector_message_set(message, sid=None):
@@ -147,7 +131,7 @@ def projector_message_set(message, sid=None):
overlay = ProjectorOverlay.objects.get(def_name='Message')
except ProjectorOverlay.DoesNotExist:
overlay = ProjectorOverlay(def_name='Message', active=False)
- overlay.sid=sid
+ overlay.sid = sid
overlay.save()
@@ -166,7 +150,6 @@ def get_all_widgets(request, session=False):
mod = import_module(app + '.views')
except ImportError:
continue
- appname = mod.__name__.split('.')[0]
try:
modul_widgets = mod.get_widgets(request)
except AttributeError:
diff --git a/openslides/projector/forms.py b/openslides/projector/forms.py
index 3c8d24498..59d69ef9c 100644
--- a/openslides/projector/forms.py
+++ b/openslides/projector/forms.py
@@ -11,7 +11,6 @@
"""
from django import forms
-from django.utils.translation import ugettext_lazy as _
from openslides.utils.forms import CssClassMixin
diff --git a/openslides/projector/models.py b/openslides/projector/models.py
index 299b41afb..f403b6395 100644
--- a/openslides/projector/models.py
+++ b/openslides/projector/models.py
@@ -19,9 +19,6 @@ from openslides.config.signals import default_config_value
from openslides.projector.api import register_slidemodel
from openslides.projector.projector import SlideMixin
-from openslides.config.models import config
-
-
class ProjectorSlide(models.Model, SlideMixin):
"""
@@ -56,8 +53,7 @@ class ProjectorSlide(models.Model, SlideMixin):
)
-register_slidemodel(ProjectorSlide,
- control_template='projector/control_customslide.html')
+register_slidemodel(ProjectorSlide, control_template='projector/control_customslide.html')
class ProjectorOverlay(models.Model):
diff --git a/openslides/projector/projector.py b/openslides/projector/projector.py
index a35e0517b..885c4291d 100644
--- a/openslides/projector/projector.py
+++ b/openslides/projector/projector.py
@@ -19,9 +19,9 @@ from openslides.config.models import config
from openslides.projector.signals import projector_overlays
-
SLIDE = {}
+
class SlideMixin(object):
"""
A Mixin for a Django-Model, for making the model a slide.
@@ -49,13 +49,14 @@ class SlideMixin(object):
"""
Return True, if the the slide is the active slide.
"""
- from api import get_active_slide
+ from openslides.projector.api import get_active_slide
return get_active_slide(only_sid=True) == self.sid
def set_active(self):
"""
Appoint this item as the active slide.
"""
+ from openslides.projector.api import set_active_slide
set_active_slide(self.sid)
def save(self, *args, **kwargs):
@@ -112,7 +113,7 @@ class Widget(object):
Class for a Widget for the Projector-Tab.
"""
def __init__(self, name, html=None, template=None, context={},
- permission_required=None, display_name=None, default_column=1):
+ permission_required=None, display_name=None, default_column=1):
self.name = name
if display_name is None:
self.display_name = name.capitalize()
diff --git a/openslides/projector/views.py b/openslides/projector/views.py
index e9ab1b3ec..997e89cf2 100644
--- a/openslides/projector/views.py
+++ b/openslides/projector/views.py
@@ -13,34 +13,28 @@
from datetime import datetime
from time import time
-from django.conf import settings
from django.contrib import messages
from django.core.cache import cache
from django.core.context_processors import csrf
from django.core.urlresolvers import reverse
from django.db import transaction
from django.db.models import Q
-from django.dispatch import receiver
from django.shortcuts import redirect
from django.template import RequestContext
-from django.utils.datastructures import SortedDict
-from django.utils.importlib import import_module
from django.utils.translation import ugettext_lazy as _
from openslides.utils.template import render_block_to_string, Tab
-from openslides.utils.utils import html_strong
-from openslides.utils.views import (TemplateView, RedirectView, CreateView,
- UpdateView, DeleteView, AjaxMixin)
-
+from openslides.utils.views import (
+ TemplateView, RedirectView, CreateView, UpdateView, DeleteView, AjaxMixin)
from openslides.config.models import config
-
-from openslides.projector.api import (get_active_slide, set_active_slide,
- projector_message_set, projector_message_delete, get_slide_from_sid,
- get_all_widgets, clear_projector_cache)
-from openslides.projector.forms import SelectWidgetsForm
-from openslides.projector.models import ProjectorOverlay, ProjectorSlide
-from openslides.projector.projector import SLIDE, Widget
-from openslides.projector.signals import projector_overlays
+from .api import (
+ get_active_slide, set_active_slide, projector_message_set,
+ projector_message_delete, get_slide_from_sid, get_all_widgets,
+ clear_projector_cache)
+from .forms import SelectWidgetsForm
+from .models import ProjectorOverlay, ProjectorSlide
+from .projector import Widget
+from .signals import projector_overlays
class DashboardView(TemplateView, AjaxMixin):
@@ -73,7 +67,7 @@ class Projector(TemplateView, AjaxMixin):
if sid is None:
try:
data = get_active_slide()
- except AttributeError: #TODO: It has to be an Slide.DoesNotExist
+ except AttributeError: # TODO: It has to be an Slide.DoesNotExist
data = None
ajax = 'on'
active_sid = get_active_slide(True)
@@ -92,10 +86,10 @@ class Projector(TemplateView, AjaxMixin):
# Projector Overlays
if self.kwargs['sid'] is None:
active_defs = ProjectorOverlay.objects.filter(active=True) \
- .filter(Q(sid=active_sid) | Q(sid=None)).values_list('def_name',
- flat=True)
- for receiver, response in projector_overlays.send(sender=sid,
- register=False, call=active_defs):
+ .filter(Q(sid=active_sid) | Q(sid=None)).values_list(
+ 'def_name', flat=True)
+ for receiver, response in projector_overlays.send(
+ sender=sid, register=False, call=active_defs):
if response is not None:
data['overlays'].append(response)
self._data = data
@@ -124,7 +118,6 @@ class Projector(TemplateView, AjaxMixin):
'scrollcontent', self.data)
cache.set('projector_scrollcontent', scrollcontent, 1)
-
# TODO: do not call the hole data-methode, if we only need some vars
data = cache.get('projector_data')
if not data:
@@ -301,7 +294,6 @@ class OverlayMessageView(RedirectView):
elif 'message-clean' in request.POST:
projector_message_delete()
-
def get_ajax_context(self, **kwargs):
clear_projector_cache()
return {
@@ -309,7 +301,6 @@ class OverlayMessageView(RedirectView):
}
-
class ActivateOverlay(RedirectView):
"""
Activate or deactivate an overlay.
@@ -379,12 +370,11 @@ def register_tab(request):
"""
Register the projector tab.
"""
- selected = True if request.path.startswith('/projector/') else False
+ selected = request.path.startswith('/projector/')
return Tab(
title=_('Dashboard'),
url=reverse('dashboard'),
- permission=request.user.has_perm('projector.can_manage_projector') or
- request.user.has_perm('projector.can_see_dashboard'),
+ permission=request.user.has_perm('projector.can_see_dashboard'),
selected=selected,
)
@@ -411,7 +401,7 @@ def get_widgets(request):
name='live_view',
display_name=_('Projector live view'),
template='projector/live_view_widget.html',
- context = RequestContext(request, {}),
+ context=RequestContext(request, {}),
permission_required='projector.can_see_projector',
default_column=2))
@@ -424,15 +414,14 @@ def get_widgets(request):
projector_overlay = ProjectorOverlay.objects.get(
def_name=name)
except ProjectorOverlay.DoesNotExist:
- projector_overlay = ProjectorOverlay(def_name=name,
- active=False)
+ projector_overlay = ProjectorOverlay(def_name=name, active=False)
projector_overlay.save()
overlays.append(projector_overlay)
context = {
- 'overlays':overlays,
- 'countdown_time': config['countdown_time'],
- 'countdown_state' : config['countdown_state']}
+ 'overlays': overlays,
+ 'countdown_time': config['countdown_time'],
+ 'countdown_state': config['countdown_state']}
context.update(csrf(request))
widgets.append(Widget(
name='overlays',
@@ -442,7 +431,6 @@ def get_widgets(request):
default_column=2,
context=context))
-
# Custom slide widget
context = {
'slides': ProjectorSlide.objects.all().order_by('weight'),
diff --git a/openslides/urls.py b/openslides/urls.py
index 509fea41c..5edb948d0 100644
--- a/openslides/urls.py
+++ b/openslides/urls.py
@@ -12,8 +12,6 @@
from django.conf import settings
from django.conf.urls.defaults import patterns, url, include
-from django.contrib.staticfiles.urls import staticfiles_urlpatterns
-from django.shortcuts import redirect
from django.utils.importlib import import_module
from openslides.utils.views import RedirectView
@@ -34,7 +32,7 @@ urlpatterns = patterns('',
)
urlpatterns += patterns('django.contrib.staticfiles.views',
- url(r'^static/(?P.*)$', 'serve', {'insecure':True}),
+ url(r'^static/(?P.*)$', 'serve', {'insecure': True}),
)
js_info_dict = {
diff --git a/openslides/utils/auth/AnonymousAuth.py b/openslides/utils/auth/AnonymousAuth.py
index 8d21cc1e0..e6c4b27fe 100644
--- a/openslides/utils/auth/AnonymousAuth.py
+++ b/openslides/utils/auth/AnonymousAuth.py
@@ -37,8 +37,8 @@ class AnonymousAuth(object):
- try to return the permissions for the 'Anonymous' group
"""
- if not user_obj.is_anonymous() or obj is not None or \
- not config['system_enable_anonymous']:
+ if (not user_obj.is_anonymous() or obj is not None or
+ not config['system_enable_anonymous']):
return set()
perms = Permission.objects.filter(group__name='Anonymous')
@@ -60,8 +60,8 @@ class AnonymousAuth(object):
"""
Check if the user as a specific permission
"""
- if not user_obj.is_anonymous() or obj is not None or \
- not config['system_enable_anonymous']:
+ if (not user_obj.is_anonymous() or obj is not None or
+ not config['system_enable_anonymous']):
return False
return (perm in self.get_all_permissions(user_obj))
@@ -70,8 +70,8 @@ class AnonymousAuth(object):
"""
Check if the user has permissions on the module app_label
"""
- if not user_obj.is_anonymous() or \
- not config['system_enable_anonymous']:
+ if (not user_obj.is_anonymous() or
+ not config['system_enable_anonymous']):
return False
for perm in self.get_all_permissions(user_obj):
@@ -87,10 +87,10 @@ class AnonymousAuth(object):
"""
return None
+
def anonymous_context_additions(RequestContext):
"""
Add a variable to the request context that will indicate
if anonymous login is possible at all.
"""
- return {'os_enable_anonymous_login' : config['system_enable_anonymous']}
-
+ return {'os_enable_anonymous_login': config['system_enable_anonymous']}
diff --git a/openslides/utils/csv_ext.py b/openslides/utils/csv_ext.py
index 864de5cf4..4f2fa8c4a 100644
--- a/openslides/utils/csv_ext.py
+++ b/openslides/utils/csv_ext.py
@@ -25,10 +25,9 @@ class excel_semikolon(Dialect):
def patchup(dialect):
if dialect:
if dialect.delimiter in [excel_semikolon.delimiter, excel.delimiter] and \
- dialect.quotechar == excel_semikolon.quotechar:
+ dialect.quotechar == excel_semikolon.quotechar:
# walks like a duck and talks like a duck.. must be one
dialect.doublequote = True
return dialect
register_dialect("excel_semikolon", excel_semikolon)
-
diff --git a/openslides/utils/jsonfield/__init__.py b/openslides/utils/jsonfield/__init__.py
index b8d87c831..6dde401ce 100644
--- a/openslides/utils/jsonfield/__init__.py
+++ b/openslides/utils/jsonfield/__init__.py
@@ -1 +1,3 @@
-from fields import JSONField
\ No newline at end of file
+from fields import JSONField
+
+__all__ = ['JSONField']
diff --git a/openslides/utils/jsonfield/fields.py b/openslides/utils/jsonfield/fields.py
index 029ca74db..45c66aee4 100644
--- a/openslides/utils/jsonfield/fields.py
+++ b/openslides/utils/jsonfield/fields.py
@@ -6,6 +6,7 @@ from django.utils.translation import ugettext_lazy as _
from django.forms.fields import Field
from django.forms.util import ValidationError as FormValidationError
+
class JSONFormField(Field):
def clean(self, value):
@@ -21,6 +22,7 @@ class JSONFormField(Field):
raise FormValidationError(_("Enter valid JSON"))
return value
+
class JSONField(models.TextField):
"""JSONField is a generic textfield that serializes/unserializes JSON objects"""
diff --git a/openslides/utils/modelfields.py b/openslides/utils/modelfields.py
index 72f63b51d..e3ccd1ef4 100644
--- a/openslides/utils/modelfields.py
+++ b/openslides/utils/modelfields.py
@@ -12,12 +12,13 @@
from django.db import models
+
class MinMaxIntegerField(models.IntegerField):
def __init__(self, min_value=None, max_value=None, *args, **kwargs):
self.min_value, self.max_value = min_value, max_value
super(MinMaxIntegerField, self).__init__(*args, **kwargs)
def formfield(self, **kwargs):
- defaults = {'min_value': self.min_value, 'max_value' : self.max_value}
+ defaults = {'min_value': self.min_value, 'max_value': self.max_value}
defaults.update(kwargs)
return super(MinMaxIntegerField, self).formfield(**defaults)
diff --git a/openslides/utils/pdf.py b/openslides/utils/pdf.py
index a50dfdcd4..439d55744 100755
--- a/openslides/utils/pdf.py
+++ b/openslides/utils/pdf.py
@@ -28,16 +28,16 @@ from openslides.config.models import config
# register new truetype fonts
-pdfmetrics.registerFont(TTFont('Ubuntu', path_join(settings.SITE_ROOT,
- 'static/fonts/Ubuntu-R.ttf')))
-pdfmetrics.registerFont(TTFont('Ubuntu-Bold', path_join(settings.SITE_ROOT,
- 'static/fonts/Ubuntu-B.ttf')))
-pdfmetrics.registerFont(TTFont('Ubuntu-Italic', path_join(settings.SITE_ROOT,
- 'static/fonts/Ubuntu-RI.ttf')))
+pdfmetrics.registerFont(TTFont(
+ 'Ubuntu', path_join(settings.SITE_ROOT, 'static/fonts/Ubuntu-R.ttf')))
+pdfmetrics.registerFont(TTFont(
+ 'Ubuntu-Bold', path_join(settings.SITE_ROOT, 'static/fonts/Ubuntu-B.ttf')))
+pdfmetrics.registerFont(TTFont(
+ 'Ubuntu-Italic', path_join(settings.SITE_ROOT, 'static/fonts/Ubuntu-RI.ttf')))
# set style information
-PAGE_HEIGHT = defaultPageSize[1];
+PAGE_HEIGHT = defaultPageSize[1]
PAGE_WIDTH = defaultPageSize[0]
@@ -105,17 +105,17 @@ stylesheet.add(ParagraphStyle(
leftIndent=0,
spaceAfter=15,
))
-stylesheet.add(ParagraphStyle(name = 'Subitem',
- parent = stylesheet['Normal'],
- fontSize = 10,
- leading = 10,
- leftIndent = 20,
- spaceAfter = 15)
- )
-stylesheet.add(ParagraphStyle(name = 'Tablecell',
- parent = stylesheet['Normal'],
- fontSize = 9)
- )
+stylesheet.add(ParagraphStyle(
+ name='Subitem',
+ parent=stylesheet['Normal'],
+ fontSize=10,
+ leading=10,
+ leftIndent=20,
+ spaceAfter=15))
+stylesheet.add(ParagraphStyle(
+ name='Tablecell',
+ parent=stylesheet['Normal'],
+ fontSize=9))
stylesheet.add(ParagraphStyle(name = 'Signaturefield',
parent = stylesheet['Normal'],
spaceBefore = 15)
diff --git a/openslides/utils/person/__init__.py b/openslides/utils/person/__init__.py
index 7a69e8f25..e262022b4 100644
--- a/openslides/utils/person/__init__.py
+++ b/openslides/utils/person/__init__.py
@@ -11,11 +11,15 @@
"""
from openslides.utils.person.signals import receive_persons
-from openslides.utils.person.api import (generate_person_id, get_person,
- Person, Persons)
+from openslides.utils.person.api import (
+ generate_person_id, get_person, Person, Persons)
from openslides.utils.person.forms import PersonFormField, MultiplePersonFormField
from openslides.utils.person.models import PersonField, PersonMixin
+__all__ = ['receive_persons', 'generate_person_id', 'get_person', 'Person',
+ 'Persons', 'PersonFormField', 'MultiplePersonFormField',
+ 'PersonField', 'PersonMixin', 'EmptyPerson']
+
class EmptyPerson(PersonMixin):
@property
diff --git a/openslides/utils/person/forms.py b/openslides/utils/person/forms.py
index cee080bce..6cb19f3ab 100644
--- a/openslides/utils/person/forms.py
+++ b/openslides/utils/person/forms.py
@@ -61,8 +61,8 @@ class MultiplePersonFormField(PersonFormField):
widget = forms.widgets.SelectMultiple
def __init__(self, *args, **kwargs):
- super(MultiplePersonFormField, self).__init__(empty_label=None,
- *args, **kwargs)
+ super(MultiplePersonFormField, self).__init__(
+ empty_label=None, *args, **kwargs)
def to_python(self, value):
if hasattr(value, '__iter__'):
diff --git a/openslides/utils/template.py b/openslides/utils/template.py
index c3b16b630..5ed5eb778 100644
--- a/openslides/utils/template.py
+++ b/openslides/utils/template.py
@@ -10,8 +10,7 @@
:license: GNU GPL, see LICENSE for more details.
"""
-from django.http import HttpResponse
-from django.template import loader, Context, RequestContext, TextNode
+from django.template import loader, Context
from django.template.loader_tags import BlockNode, ExtendsNode
@@ -24,6 +23,10 @@ class Tab(object):
self.url = url
+## All following function are only needed to render a block from a template
+## and could be removed, if the template worked with an include-statement instead.
+## Its only used for ajax-request from the projector.
+
def get_template(template):
if isinstance(template, (tuple, list)):
return loader.select_template(template)
@@ -49,22 +52,22 @@ def render_template_block_nodelist(nodelist, block, context):
for key in ('nodelist', 'nodelist_true', 'nodelist_false'):
if hasattr(node, key):
try:
- return render_template_block_nodelist(getattr(node, key),
- block, context)
+ return render_template_block_nodelist(
+ getattr(node, key), block, context)
except:
pass
for node in nodelist:
if isinstance(node, ExtendsNode):
try:
- return render_template_block(node.get_parent(context), block,
- context)
+ return render_template_block(
+ node.get_parent(context), block, context)
except BlockNotFound:
pass
raise BlockNotFound
def render_block_to_string(template_name, block, dictionary=None,
- context_instance=None):
+ context_instance=None):
"""
Loads the given template_name and renders the given block with the given
dictionary as context. Returns a string.
@@ -77,23 +80,3 @@ def render_block_to_string(template_name, block, dictionary=None,
context_instance = Context(dictionary)
t.render(context_instance)
return render_template_block(t, block, context_instance)
-
-
-def direct_block_to_template(request, template, block, extra_context=None,
- mimetype=None, **kwargs):
- """
- Render a given block in a given template with any extra URL parameters in
- the context as ``{{ params }}``.
- """
- if extra_context is None:
- extra_context = {}
- dictionary = {'params': kwargs}
- for key, value in extra_context.items():
- if callable(value):
- dictionary[key] = value()
- else:
- dictionary[key] = value
- c = RequestContext(request, dictionary)
- t = get_template(template)
- t.render(c)
- return HttpResponse(render_template_block(t, block, c), mimetype=mimetype)
diff --git a/openslides/utils/utils.py b/openslides/utils/utils.py
index 41aaf7544..d8f054eb0 100644
--- a/openslides/utils/utils.py
+++ b/openslides/utils/utils.py
@@ -10,12 +10,13 @@
:license: GNU GPL, see LICENSE for more details.
"""
+import sys
+
try:
import json
-except ImportError: # For python 2.5 support
+except ImportError: # For python 2.5 support
import simplejson as json
-from django.conf import settings
from django.contrib import messages
from django.contrib.auth.models import Permission
from django.core.context_processors import csrf
@@ -41,16 +42,17 @@ def gen_confirm_form(request, message, url):
Deprecated. Use Class base Views instead.
"""
- messages.warning(request,
- """
- %s
-
- """
- % (message, url, csrf(request)['csrf_token'], _("Yes"), _("No")))
+ messages.warning(
+ request,
+ """
+ %s
+
+ """
+ % (message, url, csrf(request)['csrf_token'], _("Yes"), _("No")))
def del_confirm_form(request, object, name=None, delete_link=None):
@@ -63,27 +65,28 @@ def del_confirm_form(request, object, name=None, delete_link=None):
name = object
if delete_link is None:
delete_link = object.get_absolute_url('delete')
- gen_confirm_form(request, _('Do you really want to delete %s?')
+ gen_confirm_form(
+ request, _('Do you really want to delete %s?')
% html_strong(name), delete_link)
-def render_response(req, *args, **kwargs):
- kwargs['context_instance'] = RequestContext(req)
- return render_to_response(*args, **kwargs)
-
-
def template(template_name):
+ """
+ Decorator to set a template for a view.
+
+ Deprecated. Use class based views instead.
+ """
def renderer(func):
def wrapper(request, *args, **kwargs):
output = func(request, *args, **kwargs)
if not isinstance(output, dict):
return output
context = {}
- template_manipulation.send(sender='utils_template', request=request,
- context=context)
+ template_manipulation.send(
+ sender='utils_template', request=request, context=context)
output.update(context)
- response = render_to_response(template_name, output,
- context_instance=RequestContext(request))
+ response = render_to_response(
+ template_name, output, context_instance=RequestContext(request))
if 'cookie' in output:
response.set_cookie(output['cookie'][0], output['cookie'][1])
return response
@@ -95,6 +98,8 @@ def permission_required(perm, login_url=None):
"""
Decorator for views that checks whether a user has a particular permission
enabled, redirecting to the log-in page if necessary.
+
+ Deprecated.
"""
def renderer(func):
def wrapper(request, *args, **kw):
@@ -107,10 +112,12 @@ def permission_required(perm, login_url=None):
return renderer
-def render_to_forbidden(request, error=
- ugettext_lazy("Sorry, you have no rights to see this page.")):
- return HttpResponseForbidden(render_to_string('403.html',
- {'error': error}, context_instance=RequestContext(request)))
+def render_to_forbidden(request,
+ error=ugettext_lazy("Sorry, you have no rights to see this page.")):
+ # TODO: Integrate this function into the PermissionMixin once the
+ # above function is deleted.
+ return HttpResponseForbidden(render_to_string(
+ '403.html', {'error': error}, context_instance=RequestContext(request)))
def delete_default_permissions(**kwargs):
@@ -118,16 +125,18 @@ def delete_default_permissions(**kwargs):
Deletes the permissions, django creates by default for the admin.
"""
for p in Permission.objects.all():
- if p.codename.startswith('add') \
- or p.codename.startswith('delete') \
- or p.codename.startswith('change'):
+ if (p.codename.startswith('add') or
+ p.codename.startswith('delete') or
+ p.codename.startswith('change')):
p.delete()
def ajax_request(data):
"""
generates a HTTPResponse-Object with json-Data for a
- ajax response
+ ajax response.
+
+ Deprecated.
"""
return HttpResponse(json.dumps(data))
diff --git a/openslides/utils/views.py b/openslides/utils/views.py
index 5e814bf9d..b9d1fc4b9 100644
--- a/openslides/utils/views.py
+++ b/openslides/utils/views.py
@@ -22,8 +22,7 @@ except ImportError:
# Is this exception realy necessary?
from StringIO import StringIO
-from reportlab.platypus import (SimpleDocTemplate, Paragraph, Frame, PageBreak,
- Spacer, Table, LongTable, TableStyle, Image)
+from reportlab.platypus import SimpleDocTemplate, Spacer
from reportlab.lib.units import cm
from django.contrib import messages
@@ -34,9 +33,9 @@ from django.conf import settings
from django.dispatch import receiver
from django.http import HttpResponseServerError, HttpResponse, HttpResponseRedirect
from django.utils.decorators import method_decorator
-from django.utils.translation import ugettext as _, ugettext_noop, ugettext_lazy
+from django.utils.translation import ugettext as _, ugettext_lazy
from django.utils.importlib import import_module
-from django.template import loader, RequestContext
+from django.template import RequestContext
from django.template.loader import render_to_string
from django.views.generic import (
TemplateView as _TemplateView,
@@ -50,8 +49,6 @@ from django.views.generic import (
from django.views.generic.detail import SingleObjectMixin
from django.views.generic.list import TemplateResponseMixin
-from openslides.config.models import config
-
from openslides.utils.utils import render_to_forbidden, html_strong
from openslides.utils.signals import template_manipulation
from openslides.utils.pdf import firstPage, laterPages
@@ -64,8 +61,8 @@ View = _View
class SetCookieMixin(object):
def render_to_response(self, context, **response_kwargs):
- response = TemplateResponseMixin.render_to_response(self, context,
- **response_kwargs)
+ response = TemplateResponseMixin.render_to_response(
+ self, context, **response_kwargs)
if 'cookie' in context:
response.set_cookie(context['cookie'][0], context['cookie'][1])
return response
@@ -90,8 +87,8 @@ class PermissionMixin(object):
if not self.has_permission(request, *args, **kwargs):
if not request.user.is_authenticated():
path = request.get_full_path()
- return HttpResponseRedirect("%s?next=%s" % (settings.LOGIN_URL,
- path))
+ return HttpResponseRedirect(
+ "%s?next=%s" % (settings.LOGIN_URL, path))
else:
return render_to_forbidden(request)
return _View.dispatch(self, request, *args, **kwargs)
@@ -130,18 +127,18 @@ class QuestionMixin(object):
option_fields = "\n".join([
'' % (option[0], unicode(option[1]))
for option in self.get_answer_options()])
- messages.warning(self.request,
+ messages.warning(
+ self.request,
"""
%(message)s
- """ % {
- 'message': self.get_question(),
- 'url': self.get_answer_url(),
- 'csrf': csrf(self.request)['csrf_token'],
- 'option_fields': option_fields})
+ """ % {'message': self.get_question(),
+ 'url': self.get_answer_url(),
+ 'csrf': csrf(self.request)['csrf_token'],
+ 'option_fields': option_fields})
def pre_post_redirect(self, request, *args, **kwargs):
# Reacts on the response of the user in a POST-request.
@@ -167,16 +164,16 @@ class QuestionMixin(object):
class TemplateView(PermissionMixin, _TemplateView):
def get_context_data(self, **kwargs):
context = super(TemplateView, self).get_context_data(**kwargs)
- template_manipulation.send(sender=self.__class__, request=self.request,
- context=context)
+ template_manipulation.send(
+ sender=self.__class__, request=self.request, context=context)
return context
class ListView(PermissionMixin, SetCookieMixin, _ListView):
def get_context_data(self, **kwargs):
context = super(ListView, self).get_context_data(**kwargs)
- template_manipulation.send(sender=self.__class__, request=self.request,
- context=context)
+ template_manipulation.send(
+ sender=self.__class__, request=self.request, context=context)
return context
@@ -217,8 +214,8 @@ class FormView(PermissionMixin, _FormView):
def get_context_data(self, **kwargs):
context = super(FormView, self).get_context_data(**kwargs)
- template_manipulation.send(sender=self.__class__, request=self.request,
- context=context)
+ template_manipulation.send(
+ sender=self.__class__, request=self.request, context=context)
return context
def form_invalid(self, form):
@@ -235,8 +232,8 @@ class UpdateView(PermissionMixin, _UpdateView):
def get_context_data(self, **kwargs):
context = super(UpdateView, self).get_context_data(**kwargs)
- template_manipulation.send(sender=self.__class__, request=self.request,
- context=context)
+ template_manipulation.send(
+ sender=self.__class__, request=self.request, context=context)
return context
def form_invalid(self, form):
@@ -256,8 +253,8 @@ class CreateView(PermissionMixin, _CreateView):
def get_context_data(self, **kwargs):
context = super(CreateView, self).get_context_data(**kwargs)
- template_manipulation.send(sender=self.__class__, request=self.request,
- context=context)
+ template_manipulation.send(
+ sender=self.__class__, request=self.request, context=context)
return context
def get_apply_url(self):
@@ -299,7 +296,6 @@ class DeleteView(SingleObjectMixin, QuestionMixin, RedirectView):
class DetailView(TemplateView, SingleObjectMixin):
def get(self, request, *args, **kwargs):
self.object = self.get_object()
- context = self.get_context_data(object=self.object)
return super(DetailView, self).get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
@@ -329,8 +325,8 @@ class PDFView(PermissionMixin, View):
return SimpleDocTemplate(buffer)
def build_document(self, pdf_document, story):
- pdf_document.build(story, onFirstPage=firstPage,
- onLaterPages=laterPages)
+ pdf_document.build(
+ story, onFirstPage=firstPage, onLaterPages=laterPages)
def render_to_response(self, filename):
response = HttpResponse(mimetype='application/pdf')
@@ -340,7 +336,7 @@ class PDFView(PermissionMixin, View):
buffer = StringIO()
pdf_document = self.get_template(buffer)
pdf_document.title = self.get_document_title()
- story = [Spacer(1, self.get_top_space()*cm)]
+ story = [Spacer(1, self.get_top_space() * cm)]
self.append_to_pdf(story)
@@ -351,9 +347,6 @@ class PDFView(PermissionMixin, View):
response.write(pdf)
return response
- def get_filename(self):
- return self.filename
-
def get(self, request, *args, **kwargs):
return self.render_to_response(self.get_filename())
@@ -364,9 +357,8 @@ def server_error(request, template_name='500.html'):
Templates: `500.html`
"""
- t = loader.get_template("500.html")
- return HttpResponseServerError(render_to_string('500.html',
- context_instance=RequestContext(request)))
+ return HttpResponseServerError(render_to_string(
+ template_name, context_instance=RequestContext(request)))
@receiver(template_manipulation, dispatch_uid="send_register_tab")
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 000000000..15fe79d8d
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,5 @@
+Django==1.4.2
+django-mptt
+reportlab
+PIL
+simplejson
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/openslides/agenda/tests.py b/tests/test_agenda.py
similarity index 91%
rename from openslides/agenda/tests.py
rename to tests/test_agenda.py
index ca56e009d..4e8a32d1d 100644
--- a/openslides/agenda/tests.py
+++ b/tests/test_agenda.py
@@ -12,13 +12,13 @@
from django.test import TestCase
from django.test.client import Client
-from django.contrib.auth.models import User
from django.db.models.query import EmptyQuerySet
from openslides.projector.api import get_active_slide
-
+from openslides.participant.models import User
from openslides.agenda.models import Item
+
class ItemTest(TestCase):
def setUp(self):
self.item1 = Item.objects.create(title='item1')
@@ -47,8 +47,9 @@ class ItemTest(TestCase):
self.assertFalse(self.item4 in self.item1.get_children())
l = Item.objects.all()
- self.assertEqual(str(l),
- "[, , , ]")
+ self.assertEqual(
+ str(l),
+ "[, , , ]")
def testForms(self):
for item in Item.objects.all():
@@ -71,8 +72,10 @@ class ViewTest(TestCase):
self.item2 = Item.objects.create(title='item2')
self.refreshItems()
- self.admin = User.objects.create_user('testadmin', '', 'default')
- self.anonym = User.objects.create_user('testanoym', '', 'default')
+ self.admin, created = User.objects.get_or_create(username='testadmin')
+ self.anonym, created = User.objects.get_or_create(username='testanonym')
+ self.admin.reset_password('default')
+ self.anonym.reset_password('default')
self.admin.is_superuser = True
self.admin.save()
@@ -131,7 +134,7 @@ class ViewTest(TestCase):
response = c.get('/agenda/%d/edit/' % 1000)
self.assertEqual(response.status_code, 404)
- data = {'title': 'newitem1', 'text': 'item1-text', 'weight':'0'}
+ data = {'title': 'newitem1', 'text': 'item1-text', 'weight': '0'}
response = c.post('/agenda/%d/edit/' % self.item1.id, data)
self.assertEqual(response.status_code, 302)
self.refreshItems()
@@ -143,4 +146,3 @@ class ViewTest(TestCase):
self.assertEqual(response.status_code, 200)
self.refreshItems()
self.assertEqual(self.item1.title, 'newitem1')
-
diff --git a/openslides/motion/tests.py b/tests/test_motion.py
similarity index 92%
rename from openslides/motion/tests.py
rename to tests/test_motion.py
index 1fb387951..26c506c37 100644
--- a/openslides/motion/tests.py
+++ b/tests/test_motion.py
@@ -11,10 +11,10 @@
"""
from django.test import TestCase
-from django.test.client import Client
from openslides.participant.models import User
-from openslides.motion.models import Motion, AVersion
+from openslides.motion.models import Motion
+
class MotionTest(TestCase):
def setUp(self):
@@ -39,4 +39,3 @@ class MotionTest(TestCase):
self.assertEqual(self.app1.versions.count(), 2)
self.assertEqual(self.app1.last_version, self.app1.versions[1])
-
diff --git a/openslides/participant/tests.py b/tests/test_participant.py
similarity index 92%
rename from openslides/participant/tests.py
rename to tests/test_participant.py
index 10013b877..4227dc66b 100644
--- a/openslides/participant/tests.py
+++ b/tests/test_participant.py
@@ -11,8 +11,6 @@
"""
from django.test import TestCase
-from django.test.client import Client
-from django.contrib.auth.hashers import check_password
from openslides.utils.person import get_person, Persons
from openslides.participant.api import gen_username, gen_password
@@ -38,9 +36,9 @@ class UserTest(TestCase):
self.assertEqual(unicode(self.user1), 'Max Mustermann')
def test_name_suffix(self):
- self.user1.structure_level = 'München'
+ self.user1.structure_level = u'München'
self.user1.save()
- self.assertEqual(unicode(self.user1), 'Max Mustermann (München)')
+ self.assertEqual(unicode(self.user1), u'Max Mustermann (München)')
def test_reset_password(self):
self.assertIsInstance(self.user1.default_password, basestring)