Changeset - 6d5c24e6354f
[Not reviewed]
Merge
! ! !
Patrick Altman - 10 years ago 2014-07-30 21:16:03
paltman@gmail.com
Merge pull request #56 from chromano/master

Fix flake8 warnings
66 files changed with 611 insertions and 604 deletions:
0 comments (0 inline, 0 general)
symposion/boxes/authorization.py
Show inline comments
...
 
@@ -15,6 +15,6 @@ def load_can_edit():
 
    import_path = getattr(settings, "BOXES_CAN_EDIT_CALLABLE", None)
 
    
 

 
    if import_path is None:
 
        return default_can_edit
 
    
 

 
    return load_path_attr(import_path)
symposion/boxes/forms.py
Show inline comments
...
 
@@ -6,3 +6,3 @@ from symposion.boxes.models import Box
 
class BoxForm(forms.ModelForm):
 
    
 

 
    class Meta:
symposion/boxes/models.py
Show inline comments
 
import datetime
 

	
 
from django.db import models
...
 
@@ -12,12 +10,12 @@ from markitup.fields import MarkupField
 
class Box(models.Model):
 
    
 

 
    label = models.CharField(max_length=100, db_index=True)
 
    content = MarkupField(blank=True)
 
    
 

 
    created_by = models.ForeignKey(User, related_name="boxes")
 
    last_updated_by = models.ForeignKey(User, related_name="updated_boxes")
 
    
 

 
    def __unicode__(self):
 
        return self.label
 
    
 

 
    class Meta:
symposion/boxes/templatetags/boxes_tags.py
Show inline comments
 
from django import template
 
from django.core.exceptions import ImproperlyConfigured
 
from django.core.urlresolvers import reverse
 
from django.utils.safestring import mark_safe
 
from django.utils.encoding import smart_str
 
from django.utils.translation import ugettext_lazy as _
 
from django.template.defaulttags import kwarg_re
 

	
...
 
@@ -18,6 +13,6 @@ register = template.Library()
 
def box(context, label, show_edit=True, *args, **kwargs):
 
    
 

 
    request = context["request"]
 
    can_edit = load_can_edit()(request, *args, **kwargs)
 
    
 

 
    try:
...
 
@@ -26,3 +21,3 @@ def box(context, label, show_edit=True, *args, **kwargs):
 
        box = None
 
    
 

 
    if can_edit and show_edit:
...
 
@@ -33,3 +28,3 @@ def box(context, label, show_edit=True, *args, **kwargs):
 
        form_action = None
 
    
 

 
    return {
symposion/boxes/urls.py
Show inline comments
 
# flake8: noqa
 
from django.conf.urls.defaults import url, patterns
...
 
@@ -5,2 +6,2 @@ urlpatterns = patterns("symposion.boxes.views",
 
    url(r"^([-\w]+)/edit/$", "box_edit", name="box_edit"),
 
)
...
 
\ No newline at end of file
 
)
symposion/boxes/views.py
Show inline comments
...
 
@@ -9,3 +9,4 @@ from symposion.boxes.models import Box
 

	
 
# @@@ problem with this is that the box_edit.html and box_create.html won't have domain objects in context
 
# @@@ problem with this is that the box_edit.html and box_create.html won't have domain objects in
 
# context
 
def get_auth_vars(request):
...
 
@@ -22,8 +23,8 @@ def get_auth_vars(request):
 
def box_edit(request, label):
 
    
 

 
    if not load_can_edit()(request, **get_auth_vars(request)):
 
        return HttpResponseForbidden()
 
    
 

 
    next = request.GET.get("next")
 
    
 

 
    try:
...
 
@@ -32,3 +33,3 @@ def box_edit(request, label):
 
        box = None
 
    
 

 
    form = BoxForm(request.POST, instance=box, prefix=label)
symposion/cms/admin.py
Show inline comments
...
 
@@ -6,2 +6,3 @@ from .models import Page
 

	
 

	
 
class PageAdmin(reversion.VersionAdmin):
symposion/cms/forms.py
Show inline comments
...
 
@@ -8,3 +8,3 @@ from .models import Page
 
class PageForm(forms.ModelForm):
 
    
 

 
    class Meta:
...
 
@@ -19,3 +19,3 @@ class PageForm(forms.ModelForm):
 
class FileUploadForm(forms.Form):
 
    
 

 
    file = forms.FileField()
symposion/cms/managers.py
Show inline comments
...
 
@@ -4,4 +4,5 @@ from django.db import models
 

	
 

	
 
class PublishedPageManager(models.Manager):
 
    
 

 
    def get_query_set(self):
symposion/cms/models.py
Show inline comments
...
 
@@ -20,3 +20,3 @@ from .managers import PublishedPageManager
 
class Page(models.Model):
 
    
 

 
    STATUS_CHOICES = (
...
 
@@ -25,3 +25,3 @@ class Page(models.Model):
 
    )
 
    
 

 
    title = models.CharField(max_length=100)
...
 
@@ -34,8 +34,8 @@ class Page(models.Model):
 
    tags = TaggableManager(blank=True)
 
    
 

 
    published = PublishedPageManager()
 
    
 

 
    def __unicode__(self):
 
        return self.title
 
    
 

 
    @models.permalink
...
 
@@ -43,3 +43,3 @@ class Page(models.Model):
 
        return ("cms_page", [self.path])
 
    
 

 
    @property
...
 
@@ -47,3 +47,3 @@ class Page(models.Model):
 
        return self.path.lower().startswith("community/")
 
    
 

 
    def save(self, *args, **kwargs):
...
 
@@ -51,3 +51,3 @@ class Page(models.Model):
 
        super(Page, self).save(*args, **kwargs)
 
    
 

 
    def clean_fields(self, exclude=None):
...
 
@@ -55,3 +55,4 @@ class Page(models.Model):
 
        if not re.match(settings.SYMPOSION_PAGE_REGEX, self.path):
 
            raise ValidationError({"path": [_("Path can only contain letters, numbers and hyphens and end with /")]})
 
            raise ValidationError(
 
                {"path": [_("Path can only contain letters, numbers and hyphens and end with /")]})
 

	
...
 
@@ -66,6 +67,6 @@ def generate_filename(instance, filename):
 
class File(models.Model):
 
    
 

 
    file = models.FileField(upload_to=generate_filename)
 
    created = models.DateTimeField(default=datetime.datetime.now)
 
    
 

 
    def download_url(self):
symposion/cms/urls.py
Show inline comments
 
# flake8: noqa
 
from django.conf.urls.defaults import url, patterns
symposion/cms/views.py
Show inline comments
...
 
@@ -25,3 +25,3 @@ def can_upload(user):
 
def page(request, path):
 
    
 

 
    try:
...
 
@@ -30,5 +30,5 @@ def page(request, path):
 
        page = None
 
    
 

 
    editable = can_edit(page, request.user)
 
    
 

 
    if page is None:
...
 
@@ -38,3 +38,3 @@ def page(request, path):
 
            raise Http404
 
    
 

 
    return render(request, "cms/page_detail.html", {
...
 
@@ -47,3 +47,3 @@ def page(request, path):
 
def page_edit(request, path):
 
    
 

 
    try:
...
 
@@ -52,6 +52,6 @@ def page_edit(request, path):
 
        page = None
 
    
 

 
    if not can_edit(page, request.user):
 
        raise Http404
 
    
 

 
    if request.method == "POST":
...
 
@@ -67,3 +67,3 @@ def page_edit(request, path):
 
        form = PageForm(instance=page, initial={"path": path})
 
    
 

 
    return render(request, "cms/page_edit.html", {
...
 
@@ -77,3 +77,3 @@ def file_index(request):
 
        raise Http404
 
    
 

 
    ctx = {
...
 
@@ -87,3 +87,3 @@ def file_create(request):
 
        raise Http404
 
    
 

 
    if request.method == "POST":
...
 
@@ -99,3 +99,3 @@ def file_create(request):
 
        form = FileUploadForm()
 
    
 

 
    ctx = {
...
 
@@ -108,3 +108,3 @@ def file_download(request, pk, *args):
 
    file = get_object_or_404(File, pk=pk)
 
    
 

 
    if getattr(settings, "USE_X_ACCEL_REDIRECT", False):
...
 
@@ -117,3 +117,3 @@ def file_download(request, pk, *args):
 
        response = static.serve(request, file.file.name, document_root=settings.MEDIA_ROOT)
 
    
 

 
    return response
...
 
@@ -124,3 +124,3 @@ def file_delete(request, pk):
 
        raise Http404
 
    
 

 
    file = get_object_or_404(File, pk=pk)
symposion/conf.py
Show inline comments
 
from django.conf import settings
 

	
 
from appconf import AppConf
...
 
@@ -6,3 +4,3 @@ from appconf import AppConf
 
class SymposionAppConf(AppConf):
 
    
 

 
    VOTE_THRESHOLD = 3
symposion/conference/admin.py
Show inline comments
...
 
@@ -8,4 +8,4 @@ admin.site.register(
 
    Section,
 
    prepopulated_fields = {"slug": ("name",)},
 
    list_display = ("name", "conference", "start_date", "end_date")
 
    prepopulated_fields={"slug": ("name",)},
 
    list_display=("name", "conference", "start_date", "end_date")
 
)
symposion/conference/models.py
Show inline comments
...
 
@@ -13,5 +13,5 @@ class Conference(models.Model):
 
    """
 
    
 

 
    title = models.CharField(_("title"), max_length=100)
 
    
 

 
    # when the conference runs
...
 
@@ -19,9 +19,9 @@ class Conference(models.Model):
 
    end_date = models.DateField(_("end date"), null=True, blank=True)
 
    
 

 
    # timezone the conference is in
 
    timezone = TimeZoneField(_("timezone"), blank=True)
 
    
 

 
    def __unicode__(self):
 
        return self.title
 
    
 

 
    def save(self, *args, **kwargs):
...
 
@@ -30,3 +30,3 @@ class Conference(models.Model):
 
            del CONFERENCE_CACHE[self.id]
 
    
 

 
    def delete(self):
...
 
@@ -38,3 +38,3 @@ class Conference(models.Model):
 
            pass
 
    
 

 
    class Meta(object):
...
 
@@ -50,5 +50,5 @@ class Section(models.Model):
 
    """
 
    
 

 
    conference = models.ForeignKey(Conference, verbose_name=_("conference"))
 
    
 

 
    name = models.CharField(_("name"), max_length=100)
...
 
@@ -59,6 +59,6 @@ class Section(models.Model):
 
    end_date = models.DateField(_("end date"), null=True, blank=True)
 
    
 

 
    def __unicode__(self):
 
        return "%s %s" % (self.conference, self.name)
 
    
 

 
    class Meta(object):
symposion/conference/urls.py
Show inline comments
 
from django.conf.urls.defaults import *
 
# flake8: noqa
 
from django.conf.urls.defaults import patterns, url
 

	
symposion/conference/views.py
Show inline comments
...
 
@@ -9,6 +9,6 @@ from django.contrib.auth.models import User
 
def user_list(request):
 
    
 

 
    if not request.user.is_staff:
 
        raise Http404()
 
    
 

 
    return render(request, "conference/user_list.html", {
symposion/forms.py
Show inline comments
...
 
@@ -6,3 +6,3 @@ import account.forms
 
class SignupForm(account.forms.SignupForm):
 
    
 

 
    first_name = forms.CharField()
...
 
@@ -22,3 +22,3 @@ class SignupForm(account.forms.SignupForm):
 
        ]
 
    
 

 
    def clean_email_confirm(self):
...
 
@@ -28,3 +28,4 @@ class SignupForm(account.forms.SignupForm):
 
            if email != email_confirm:
 
                raise forms.ValidationError("Email address must match previously typed email address")
 
                raise forms.ValidationError(
 
                    "Email address must match previously typed email address")
 
        return email_confirm
symposion/markdown_parser.py
Show inline comments
 
import html5lib
 
from html5lib import html5parser, sanitizer
...
 
@@ -7,6 +6,6 @@ import markdown
 
def parse(text):
 
    
 

 
    # First run through the Markdown parser
 
    text = markdown.markdown(text, extensions=["extra"], safe_mode=False)
 
    
 

 
    # Sanitize using html5lib
symposion/proposals/actions.py
Show inline comments
...
 
@@ -5,5 +5,4 @@ from django.http import HttpResponse
 

	
 
def export_as_csv_action(
 
    description="Export selected objects as CSV file",
 
    fields=None, exclude=None, header=True):
 
def export_as_csv_action(description="Export selected objects as CSV file",
 
                         fields=None, exclude=None, header=True):
 
    """
...
 
@@ -26,3 +25,4 @@ def export_as_csv_action(
 
        response = HttpResponse(mimetype="text/csv")
 
        response["Content-Disposition"] = "attachment; filename=%s.csv" % unicode(opts).replace(".", "_")
 
        response["Content-Disposition"] = \
 
            "attachment; filename=%s.csv" % unicode(opts).replace(".", "_")
 
        writer = csv.writer(response)
...
 
@@ -31,3 +31,4 @@ def export_as_csv_action(
 
        for obj in queryset:
 
            writer.writerow([unicode(getattr(obj, field)).encode("utf-8", "replace") for field in field_names])
 
            writer.writerow(
 
                [unicode(getattr(obj, field)).encode("utf-8", "replace") for field in field_names])
 
        return response
symposion/proposals/forms.py
Show inline comments
...
 
@@ -11,3 +11,3 @@ from symposion.proposals.models import SupportingDocument
 
class AddSpeakerForm(forms.Form):
 
    
 

 
    email = forms.EmailField(
...
 
@@ -15,3 +15,3 @@ class AddSpeakerForm(forms.Form):
 
    )
 
    
 

 
    def __init__(self, *args, **kwargs):
...
 
@@ -19,3 +19,3 @@ class AddSpeakerForm(forms.Form):
 
        super(AddSpeakerForm, self).__init__(*args, **kwargs)
 
    
 

 
    def clean_email(self):
...
 
@@ -34,3 +34,3 @@ class AddSpeakerForm(forms.Form):
 
class SupportingDocumentCreateForm(forms.ModelForm):
 
    
 

 
    class Meta:
symposion/proposals/managers.py
Show inline comments
 
deleted file
symposion/proposals/models.py
Show inline comments
...
 
@@ -23,3 +23,3 @@ class ProposalSection(models.Model):
 
    configuration of proposal submissions for a specific Section.
 
    
 

 
    a section is available for proposals iff:
...
 
@@ -29,5 +29,5 @@ class ProposalSection(models.Model):
 
    """
 
    
 

 
    section = models.OneToOneField(Section)
 
    
 

 
    start = models.DateTimeField(null=True, blank=True)
...
 
@@ -36,3 +36,3 @@ class ProposalSection(models.Model):
 
    published = models.NullBooleanField()
 
    
 

 
    @classmethod
...
 
@@ -45,3 +45,3 @@ class ProposalSection(models.Model):
 
        )
 
    
 

 
    def is_available(self):
...
 
@@ -55,3 +55,3 @@ class ProposalSection(models.Model):
 
        return True
 
    
 

 
    def __unicode__(self):
...
 
@@ -63,3 +63,3 @@ class ProposalKind(models.Model):
 
    e.g. talk vs panel vs tutorial vs poster
 
    
 

 
    Note that if you have different deadlines, reviewers, etc. you'll want
...
 
@@ -67,8 +67,8 @@ class ProposalKind(models.Model):
 
    """
 
    
 

 
    section = models.ForeignKey(Section, related_name="proposal_kinds")
 
    
 

 
    name = models.CharField(_("Name"), max_length=100)
 
    slug = models.SlugField()
 
    
 

 
    def __unicode__(self):
...
 
@@ -78,7 +78,7 @@ class ProposalKind(models.Model):
 
class ProposalBase(models.Model):
 
    
 

 
    objects = InheritanceManager()
 
    
 

 
    kind = models.ForeignKey(ProposalKind)
 
    
 

 
    title = models.CharField(max_length=100)
...
 
@@ -87,3 +87,4 @@ class ProposalBase(models.Model):
 
        max_length=400,  # @@@ need to enforce 400 in UI
 
        help_text="If your proposal is accepted this will be made public and printed in the program. Should be one paragraph, maximum 400 characters."
 
        help_text=_("If your proposal is accepted this will be made public and printed in the "
 
                    "program. Should be one paragraph, maximum 400 characters.")
 
    )
...
 
@@ -91,3 +92,5 @@ class ProposalBase(models.Model):
 
        _("Detailed Abstract"),
 
        help_text=_("Detailed outline. Will be made public if your proposal is accepted. Edit using <a href='http://daringfireball.net/projects/markdown/basics' target='_blank'>Markdown</a>.")
 
        help_text=_("Detailed outline. Will be made public if your proposal is accepted. Edit "
 
                    "using <a href='http://daringfireball.net/projects/markdown/basics' "
 
                    "target='_blank'>Markdown</a>.")
 
    )
...
 
@@ -95,3 +98,6 @@ class ProposalBase(models.Model):
 
        blank=True,
 
        help_text=_("Anything else you'd like the program committee to know when making their selection: your past experience, etc. This is not made public. Edit using <a href='http://daringfireball.net/projects/markdown/basics' target='_blank'>Markdown</a>.")
 
        help_text=_("Anything else you'd like the program committee to know when making their "
 
                    "selection: your past experience, etc. This is not made public. Edit using "
 
                    "<a href='http://daringfireball.net/projects/markdown/basics' "
 
                    "target='_blank'>Markdown</a>.")
 
    )
...
 
@@ -102,8 +108,9 @@ class ProposalBase(models.Model):
 
    speaker = models.ForeignKey("speakers.Speaker", related_name="proposals")
 
    additional_speakers = models.ManyToManyField("speakers.Speaker", through="AdditionalSpeaker", blank=True)
 
    additional_speakers = models.ManyToManyField("speakers.Speaker", through="AdditionalSpeaker",
 
                                                 blank=True)
 
    cancelled = models.BooleanField(default=False)
 
    
 

 
    def can_edit(self):
 
        return True
 
    
 

 
    @property
...
 
@@ -111,3 +118,3 @@ class ProposalBase(models.Model):
 
        return self.kind.section
 
    
 

 
    @property
...
 
@@ -115,3 +122,3 @@ class ProposalBase(models.Model):
 
        return self.speaker.email
 
    
 

 
    @property
...
 
@@ -119,8 +126,10 @@ class ProposalBase(models.Model):
 
        return str(self.pk).zfill(3)
 
    
 

 
    def speakers(self):
 
        yield self.speaker
 
        for speaker in self.additional_speakers.exclude(additionalspeaker__status=AdditionalSpeaker.SPEAKING_STATUS_DECLINED):
 
        speakers = self.additional_speakers.exclude(
 
            additionalspeaker__status=AdditionalSpeaker.SPEAKING_STATUS_DECLINED)
 
        for speaker in speakers:
 
            yield speaker
 
    
 

 
    def notification_email_context(self):
...
 
@@ -137,3 +146,3 @@ reversion.register(ProposalBase)
 
class AdditionalSpeaker(models.Model):
 
    
 

 
    SPEAKING_STATUS_PENDING = 1
...
 
@@ -141,3 +150,3 @@ class AdditionalSpeaker(models.Model):
 
    SPEAKING_STATUS_DECLINED = 3
 
    
 

 
    SPEAKING_STATUS = [
...
 
@@ -147,3 +156,3 @@ class AdditionalSpeaker(models.Model):
 
    ]
 
    
 

 
    speaker = models.ForeignKey("speakers.Speaker")
...
 
@@ -151,3 +160,3 @@ class AdditionalSpeaker(models.Model):
 
    status = models.IntegerField(choices=SPEAKING_STATUS, default=SPEAKING_STATUS_PENDING)
 
    
 

 
    class Meta:
...
 
@@ -164,8 +173,8 @@ def uuid_filename(instance, filename):
 
class SupportingDocument(models.Model):
 
    
 

 
    proposal = models.ForeignKey(ProposalBase, related_name="supporting_documents")
 
    
 

 
    uploaded_by = models.ForeignKey(User)
 
    created_at = models.DateTimeField(default=datetime.datetime.now)
 
    
 

 
    file = models.FileField(upload_to=uuid_filename)
...
 
@@ -174,2 +183,3 @@ class SupportingDocument(models.Model):
 
    def download_url(self):
 
        return reverse("proposal_document_download", args=[self.pk, os.path.basename(self.file.name).lower()])
 
        return reverse("proposal_document_download",
 
                       args=[self.pk, os.path.basename(self.file.name).lower()])
symposion/proposals/templatetags/proposal_tags.py
Show inline comments
...
 
@@ -9,3 +9,3 @@ register = template.Library()
 
class AssociatedProposalsNode(template.Node):
 
    
 

 
    @classmethod
...
 
@@ -17,6 +17,6 @@ class AssociatedProposalsNode(template.Node):
 
            raise template.TemplateSyntaxError("%r takes 'as var'" % bits[0])
 
    
 

 
    def __init__(self, context_var):
 
        self.context_var = context_var
 
    
 

 
    def render(self, context):
...
 
@@ -34,3 +34,3 @@ class AssociatedProposalsNode(template.Node):
 
class PendingProposalsNode(template.Node):
 
    
 

 
    @classmethod
...
 
@@ -42,6 +42,6 @@ class PendingProposalsNode(template.Node):
 
            raise template.TemplateSyntaxError("%r takes 'as var'" % bits[0])
 
    
 

 
    def __init__(self, context_var):
 
        self.context_var = context_var
 
    
 

 
    def render(self, context):
...
 
@@ -72,2 +72 @@ def associated_proposals(parser, token):
 
    return AssociatedProposalsNode.handle_token(parser, token)
 

	
symposion/proposals/urls.py
Show inline comments
 
# flake8: noqa
 
from django.conf.urls.defaults import *
...
 
@@ -13,3 +14,3 @@ urlpatterns = patterns("symposion.proposals.views",
 
    url(r"^(\d+)/decline/$", "proposal_pending_decline", name="proposal_pending_decline"),
 
    
 

 
    url(r"^(\d+)/document/create/$", "document_create", name="proposal_document_create"),
symposion/proposals/views.py
Show inline comments
...
 
@@ -39,3 +39,3 @@ def proposal_submit(request):
 
            return redirect("dashboard")
 
    
 

 
    kinds = []
...
 
@@ -44,3 +44,3 @@ def proposal_submit(request):
 
            kinds.append(kind)
 
    
 

 
    return render(request, "proposals/proposal_submit.html", {
...
 
@@ -51,5 +51,5 @@ def proposal_submit(request):
 
def proposal_submit_kind(request, kind_slug):
 
    
 

 
    kind = get_object_or_404(ProposalKind, slug=kind_slug)
 
    
 

 
    if not request.user.is_authenticated():
...
 
@@ -61,8 +61,8 @@ def proposal_submit_kind(request, kind_slug):
 
            return redirect("dashboard")
 
    
 

 
    if not kind.section.proposalsection.is_available():
 
        return redirect("proposal_submit")
 
    
 

 
    form_class = get_form(settings.PROPOSAL_FORMS[kind_slug])
 
    
 

 
    if request.method == "POST":
...
 
@@ -81,3 +81,3 @@ def proposal_submit_kind(request, kind_slug):
 
        form = form_class()
 
    
 

 
    return render(request, "proposals/proposal_submit_kind.html", {
...
 
@@ -93,6 +93,6 @@ def proposal_speaker_manage(request, pk):
 
    proposal = ProposalBase.objects.get_subclass(pk=proposal.pk)
 
    
 

 
    if proposal.speaker != request.user.speaker_profile:
 
        raise Http404()
 
    
 

 
    if request.method == "POST":
...
 
@@ -103,3 +103,3 @@ def proposal_speaker_manage(request, pk):
 
            }
 
            
 

 
            def create_speaker_token(email_address):
...
 
@@ -137,3 +137,3 @@ def proposal_speaker_manage(request, pk):
 
                        [email_address], "speaker_no_profile",
 
                        context = message_ctx
 
                        context=message_ctx
 
                    )
...
 
@@ -143,3 +143,3 @@ def proposal_speaker_manage(request, pk):
 
                        [email_address], "speaker_addition",
 
                        context = message_ctx
 
                        context=message_ctx
 
                    )
...
 
@@ -152,5 +152,6 @@ def proposal_speaker_manage(request, pk):
 
                    [email_address], "speaker_invite",
 
                    context = message_ctx
 
                    context=message_ctx
 
                )
 
            invitation, created = AdditionalSpeaker.objects.get_or_create(proposalbase=proposal.proposalbase_ptr, speaker=speaker)
 
            invitation, created = AdditionalSpeaker.objects.get_or_create(
 
                proposalbase=proposal.proposalbase_ptr, speaker=speaker)
 
            messages.success(request, "Speaker invited to proposal.")
...
 
@@ -175,3 +176,3 @@ def proposal_edit(request, pk):
 
        raise Http404()
 
    
 

 
    if not proposal.can_edit():
...
 
@@ -182,3 +183,3 @@ def proposal_edit(request, pk):
 
        return render(request, "proposals/proposal_error.html", ctx)
 
    
 

 
    form_class = get_form(settings.PROPOSAL_FORMS[proposal.kind.slug])
...
 
@@ -208,3 +209,3 @@ def proposal_edit(request, pk):
 
        form = form_class(instance=proposal)
 
    
 

 
    return render(request, "proposals/proposal_edit.html", {
...
 
@@ -220,6 +221,6 @@ def proposal_detail(request, pk):
 
    proposal = ProposalBase.objects.get_subclass(pk=proposal.pk)
 
    
 

 
    if request.user not in [p.user for p in proposal.speakers()]:
 
        raise Http404()
 
    
 

 
    if "symposion.reviews" in settings.INSTALLED_APPS:
...
 
@@ -230,3 +231,3 @@ def proposal_detail(request, pk):
 
            if message_form.is_valid():
 
                
 

 
                message = message_form.save(commit=False)
...
 
@@ -235,3 +236,3 @@ def proposal_detail(request, pk):
 
                message.save()
 
                
 

 
                ProposalMessage = SpeakerCommentForm.Meta.model
...
 
@@ -244,3 +245,3 @@ def proposal_detail(request, pk):
 
                )
 
                
 

 
                for reviewer in reviewers:
...
 
@@ -255,3 +256,3 @@ def proposal_detail(request, pk):
 
                    )
 
                
 

 
                return redirect(request.path)
...
 
@@ -261,3 +262,3 @@ def proposal_detail(request, pk):
 
        message_form = None
 
    
 

 
    return render(request, "proposals/proposal_detail.html", {
...
 
@@ -273,3 +274,3 @@ def proposal_cancel(request, pk):
 
    proposal = ProposalBase.objects.get_subclass(pk=proposal.pk)
 
    
 

 
    if proposal.speaker.user != request.user:
...
 
@@ -283,3 +284,3 @@ def proposal_cancel(request, pk):
 
        return redirect("dashboard")
 
    
 

 
    return render(request, "proposals/proposal_cancel.html", {
...
 
@@ -313,3 +314,4 @@ def proposal_pending_join(request, pk):
 
    proposal = get_object_or_404(ProposalBase, pk=pk)
 
    speaking = get_object_or_404(AdditionalSpeaker, speaker=request.user.speaker_profile, proposalbase=proposal)
 
    speaking = get_object_or_404(AdditionalSpeaker, speaker=request.user.speaker_profile,
 
                                 proposalbase=proposal)
 
    if speaking.status == AdditionalSpeaker.SPEAKING_STATUS_PENDING:
...
 
@@ -326,3 +328,4 @@ def proposal_pending_decline(request, pk):
 
    proposal = get_object_or_404(ProposalBase, pk=pk)
 
    speaking = get_object_or_404(AdditionalSpeaker, speaker=request.user.speaker_profile, proposalbase=proposal)
 
    speaking = get_object_or_404(AdditionalSpeaker, speaker=request.user.speaker_profile,
 
                                 proposalbase=proposal)
 
    if speaking.status == AdditionalSpeaker.SPEAKING_STATUS_PENDING:
...
 
@@ -341,6 +344,6 @@ def document_create(request, proposal_pk):
 
    proposal = ProposalBase.objects.get_subclass(pk=proposal.pk)
 
    
 

 
    if proposal.cancelled:
 
        return HttpResponseForbidden()
 
    
 

 
    if request.method == "POST":
...
 
@@ -355,3 +358,3 @@ def document_create(request, proposal_pk):
 
        form = SupportingDocumentCreateForm()
 
        
 

 
    return render(request, "proposals/document_create.html", {
...
 
@@ -380,6 +383,6 @@ def document_delete(request, pk):
 
    proposal_pk = document.proposal.pk
 
    
 

 
    if request.method == "POST":
 
        document.delete()
 
    
 

 
    return redirect("proposal_detail", proposal_pk)
symposion/reviews/context_processors.py
Show inline comments
 
from django.contrib.contenttypes.models import ContentType
 

	
 
from symposion.proposals.models import ProposalSection
symposion/reviews/forms.py
Show inline comments
...
 
@@ -11,4 +11,4 @@ class ReviewForm(forms.ModelForm):
 
        fields = ["vote", "comment"]
 
        widgets = { "comment": MarkItUpWidget() }
 
    
 
        widgets = {"comment": MarkItUpWidget()}
 

	
 
    def __init__(self, *args, **kwargs):
...
 
@@ -16,4 +16,4 @@ class ReviewForm(forms.ModelForm):
 
        self.fields["vote"] = forms.ChoiceField(
 
            widget = forms.RadioSelect(),
 
            choices = VOTES.CHOICES
 
            widget=forms.RadioSelect(),
 
            choices=VOTES.CHOICES
 
        )
...
 
@@ -25,3 +25,3 @@ class ReviewCommentForm(forms.ModelForm):
 
        fields = ["text"]
 
        widgets = { "text": MarkItUpWidget() }
 
        widgets = {"text": MarkItUpWidget()}
 

	
...
 
@@ -32,3 +32,3 @@ class SpeakerCommentForm(forms.ModelForm):
 
        fields = ["message"]
 
        widgets = { "message": MarkItUpWidget() }
 
        widgets = {"message": MarkItUpWidget()}
 

	
symposion/reviews/management/commands/assign_reviewers.py
Show inline comments
 
import csv
 
import os
 
import random
 

	
 
from django.contrib.auth import models
 
from django.core.management.base import BaseCommand
symposion/reviews/management/commands/calculate_results.py
Show inline comments
...
 
@@ -2,4 +2,2 @@ from django.core.management.base import BaseCommand
 

	
 
from django.contrib.auth.models import Group
 

	
 
from symposion.reviews.models import ProposalResult
...
 
@@ -8,3 +6,3 @@ from symposion.reviews.models import ProposalResult
 
class Command(BaseCommand):
 
    
 

 
    def handle(self, *args, **options):
symposion/reviews/management/commands/create_review_permissions.py
Show inline comments
...
 
@@ -9,3 +9,3 @@ from symposion.proposals.models import ProposalSection
 
class Command(BaseCommand):
 
    
 

 
    def handle(self, *args, **options):
...
 
@@ -16,3 +16,3 @@ class Command(BaseCommand):
 
        )
 
        
 

 
        for ps in ProposalSection.objects.all():
symposion/reviews/management/commands/promoteproposals.py
Show inline comments
...
 
@@ -7,3 +7,3 @@ from symposion.reviews.models import ProposalResult, promote_proposal
 
class Command(BaseCommand):
 
    
 

 
    def handle(self, *args, **options):
...
 
@@ -11,5 +11,6 @@ class Command(BaseCommand):
 
        accepted_proposals = accepted_proposals.order_by("proposal")
 
        
 

 
        for result in accepted_proposals:
 
            promote_proposal(result.proposal)
 
        connections["default"].cursor().execute("SELECT setval('schedule_session_id_seq', (SELECT max(id) FROM schedule_session))")
 
        connections["default"].cursor().execute(
 
            "SELECT setval('schedule_session_id_seq', (SELECT max(id) FROM schedule_session))")
symposion/reviews/models.py
Show inline comments
...
 
@@ -17,3 +17,3 @@ from symposion.schedule.models import Presentation
 
class ProposalScoreExpression(object):
 
    
 

 
    def as_sql(self, qn, connection=None):
...
 
@@ -21,3 +21,3 @@ class ProposalScoreExpression(object):
 
        return sql, []
 
    
 

 
    def prepare_database_save(self, unused):
...
 
@@ -31,3 +31,3 @@ class Votes(object):
 
    MINUS_ONE = u"−1"
 
    
 

 
    CHOICES = [
...
 
@@ -47,3 +47,3 @@ class ReviewAssignment(models.Model):
 
    NUM_REVIEWERS = 3
 
    
 

 
    ORIGIN_CHOICES = [
...
 
@@ -53,11 +53,11 @@ class ReviewAssignment(models.Model):
 
    ]
 
    
 

 
    proposal = models.ForeignKey("proposals.ProposalBase")
 
    user = models.ForeignKey(User)
 
    
 

 
    origin = models.IntegerField(choices=ORIGIN_CHOICES)
 
    
 

 
    assigned_at = models.DateTimeField(default=datetime.now)
 
    opted_out = models.BooleanField()
 
    
 

 
    @classmethod
...
 
@@ -96,3 +96,3 @@ class ProposalMessage(models.Model):
 
    user = models.ForeignKey(User)
 
    
 

 
    message = MarkupField()
...
 
@@ -106,6 +106,6 @@ class Review(models.Model):
 
    VOTES = VOTES
 
    
 

 
    proposal = models.ForeignKey("proposals.ProposalBase", related_name="reviews")
 
    user = models.ForeignKey(User)
 
    
 

 
    # No way to encode "-0" vs. "+0" into an IntegerField, and I don't feel
...
 
@@ -115,3 +115,3 @@ class Review(models.Model):
 
    submitted_at = models.DateTimeField(default=datetime.now, editable=False)
 
    
 

 
    def save(self, **kwargs):
...
 
@@ -119,7 +119,7 @@ class Review(models.Model):
 
            vote, created = LatestVote.objects.get_or_create(
 
                proposal = self.proposal,
 
                user = self.user,
 
                defaults = dict(
 
                    vote = self.vote,
 
                    submitted_at = self.submitted_at,
 
                proposal=self.proposal,
 
                user=self.user,
 
                defaults=dict(
 
                    vote=self.vote,
 
                    submitted_at=self.submitted_at,
 
                )
...
 
@@ -132,3 +132,3 @@ class Review(models.Model):
 
        super(Review, self).save(**kwargs)
 
    
 

 
    def delete(self):
...
 
@@ -154,3 +154,4 @@ class Review(models.Model):
 
                # previous vote
 
                previous = user_reviews.filter(submitted_at__lt=self.submitted_at).order_by("-submitted_at")[0]
 
                previous = user_reviews.filter(submitted_at__lt=self.submitted_at)\
 
                    .order_by("-submitted_at")[0]
 
                self.proposal.result.update_vote(self.vote, previous=previous.vote, removal=True)
...
 
@@ -168,3 +169,3 @@ class Review(models.Model):
 
        super(Review, self).delete()
 
    
 

 
    def css_class(self):
...
 
@@ -176,3 +177,3 @@ class Review(models.Model):
 
        }[self.vote]
 
    
 

 
    @property
...
 
@@ -184,6 +185,6 @@ class LatestVote(models.Model):
 
    VOTES = VOTES
 
    
 

 
    proposal = models.ForeignKey("proposals.ProposalBase", related_name="votes")
 
    user = models.ForeignKey(User)
 
    
 

 
    # No way to encode "-0" vs. "+0" into an IntegerField, and I don't feel
...
 
@@ -192,6 +193,6 @@ class LatestVote(models.Model):
 
    submitted_at = models.DateTimeField(default=datetime.now, editable=False)
 
    
 

 
    class Meta:
 
        unique_together = [("proposal", "user")]
 
    
 

 
    def css_class(self):
...
 
@@ -225,3 +226,3 @@ class ProposalResult(models.Model):
 
    ], default="undecided")
 
    
 

 
    @classmethod
...
 
@@ -233,16 +234,16 @@ class ProposalResult(models.Model):
 
            result.plus_one = LatestVote.objects.filter(
 
                proposal = proposal,
 
                vote = VOTES.PLUS_ONE
 
                proposal=proposal,
 
                vote=VOTES.PLUS_ONE
 
            ).count()
 
            result.plus_zero = LatestVote.objects.filter(
 
                proposal = proposal,
 
                vote = VOTES.PLUS_ZERO
 
                proposal=proposal,
 
                vote=VOTES.PLUS_ZERO
 
            ).count()
 
            result.minus_zero = LatestVote.objects.filter(
 
                proposal = proposal,
 
                vote = VOTES.MINUS_ZERO
 
                proposal=proposal,
 
                vote=VOTES.MINUS_ZERO
 
            ).count()
 
            result.minus_one = LatestVote.objects.filter(
 
                proposal = proposal,
 
                vote = VOTES.MINUS_ONE
 
                proposal=proposal,
 
                vote=VOTES.MINUS_ONE
 
            ).count()
...
 
@@ -250,3 +251,3 @@ class ProposalResult(models.Model):
 
            cls._default_manager.filter(pk=result.pk).update(score=ProposalScoreExpression())
 
    
 

 
    def update_vote(self, vote, previous=None, removal=False):
...
 
@@ -285,3 +286,3 @@ class Comment(models.Model):
 
    text = MarkupField()
 
    
 

 
    # Or perhaps more accurately, can the user see this comment.
...
 
@@ -295,3 +296,3 @@ class Comment(models.Model):
 
class NotificationTemplate(models.Model):
 
    
 

 
    label = models.CharField(max_length=100)
...
 
@@ -303,5 +304,6 @@ class NotificationTemplate(models.Model):
 
class ResultNotification(models.Model):
 
    
 

 
    proposal = models.ForeignKey("proposals.ProposalBase", related_name="notifications")
 
    template = models.ForeignKey(NotificationTemplate, null=True, blank=True, on_delete=models.SET_NULL)
 
    template = models.ForeignKey(NotificationTemplate, null=True, blank=True,
 
                                 on_delete=models.SET_NULL)
 
    timestamp = models.DateTimeField(default=datetime.now)
...
 
@@ -311,3 +313,3 @@ class ResultNotification(models.Model):
 
    body = models.TextField()
 
    
 

 
    @property
...
 
@@ -323,8 +325,8 @@ def promote_proposal(proposal):
 
        presentation = Presentation(
 
            title = proposal.title,
 
            description = proposal.description,
 
            abstract = proposal.abstract,
 
            speaker = proposal.speaker,
 
            section = proposal.section,
 
            proposal_base = proposal,
 
            title=proposal.title,
 
            description=proposal.description,
 
            abstract=proposal.abstract,
 
            speaker=proposal.speaker,
 
            section=proposal.section,
 
            proposal_base=proposal,
 
        )
...
 
@@ -334,3 +336,3 @@ def promote_proposal(proposal):
 
            presentation.save()
 
    
 

 
    return presentation
symposion/reviews/templatetags/review_tags.py
Show inline comments
...
 
@@ -2,3 +2,3 @@ from django import template
 

	
 
from symposion.reviews.models import Review, ReviewAssignment
 
from symposion.reviews.models import ReviewAssignment
 

	
symposion/reviews/tests.py
Show inline comments
...
 
@@ -17,6 +17,6 @@ class login(object):
 
        )
 
    
 

 
    def __enter__(self):
 
        pass
 
    
 

 
    def __exit__(self, *args):
...
 
@@ -27,6 +27,6 @@ class ReviewTests(TestCase):
 
    fixtures = ["proposals"]
 
    
 

 
    def get(self, url_name, *args, **kwargs):
 
        return self.client.get(reverse(url_name, args=args, kwargs=kwargs))
 
    
 

 
    def post(self, url_name, *args, **kwargs):
...
 
@@ -34,6 +34,6 @@ class ReviewTests(TestCase):
 
        return self.client.post(reverse(url_name, args=args, kwargs=kwargs), data)
 
    
 

 
    def login(self, user, password):
 
        return login(self, user, password)
 
    
 

 
    def test_detail_perms(self):
...
 
@@ -41,6 +41,6 @@ class ReviewTests(TestCase):
 
        response = self.get("review_detail", pk=guidos_proposal.pk)
 
        
 

 
        # Not logged in
 
        self.assertEqual(response.status_code, 302)
 
        
 

 
        with self.login("guido", "pythonisawesome"):
...
 
@@ -49,3 +49,3 @@ class ReviewTests(TestCase):
 
            self.assertEqual(response.status_code, 200)
 
        
 

 
        with self.login("matz", "pythonsucks"):
...
 
@@ -54,3 +54,3 @@ class ReviewTests(TestCase):
 
            self.assertEqual(response.status_code, 302)
 
        
 

 
        larry = User.objects.get(username="larryw")
...
 
@@ -62,6 +62,6 @@ class ReviewTests(TestCase):
 
            self.assertEqual(response.status_code, 200)
 
    
 

 
    def test_reviewing(self):
 
        guidos_proposal = Proposal.objects.all()[0]
 
        
 

 
        with self.login("guido", "pythonisawesome"):
...
 
@@ -74,3 +74,3 @@ class ReviewTests(TestCase):
 
            self.assertEqual(guidos_proposal.reviews.count(), 0)
 
        
 

 
        larry = User.objects.get(username="larryw")
...
 
@@ -92,3 +92,3 @@ class ReviewTests(TestCase):
 
            self.assertFalse(comment.public)
 
            
 

 
            response = self.post("review_review", pk=guidos_proposal.pk, data={
...
 
@@ -102,3 +102,3 @@ class ReviewTests(TestCase):
 
            self.assertEqual(guidos_proposal.comments.count(), 2)
 
            
 

 
            # Larry's a big fan...
...
 
@@ -108,6 +108,6 @@ class ReviewTests(TestCase):
 
            self.assertEqual(guidos_proposal.reviews.count(), 2)
 
    
 

 
    def test_speaker_commenting(self):
 
        guidos_proposal = Proposal.objects.all()[0]
 
        
 

 
        with self.login("guido", "pythonisawesome"):
...
 
@@ -116,3 +116,3 @@ class ReviewTests(TestCase):
 
            self.assertEqual(response.status_code, 200)
 
            
 

 
            response = self.post("review_comment", pk=guidos_proposal.pk, data={
...
 
@@ -124,3 +124,3 @@ class ReviewTests(TestCase):
 
            self.assertTrue(comment.public)
 
        
 

 
        larry = User.objects.get(username="larryw")
...
 
@@ -132,3 +132,3 @@ class ReviewTests(TestCase):
 
            self.assertEqual(response.status_code, 200)
 
            
 

 
            response = self.post("review_comment", pk=guidos_proposal.pk, data={
...
 
@@ -138,3 +138,3 @@ class ReviewTests(TestCase):
 
            self.assertEqual(guidos_proposal.comments.count(), 2)
 
        
 

 
        with self.login("matz", "pythonsucks"):
symposion/reviews/urls.py
Show inline comments
 
# flake8: noqa
 
from django.conf.urls.defaults import patterns, url
...
 
@@ -16,5 +17,5 @@ urlpatterns = patterns("symposion.reviews.views",
 
    url(r"^section/(?P<section_slug>[\w\-]+)/notification/(?P<status>\w+)/send/$", "result_notification_send", name="result_notification_send"),
 
    
 

 
    url(r"^review/(?P<pk>\d+)/$", "review_detail", name="review_detail"),
 
    
 

 
    url(r"^(?P<pk>\d+)/delete/$", "review_delete", name="review_delete"),
symposion/reviews/utils.py
Show inline comments
...
 
@@ -4,4 +4,4 @@ def has_permission(user, proposal, speaker=False, reviewer=False):
 
    with the specified requirements.
 
    
 
    If ``speaker`` is ``True`` then the user can be one of the speakers for the 
 

	
 
    If ``speaker`` is ``True`` then the user can be one of the speakers for the
 
    proposal.  If ``reviewer`` is ``True`` the speaker can be a part of the
...
 
@@ -12,4 +12,4 @@ def has_permission(user, proposal, speaker=False, reviewer=False):
 
    if speaker:
 
        if (user == proposal.speaker.user or 
 
            proposal.additional_speakers.filter(user=user).exists()):
 
        if user == proposal.speaker.user or \
 
           proposal.additional_speakers.filter(user=user).exists():
 
            return True
symposion/reviews/views.py
Show inline comments
 
import re
 

	
 
from django.core.mail import send_mass_mail
...
 
@@ -29,3 +27,3 @@ def access_not_permitted(request):
 
def proposals_generator(request, queryset, user_pk=None, check_speaker=True):
 
    
 

 
    for obj in queryset:
...
 
@@ -35,3 +33,3 @@ def proposals_generator(request, queryset, user_pk=None, check_speaker=True):
 
                continue
 
        
 

 
        try:
...
 
@@ -40,3 +38,3 @@ def proposals_generator(request, queryset, user_pk=None, check_speaker=True):
 
            ProposalResult.objects.get_or_create(proposal=obj)
 
        
 

 
        obj.comment_count = obj.result.comment_count
...
 
@@ -48,3 +46,3 @@ def proposals_generator(request, queryset, user_pk=None, check_speaker=True):
 
        lookup_params = dict(proposal=obj)
 
        
 

 
        if user_pk:
...
 
@@ -53,3 +51,3 @@ def proposals_generator(request, queryset, user_pk=None, check_speaker=True):
 
            lookup_params["user"] = request.user
 
        
 

 
        try:
...
 
@@ -60,3 +58,3 @@ def proposals_generator(request, queryset, user_pk=None, check_speaker=True):
 
            obj.user_vote_css = "no-vote"
 
        
 

 
        yield obj
...
 
@@ -64,17 +62,18 @@ def proposals_generator(request, queryset, user_pk=None, check_speaker=True):
 

	
 
# Returns a list of all proposals, proposals reviewed by the user, or the proposals the user has yet to review
 
# depending on the link user clicks in dashboard
 
# Returns a list of all proposals, proposals reviewed by the user, or the proposals the user has
 
# yet to review depending on the link user clicks in dashboard
 
@login_required
 
def review_section(request, section_slug, assigned=False, reviewed="all"):
 
    
 

 
    if not request.user.has_perm("reviews.can_review_%s" % section_slug):
 
        return access_not_permitted(request)
 
    
 

 
    section = get_object_or_404(ProposalSection, section__slug=section_slug)
 
    queryset = ProposalBase.objects.filter(kind__section=section)
 
    
 

 
    if assigned:
 
        assignments = ReviewAssignment.objects.filter(user=request.user).values_list("proposal__id")
 
        assignments = ReviewAssignment.objects.filter(user=request.user)\
 
            .values_list("proposal__id")
 
        queryset = queryset.filter(id__in=assignments)
 
    
 

 
    # passing reviewed in from reviews.urls and out to review_list for
...
 
@@ -90,5 +89,5 @@ def review_section(request, section_slug, assigned=False, reviewed="all"):
 
        reviewed = "user_not_reviewed"
 
    
 

 
    proposals = proposals_generator(request, queryset)
 
    
 

 
    ctx = {
...
 
@@ -98,8 +97,9 @@ def review_section(request, section_slug, assigned=False, reviewed="all"):
 
    }
 
    
 

 
    return render(request, "reviews/review_list.html", ctx)
 

	
 

	
 
@login_required
 
def review_list(request, section_slug, user_pk):
 
    
 

 
    # if they're not a reviewer admin and they aren't the person whose
...
 
@@ -109,3 +109,3 @@ def review_list(request, section_slug, user_pk):
 
            return access_not_permitted(request)
 
    
 

 
    queryset = ProposalBase.objects.select_related("speaker__user", "result")
...
 
@@ -114,7 +114,7 @@ def review_list(request, section_slug, user_pk):
 
    proposals = queryset.order_by("submitted")
 
    
 

 
    admin = request.user.has_perm("reviews.can_manage_%s" % section_slug)
 
    
 

 
    proposals = proposals_generator(request, proposals, user_pk=user_pk, check_speaker=not admin)
 
    
 

 
    ctx = {
...
 
@@ -127,9 +127,9 @@ def review_list(request, section_slug, user_pk):
 
def review_admin(request, section_slug):
 
    
 

 
    if not request.user.has_perm("reviews.can_manage_%s" % section_slug):
 
        return access_not_permitted(request)
 
    
 

 
    def reviewers():
 
        already_seen = set()
 
        
 

 
        for team in Team.objects.filter(permissions__codename="can_review_%s" % section_slug):
...
 
@@ -140,3 +140,3 @@ def review_admin(request, section_slug):
 
                already_seen.add(user.pk)
 
                
 

 
                user.comment_count = Review.objects.filter(user=user).count()
...
 
@@ -144,20 +144,20 @@ def review_admin(request, section_slug):
 
                user.plus_one = LatestVote.objects.filter(
 
                    user = user,
 
                    vote = LatestVote.VOTES.PLUS_ONE
 
                    user=user,
 
                    vote=LatestVote.VOTES.PLUS_ONE
 
                ).count()
 
                user.plus_zero = LatestVote.objects.filter(
 
                    user = user,
 
                    vote = LatestVote.VOTES.PLUS_ZERO
 
                    user=user,
 
                    vote=LatestVote.VOTES.PLUS_ZERO
 
                ).count()
 
                user.minus_zero = LatestVote.objects.filter(
 
                    user = user,
 
                    vote = LatestVote.VOTES.MINUS_ZERO
 
                    user=user,
 
                    vote=LatestVote.VOTES.MINUS_ZERO
 
                ).count()
 
                user.minus_one = LatestVote.objects.filter(
 
                    user = user,
 
                    vote = LatestVote.VOTES.MINUS_ONE
 
                    user=user,
 
                    vote=LatestVote.VOTES.MINUS_ONE
 
                ).count()
 
                
 

 
                yield user
 
    
 

 
    ctx = {
...
 
@@ -171,16 +171,16 @@ def review_admin(request, section_slug):
 
def review_detail(request, pk):
 
    
 

 
    proposals = ProposalBase.objects.select_related("result").select_subclasses()
 
    proposal = get_object_or_404(proposals, pk=pk)
 
    
 

 
    if not request.user.has_perm("reviews.can_review_%s" % proposal.kind.section.slug):
 
        return access_not_permitted(request)
 
    
 

 
    speakers = [s.user for s in proposal.speakers()]
 
    
 

 
    if not request.user.is_superuser and request.user in speakers:
 
        return access_not_permitted(request)
 
    
 

 
    admin = request.user.is_staff
 
    
 

 
    try:
...
 
@@ -189,3 +189,3 @@ def review_detail(request, pk):
 
        latest_vote = None
 
    
 

 
    if request.method == "POST":
...
 
@@ -193,3 +193,3 @@ def review_detail(request, pk):
 
            return access_not_permitted(request)
 
        
 

 
        if "vote_submit" in request.POST:
...
 
@@ -197,3 +197,3 @@ def review_detail(request, pk):
 
            if review_form.is_valid():
 
                
 

 
                review = review_form.save(commit=False)
...
 
@@ -202,3 +202,3 @@ def review_detail(request, pk):
 
                review.save()
 
                
 

 
                return redirect(request.path)
...
 
@@ -209,3 +209,3 @@ def review_detail(request, pk):
 
            if message_form.is_valid():
 
                
 

 
                message = message_form.save(commit=False)
...
 
@@ -214,3 +214,3 @@ def review_detail(request, pk):
 
                message.save()
 
                
 

 
                for speaker in speakers:
...
 
@@ -224,5 +224,5 @@ def review_detail(request, pk):
 
                            [speaker.email], "proposal_new_message",
 
                            context = ctx
 
                            context=ctx
 
                        )
 
                
 

 
                return redirect(request.path)
...
 
@@ -239,3 +239,3 @@ def review_detail(request, pk):
 
                result = request.POST["result_submit"]
 
                
 

 
                if result == "accept":
...
 
@@ -252,3 +252,3 @@ def review_detail(request, pk):
 
                    proposal.result.save()
 
            
 

 
            return redirect(request.path)
...
 
@@ -263,3 +263,3 @@ def review_detail(request, pk):
 
        message_form = SpeakerCommentForm()
 
    
 

 
    proposal.comment_count = proposal.result.comment_count
...
 
@@ -270,6 +270,6 @@ def review_detail(request, pk):
 
    proposal.minus_one = proposal.result.minus_one
 
    
 

 
    reviews = Review.objects.filter(proposal=proposal).order_by("-submitted_at")
 
    messages = proposal.messages.order_by("submitted_at")
 
    
 

 
    return render(request, "reviews/review_detail.html", {
...
 
@@ -289,9 +289,9 @@ def review_delete(request, pk):
 
    section_slug = review.section.slug
 
    
 

 
    if not request.user.has_perm("reviews.can_manage_%s" % section_slug):
 
        return access_not_permitted(request)
 
    
 

 
    review = get_object_or_404(Review, pk=pk)
 
    review.delete()
 
    
 

 
    return redirect("review_detail", pk=review.proposal.pk)
...
 
@@ -301,8 +301,8 @@ def review_delete(request, pk):
 
def review_status(request, section_slug=None, key=None):
 
    
 

 
    if not request.user.has_perm("reviews.can_review_%s" % section_slug):
 
        return access_not_permitted(request)
 
    
 

 
    VOTE_THRESHOLD = settings.SYMPOSION_VOTE_THRESHOLD
 
    
 

 
    ctx = {
...
 
@@ -311,3 +311,3 @@ def review_status(request, section_slug=None, key=None):
 
    }
 
    
 

 
    queryset = ProposalBase.objects.select_related("speaker__user", "result").select_subclasses()
...
 
@@ -315,18 +315,28 @@ def review_status(request, section_slug=None, key=None):
 
        queryset = queryset.filter(kind__section__slug=section_slug)
 
    
 

 
    proposals = {
 
        # proposals with at least VOTE_THRESHOLD reviews and at least one +1 and no -1s, sorted by the 'score'
 
        "positive": queryset.filter(result__vote_count__gte=VOTE_THRESHOLD, result__plus_one__gt=0, result__minus_one=0).order_by("-result__score"),
 
        # proposals with at least VOTE_THRESHOLD reviews and at least one -1 and no +1s, reverse sorted by the 'score'
 
        "negative": queryset.filter(result__vote_count__gte=VOTE_THRESHOLD, result__minus_one__gt=0, result__plus_one=0).order_by("result__score"),
 
        # proposals with at least VOTE_THRESHOLD reviews and neither a +1 or a -1, sorted by total votes (lowest first)
 
        "indifferent": queryset.filter(result__vote_count__gte=VOTE_THRESHOLD, result__minus_one=0, result__plus_one=0).order_by("result__vote_count"),
 
        # proposals with at least VOTE_THRESHOLD reviews and both a +1 and -1, sorted by total votes (highest first)
 
        "controversial": queryset.filter(result__vote_count__gte=VOTE_THRESHOLD, result__plus_one__gt=0, result__minus_one__gt=0).order_by("-result__vote_count"),
 
        # proposals with at least VOTE_THRESHOLD reviews and at least one +1 and no -1s, sorted by
 
        # the 'score'
 
        "positive": queryset.filter(result__vote_count__gte=VOTE_THRESHOLD, result__plus_one__gt=0,
 
                                    result__minus_one=0).order_by("-result__score"),
 
        # proposals with at least VOTE_THRESHOLD reviews and at least one -1 and no +1s, reverse
 
        # sorted by the 'score'
 
        "negative": queryset.filter(result__vote_count__gte=VOTE_THRESHOLD, result__minus_one__gt=0,
 
                                    result__plus_one=0).order_by("result__score"),
 
        # proposals with at least VOTE_THRESHOLD reviews and neither a +1 or a -1, sorted by total
 
        # votes (lowest first)
 
        "indifferent": queryset.filter(result__vote_count__gte=VOTE_THRESHOLD, result__minus_one=0,
 
                                       result__plus_one=0).order_by("result__vote_count"),
 
        # proposals with at least VOTE_THRESHOLD reviews and both a +1 and -1, sorted by total
 
        # votes (highest first)
 
        "controversial": queryset.filter(result__vote_count__gte=VOTE_THRESHOLD,
 
                                         result__plus_one__gt=0, result__minus_one__gt=0)
 
        .order_by("-result__vote_count"),
 
        # proposals with fewer than VOTE_THRESHOLD reviews
 
        "too_few": queryset.filter(result__vote_count__lt=VOTE_THRESHOLD).order_by("result__vote_count"),
 
        "too_few": queryset.filter(result__vote_count__lt=VOTE_THRESHOLD)
 
        .order_by("result__vote_count"),
 
    }
 
    
 

 
    admin = request.user.has_perm("reviews.can_manage_%s" % section_slug)
 
    
 

 
    for status in proposals:
...
 
@@ -334,4 +344,5 @@ def review_status(request, section_slug=None, key=None):
 
            continue
 
        proposals[status] = list(proposals_generator(request, proposals[status], check_speaker=not admin))
 
    
 
        proposals[status] = list(proposals_generator(request, proposals[status],
 
                                                     check_speaker=not admin))
 

	
 
    if key:
...
 
@@ -343,3 +354,3 @@ def review_status(request, section_slug=None, key=None):
 
        ctx["proposals"] = proposals
 
    
 

 
    return render(request, "reviews/review_stats.html", ctx)
...
 
@@ -363,6 +374,4 @@ def review_assignments(request):
 
def review_assignment_opt_out(request, pk):
 
    review_assignment = get_object_or_404(ReviewAssignment,
 
        pk=pk,
 
        user=request.user
 
    )
 
    review_assignment = get_object_or_404(
 
        ReviewAssignment, pk=pk, user=request.user)
 
    if not review_assignment.opted_out:
...
 
@@ -370,3 +379,4 @@ def review_assignment_opt_out(request, pk):
 
        review_assignment.save()
 
        ReviewAssignment.create_assignments(review_assignment.proposal, origin=ReviewAssignment.AUTO_ASSIGNED_LATER)
 
        ReviewAssignment.create_assignments(
 
            review_assignment.proposal, origin=ReviewAssignment.AUTO_ASSIGNED_LATER)
 
    return redirect("review_assignments")
...
 
@@ -389,3 +399,3 @@ def review_bulk_accept(request, section_slug):
 
        form = BulkPresentationForm()
 
    
 

 
    return render(request, "reviews/review_bulk_accept.html", {
...
 
@@ -399,6 +409,8 @@ def result_notification(request, section_slug, status):
 
        return access_not_permitted(request)
 
    
 
    proposals = ProposalBase.objects.filter(kind__section__slug=section_slug, result__status=status).select_related("speaker__user", "result").select_subclasses()
 

	
 
    proposals = ProposalBase.objects.filter(kind__section__slug=section_slug,
 
                                            result__status=status)\
 
        .select_related("speaker__user", "result").select_subclasses()
 
    notification_templates = NotificationTemplate.objects.all()
 
    
 

 
    ctx = {
...
 
@@ -416,6 +428,6 @@ def result_notification_prepare(request, section_slug, status):
 
        return HttpResponseNotAllowed(["POST"])
 
    
 

 
    if not request.user.has_perm("reviews.can_manage_%s" % section_slug):
 
        return access_not_permitted(request)
 
    
 

 
    proposal_pks = []
...
 
@@ -433,3 +445,3 @@ def result_notification_prepare(request, section_slug, status):
 
    proposals = proposals.select_subclasses()
 
    
 

 
    notification_template_pk = request.POST.get("notification_template", "")
...
 
@@ -439,3 +451,3 @@ def result_notification_prepare(request, section_slug, status):
 
        notification_template = None
 
    
 

 
    ctx = {
...
 
@@ -454,9 +466,9 @@ def result_notification_send(request, section_slug, status):
 
        return HttpResponseNotAllowed(["POST"])
 
    
 

 
    if not request.user.has_perm("reviews.can_manage_%s" % section_slug):
 
        return access_not_permitted(request)
 
    
 

 
    if not all([k in request.POST for k in ["proposal_pks", "from_address", "subject", "body"]]):
 
        return HttpResponseBadRequest()
 
    
 

 
    try:
...
 
@@ -465,3 +477,3 @@ def result_notification_send(request, section_slug, status):
 
        return HttpResponseBadRequest()
 
    
 

 
    proposals = ProposalBase.objects.filter(
...
 
@@ -473,3 +485,3 @@ def result_notification_send(request, section_slug, status):
 
    proposals = proposals.select_subclasses()
 
    
 

 
    notification_template_pk = request.POST.get("notification_template", "")
...
 
@@ -479,5 +491,5 @@ def result_notification_send(request, section_slug, status):
 
        notification_template = None
 
    
 

 
    emails = []
 
    
 

 
    for proposal in proposals:
...
 
@@ -496,5 +508,5 @@ def result_notification_send(request, section_slug, status):
 
        emails.append(rn.email_args)
 
    
 

 
    send_mass_mail(emails)
 
    
 

 
    return redirect("result_notification", section_slug=section_slug, status=status)
symposion/schedule/forms.py
Show inline comments
...
 
@@ -9,3 +9,3 @@ from symposion.schedule.models import Presentation
 
class SlotEditForm(forms.Form):
 
    
 

 
    def __init__(self, *args, **kwargs):
...
 
@@ -18,3 +18,3 @@ class SlotEditForm(forms.Form):
 
            self.fields["content_override"] = self.build_content_override_field()
 
    
 

 
    def build_presentation_field(self):
...
 
@@ -33,3 +33,3 @@ class SlotEditForm(forms.Form):
 
        return forms.ModelChoiceField(**kwargs)
 
    
 

 
    def build_content_override_field(self):
symposion/schedule/models.py
Show inline comments
...
 
@@ -4,3 +4,2 @@ from django.db import models
 
from markitup.fields import MarkupField
 
from model_utils.managers import InheritanceManager
 

	
...
 
@@ -11,3 +10,3 @@ from symposion.conference.models import Section
 
class Schedule(models.Model):
 
    
 

 
    section = models.OneToOneField(Section)
...
 
@@ -15,6 +14,6 @@ class Schedule(models.Model):
 
    hidden = models.BooleanField("Hide schedule from overall conference view", default=False)
 
    
 

 
    def __unicode__(self):
 
        return "%s Schedule" % self.section
 
    
 

 
    class Meta:
...
 
@@ -24,9 +23,9 @@ class Schedule(models.Model):
 
class Day(models.Model):
 
    
 

 
    schedule = models.ForeignKey(Schedule)
 
    date = models.DateField()
 
    
 

 
    def __unicode__(self):
 
        return "%s" % self.date
 
    
 

 
    class Meta:
...
 
@@ -37,3 +36,3 @@ class Day(models.Model):
 
class Room(models.Model):
 
    
 

 
    schedule = models.ForeignKey(Schedule)
...
 
@@ -41,3 +40,3 @@ class Room(models.Model):
 
    order = models.PositiveIntegerField()
 
    
 

 
    def __unicode__(self):
...
 
@@ -51,6 +50,6 @@ class SlotKind(models.Model):
 
    """
 
    
 

 
    schedule = models.ForeignKey(Schedule)
 
    label = models.CharField(max_length=50)
 
    
 

 
    def __unicode__(self):
...
 
@@ -60,3 +59,3 @@ class SlotKind(models.Model):
 
class Slot(models.Model):
 
    
 

 
    day = models.ForeignKey(Day)
...
 
@@ -66,3 +65,3 @@ class Slot(models.Model):
 
    content_override = MarkupField(blank=True)
 
    
 

 
    def assign(self, content):
...
 
@@ -75,3 +74,3 @@ class Slot(models.Model):
 
        content.save()
 
    
 

 
    def unassign(self):
...
 
@@ -83,3 +82,3 @@ class Slot(models.Model):
 
            self.content.save()
 
    
 

 
    @property
...
 
@@ -94,3 +93,3 @@ class Slot(models.Model):
 
            return None
 
    
 

 
    @property
...
 
@@ -98,6 +97,6 @@ class Slot(models.Model):
 
        return Room.objects.filter(pk__in=self.slotroom_set.values("room"))
 
    
 

 
    def __unicode__(self):
 
        return "%s %s (%s - %s)" % (self.day, self.kind, self.start, self.end)
 
    
 

 
    class Meta:
...
 
@@ -110,9 +109,9 @@ class SlotRoom(models.Model):
 
    """
 
    
 

 
    slot = models.ForeignKey(Slot)
 
    room = models.ForeignKey(Room)
 
    
 

 
    def __unicode__(self):
 
        return "%s %s" % (self.room, self.slot)
 
    
 

 
    class Meta:
...
 
@@ -123,3 +122,3 @@ class SlotRoom(models.Model):
 
class Presentation(models.Model):
 
    
 

 
    slot = models.OneToOneField(Slot, null=True, blank=True, related_name="content_ptr")
...
 
@@ -129,3 +128,4 @@ class Presentation(models.Model):
 
    speaker = models.ForeignKey("speakers.Speaker", related_name="presentations")
 
    additional_speakers = models.ManyToManyField("speakers.Speaker", related_name="copresentations", blank=True)
 
    additional_speakers = models.ManyToManyField("speakers.Speaker", related_name="copresentations",
 
                                                 blank=True)
 
    cancelled = models.BooleanField(default=False)
...
 
@@ -133,3 +133,3 @@ class Presentation(models.Model):
 
    section = models.ForeignKey(Section, related_name="presentations")
 
    
 

 
    @property
...
 
@@ -137,3 +137,3 @@ class Presentation(models.Model):
 
        return self.proposal.number
 
    
 

 
    @property
...
 
@@ -143,3 +143,3 @@ class Presentation(models.Model):
 
        return ProposalBase.objects.get_subclass(pk=self.proposal_base_id)
 
    
 

 
    def speakers(self):
...
 
@@ -149,6 +149,6 @@ class Presentation(models.Model):
 
                yield speaker
 
    
 

 
    def __unicode__(self):
 
        return "#%s %s (%s)" % (self.number, self.title, self.speaker)
 
    
 

 
    class Meta:
symposion/schedule/timetable.py
Show inline comments
 
import itertools
 
import operator
 

	
...
 
@@ -9,6 +8,6 @@ from symposion.schedule.models import Room, Slot, SlotRoom
 
class TimeTable(object):
 
    
 

 
    def __init__(self, day):
 
        self.day = day
 
    
 

 
    def slots_qs(self):
...
 
@@ -17,3 +16,3 @@ class TimeTable(object):
 
        return qs
 
    
 

 
    def rooms(self):
...
 
@@ -21,6 +20,7 @@ class TimeTable(object):
 
        qs = qs.filter(schedule=self.day.schedule)
 
        qs = qs.filter(pk__in=SlotRoom.objects.filter(slot__in=self.slots_qs().values("pk")).values("room"))
 
        qs = qs.filter(
 
            pk__in=SlotRoom.objects.filter(slot__in=self.slots_qs().values("pk")).values("room"))
 
        qs = qs.order_by("order")
 
        return qs
 
    
 

 
    def __iter__(self):
...
 
@@ -40,3 +40,3 @@ class TimeTable(object):
 
                yield row
 
    
 

 
    @staticmethod
symposion/schedule/urls.py
Show inline comments
 
# flake8: noqa
 
from django.conf.urls.defaults import url, patterns
symposion/schedule/views.py
Show inline comments
 
from django.core.exceptions import ObjectDoesNotExist
 
from django.http import Http404, HttpResponse
...
 
@@ -14,3 +13,3 @@ def fetch_schedule(slug):
 
    qs = Schedule.objects.all()
 
    
 

 
    if slug is None:
...
 
@@ -23,3 +22,3 @@ def fetch_schedule(slug):
 
        schedule = get_object_or_404(qs, section__slug=slug)
 
    
 

 
    return schedule
...
 
@@ -28,5 +27,5 @@ def fetch_schedule(slug):
 
def schedule_conference(request):
 
    
 

 
    schedules = Schedule.objects.filter(published=True, hidden=False)
 
    
 

 
    sections = []
...
 
@@ -39,3 +38,3 @@ def schedule_conference(request):
 
        })
 
    
 

 
    ctx = {
...
 
@@ -47,3 +46,3 @@ def schedule_conference(request):
 
def schedule_detail(request, slug=None):
 
    
 

 
    schedule = fetch_schedule(slug)
...
 
@@ -51,6 +50,6 @@ def schedule_detail(request, slug=None):
 
        raise Http404()
 
    
 

 
    days_qs = Day.objects.filter(schedule=schedule)
 
    days = [TimeTable(day) for day in days_qs]
 
    
 

 
    ctx = {
...
 
@@ -64,6 +63,6 @@ def schedule_list(request, slug=None):
 
    schedule = fetch_schedule(slug)
 
    
 

 
    presentations = Presentation.objects.filter(section=schedule.section)
 
    presentations = presentations.exclude(cancelled=True)
 
    
 

 
    ctx = {
...
 
@@ -77,6 +76,6 @@ def schedule_list_csv(request, slug=None):
 
    schedule = fetch_schedule(slug)
 
    
 

 
    presentations = Presentation.objects.filter(section=schedule.section)
 
    presentations = presentations.exclude(cancelled=True).order_by("id")
 
    
 

 
    response = HttpResponse(mimetype="text/csv")
...
 
@@ -87,6 +86,6 @@ def schedule_list_csv(request, slug=None):
 
    response["Content-Disposition"] = 'attachment; filename="%s.csv"' % file_slug
 
    
 

 
    response.write(loader.get_template("schedule/schedule_list.csv").render(Context({
 
        "presentations": presentations,
 
        
 

 
    })))
...
 
@@ -97,8 +96,8 @@ def schedule_list_csv(request, slug=None):
 
def schedule_edit(request, slug=None):
 
    
 

 
    if not request.user.is_staff:
 
        raise Http404()
 
    
 

 
    schedule = fetch_schedule(slug)
 
    
 

 
    days_qs = Day.objects.filter(schedule=schedule)
...
 
@@ -114,8 +113,8 @@ def schedule_edit(request, slug=None):
 
def schedule_slot_edit(request, slug, slot_pk):
 
    
 

 
    if not request.user.is_staff:
 
        raise Http404()
 
    
 

 
    slot = get_object_or_404(Slot, day__schedule__section__slug=slug, pk=slot_pk)
 
    
 

 
    if request.method == "POST":
...
 
@@ -147,3 +146,3 @@ def schedule_slot_edit(request, slug, slot_pk):
 
def schedule_presentation_detail(request, pk):
 
    
 

 
    presentation = get_object_or_404(Presentation, pk=pk)
...
 
@@ -153,3 +152,3 @@ def schedule_presentation_detail(request, pk):
 
        schedule = None
 
    
 

 
    ctx = {
symposion/speakers/admin.py
Show inline comments
...
 
@@ -6,4 +6,3 @@ from symposion.speakers.models import Speaker
 
admin.site.register(Speaker,
 
    list_display = ["name", "email", "created"],
 
    search_fields = ["name"],
 
)
...
 
\ No newline at end of file
 
                    list_display=["name", "email", "created"],
 
                    search_fields=["name"])
symposion/speakers/fixture_gen.py
Show inline comments
...
 
@@ -12,3 +12,3 @@ def speakers():
 
    larry = User.objects.create_user("larryw", "larry@perl.org", "linenoisehere")
 
    
 

 
    Speaker.objects.create(
...
 
@@ -21,4 +21,4 @@ def speakers():
 
        name="Yukihiro Matsumoto",
 
        biography="I wrote Ruby, and named it after the rare gem Ruby, a pun "
 
            "on Perl/pearl.",
 
        biography=("I wrote Ruby, and named it after the rare gem Ruby, a pun "
 
                   "on Perl/pearl."),
 
    )
symposion/speakers/forms.py
Show inline comments
...
 
@@ -8,3 +8,3 @@ from symposion.speakers.models import Speaker
 
class SpeakerForm(forms.ModelForm):
 
    
 

 
    class Meta:
symposion/speakers/management/commands/export_speaker_data.py
Show inline comments
...
 
@@ -3,3 +3,3 @@ import os
 

	
 
from django.core.management.base import BaseCommand, CommandError
 
from django.core.management.base import BaseCommand
 

	
...
 
@@ -9,3 +9,3 @@ from symposion.speakers.models import Speaker
 
class Command(BaseCommand):
 
    
 

 
    def handle(self, *args, **options):
...
 
@@ -13,3 +13,3 @@ class Command(BaseCommand):
 
        csv_file.writerow(["Name", "Bio"])
 
        
 

 
        for speaker in Speaker.objects.all():
symposion/speakers/models.py
Show inline comments
...
 
@@ -11,3 +11,3 @@ from markitup.fields import MarkupField
 
class Speaker(models.Model):
 
    
 

 
    SESSION_COUNT_CHOICES = [
...
 
@@ -16,6 +16,10 @@ class Speaker(models.Model):
 
    ]
 
    
 

 
    user = models.OneToOneField(User, null=True, related_name="speaker_profile")
 
    name = models.CharField(max_length=100, help_text="As you would like it to appear in the conference program.")
 
    biography = MarkupField(blank=True, help_text="A little bit about you. Edit using <a href='http://warpedvisions.org/projects/markdown-cheat-sheet/' target='_blank'>Markdown</a>.")
 
    name = models.CharField(max_length=100, help_text=("As you would like it to appear in the "
 
                                                       "conference program."))
 
    biography = MarkupField(blank=True, help_text=("A little bit about you.  Edit using "
 
                                                   "<a href='http://warpedvisions.org/projects/"
 
                                                   "markdown-cheat-sheet/target='_blank'>"
 
                                                   "Markdown</a>."))
 
    photo = models.ImageField(upload_to="speaker_photos", blank=True)
...
 
@@ -25,4 +29,4 @@ class Speaker(models.Model):
 
    created = models.DateTimeField(
 
        default = datetime.datetime.now,
 
        editable = False
 
        default=datetime.datetime.now,
 
        editable=False
 
    )
...
 
@@ -31,3 +35,3 @@ class Speaker(models.Model):
 
        ordering = ['name']
 
    
 

 
    def __unicode__(self):
...
 
@@ -38,6 +42,5 @@ class Speaker(models.Model):
 

	
 
    
 
    def get_absolute_url(self):
 
        return reverse("speaker_edit")
 
    
 

 
    @property
...
 
@@ -48,3 +51,3 @@ class Speaker(models.Model):
 
            return self.invite_email
 
    
 

 
    @property
symposion/speakers/urls.py
Show inline comments
 
# flake8: noqa
 
from django.conf.urls.defaults import *
symposion/speakers/views.py
Show inline comments
...
 
@@ -19,3 +19,3 @@ def speaker_create(request):
 
        pass
 
    
 

 
    if request.method == "POST":
...
 
@@ -28,3 +28,3 @@ def speaker_create(request):
 
        form = SpeakerForm(request.POST, request.FILES, instance=speaker)
 
        
 

 
        if form.is_valid():
...
 
@@ -39,3 +39,3 @@ def speaker_create(request):
 
        form = SpeakerForm(initial={"name": request.user.get_full_name()})
 
    
 

 
    return render(request, "speakers/speaker_create.html", {
...
 
@@ -50,3 +50,3 @@ def speaker_create_staff(request, pk):
 
        raise Http404
 
    
 

 
    try:
...
 
@@ -55,6 +55,6 @@ def speaker_create_staff(request, pk):
 
        pass
 
    
 

 
    if request.method == "POST":
 
        form = SpeakerForm(request.POST, request.FILES)
 
        
 

 
        if form.is_valid():
...
 
@@ -67,3 +67,3 @@ def speaker_create_staff(request, pk):
 
        form = SpeakerForm(initial={"name": user.get_full_name()})
 
    
 

 
    return render(request, "speakers/speaker_create.html", {
...
 
@@ -90,4 +90,4 @@ def speaker_create_token(request, token):
 
            )
 
            messages.info(request, "You have been associated with all pending "
 
                "talk proposals")
 
            messages.info(request, ("You have been associated with all pending "
 
                                    "talk proposals"))
 
            return redirect("dashboard")
...
 
@@ -111,3 +111,3 @@ def speaker_edit(request, pk=None):
 
            raise Http404()
 
    
 

 
    if request.method == "POST":
...
 
@@ -120,3 +120,3 @@ def speaker_edit(request, pk=None):
 
        form = SpeakerForm(instance=speaker)
 
    
 

 
    return render(request, "speakers/speaker_edit.html", {
...
 
@@ -131,3 +131,3 @@ def speaker_profile(request, pk):
 
        raise Http404()
 
    
 

 
    return render(request, "speakers/speaker_profile.html", {
symposion/sponsorship/admin.py
Show inline comments
...
 
@@ -2,3 +2,4 @@ from django.contrib import admin
 

	
 
from symposion.sponsorship.models import SponsorLevel, Sponsor, Benefit, BenefitLevel, SponsorBenefit
 
from symposion.sponsorship.models import SponsorLevel, Sponsor, Benefit, BenefitLevel, \
 
    SponsorBenefit
 

	
...
 
@@ -26,3 +27,3 @@ class SponsorBenefitInline(admin.StackedInline):
 
class SponsorAdmin(admin.ModelAdmin):
 
    
 

 
    save_on_top = True
...
 
@@ -45,3 +46,3 @@ class SponsorAdmin(admin.ModelAdmin):
 
    list_display = ["name", "external_url", "level", "active"]
 
    
 

 
    def get_form(self, *args, **kwargs):
...
 
@@ -58,3 +59,3 @@ class SponsorAdmin(admin.ModelAdmin):
 
class BenefitAdmin(admin.ModelAdmin):
 
    
 

 
    list_display = ["name", "type", "description"]
...
 
@@ -64,3 +65,3 @@ class BenefitAdmin(admin.ModelAdmin):
 
class SponsorLevelAdmin(admin.ModelAdmin):
 
    
 

 
    inlines = [BenefitLevelInline]
symposion/sponsorship/forms.py
Show inline comments
...
 
@@ -18,3 +18,3 @@ class SponsorApplicationForm(forms.ModelForm):
 
        super(SponsorApplicationForm, self).__init__(*args, **kwargs)
 
    
 

 
    class Meta:
...
 
@@ -28,3 +28,3 @@ class SponsorApplicationForm(forms.ModelForm):
 
        ]
 
    
 

 
    def save(self, commit=True):
...
 
@@ -49,6 +49,6 @@ class SponsorDetailsForm(forms.ModelForm):
 
class SponsorBenefitsInlineFormSet(BaseInlineFormSet):
 
    
 

 
    def _construct_form(self, i, **kwargs):
 
        form = super(SponsorBenefitsInlineFormSet, self)._construct_form(i, **kwargs)
 
        
 

 
        # only include the relevant data fields for this benefit type
...
 
@@ -56,3 +56,3 @@ class SponsorBenefitsInlineFormSet(BaseInlineFormSet):
 
        form.fields = dict((k, v) for (k, v) in form.fields.items() if k in fields + ["id"])
 
        
 

 
        for field in fields:
...
 
@@ -60,3 +60,3 @@ class SponsorBenefitsInlineFormSet(BaseInlineFormSet):
 
            form.fields[field].label = ""
 
            
 

 
            # provide word limit as help_text
...
 
@@ -64,3 +64,3 @@ class SponsorBenefitsInlineFormSet(BaseInlineFormSet):
 
                form.fields[field].help_text = u"maximum %s words" % form.instance.max_words
 
            
 

 
            # use admin file widget that shows currently uploaded file
...
 
@@ -68,3 +68,3 @@ class SponsorBenefitsInlineFormSet(BaseInlineFormSet):
 
                form.fields[field].widget = AdminFileWidget()
 
        
 

 
        return form
symposion/sponsorship/management/commands/reset_sponsor_benefits.py
Show inline comments
...
 
@@ -2,5 +2,3 @@ from django.core.management.base import BaseCommand
 

	
 
from django.contrib.auth.models import Group
 

	
 
from symposion.sponsorship.models import Sponsor, SponsorBenefit
 
from symposion.sponsorship.models import Sponsor, SponsorBenefit, SponsorLevel
 

	
...
 
@@ -8,6 +6,6 @@ from symposion.sponsorship.models import Sponsor, SponsorBenefit
 
class Command(BaseCommand):
 
    
 

 
    def handle(self, *args, **options):
 
        for sponsor in Sponsor.objects.all():
 
            level = None  
 
            level = None
 
            try:
...
 
@@ -21,6 +19,6 @@ class Command(BaseCommand):
 
                        sponsor=sponsor, benefit=benefit_level.benefit)
 
                    
 

 
                    if created:
 
                        print "created", sponsor_benefit, "for", sponsor
 
                    
 

 
                    # and set to default limits for this level.
...
 
@@ -28,6 +26,6 @@ class Command(BaseCommand):
 
                    sponsor_benefit.other_limits = benefit_level.other_limits
 
                    
 

 
                    # and set to active
 
                    sponsor_benefit.active = True
 
                    
 

 
                    # @@@ We don't call sponsor_benefit.clean here. This means
symposion/sponsorship/models.py
Show inline comments
...
 
@@ -16,3 +16,3 @@ from symposion.sponsorship.managers import SponsorManager
 
class SponsorLevel(models.Model):
 
    
 

 
    conference = models.ForeignKey(Conference, verbose_name=_("conference"))
...
 
@@ -22,3 +22,3 @@ class SponsorLevel(models.Model):
 
    description = models.TextField(_("description"), blank=True, help_text=_("This is private."))
 
    
 

 
    class Meta:
...
 
@@ -27,6 +27,6 @@ class SponsorLevel(models.Model):
 
        verbose_name_plural = _("sponsor levels")
 
    
 

 
    def __unicode__(self):
 
        return self.name
 
    
 

 
    def sponsors(self):
...
 
@@ -36,5 +36,6 @@ class SponsorLevel(models.Model):
 
class Sponsor(models.Model):
 
    
 
    applicant = models.ForeignKey(User, related_name="sponsorships", verbose_name=_("applicant"), null=True)
 
    
 

	
 
    applicant = models.ForeignKey(User, related_name="sponsorships", verbose_name=_("applicant"),
 
                                  null=True)
 

	
 
    name = models.CharField(_("Sponsor Name"), max_length=100)
...
 
@@ -47,11 +48,12 @@ class Sponsor(models.Model):
 
    active = models.BooleanField(_("active"), default=False)
 
    
 

 
    # Denormalization (this assumes only one logo)
 
    sponsor_logo = models.ForeignKey("SponsorBenefit", related_name="+", null=True, blank=True, editable=False)
 
    
 
    sponsor_logo = models.ForeignKey("SponsorBenefit", related_name="+", null=True, blank=True,
 
                                     editable=False)
 

	
 
    objects = SponsorManager()
 
    
 

 
    def __unicode__(self):
 
        return self.name
 
    
 

 
    class Meta:
...
 
@@ -59,3 +61,3 @@ class Sponsor(models.Model):
 
        verbose_name_plural = _("sponsors")
 
    
 

 
    def get_absolute_url(self):
...
 
@@ -64,3 +66,3 @@ class Sponsor(models.Model):
 
        return reverse("sponsor_list")
 
    
 

 
    @property
...
 
@@ -68,3 +70,4 @@ class Sponsor(models.Model):
 
        if self.sponsor_logo is None:
 
            benefits = self.sponsor_benefits.filter(benefit__type="weblogo", upload__isnull=False)[:1]
 
            benefits = self.sponsor_benefits.filter(
 
                benefit__type="weblogo", upload__isnull=False)[:1]
 
            if benefits.count():
...
 
@@ -74,3 +77,3 @@ class Sponsor(models.Model):
 
        return self.sponsor_logo.upload
 
    
 

 
    @property
...
 
@@ -84,3 +87,3 @@ class Sponsor(models.Model):
 
        return self._listing_text
 
    
 

 
    def reset_benefits(self):
...
 
@@ -91,3 +94,3 @@ class Sponsor(models.Model):
 
        level = None
 
        
 

 
        try:
...
 
@@ -96,3 +99,3 @@ class Sponsor(models.Model):
 
            pass
 
        
 

 
        allowed_benefits = []
...
 
@@ -103,3 +106,3 @@ class Sponsor(models.Model):
 
                    sponsor=self, benefit=benefit_level.benefit)
 
                
 

 
                # and set to default limits for this level.
...
 
@@ -107,6 +110,6 @@ class Sponsor(models.Model):
 
                sponsor_benefit.other_limits = benefit_level.other_limits
 
                
 

 
                # and set to active
 
                sponsor_benefit.active = True
 
                
 

 
                # @@@ We don't call sponsor_benefit.clean here. This means
...
 
@@ -117,9 +120,10 @@ class Sponsor(models.Model):
 
                sponsor_benefit.save()
 
                
 

 
                allowed_benefits.append(sponsor_benefit.pk)
 
        
 

 
        # Any remaining sponsor benefits that don't normally belong to
 
        # this level are set to inactive
 
        self.sponsor_benefits.exclude(pk__in=allowed_benefits).update(active=False, max_words=None, other_limits="")
 
    
 
        self.sponsor_benefits.exclude(pk__in=allowed_benefits)\
 
            .update(active=False, max_words=None, other_limits="")
 

	
 
    def send_coordinator_emails(self):
...
 
@@ -149,7 +153,8 @@ BENEFIT_TYPE_CHOICES = [
 
class Benefit(models.Model):
 
    
 

 
    name = models.CharField(_("name"), max_length=100)
 
    description = models.TextField(_("description"), blank=True)
 
    type = models.CharField(_("type"), choices=BENEFIT_TYPE_CHOICES, max_length=10, default="simple")
 
    
 
    type = models.CharField(_("type"), choices=BENEFIT_TYPE_CHOICES, max_length=10,
 
                            default="simple")
 

	
 
    def __unicode__(self):
...
 
@@ -159,6 +164,6 @@ class Benefit(models.Model):
 
class BenefitLevel(models.Model):
 
    
 

 
    benefit = models.ForeignKey(Benefit, related_name="benefit_levels", verbose_name=_("benefit"))
 
    level = models.ForeignKey(SponsorLevel, related_name="benefit_levels", verbose_name=_("level"))
 
    
 

 
    # default limits for this benefit at given level
...
 
@@ -166,6 +171,6 @@ class BenefitLevel(models.Model):
 
    other_limits = models.CharField(_("other limits"), max_length=200, blank=True)
 
    
 

 
    class Meta:
 
        ordering = ["level"]
 
    
 

 
    def __unicode__(self):
...
 
@@ -175,3 +180,3 @@ class BenefitLevel(models.Model):
 
class SponsorBenefit(models.Model):
 
    
 

 
    sponsor = models.ForeignKey(Sponsor, related_name="sponsor_benefits", verbose_name=_("sponsor"))
...
 
@@ -179,3 +184,3 @@ class SponsorBenefit(models.Model):
 
    active = models.BooleanField(default=True)
 
    
 

 
    # Limits: will initially be set to defaults from corresponding BenefitLevel
...
 
@@ -183,3 +188,3 @@ class SponsorBenefit(models.Model):
 
    other_limits = models.CharField(_("other limits"), max_length=200, blank=True)
 
    
 

 
    # Data: zero or one of these fields will be used, depending on the
...
 
@@ -188,9 +193,9 @@ class SponsorBenefit(models.Model):
 
    upload = models.FileField(_("file"), blank=True, upload_to="sponsor_files")
 
    
 

 
    class Meta:
 
        ordering = ["-active"]
 
    
 

 
    def __unicode__(self):
 
        return u"%s - %s" % (self.sponsor, self.benefit)
 
    
 

 
    def clean(self):
...
 
@@ -201,3 +206,3 @@ class SponsorBenefit(models.Model):
 
                    self.max_words, num_words))
 
    
 

 
    def data_fields(self):
symposion/sponsorship/templatetags/sponsorship_tags.py
Show inline comments
...
 
@@ -10,3 +10,3 @@ register = template.Library()
 
class SponsorsNode(template.Node):
 
    
 

 
    @classmethod
...
 
@@ -20,3 +20,3 @@ class SponsorsNode(template.Node):
 
            raise template.TemplateSyntaxError("%r takes 'as var' or 'level as var'" % bits[0])
 
    
 

 
    def __init__(self, context_var, level=None):
...
 
@@ -27,3 +27,3 @@ class SponsorsNode(template.Node):
 
        self.context_var = context_var
 
    
 

 
    def render(self, context):
...
 
@@ -32,5 +32,8 @@ class SponsorsNode(template.Node):
 
            level = self.level.resolve(context)
 
            queryset = Sponsor.objects.filter(level__conference = conference, level__name__iexact = level, active = True).order_by("added")
 
            queryset = Sponsor.objects.filter(
 
                level__conference=conference, level__name__iexact=level, active=True)\
 
                .order_by("added")
 
        else:
 
            queryset = Sponsor.objects.filter(level__conference = conference, active = True).order_by("level__order", "added")
 
            queryset = Sponsor.objects.filter(level__conference=conference, active=True)\
 
                .order_by("level__order", "added")
 
        context[self.context_var] = queryset
...
 
@@ -40,3 +43,3 @@ class SponsorsNode(template.Node):
 
class SponsorLevelNode(template.Node):
 
    
 

 
    @classmethod
...
 
@@ -48,6 +51,6 @@ class SponsorLevelNode(template.Node):
 
            raise template.TemplateSyntaxError("%r takes 'as var'" % bits[0])
 
    
 

 
    def __init__(self, context_var):
 
        self.context_var = context_var
 
    
 

 
    def render(self, context):
...
 
@@ -74,2 +77 @@ def sponsor_levels(parser, token):
 
    return SponsorLevelNode.handle_token(parser, token)
 
    
...
 
\ No newline at end of file
symposion/sponsorship/urls.py
Show inline comments
 
# flake8: noqa
 
from django.conf.urls.defaults import patterns, url
symposion/sponsorship/views.py
Show inline comments
...
 
@@ -7,3 +7,4 @@ from django.contrib.auth.decorators import login_required
 

	
 
from symposion.sponsorship.forms import SponsorApplicationForm, SponsorDetailsForm, SponsorBenefitsFormSet
 
from symposion.sponsorship.forms import SponsorApplicationForm, SponsorDetailsForm, \
 
    SponsorBenefitsFormSet
 
from symposion.sponsorship.models import Sponsor, SponsorBenefit
...
 
@@ -20,3 +21,3 @@ def sponsor_apply(request):
 
        form = SponsorApplicationForm(user=request.user)
 
    
 

 
    return render_to_response("sponsorship/apply.html", {
...
 
@@ -30,3 +31,3 @@ def sponsor_add(request):
 
        raise Http404()
 
    
 

 
    if request.method == "POST":
...
 
@@ -40,3 +41,3 @@ def sponsor_add(request):
 
        form = SponsorApplicationForm(user=request.user)
 
    
 

 
    return render_to_response("sponsorship/add.html", {
...
 
@@ -49,6 +50,6 @@ def sponsor_detail(request, pk):
 
    sponsor = get_object_or_404(Sponsor, pk=pk)
 
    
 

 
    if sponsor.applicant != request.user:
 
        return redirect("sponsor_list")
 
    
 

 
    formset_kwargs = {
...
 
@@ -57,8 +58,8 @@ def sponsor_detail(request, pk):
 
    }
 
    
 

 
    if request.method == "POST":
 
        
 

 
        form = SponsorDetailsForm(request.POST, instance=sponsor)
 
        formset = SponsorBenefitsFormSet(request.POST, request.FILES, **formset_kwargs)
 
        
 

 
        if form.is_valid() and formset.is_valid():
...
 
@@ -66,5 +67,5 @@ def sponsor_detail(request, pk):
 
            formset.save()
 
            
 

 
            messages.success(request, "Sponsorship details have been updated")
 
            
 

 
            return redirect("dashboard")
...
 
@@ -73,3 +74,3 @@ def sponsor_detail(request, pk):
 
        formset = SponsorBenefitsFormSet(**formset_kwargs)
 
    
 

 
    return render_to_response("sponsorship/detail.html", {
symposion/teams/admin.py
Show inline comments
...
 
@@ -7,4 +7,3 @@ from symposion.teams.models import Team, Membership
 
admin.site.register(Team,
 
    prepopulated_fields={"slug": ("name",)},
 
)
 
                    prepopulated_fields={"slug": ("name",)})
 

	
symposion/teams/backends.py
Show inline comments
...
 
@@ -6,6 +6,6 @@ from .models import Team
 
class TeamPermissionsBackend(object):
 
    
 

 
    def authenticate(self, username=None, password=None):
 
        return None
 
    
 

 
    def get_team_permissions(self, user_obj, obj=None):
symposion/teams/forms.py
Show inline comments
...
 
@@ -11,5 +11,6 @@ from symposion.teams.models import Membership
 
class TeamInvitationForm(forms.Form):
 
    
 
    email = forms.EmailField(help_text="email address must be that of an account on this conference site")
 
    
 

	
 
    email = forms.EmailField(help_text=("email address must be that of an account on this "
 
                                        "conference site"))
 

	
 
    def __init__(self, *args, **kwargs):
...
 
@@ -17,3 +18,3 @@ class TeamInvitationForm(forms.Form):
 
        super(TeamInvitationForm, self).__init__(*args, **kwargs)
 
    
 

 
    def clean(self):
...
 
@@ -21,6 +22,6 @@ class TeamInvitationForm(forms.Form):
 
        email = cleaned_data.get("email")
 
        
 

 
        if email is None:
 
            raise forms.ValidationError("valid email address required")
 
        
 

 
        try:
...
 
@@ -30,17 +31,19 @@ class TeamInvitationForm(forms.Form):
 
            # already on the site
 
            raise forms.ValidationError(mark_safe("no account with email address <b>%s</b> found on this conference site" % escape(email)))
 
        
 
            raise forms.ValidationError(
 
                mark_safe("no account with email address <b>%s</b> found on this conference "
 
                          "site" % escape(email)))
 

	
 
        state = self.team.get_state_for_user(user)
 
        
 

 
        if state in ["member", "manager"]:
 
            raise forms.ValidationError("user already in team")
 
        
 

 
        if state in ["invited"]:
 
            raise forms.ValidationError("user already invited to team")
 
        
 

 
        self.user = user
 
        self.state = state
 
        
 

 
        return cleaned_data
 
    
 

 
    def invite(self):
symposion/teams/models.py
Show inline comments
...
 
@@ -22,11 +22,12 @@ class Team(models.Model):
 
    access = models.CharField(max_length=20, choices=TEAM_ACCESS_CHOICES)
 
    
 

 
    # member permissions
 
    permissions = models.ManyToManyField(Permission, blank=True, related_name="member_teams")
 
    
 

 
    # manager permissions
 
    manager_permissions = models.ManyToManyField(Permission, blank=True, related_name="manager_teams")
 
    
 
    manager_permissions = models.ManyToManyField(Permission, blank=True,
 
                                                 related_name="manager_teams")
 

	
 
    created = models.DateTimeField(default=datetime.datetime.now, editable=False)
 
    
 

 
    @models.permalink
...
 
@@ -34,3 +35,3 @@ class Team(models.Model):
 
        return ("team_detail", [self.slug])
 
    
 

 
    def __unicode__(self):
...
 
@@ -43,12 +44,12 @@ class Team(models.Model):
 
            return None
 
    
 

 
    def applicants(self):
 
        return self.memberships.filter(state="applied")
 
    
 

 
    def invitees(self):
 
        return self.memberships.filter(state="invited")
 
    
 

 
    def members(self):
 
        return self.memberships.filter(state="member")
 
    
 

 
    def managers(self):
symposion/teams/templatetags/teams_tags.py
Show inline comments
...
 
@@ -8,3 +8,3 @@ register = template.Library()
 
class AvailableTeamsNode(template.Node):
 
    
 

 
    @classmethod
...
 
@@ -16,6 +16,6 @@ class AvailableTeamsNode(template.Node):
 
            raise template.TemplateSyntaxError("%r takes 'as var'" % bits[0])
 
    
 

 
    def __init__(self, context_var):
 
        self.context_var = context_var
 
    
 

 
    def render(self, context):
symposion/teams/urls.py
Show inline comments
 
# flake8: noqa
 
from django.conf.urls.defaults import *
...
 
@@ -9,3 +10,3 @@ urlpatterns = patterns("symposion.teams.views",
 
    url(r"^(?P<slug>[\w\-]+)/apply/$", "team_apply", name="team_apply"),
 
    
 

 
    # membership specific
symposion/teams/views.py
Show inline comments
...
 
@@ -12,3 +12,3 @@ from symposion.teams.models import Team, Membership
 

	
 
## perm checks
 
# perm checks
 
#
...
 
@@ -52,3 +52,3 @@ def can_invite(team, user):
 

	
 
## views
 
# views
 

	
...
 
@@ -61,3 +61,3 @@ def team_detail(request, slug):
 
        raise Http404()
 
    
 

 
    if can_invite(team, request.user):
...
 
@@ -74,3 +74,3 @@ def team_detail(request, slug):
 
        form = None
 
    
 

 
    return render(request, "teams/team_detail.html", {
...
 
@@ -91,3 +91,3 @@ def team_join(request, slug):
 
        raise Http404()
 
    
 

 
    if can_join(team, request.user) and request.method == "POST":
...
 
@@ -108,3 +108,3 @@ def team_leave(request, slug):
 
        raise Http404()
 
    
 

 
    if can_leave(team, request.user) and request.method == "POST":
...
 
@@ -124,3 +124,3 @@ def team_apply(request, slug):
 
        raise Http404()
 
    
 

 
    if can_apply(team, request.user) and request.method == "POST":
symposion/utils/mail.py
Show inline comments
...
 
@@ -9,5 +9,5 @@ from django.contrib.sites.models import Site
 
def send_email(to, kind, **kwargs):
 
    
 

 
    current_site = Site.objects.get_current()
 
    
 

 
    ctx = {
...
 
@@ -21,8 +21,8 @@ def send_email(to, kind, **kwargs):
 
    )
 
    
 

 
    message_html = render_to_string("emails/%s/message.html" % kind, ctx)
 
    message_plaintext = strip_tags(message_html)
 
    
 

 
    from_email = settings.DEFAULT_FROM_EMAIL
 
    
 

 
    email = EmailMultiAlternatives(subject, message_plaintext, from_email, to)
symposion/views.py
Show inline comments
...
 
@@ -14,3 +14,3 @@ import symposion.forms
 
class SignupView(account.views.SignupView):
 
    
 

 
    form_class = symposion.forms.SignupForm
...
 
@@ -19,3 +19,3 @@ class SignupView(account.views.SignupView):
 
    }
 
    
 

 
    def create_user(self, form, commit=True):
0 comments (0 inline, 0 general)